WebService不会反序列化某些对象 [英] WebService not Deserializing some objects

查看:105
本文介绍了WebService不会反序列化某些对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经制作了一个Web服务(REST),并且正在从Windows服务中调用它.

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

有些呼叫似乎没有问题,也无法正常工作.而其他一些则返回Bad Request.当反序列化数据为NULL时,我将服务器设置为返回Bad Request.

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.

Web服务已使用EDMX从数据库生成了对象类.

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

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

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

我正在使用Microsoft.AspNet.WebApi.Client Nuget包从本地服务进行呼叫.

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);

网络服务代码

//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();
        }

本地服务代码

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;
    }

不工作对象类别

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; }
}

发布数据示例

{"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.

谢谢

推荐答案

您的问题是,您正在使用的两种技术(WCF Rest和HttpClient.PostAsJsonAsync())使用不同的序列化程序. WCF Rest使用 DataContractJsonSerializer ,而 PostAsJsonAsync 内部使用 JsonMediaTypeFormatter ,它使用

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.

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

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):

  • 在Json.NET中,您的日期已序列化为ISO 8601标准字符串"date_lodged": "2012-05-03T00:00:00".
  • 通过数据合约序列化程序,它使用特殊的Microsoft格式 "date_lodged":"\/Date(1336017600000-0400)\/".
  • 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)\/".

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

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.

首先,您可以将WCF rest配置为使用其他序列化程序.这涉及,请参见 WCF可扩展性–邮件格式化程序 WCF原始"编程模型(Web).

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);
    }
}

或者您可以在客户端使用Json.NET并

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);
    }
}

使用设置

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

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

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#).

最后,您还可以考虑切换到 ASP.NET Web API ,其中

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

这篇关于WebService不会反序列化某些对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆