4

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;
        }
    }
}
FKorni
  • 405
  • 1
  • 5
  • 11
  • try adding `WebOperationContext.Current.OutgoingResponse.ContentType = "application/json";` before retuning – Amit Kumar Ghosh Feb 17 '16 at 13:19
  • Adding `"application/json"` to the outgoing response allows me now to serialize to json, but i have one more Problem. Both XML and JSON serializes the backing fields instead of the properties. I can avoid this for XML using the attribute `XmlSerializerFormat` for my Service Contract, but than I again can't use JSON because it doesn't like this attribute. It suggests my to use `DataContractFormatAttribute`, which will again result in serializing the backing fields.. – FKorni Feb 17 '16 at 13:37

1 Answers1

1

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.

dbc
  • 104,963
  • 20
  • 228
  • 340