I have a windows service which has the following code
public class CertificationStatusCheckJob : IJob
{
public readonly ILog _logger = LogManager.GetCurrentClassLogger();
readonly HttpClient client = new HttpClient { BaseAddress = new Uri(ConfigurationManager.AppSettings["MercuryServicesWebApiUrl"]) };
// Temporary local versoin of statuses
private enum CertificationStatus
{
Active = 1,
Pending,
PendingRenewal,
RenewalPastDue,
ReinstatementOnCurrentCycle,
ClosedInactive,
ClosedRenewed
};
public async void Execute(IJobExecutionContext context)
{
Dictionary<string, int> designationWindows = new Dictionary<string, int>
{
{"RenewalWindow", 10},
{"CertificationLength", 12},
{"FreeGrace", 1},
{"InactiveAccessLength",1},
{"InactivityLength", 36}
};
Console.WriteLine("CertificationApplicationStatusCheckJob: Creating Cert application status job");
string content = null;
List<Certification> retrievedCerts = null;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Call webapi to retrieve all applications
var certificationsResponse = client.GetAsync("certifications/getAllCertifications").Result;
// loop through all applications and compare to rules
if (certificationsResponse.IsSuccessStatusCode)
{
content = certificationsResponse.Content.ReadAsStringAsync().Result;
Console.WriteLine(content);
}
if (content != null)
{
retrievedCerts = JsonConvert.DeserializeObject<List<Certification>>(content);
_logger.Debug("Got Certifications OK");
}
// Allows for all task calls to service api to be performed in parallel in async
if (retrievedCerts != null)
await Task.WhenAll(retrievedCerts.Select(i => CheckCert(i)) as IEnumerable<Task>);
}
private async Task<object> CheckCert(Certification cert)
{
// current date time to compare the range for each state below to.
// if this date falls in the range for the state, do not change the state,
// otherwise kick them into the next state.
DateTime currentDateTime = DateTime.UtcNow;
var newCertStatus = new { certUniqueId = Guid.NewGuid(), statusId=6 };
switch ((CertificationStatus)cert.CertificationStatusId)
{
case CertificationStatus.Active:
//Condition to test for when the cert is in the active state
await client.PostAsJsonAsync("certifications/updateStateForCertification", newCertStatus);
break;
case CertificationStatus.Pending:
break;
case CertificationStatus.PendingRenewal:
break;
case CertificationStatus.RenewalPastDue:
break;
case CertificationStatus.ReinstatementOnCurrentCycle:
break;
case CertificationStatus.ClosedInactive:
break;
case CertificationStatus.ClosedRenewed:
break;
}
return null;
}
}
The Following are the services that are getting called
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Gets all certifications. </summary>
/// <returns> all certifications. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
[Route("getAllCertifications")]
[AllowAnonymous]
public async Task<List<Certification>> GetAllCertifications()
{
List<Certification> certList = null;
try
{
certList = await _certificationService.GetAllCertifications();
}
catch (Exception e)
{
_logger.Error("exception GetAllCertifications", e);
throw;
}
return certList;
}
//TODO WRITE SERVICE ENTRY POINT FOR SAVE ROUTINE
[Route("updateStateForCertification")]
[AcceptVerbs("POST")]
[AllowAnonymous]
public void UpdateStateForCertification(Guid certUniqueId, int statusId)
{
List<Certification> certList = null;
try
{
_certificationService.UpdateStateForCertification(certUniqueId, statusId);
}
catch (Exception e)
{
_logger.Error("exception UpdateStateForCertification", e);
throw;
}
}
}
I've verified the GetAsync GetAllCertifications() call works as I can debug into that code block. However when I do the PostAsJsonAsync using the anonymous type it won't work. I know json only cares about the properties. I've also verified that it DOES hit the PostAsJsonAsync line of code, so it should be performing the post. So what am I doing wrong?
the problem is your web api method. Your post method accepts two "simple" types. And per default simple types are read from the URI NOT from the body.
The body is read for a complex type. So you have two options:
You can't read two primitive types from the body, you can only force one to be read with
[FromBody]
Attribute.In more detail you can read the parameter binding here: Parameter Binding in ASP.NET Web API