我想用WCF编写RESTful Webservice,它能够以JSON和XML进行回复。我有一个XML模式,我使用xsd.exe
从中生成了我的类。只要我请求XML,Everthing就可以正常工作,但如果我想要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;
}
}
}
答案 0 :(得分:1)
您在JSON中看到私有字段而非公共属性的原因是xsd.exe
已使用[SerializableAttribute]
标记了您的类。将此属性应用于某个类型时,它表示可以通过序列化所有私有和公共字段而不是属性来序列化该类型的实例。
在幕后,WCF使用DataContractJsonSerializer
与JSON进行序列化。当此序列化程序为没有data contract attributes的类型生成默认的隐式数据协定时,它会注意到[Serializable]
属性并尊重它,生成一个序列化和反序列化公共和私有字段的合同。这就是你所看到的。
有点奇怪的是xsd.exe
不需要将[Serializable]
添加到其生成的类中。 XmlSerializer
完全忽略此属性,因为只能序列化公共成员。 (它也完全忽略了数据契约属性。同样,数据契约序列化程序都忽略了XmlSerializer
control attributes。)
很遗憾,我没有看到任何xsd
command line switches来禁用此属性。因此,您将进行某种手动修复:
从生成的类中删除[System.SerializableAttribute()]
。除非你在某个地方使用BinaryFormatter
,否则这应该是无害的;你可能不是。
将[DataContract]
和[DataMember]
属性添加到生成的类中。 (请记住,这些被<{1}}忽略,因此您预先存在的XML架构将保持不变。)
您还可以考虑使用XmlSerializer
生成与合约相关的课程,然后使用automapper将旧课程映射到新课程。
或者您可以考虑切换到其他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休息可能不是最适合您的技术。 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。