2015-10-12 63 views
1

我已經做了一個Web服務(REST),我從Windows服務調用它。WebService不反序列化一些對象

有些呼叫似乎沒有工作,也沒有問題。而其他一些人正在返回錯誤請求。當反序列化數據爲NULL時,我將服務器設置爲返回錯誤請求。

Web服務使用EDMX從數據庫生成了對象類。

本地服務具有對Web服務的服務引用,因此它具有與其相同的對象類。

我正在使用Microsoft.AspNet.WebApi.Client Nuget包進行本地服務調用。

下面的代碼 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); 

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

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

不工作對象類

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數據例

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

任何想法將不勝感激。

感謝

+0

你在服務器端使用什麼? [WCF Rest](http://www.codeproject.com/Articles/105273/Create-RESTful-WCF-Service-API-Step-By-Step-Guide)? – dbc

+0

這是一個WCF休息服務 – Seige

回答

4

你的問題是,這兩種技術使用的是,WCF休息和HttpClient.PostAsJsonAsync(),使用不同的序列化。 WCF Rest使用DataContractJsonSerializer,而PostAsJsonAsync內部使用JsonMediaTypeFormatter,其使用Json.NET by default

而且,不幸的是,這兩個串行器有不同的默認格式日期(銘記,有no standard representation for a date in JSON):

  • 在Json.NET,您的日期序列化爲ISO 8601標準字符串"date_lodged": "2012-05-03T00:00:00"
  • 使用數據合同序列化程序,它uses an idiosyncratic Microsoft format"date_lodged":"\/Date(1336017600000-0400)\/"

所以,當你的WCF REST服務內部使用的DataContractJsonSerializer試圖反序列化的日期,它失敗並拋出異常。

你有幾個選擇來解決這個問題。

首先,您可以配置WCF休息以使用不同的序列化程序。這涉及到,參見WCF Extensibility – Message FormattersWCF "Raw" programming model (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); 
    } 
} 

或者你可以用Json.NET堅持在客戶端和change the default date 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 }; 

或者,您可以修改您的客戶端以使用沿Using the REST Services with .NETParsing REST Services JSON Responses (C#)行的REST服務。

最後,你也可以考慮切換到ASP.NET Web API其中uses Json.NET在服務器端。

+0

我永遠不會懷疑時間會是問題。所有其他的JSON調用都在工作,所以我認爲它們是兼容的。如果我可以給代表禮物,我會爲此付出代價。感謝堆 – Seige