4
votes

I have created a webAPI controller method that looks the following:

 [HttpGet]
 public HttpResponseMessage RealEstates()
 {
     using (BoligsideDbContext context = new BoligsideDbContext())
     {
         List<RealEstateVm> realEstateVms = context.RealEstates.OrderByDescending(x => x.Id).ToList().Select(x => new RealEstateVm(x)).ToList();

          return Request.CreateResponse(HttpStatusCode.OK, realEstateVms);
     }
}

My VM looks the following:

public class RealEstateVm
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public int Area { get; set; }
        public int Rooms { get; set; }
        public int Rent { get; set; }
        public string Picture { get; set; }
        public RealEstateType Type { get; set; } //this is just an enum
        public string Address { get; set; }
        public List<string> Images { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string Phone2 { get; set; }
        public string OriginalUrl { get; set; }
        public string OriginalSource { get; set; }
        public string City { get; set; }
        public int ZipCode { get; set; }
        public string StreetAddress { get; set; }
        public double Longtitude { get; set; }
        public double Latitude { get; set; }
}

However whenever I go to the endpoint I get the following error:

Type 'Boligside.ViewModels.RealEstateVm' 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.

What could be the issue? I don't see why I should have to mark my VM with [DataContractAttribute]?

By the way the complete error message is here:

This XML file does not appear to have any style information associated with it. The document tree is shown below. An error has occurred. The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'. System.InvalidOperationException An error has occurred. Type 'Boligside.ViewModels.RealEstateVm' 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. System.Runtime.Serialization.InvalidDataContractException at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(Int32 id, RuntimeTypeHandle typeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) at WriteArrayOfRealEstateVmToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract ) at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()

3

3 Answers

6
votes

As the error said, It cannot be serialized and consider adding the data contract attribute..

using System.Runtime.Serialization;
[DataContract]
public class RealEstateVm
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Title { get; set; }
        [DataMember]
        public string Description { get; set; }
        [DataMember]
        public int Area { get; set; }
        [DataMember]
        public int Rooms { get; set; }
        [DataMember]
        public int Rent { get; set; }
        [DataMember]
        public string Picture { get; set; }
        [DataMember]
        public RealEstateType Type { get; set; } //this is just an enum
        public string Address { get; set; }
        [DataMember]
        public List<string> Images { get; set; }
        public string Name { get; set; }
        [DataMember]
        public string Email { get; set; }
        [DataMember]
        public string Phone { get; set; }
        [DataMember]
        public string Phone2 { get; set; }
        [DataMember]
        public string OriginalUrl { get; set; }
        [DataMember]
        public string OriginalSource { get; set; }
        [DataMember]
        public string City { get; set; }
        [DataMember]
        public int ZipCode { get; set; }
        [DataMember]
        public string StreetAddress { get; set; }
        [DataMember]
        public double Longtitude { get; set; }
        [DataMember]
        public double Latitude { get; set; }
}

More information about Data Contracts

7
votes

Your DTO class is missing an parameterless constructor. See here : Why XML-Serializable class need a parameterless constructor (Sorry to wake up this question but I have the same problem right now)

2
votes

Calling the API from browser will not set Accept Header to application/json, so the api will use XmlFormatter which uses DataContractSerializer by default, which is opt-in.

you can change that default behavior for XML like this

// XML Serializer Settings
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
// use UseXmlSerializer because we use opu-out in our model classes
xml.UseXmlSerializer = true;