我已经创建了一个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);
本地服务代码
//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;
}
POST数据示例
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; }
}
任何想法都将不胜感激。
由于
答案 0 :(得分:5)
您的问题是您使用的两种技术WCF Rest和HttpClient.PostAsJsonAsync()
使用不同的序列化程序。 WCF Rest使用DataContractJsonSerializer
,PostAsJsonAsync
内部使用JsonMediaTypeFormatter
,Json.NET by default。
不幸的是,这两个序列化程序对日期有不同的默认格式(请记住有no standard representation for a date in JSON):
"date_lodged": "2012-05-03T00:00:00"
。"date_lodged":"\/Date(1336017600000-0400)\/"
。因此,当WCF休息服务在内部使用的DataContractJsonSerializer
尝试反序列化日期时,它会失败并抛出异常。
您有几个选项可以解决此问题。
首先,您可以配置WCF rest以使用不同的序列化程序。这涉及到,请参阅WCF Extensibility – Message Formatters和WCF "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使用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);
}
}
使用设置
settings = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
或者,您可以修改客户端以使用Using the REST Services with .NET和Parsing REST Services JSON Responses (C#)行的REST服务。
最后,您还可以考虑在服务器端切换到ASP.NET Web API uses Json.NET。