我有一个POST到Web API的客户端。收到POST内容时,JSON使用属性的私有成员名称而不是公共属性。 (客户端应用程序正在使用Asp.Net-Web-api2库,而Web API本身是使用IIS7.5上的IHttpHandler实现的,并且不是MVC样式的应用程序,代码也在使用现有的Usage类之前导致我重新编码的TFS事故,现在是奇怪的行为)
//Object I am passing
[Serializable]
public class Usage
{
private string _user;
private string _trackingUnit;
public string User {get {return _user;} set {_user = value;}}
public string TrackingUnit { get{return _trackingUnit;} set { _trackingUnit = value;}}
}
我使用以下
发帖Usage usage = new Usage();
usage.User = "pete";
usage.TrackingUnit = "unit of work";
HttpClientHandler handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
HttpClient client = new HttpClient(handler);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.PostAsJsonAsync(url, usage);
我使用以下
接收POSTbyte[] postData = context.Request.BinaryRead(context.Request.ContentLength);
string strData = Encoding.UTF8.GetString(postData);
Usage newUsage = JsonConvert.DeserializeObject<Usage>(strData);
当我检查strData时,它看起来如下所示,这会导致反序列化返回一个未填充的Usage对象
{"_user":"pete","_trackingUnit":"unit of work"}
我希望
{"User":"pete","TrackingUnit":"unit of work"}
注意:
如果我新建一个新的Usage对象并尝试在Web API中对其进行序列化并返回该字符串,则其格式正确
JsonConvert.SerializeObject(usage);
{"User":"pete","TrackingUnit":"unit of work"}
此外,如果我在客户端应用程序中尝试JsonConvert.Serialize,它也可以按预期工作
答案 0 :(得分:1)
您看到的原因是您的框架使用json.net进行JSON序列化,而在代码库中的某个位置,选项DefaultContractResolver.IgnoreSerializableAttribute
已设置为{{ 1}}。当这个设置时,Json.NET将序列化标记为false
的类型的公共和私有字段 - 你的。
为了确认这种情况发生,我们可以检查参考源。首先,HttpClientExtensions.PostAsJsonAsync<T>()
使用新构造的[Serializable]
JsonMediaTypeFormatter
它的基类BaseJsonMediaTypeFormatter
又有一个类型为JsonContractResolver
的内部public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, Uri requestUri, T value, CancellationToken cancellationToken)
{
return client.PostAsync(requestUri, value, new JsonMediaTypeFormatter(), cancellationToken);
}
,在其构造函数中设置
IContractResolver _defaultContractResolver
这就是问题的根源。
解决此问题的您的选项如下所示。
首先,如果您愿意为模型添加Json.NET依赖项,可以使用[JsonObject]
// Need this setting to have [Serializable] types serialized correctly
IgnoreSerializableAttribute = false;
这会将JsonObjectAttribute.MemberSerialization
重置为默认值MemberSerialization.OptOut
,从而覆盖[Serializable]
[JsonObject]
public class Usage
{
private string _user;
private string _trackingUnit;
public string User {get {return _user;} set {_user = value;}}
public string TrackingUnit { get{return _trackingUnit;} set { _trackingUnit = value;}}
}
。
其次,您可以使用data contract attributes注释您的类型,Json.NET尊重它:
[Serializable]
请注意,数据合同序列化是选择性的,因此您需要注释要序列化的每个成员。
第三,您可以删除[Serializable]
[DataContract]
public class Usage
{
private string _user;
private string _trackingUnit;
[DataMember]
public string User {get {return _user;} set {_user = value;}}
[DataMember]
public string TrackingUnit { get{return _trackingUnit;} set { _trackingUnit = value;}}
}
- 但在您的问题中,您表明这不是一个选项。
最后,您可以根据reference source制作自己的扩展方法,以取代HttpClientExtensions
中的扩展方法,并使用[Serializable]
序列化您的对象,例如(未经测试):
IgnoreSerializableAttribute = true