简体   繁体   中英

WebService not Deserializing some objects

I have made a Web Service (REST), and I am calling it from a Windows Service.

Some of the calls seem to be working without and problems. While some of the others are returning Bad Request. I set the server to return Bad Request when ever the Deserialized data was NULL.

The Web Service has Generated the Object Classes from the database using EDMX.

The Local Service has a Service Reference to the Web Service, so it has the same Object Classes available to it.

I am using Microsoft.AspNet.WebApi.Client Nuget Package to make the calls from the Local Service.

CODE BELOW WEB SERVICE OPERATIONS

//NOT WORKING
 [OperationContract]
 [WebInvoke(Method = "POST",
       UriTemplate = "{entity}/consent/{consent_id}/info")]
 bool ConsentInformation(string entity, string consent_id, consent info);

//WORKING
 [OperationContract]
 [WebInvoke(Method = "POST",
        UriTemplate = "{entity}/council/users")]
 void GoGetUsers(string entity, IEnumerable<council_user> user);

WEB SERVICE CODE

//NOT WORKING
 public void ConsentStatus(string entity, string consent_id, consent_status status)
        {            
            Utilities.SetResponseFormat();
            if (status == null)
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.BadRequest;
                return;
            }
            gosubmitEntity entitys = new gosubmitEntity();
            consent_status consent = entitys.consent_status.FirstOrDefault(c => c.consent_id == consent_id && c.council_code == entity);
            if (consent == null)
                entitys.consent_status.Add(status);
            else
                consent = status;
            entitys.SaveChanges();
            WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Created;
        }
//WORKING
public void GoGetUsers(string entity, IEnumerable<council_user> users)
        {
            Utilities.SetResponseFormat();
            if (users == null || users.Count() == 0)
            {
                WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.BadRequest;
                return;
            }
            gosubmitEntity entitys = new gosubmitEntity();
            foreach (council_user user in users)
            {
                council_user dbUser = entitys.council_user.FirstOrDefault(u => u.username == user.username && u.council_code == entity);
                if (dbUser == null)
                    entitys.council_user.Add(user);                
                else
                    dbUser = user;
            }
            entitys.SaveChanges();
        }

LOCAL SERVICE CODE

public static async Task<bool> POST<T>(string requestURI, T data)
        {
            HttpClient client = CreateClient();
            HttpResponseMessage response = await client.PostAsJsonAsync(requestURI, data);
            if (response.IsSuccessStatusCode)
                return true;
            else
            {
                DiagnosticLog.Write(99, $"Status response from webservice = {response.StatusCode}", string.Empty);
                return false;
            }
        }
 private static HttpClient CreateClient()
    {
        var client = new HttpClient();
        client.BaseAddress = new Uri(Settings.BaseWebservice);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        return client;
    }

NOT WORKING OBJECT CLASS

public partial class consent_status
{
    public string consent_id { get; set; }
    public string council_code { get; set; }
    public string lodged { get; set; }
    public string processing { get; set; }
    public string rfis { get; set; }
    public string issued { get; set; }
    public string inspections { get; set; }
    public string ccc { get; set; }
    public Nullable<System.DateTime> date_lodged { get; set; }
    public Nullable<System.DateTime> date_granted { get; set; }
    public Nullable<System.DateTime> date_issued { get; set; }
    public Nullable<System.DateTime> date_cccissued { get; set; }
    public Nullable<int> days_live { get; set; }
    public Nullable<int> days_inactive { get; set; }
    public Nullable<int> days_suspended { get; set; }
    public Nullable<System.DateTime> form6_received { get; set; }
    public string ccc_file_name { get; set; }
    public Nullable<System.DateTime> last_updated { get; set; }
}

POST DATA EXAMPLE

{"ccc":"","ccc_file_name":"","consent_id":"120266","council_code":"DEMO","date_cccissued":null,"date_granted":null,"date_issued":null,"date_lodged":"2012-05-03T00:00:00","days_inactive":null,"days_live":null,"days_suspended":null,"form6_received":null,"inspections":"In Progress","issued":"","last_updated":null,"lodged":"Accepted","processing":"","rfis":"Pending"}

Any ideas would be greatly appreciated.

Thanks

Your problem is that the two technologies you are using, WCF Rest and HttpClient.PostAsJsonAsync() , use different serializers. WCF Rest uses DataContractJsonSerializer while PostAsJsonAsync internally uses JsonMediaTypeFormatter which uses Json.NET by default .

And, unfortunately, these two serializers have different default formatting for dates (bearing in mind that there is no standard representation for a date in JSON ):

  • In Json.NET, your date is serialized as an ISO 8601 standard string "date_lodged": "2012-05-03T00:00:00" .
  • With the data contract serializer, it uses an idiosyncratic Microsoft format "date_lodged":"\\/Date(1336017600000-0400)\\/" .

So when the DataContractJsonSerializer used internally by your WCF rest service tries to deserialize the date, it fails and throws an exception.

You have a few options to resolve this.

Firstly, you could configure WCF rest to use a different serializer. This is involved, see WCF Extensibility – Message Formatters and WCF "Raw" programming model (Web) .

Secondly, you could make your client serialize using the data contract serializer. This is quite easy, just set JsonMediaTypeFormatter.UseDataContractJsonSerializer = true . I believe the following extensions should do the job:

public static class HttpClientExtensions
{
    public static Task<HttpResponseMessage> PostAsDataContractJsonAsync<T>(this HttpClient client, string requestUri, T value)
    {
        return client.PostAsJsonAsync(requestUri, value, CancellationToken.None);
    }

    public static Task<HttpResponseMessage> PostAsDataContractJsonAsync<T>(this HttpClient client, string requestUri, T value, CancellationToken cancellationToken)
    {
        return client.PostAsync(requestUri, value, new JsonMediaTypeFormatter { UseDataContractJsonSerializer = true }, cancellationToken);
    }
}

Or you could stick with Json.NET on the client side and change the default date format to Microsoft format:

public static class HttpClientExtensions
{
    public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T value, JsonSerializerSettings settings)
    {
        return client.PostAsJsonAsync(requestUri, value, settings, CancellationToken.None);
    }

    public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T value, JsonSerializerSettings settings, CancellationToken cancellationToken)
    {
        return client.PostAsync(requestUri, value, new JsonMediaTypeFormatter { SerializerSettings = settings }, cancellationToken);
    }
}

Using the settings

        settings =  new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };

Alternatively, you could modify your client to consume the REST service along the lines of Using the REST Services with .NET and Parsing REST Services JSON Responses (C#) .

Finally, you could also consider switching to ASP.NET Web API which uses Json.NET on the server side.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM