ASP.NET MVC 4 ApiController serialization error: No readonly properties serialized and System.Runtime.Serialization.InvalidDataContractException

I’m starting a new project using the ASP.NET MVC 4 runtime. I’m using the new ApiController feature, really cool indeed. I had a business entity (domain class) that I wished to expose. But since the ApiController default serializer don’t write readonly properties, the best answer I found on the net was to create a ViewModel wrapping an instance of my business entity exposing the properties I wanted. Check the code:

public class DomainEntityApiController : ApiController
{
	// GET /api/domainentityapi
	public IEnumerable<DomainEntityViewModel> Get()
	{
		List<DomainEntityViewModel> list = new List<DomainEntityViewModel>();

		for (int i = 0; i < 10; i++)
		{
			list.Add(new DomainEntityViewModel(new DomainEntity(i + "Id", i + "Name")));
		}

		return list;
	}
}

public class DomainEntityViewModel
{
	private DomainEntity _entity;

	public DomainEntityViewModel(DomainEntity entity)
	{
		_entity = entity;
	}

	public String Id
	{
		get { return _entity.Id; }
		set 
		{ 
			// Do nothing 
		}
	}

	public String Name
	{
		get { return _entity.Name; }
		set
		{
			// Do nothing 
		}
	}
}

public class DomainEntity
{
	private String _id;

	private String _name;

	public DomainEntity(String id, String name)
	{
		this._id = id;
		this._name = name;
	}

	public String Id
	{
		get { return _id; }
	}

	public String Name
	{
		get { return _name; }
	}
}

Compiled. Went to http://localhost/api/DomainEntityApi and BANG! Error:

Type ‘TakeThatTime.Web.Models.DomainEntityViewModel’ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types.

body {font-family:”Verdana”;font-weight:normal;font-size: .7em;color:black;}
p {font-family:”Verdana”;font-weight:normal;color:black;margin-top: -5px}
b {font-family:”Verdana”;font-weight:bold;color:black;margin-top: -5px}
H1 { font-family:”Verdana”;font-weight:normal;font-size:18pt;color:red }
H2 { font-family:”Verdana”;font-weight:normal;font-size:14pt;color:maroon }
pre {font-family:”Lucida Console”;font-size: .9em}
.marker {font-weight: bold; color: black;text-decoration: none;}
.version {color: gray;}
.error {margin-bottom: 10px;}
.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }

After a long research about the error and nothing found (at least not on google first result page ;)) I tried something: Putting a no args constructor on the ViewModelClass, like this:

public class DomainEntityViewModel
{
	private DomainEntity _entity;

	// Constructor that does nothing just because of the serialization issue
	public DomainEntityViewModel()
	{
		throw new NotSupportedException();
	}

	public DomainEntityViewModel(DomainEntity entity)
	{
		_entity = entity;
	}

	public String Id
	{
		get { return _entity.Id; }
		set 
		{ 
			// Do nothing 
		}
	}

	public String Name
	{
		get { return _entity.Name; }
		set
		{
			// Do nothing 
		}
	}
}

And tried again. And it worked. Here is the response now:

<?xml version="1.0" encoding="utf-8"?><ArrayOfDomainEntityViewModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><DomainEntityViewModel><Id>0Id</Id><Name>0Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>1Id</Id><Name>1Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>2Id</Id><Name>2Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>3Id</Id><Name>3Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>4Id</Id><Name>4Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>5Id</Id><Name>5Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>6Id</Id><Name>6Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>7Id</Id><Name>7Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>8Id</Id><Name>8Name</Name></DomainEntityViewModel><DomainEntityViewModel><Id>9Id</Id><Name>9Name</Name></DomainEntityViewModel></ArrayOfDomainEntityViewModel>
Advertisements

1 comment so far

  1. Matt Hancock on

    This was a BIG help. Thanks!!!!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: