WebService不反序列化某些对象

Sei*_*ige 3 c# json web-services

我已经创建了一个Web服务(REST),我从Windows服务中调用它.

一些电话似乎没有工作和问题.而其他一些人正在返回Bad Request.我将服务器设置为在反序列化数据为NULL时返回Bad Request.

Web Service使用EDMX从数据库生成对象类.

本地服务具有对Web服务的服务引用,因此它具有相同的对象类.

我正在使用Microsoft.AspNet.WebApi.Client Nuget Package来从本地服务进行调用.

代码低于Web服务操作

//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);
Run Code Online (Sandbox Code Playgroud)

WEB服务代码

//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();
        }
Run Code Online (Sandbox Code Playgroud)

本地服务代码

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;
    }
Run Code Online (Sandbox Code Playgroud)

不工作的对象类

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; }
}
Run Code Online (Sandbox Code Playgroud)

POST数据示例

{"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"}
Run Code Online (Sandbox Code Playgroud)

任何想法将不胜感激.

谢谢

dbc*_*dbc 5

您的问题是您使用的两种技术,WCF Rest和HttpClient.PostAsJsonAsync()使用不同的序列化程序.WCF Rest DataContractJsonSerializerPostAsJsonAsync内部使用时默认JsonMediaTypeFormatter使用Json.NET.

而且,遗憾的是,这两个序列化程序对日期具有不同的默认格式(请记住,JSON中没有日期的标准表示):

  • 在Json.NET中,您的日期序列化为ISO 8601标准字符串"date_lodged": "2012-05-03T00:00:00".
  • 使用数据协定序列化程序,它使用特殊的Microsoft格式 "date_lodged":"\/Date(1336017600000-0400)\/".

因此,当DataContractJsonSerializer您的WCF休息服务在内部使用时尝试反序列化日期时,它会失败并引发异常.

您有几个选项可以解决此问题.

首先,您可以配置WCF休息以使用不同的序列化程序.这涉及到,请参阅WCF可扩展性 - 消息格式化程序WCF"原始"编程模型(Web).

其次,您可以使用数据协定序列化程序使您的客户端序列化.这很简单,只需设置即可JsonMediaTypeFormatter.UseDataContractJsonSerializer = true.我相信以下扩展应该做的工作:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者您可以在客户端坚持使用Json.NET 并将默认日期格式更改为Microsoft格式:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用设置

        settings =  new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
Run Code Online (Sandbox Code Playgroud)

或者,您可以修改客户端以使用REST服务,这与使用REST服务和.NET以及解析REST服务JSON响应(C#)一致.

最后,你还可以考虑切换到的ASP.NET Web API使用Json.NET在服务器端.