我想用 WCF 编写一个 RESTful Web 服务,它能够以 JSON 和 XML 进行回复。我有一个 XML 架构,我使用 xsd.exe
从中生成了我的类。只要我请求 XML,一切都可以正常工作,但如果我想要 JSON 作为响应,它就会失败。
System.ServiceModel.Dispatcher.MultiplexingDispatchMessageFormatter
抛出 System.Collections.Generic.KeyNotFoundException
。问题是,到目前为止,我发现 xsd.exe
不会生成 DataContract
和 DataMember
属性。有什么解决方案可以解决我不需要使用 SvcUtil.exe
的问题,因为因此我需要更改我的架构..
这是失败的代码,JsonDispatchMessageFormatter
是 MultiplexingDispatchMessageFormatter
类型。 (无论如何这是默认类型)
var headers = requestProperty.Headers[HttpRequestHeader.Accept] ?? requestProperty.Headers[HttpRequestHeader.ContentType];
if (headers != null && headers.Contains("application/json"))
{
return this.JsonDispatchMessageFormatter.SerializeReply(messageVersion, parameters, result);
}
生成的代码:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="...")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="...", IsNullable=false)]
public partial class Incident {
private long incidentIdField;
/// <remarks/>
public long IncidentId {
get {
return this.incidentIdField;
}
set {
this.incidentIdField = value;
}
}
}
最佳答案
您在 JSON 中看到私有(private)字段而不是公共(public)属性的原因是 xsd.exe
已将您的类标记为 [SerializableAttribute]
.当此属性应用于类型时,它表示可以通过序列化所有私有(private)和公共(public)字段 来序列化该类型的实例——而不是属性。
在幕后,WCF 使用 DataContractJsonSerializer
序列化到 JSON 和从 JSON 序列化。当此序列化程序为没有 data contract attributes 的类型生成默认的隐式数据协定时,它注意到 [Serializable]
属性并遵守它,生成一个契约(Contract)来序列化和反序列化公共(public)和私有(private)字段。这就是您所看到的。
有点奇怪的是 xsd.exe
不需要将 [Serializable]
添加到其生成的类中。 XmlSerializer
完全忽略此属性 因为它只能序列化公共(public)成员。 (它也完全忽略了数据契约属性。同样,数据契约序列化程序都忽略了 XmlSerializer
control attributes 。)
不幸的是,我没有看到任何 xsd
command line switches禁用此属性。因此,您将进行某种手动修复:
从生成的类中删除
[System.SerializableAttribute()]
。这应该是无害的,除非你在某处使用BinaryFormatter
;你可能不是。将
[DataContract]
和[DataMember]
属性添加到生成的类中。 (请记住,XmlSerializer
会忽略,因此您预先存在的 XML 架构将保持不变。)您还可以考虑使用
SvcUtil.exe
生成适用于契约(Contract)的类,然后使用 automapper将旧类(class)映射到新类(class)。或者您可以考虑切换到不同的 JSON 序列化程序,例如 json.net ,在那里你可以control whether to ignore or respect
[Serializable]
.问题How to set Json.Net as the default serializer for WCF REST service和 C# WCF REST - How do you use JSON.Net serializer instead of the default DataContractSerializer?应该让你开始。
顺便说一句,如果您想精确控制 XML 和 JSON 格式,WCF rest 可能不是最适合您的技术。 ASP.NET Web API 允许使用 json.net 更精确地控制序列化格式。 ;见JSON and XML Serialization in ASP.NET Web API连同 Setting IgnoreSerializableAttribute Globally in Json.net和 .NET WebAPI Serialization k_BackingField Nastiness .
关于c# - 使用 WCF 将类序列化为由 xsd.exe 生成的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35457465/