【问题标题】:ASP.NET API action only returning JSON even when XML is requested即使请求 XML,ASP.NET API 操作也仅返回 JSON
【发布时间】:2015-10-17 23:34:45
【问题描述】:

我的 API 控制器有两个动作,一个可以正常工作,并且会根据请求返回 JSON 或 XML。工作方式基本如下,返回一个IQueryable

public IQueryable<UserDTO> GetUsers()
{
    var users = db.Users.Select(user => new UserDTO()
    {
        Name = user.Name,
        ...
    });
    return users;
}

然后我有第二种方法,它返回一个匿名类型,它是User 的简化版本。因为它返回一个匿名类型,所以我在我构造的地方使用HttpResponseMessage 的返回类型。 JSON-only 方法如下:

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);
    }

为什么第二种方法只返回 JSON?我玩过 Fiddler 和 Chrome 并调整了 Accept 请求标头。如果请求 XML,则会出现错误 500,并出现以下错误:

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 '&lt;&gt;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.&lt;WriteBufferedResponseContentAsync&gt;d__1b.MoveNext()</StackTrace></InnerException></Error>

编辑:澄清问题并添加错误响应。

【问题讨论】:

  • 请求呢?提供了什么Accepts
  • 我在我的问题中说错了,我会解决这个问题。 Chrome 中的 Accept 标头是“ text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8 ”,而在 Fiddler 中我只尝试过“ application/xml " 并且都导致错误500
  • 我刚刚意识到我的问题缺少大量重要信息,即错误代码 500 中的错误。我已将问题修复为更具描述性。
  • This question 似乎表明没有办法将匿名类型序列化为开箱即用的 XML,而答案似乎表明这样做麻烦多于其价值。我可能会坚持“改用真正的课程”cmets。

标签: c# asp.net


【解决方案1】:

在堆栈跟踪中有以下信息:

类型'f__AnonymousType24[System.Int32,System.String,System.String,System.Collections.Generic.IEnumerable1[System.Int32]]' 不能序列化。考虑用 DataContractAttribute 属性,并标记您的所有成员 想要使用 DataMemberAttribute 属性进行序列化。如果类型 是一个集合,考虑用 集合数据合同属性。请参阅 Microsoft .NET 框架 其他受支持类型的文档。

所以看起来你不能序列化匿名类的集合。

尝试创建专门的响应类,或者使用UserDTO(如果它适用于您的新方法)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 2020-09-12
    • 2012-10-14
    • 2020-11-03
    • 2014-12-08
    相关资源
    最近更新 更多