C# 如何为HttpClient(WinForms)设置默认json序列化设置
我有一个WinForms应用程序,它使用Web API后端,我希望所有HTTP请求/响应都使用特定的json SerializerSettings。在服务器端,只需在Global.asax.cs中执行此操作即可轻松实现:C# 如何为HttpClient(WinForms)设置默认json序列化设置,c#,.net,winforms,asp.net-web-api,json.net,C#,.net,Winforms,Asp.net Web Api,Json.net,我有一个WinForms应用程序,它使用Web API后端,我希望所有HTTP请求/响应都使用特定的json SerializerSettings。在服务器端,只需在Global.asax.cs中执行此操作即可轻松实现: GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateParseHandling = DateParseHandling.None; GlobalConfigurati
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateParseHandling = DateParseHandling.None;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
在客户端,我尝试了以下方法:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateParseHandling = DateParseHandling.None
}.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
当我显式地使用JsonConvert时,这是有效的,例如:
var someVm = JsonConvert.DeserializeObject<SomeVm>(jsonString);
var someVm=JsonConvert.DeserializeObject(jsonString);
但是,对于使用HttpClient.GetAsync/PostAsAsync等的调用,它不起作用,从而导致异常:
将值2/24/2018 4:00:00 PM转换为类型时出错
'System.Nullable1[NodaTime.LocalDateTime]'。路径
“折叠预期日期”,第16行,位置45。
Newtonsoft.Json.JsonSerializationException:转换值时出错
2018年2月24日下午4:00:00输入
'System.Nullable
1[NodaTime.LocalDateTime]'。路径
“折叠预期日期”,第16行,位置45。-->
System.ArgumentException:无法从中强制转换或转换
System.DateTime到NodeTime.LocalDateTime
请注意,当如上所述调用反序列化对象时,导致上述异常的JSON可以正常工作
如何设置/修改HttpClient使用的默认序列化设置(我不想在每次调用中都指定它-有几百个)?
HttpContent
扩展方法在中定义,它们使用包含JsonMediaTypeFormatter的私有静态,XmlMediaTypeFormatter
和新FormUrlEncodedMediaTypeFormatter
这些扩展方法允许您传递一个自定义的MediaTypeFormatter
列表。它们使用您传递的格式化程序,或者如果您不传递任何格式化程序,它们将使用私有静态格式化程序集合。因此,作为结论:
- 您可以创建格式化程序的静态列表,并对其进行设置,并在每次调用方法时将其传递给方法
- 您可以选择使用反射设置
类的静态格式化程序集合。然后这些扩展方法将始终使用该设置HttpContentExtensions
HttpContextException
的静态私有DefaultMediaTypeFormatterCollection
属性:
public class HttpClientDefaults
{
public static MediaTypeFormatterCollection MediaTypeFormatters
{
get
{
var p = typeof(HttpContentExtensions).
GetProperty("DefaultMediaTypeFormatterCollection",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static);
return (MediaTypeFormatterCollection)p.GetValue(null, null);
}
}
}
然后在应用程序启动时,您可以在一个点中设置格式化程序:
var jsonFormatter = HttpClientDefaults.MediaTypeFormatters
.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
// Setup jsonFormatter, for example using jsonFormatter.SerializerSettings
var jsonFormatter=HttpClientDefaults.MediaTypeFormatters
.OfType().FirstOrDefault();
//设置jsonFormatter,例如使用jsonFormatter.SerializerSettings
该设置将用于所有从json反序列化的扩展方法,您无需更改调用这些方法的方式:
HttpClient client = new HttpClient();
var response = await client.GetAsync("http://localhost:58045/api/products/1");
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsAsync<Product>();
}
HttpClient=newhttpclient();
var response=wait client.GetAsync(“http://localhost:58045/api/products/1");
if(响应。IsSuccessStatusCode)
{
var result=await response.Content.ReadAsAsync();
}
这是我想到的,到目前为止似乎效果不错(就我而言),而且非常干净
用于从服务器读取Json响应(基于:):
以下是JsonFormatter实用程序方法(将重构上面的ReadAsJsonAsync以使用此方法):
当然欢迎对该解决方案的反馈…当然,根据本文分享的想法,您可以创建自定义扩展方法,使用自定义格式化程序/settings.man,为什么
HttpClient
不允许全局配置此方法,对吗?对于Content.ReadAsAsync
来说,传递json转换器“很容易”,但是对于client.PostAsJson
来说,没有办法。。。通过反射进行设置将适用于客户端。PostAsJson
?
public static class HttpContentExtensions
{
public static async Task<T> ReadAsJsonAsync<T>(this HttpContent content, JsonSerializerSettings jsonSerializerSettings = null)
{
if (jsonSerializerSettings == null)
{
jsonSerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateParseHandling = DateParseHandling.None
}.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
}
string json = await content.ReadAsStringAsync();
T value = JsonConvert.DeserializeObject<T>(json, jsonSerializerSettings);
return value;
}
}
var someVm = await response.Content.ReadAsJsonAsync<SomeVm>().ConfigureAwait(false);
//var response = await WebServiceUtil.HttpClient.PostAsJsonAsync("designSalesJob/new", designSalesJob).ConfigureAwait(false);
var response = await WebServiceUtil.HttpClient.PostAsync("designSalesJob/new", designSalesJob, HttpUtil.JsonFormatter).ConfigureAwait(false);
public static class HttpUtil
{
public static JsonMediaTypeFormatter JsonFormatter => new JsonMediaTypeFormatter
{
SerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateParseHandling = DateParseHandling.None
}.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)
};
}