FKorni
FKorni

Reputation: 445

Serializing a class to JSON generated by xsd.exe using WCF

I want to write a RESTful Webservice with WCF which is able to reply in JSON and XML. I have a XML schema from which I generated my classes by using xsd.exe. Everthing works fine as long as I request XML, but it fails if I want JSON as response.

The System.ServiceModel.Dispatcher.MultiplexingDispatchMessageFormatter throws a System.Collections.Generic.KeyNotFoundException. The problem is, what I found out so far, that xsd.exe does not generate DataContract and DataMember Attributes. Is there any solution to this where I do not need to use the SvcUtil.exe, because therefore I would need to change my schema..

That is the code where it fails, JsonDispatchMessageFormatter is of the type MultiplexingDispatchMessageFormatter. (Which is the default type anyway)

var headers = requestProperty.Headers[HttpRequestHeader.Accept] ?? requestProperty.Headers[HttpRequestHeader.ContentType];
if (headers != null && headers.Contains("application/json"))
{
    return this.JsonDispatchMessageFormatter.SerializeReply(messageVersion, parameters, result);
}

Generated code:

[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;
        }
    }
}

Upvotes: 4

Views: 1669

Answers (1)

dbc
dbc

Reputation: 116544

The reason you are seeing private fields rather than public properties in your JSON is that xsd.exe has marked your classes with [SerializableAttribute]. When this attribute is applied to a type, it signifies that instances of the type can be serialized by serializing all private and public fields -- not the properties.

Under the covers, WCF uses DataContractJsonSerializer to serialize to and from JSON. When this serializer goes to generate a default, implicit data contract for a type without data contract attributes, it notices the [Serializable] attribute and respects it, generating a contract to serialize and deserialize public and private fields. This is what you are seeing.

What is a bit odd is that xsd.exe doesn't need to add [Serializable] to its generated classes. XmlSerializer completely ignores this attribute since it can only serialize public members. (It also completely ignores data contract attributes. Similarly the data contract serializers all ignore XmlSerializer control attributes.)

Unfortunately, I don't see any xsd command line switches to disable this attribute. Thus you're going to do some sort of manual fix:

As an aside, WCF rest may not be the best technology for you if you want precise control over your XML and JSON formatting. ASP.NET Web API allows for much more precise control of serialization formats by using ; see JSON and XML Serialization in ASP.NET Web API along with Setting IgnoreSerializableAttribute Globally in Json.net and .NET WebAPI Serialization k_BackingField Nastiness.

Upvotes: 1

Related Questions