简体   繁体   中英

WebAPI v2 XMLFormatter not serializing get only properties

I'm using ASP.NET WebAPI and everything works well with accept: application/json header, but when using accept: application/xml header the XMLFormatter doesn't seem to be able to serialize get only properties.

This is the base class I'm trying to serialize

public class RequestResponse
{
    public string Status
    {
        get
        {
            if (Success)
                return "SUCCESS";
            else
            {
                return "FAIL";
            }
        }
    }
    public IList<RequestError> Errors { get; set; }
    protected bool Success { get; set; }
}

This is the XML response

<RequestResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Backend.Models">
    <Errors i:nil="true" />
</RequestResponse>

And this is the JSON response

{
  "Status": "FAIL",
  "Errors": null
}

The XML version is missing the get only property Status. I tried adding XmlElement("Status") and even XmlElement(IsNullable=true) just to see if it would come up with that, but it didn't seem to change anything. Only way I can seem to get it to work is by adding set method to my property, but I really don't want to do that.

Is this a bug inside WebAPI v2 or is there some way to serialize get only properties.

This is my controller method.

[HttpGet]
public RequestResponse Test()
{
    RequestResponse response = new RequestResponse();
    return response;
}

I do not think you can serialize get only props. When the string gets deserialized first it has to construct the new instance with a default constructor and then it uses the set props to write the value so no setter, no serialize.

Also the json serializer will serialize the read only prop but it would not be able to deserialize it back to an object.

If you REALLY need this to work you can implement ISerializable on your object and control the entire flow manually but its non-trivial https://msdn.microsoft.com/en-us/library/ty01x675(v=vs.110).aspx

Taken off msdn https://social.msdn.microsoft.com/Forums/en-US/3dff9c8b-083b-4ac5-8e43-249c4071d3bf/serialize-readonly-properties?forum=asmxandxml

"Well, unfortunately the short answer to your long post is that XML Serialization has no support for non-public or read-only properties. That being said, there's nothing that says your setter has to actualy do anything; it just has to exist. You could take the passive-aggresive route and just have an empty setter, then make an obscure comment in your documentation about the fact that the properties are really read-only in nature (and blame the whole thing on Microsoft of course). Alternatively, you could throw an exception in your setter, which will give developers consuming your class better debugging info."

If you do not mind performing your own serializing of the data, build a HttpResponseMessage and fill it out accordingly.

[HttpGet]
public HttpResponseMessage Test()
{
    HttpResponseMessage TestResponse = new HttpResponseMessage();
    RequestResponse response = new RequestResponse();
    string JsonData = JsonConvert.SerializeObject(response);
    if (Request.Headers.Accept.Contains(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml")))
    {
        XmlDocument doc = JsonConvert.DeserializeXmlNode(JsonData, "RequestResponse");
        TestResponse.Content = new StringContent(doc.InnerXml, System.Text.Encoding.UTF8, "application/xml");
    }
    else
    {
        TestResponse.Content = new StringContent(JsonData, System.Text.Encoding.UTF8, "application/json");
    }
    return TestResponse;
}

This will completely bypass the system formatters.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM