Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何为HttpClient(WinForms)设置默认json序列化设置_C#_.net_Winforms_Asp.net Web Api_Json.net - Fatal编程技术网

C# 如何为HttpClient(WinForms)设置默认json序列化设置

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

我有一个WinForms应用程序,它使用Web API后端,我希望所有HTTP请求/响应都使用特定的json SerializerSettings。在服务器端,只需在Global.asax.cs中执行此操作即可轻松实现:

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.Nullable
1[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)
    };
}