My API controller has two actions, one works properly and will return either JSON or XML depending on the request. The working method is basically the following and returns an IQueryable
:
public IQueryable<UserDTO> GetUsers()
{
var users = db.Users.Select(user => new UserDTO()
{
Name = user.Name,
...
});
return users;
}
Then I have a second method that returns an anonymous type that is a simplified version of the User
. Since it returns an anonymous type I use a return type of HttpResponseMessage
where I construct. The JSON-only method is the following:
public HttpResponseMessage GetSimplifiedUsers()
{
var users = db.Users.Select(user => new
{
Id = user.Id,
OtherIds = user.Others.Select(o=>o.Id),
...
});
return this.Request.CreateResponse(HttpStatusCode.OK,users);
}
Why is this second method only returning JSON? I have played around with Fiddler and Chrome and adjusting the Accept
request headers. If XML is requested there is an error 500
with the following error:
HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: application/xml; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcZ2l0XGJvb3RjYW1wXExhYnNcTE1TIExhYlxMZWFybmluZ01hbmFnZW1lbnRTeXN0ZW1cTGVhcm5pbmdNYW5hZ2VtZW50U3lzdGVtXGFwaVx1c2Vyc1xzaW1wbGU=?=
X-Powered-By: ASP.NET
Date: Mon, 27 Jul 2015 17:06:26 GMT
Content-Length: 3894
<Error><Message>An error has occurred.</Message><ExceptionMessage>The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.</ExceptionMessage><ExceptionType>System.InvalidOperationException</ExceptionType><StackTrace /><InnerException><Message>An error has occurred.</Message><ExceptionMessage>Type '<>f__AnonymousType2`4[System.Int32,System.String,System.String,System.Collections.Generic.IEnumerable`1[System.Int32]]' 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.</ExceptionMessage><ExceptionType>System.Runtime.Serialization.InvalidDataContractException</ExceptionType><StackTrace> 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 WriteArrayOf_x003C__x003E_f__AnonymousType2OfintstringstringArrayOfintNHLuklIfToXml(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.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()</StackTrace></InnerException></Error>
EDIT: Clarified issue and added error response.