0

I have created a class from a schema using xsd.exe. This class contains System.Xml.Serialization attributes.

I have used this class as a parameter for a web api method. I need to serialise the parameter to xml so I can validate against schema and create a Oracle xmltype. My web api method is as follows

[HttpPost]
public HttpResponseMessage Create([FromBody]MyClass obj)

I switched the default Serializer to XmlSerializer in webapi.config as follows

config.Formatters.XmlFormatter.UseXmlSerializer = true;

From the client using HttpWebRequest or WebClient I can successfully serialise (XmlSerializer) an instance of the class and post it to the web api using application/xml content type. So far so good.

However, if I try to send application/json content type the parameter object proerties at the web api is always null. The parameter itself is not null just the properties within.

I create the json content as follows

MyClass data = new MyClass();
// assign some values
string json = new JavaScriptSerializer().Serialize(data);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json);

The instance of the class serialises to JSON ok and contains values assigned, however, when I post the byte array, always null at web api.

I am sure it is something to do with the System.Xml.Serialization attributes in the class at the web api.

Does anyone have any suggestion on how to get around this? Ade

Update My class generated with xsd

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://Ade.interface")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://Ade.interface", IsNullable = false)]
public partial class MyClass
{

    private string nameField;



    /// <remarks/>
    public string Name
    {
        get
        {
            return this.nameField;
        }
        set
        {
            this.nameField = value;
        }
    }
}

Web api

[HttpPost]
public HttpResponseMessage Create([FromBody]MyClass payload)
{
   // payload.Name is null
}

Fiddler

POST http://myhostname/Create HTTP/1.1
Content-Type: application/json
Host: myhostname
Content-Length: 14
Expect: 100-continue

{"Name":"Ade"}

Client

string json = new JavaScriptSerializer().Serialize(data);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json);

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://myhostname/Create");
request.Method = "POST";
request.ContentLength = bytes.Length;
request.ContentType = "application/json";
 try
    {
       using (Stream requestStream = request.GetRequestStream())
       {
           requestStream.Write(bytes, 0, bytes.Length);
       }
       // code removed            

    }                                                                                                    catch (WebException we)
    {
        // code removed           
    }
6
  • Did you check the model state for any errors? if (!ModelState.IsValid) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState)); } Commented Nov 13, 2013 at 16:28
  • The ModelState is true. The properties within the parameter object are all null not the parameter itself. Commented Nov 13, 2013 at 16:48
  • Could you share how your request over the wire looks like and also your type? Commented Nov 13, 2013 at 17:26
  • Unfortunately I cannot send the class contents. I will try a simple case and post here later Commented Nov 13, 2013 at 18:11
  • I have posted an update above. Commented Nov 13, 2013 at 18:52

2 Answers 2

1

This worked for me using version="4.0.20710.0" of Microsoft.AspNet.WebApi.Core

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
json.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
    IgnoreSerializableInterface = true,
    IgnoreSerializableAttribute = true
}; 
Sign up to request clarification or add additional context in comments.

Comments

0

Based on the repro, I noticed that Json formatter works fine if your request body was rather {"nameField":"Ade"}...

You can change this behavior by modifying the serialization settings on the contract resolver. After this change, you should be able to use {"Name":"Ade"}

Example:

JsonContractResolver resolver = (JsonContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver;
resolver.IgnoreSerializableAttribute = true; // default is 'false'

7 Comments

What assembly does JsonContractResolver belong to? I am using VS2010 Framework 4 I cannot resolve it
In System.Net.Formatting
I don't have a system.net.formatting. I have a system.net.http.formatting. If I use that I get following error 'System.Net.Http.Formatting.JsonContractResolver' is inaccessible due to its protection level
sorry that was a typo..i actually meant 'System.Net.Http.Formatting'...it appears you are using older version of Web API when this contract resolver was not public...
Just tried on another dev machine framework 4.5 and VS2012 still same error. Is Web API not part of the framework, if not how do I update web apiversion?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.