Archive for June 1st, 2012|Daily archive page
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>
Comments (1)