0

I found quite a nasty difference between the XML and Json serializer used by MVC4 today.

I tried to return an object that looks like this:

public class Person
{
  public string FirstName {get;set;}
  public string LastName {get;set;}
  public string FullName{ get{ return FirstName + " " + LastName }}
}

When the client request json as the result, I get FirstName, LastName and FullName returned with the expected values.

However, when the client asks for XML data, he only get FirstName and LastName.

This is in my opinion very bad, as it means that the client will get different data depending on which format they request.

It seems this is intentional since the documentation for the Json serializer says that read-only properties are included by default, and for the Xml serializer that they are excluded by default.

So my questions is: How chan I change the Xml serializer used by MVC4 to include those read-only by default. I know it manages to, because if you add the DataContract attribute to the class, and DataMember attribute to each property of the class it returnes the read-only variable as well, but I really don't want to do that.

Øyvind Bråthen
  • 59,338
  • 27
  • 124
  • 151

2 Answers2

0

You must use the datacontractserializer and mark your entities with the DataContract attribute, and each member you want serialized with DataMember.

The datacontractserializer allows the serialization of readonly properties.

Slicksim
  • 7,054
  • 28
  • 32
  • Re-read my question: I do **not** want to mark all my classes with `DataContract/DataMember` attributes just for this. I want to change the settings on the serializer to include read-only properties by default (just like the Json serializer does) – Øyvind Bråthen Sep 25 '13 at 12:16
0

First of all, I would recommend this article:

http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization#xml_readonly

As it gives an excellent rundown of serialization in WebAPI/MVC including showing how you can tell MVC what serializer to use (if you decide to implement your own to work around the read-only issue)

Now, if you want to use the default serializers (either DataContract or Xml), unfortunately you can't tell it to automatically serialize read-only properties; this is by design - if you think about it, it makes a certain kind of sense; since the typical use-case for XML serialization is

  • Serialize Type A
  • Send across the wire/save to disk
  • Read it back at some point in the future
  • Deserialize into instance of class A

I would imagine that this is because traditionally (back before there was much concept that you might want to send this data over HTTP to a weakly-typed browser based language) it would make little or no sense to serialise read-only properties - since you couldn't deserialize back to the original type as the field is read-only!

Of course nowadays it makes lots of sense that you might want these and I am sure that the JSON serializer folks had this in mind when they made the decision to include read-only properties by default for JSON since the more typical use-case for this is not serialization back to a strongly-typed instance but to a dynamically typed java script object.

i.e given

 public class Foo
    {
        public int Bar { get; set; }
        public string BarName { get { return "This is Bar# " + Bar; } }
    }

Let's suppose by default the Xml or DataContract Serializer produced this:

   <Foo>
     <Bar>10</Bar>
     <BarName>This is Bar# 10</BarName>
   </Foo>

How would you expect the following code to work?

 var xs = new XmlSerializer(typeof(Foo));
 var y = xs.Deserialize(new StreamReader(@"C:\foo.xml")) as Foo;

without throwing an exception that BarName is a readonly property?

The entire point of a non-settable property is that the conditions that make up the getter return value are unknown (i.e private) to the caller and therefore cannot be serialised...

Hence the DataContract and DataMembers which allow you to override the default behaviour.

Stephen Byrne
  • 7,400
  • 1
  • 31
  • 51