使用 WCF 将类序列化为 xsd 生成的 JSON .exe

本文关键字:JSON exe xsd WCF 序列化 使用 | 更新日期: 2023-09-27 18:34:55

我想用WCF编写一个RESTful Web服务,它能够用JSON和XML回复。我有一个 XML 架构,我使用 xsd.exe 从中生成了我的类。只要我请求 XML,一切都可以正常工作,但如果我想让 JSON 作为响应,它会失败。

System.ServiceModel.Dispatcher.MultiplexingDispatchMessageFormatter抛出System.Collections.Generic.KeyNotFoundException.问题是,到目前为止我发现,xsd.exe不会生成DataContractDataMember属性。有没有解决方案,我不需要使用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;
        }
    }
}

使用 WCF 将类序列化为 xsd 生成的 JSON .exe

您在 JSON 中看到私有字段而不是公共属性的原因是xsd.exe[SerializableAttribute] 标记了您的类。 当此属性应用于类型时,它表示可以通过序列化所有私有和公共字段(而不是属性(来序列化该类型的实例。

在后台,WCF 使用 DataContractJsonSerializer 来序列化到 JSON 和从 JSON 序列化。 当此序列化程序为没有数据协定属性的类型生成默认的隐式数据协定时,它会注意到 [Serializable] 属性并遵循它,生成一个协定来序列化和反序列化公共和私有字段。 这就是你所看到的。

有点奇怪的是,xsd.exe不需要向其生成的类添加[Serializable]XmlSerializer完全忽略此属性,因为它只能序列化公共成员。 (它还完全忽略数据协定属性。 同样,数据协定序列化程序都忽略XmlSerializer控件属性。

不幸的是,我没有看到任何xsd命令行开关来禁用此属性。 因此,您将执行某种手动修复:

  • 从生成的类中删除[System.SerializableAttribute()]。 这应该是无害的,除非您在某处使用BinaryFormatter;你可能不是。

  • [DataContract][DataMember]属性添加到生成的类。 (请记住,这些将被XmlSerializer忽略,因此您预先存在的 XML 架构将保持不变。

  • 您还可以考虑使用 SvcUtil.exe 生成适合契约的类,然后使用自动映射器将旧类映射到新类。

  • 或者,您可以考虑切换到其他 JSON 序列化程序,例如 json.net,您可以在其中控制是忽略还是尊重[Serializable]。 问题 如何将 Json.Net 设置为 WCF REST 服务和 C# WCF REST 的默认序列化程序 - 如何使用 JSON.Net 序列化程序而不是默认的数据合同序列化程序?应该让你开始。

顺便说一句,如果要精确控制 XML 和 JSON 格式,WCF rest 可能不是最适合您的技术。 ASP.NET Web API 允许使用 json.net 更精确地控制序列化格式;请参阅 Web API 中的 JSON 和 XML 序列化 ASP.NET 以及 Json.net 中的全局设置 IgnoreSerializableAttribute 和 .NET WebAPI 序列化k_BackingField讨厌。