Servicestack SerializationException:无法反序列化'application / json'

时间:2013-10-23 11:23:05

标签: c# android json servicestack deserialization

来自Android设备的某些请求会使我们的servicestack.net服务失败并出现此异常:

System.Runtime.Serialization.SerializationException: Could not deserialize 'application/json' request using CSharpRequestMappedObject'
Error: System.Threading.ThreadAbortException: Thread was being aborted.
   at System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest(IntPtr pHandler, Byte[] pBuffer, Int32 offset, Int32 cbBuffer, Int32& pBytesRead)
   at System.Web.Hosting.IIS7WorkerRequest.ReadEntityCoreSync(Byte[] buffer, Int32 offset, Int32 size)
   at System.Web.HttpRequest.GetEntireRawContent()
   at System.Web.HttpRequest.get_InputStream()
   at ServiceStack.WebHost.Endpoints.Support.EndpointHandlerBase.CreateContentTypeRequest(IHttpRequest httpReq, Type requestType, String contentType)
   at ServiceStack.WebHost.Endpoints.Support.EndpointHandlerBase.CreateContentTypeRequest(IHttpRequest httpReq, Type requestType, String contentType)
   at ServiceStack.WebHost.Endpoints.RestHandler.GetRequest(IHttpRequest httpReq, IRestPath restPath)
   at ServiceStack.WebHost.Endpoints.RestHandler.ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, String operationName)

我知道它有一些与Post'ed json数据无关,无法解析为CSharpRequestMappedObject。

映射如下:

[Route("/RequestPath/", Verbs = "POST"), UsedImplicitly]
public class CSharpRequestMappedObject
{
    public string Name{ get; set; }
    public IList<SomeClass> Items{ get; set; }
    public bool State { get; set; }
    public string SpecialType { get; set; } //Not required
}

我的问题是如何弄清楚请求有什么问题?
它有时只会发生 - 我在服务器日志中看到它,但我无法重现它。

我在global.asax中试过这个:

public override void Configure(Container container)
{       
    ServiceExceptionHandler = (request, ex) =>
    {
        //Enrich exceptions with request body data.
        var propertyInfo = HttpContext.Current.Request.GetType().GetProperty("EntityBody", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        var postBody = Encoding.UTF8.GetString((byte[])propertyInfo.GetValue(HttpContext.Current.Request, null));

        throw new Exception("Request body: " + postBody, ex);
    };
}

它添加了关于其他异常的请求正文数据 - 但是这个异常并没有被捕获。 (我还有一些其他日志记录可以捕获后者 - elmah)

3 个答案:

答案 0 :(得分:2)

我建议关注

  • 开始使用Fiddler跟踪来回的请求和响应
  • 使用jsonlint验证您的json传递是否为输入。
  • 在请求DTO中添加构造函数,用于创建像public CSharpRequestMappedObject() { Items= New List<SomeClass>(); }
  • 这样的项目的新对象

这些是一些通用指南,请发布您的json输入,以便我可以推荐一些更精确的提示。

答案 1 :(得分:1)

我们结束时发现异常实际上是由另一个异常抛出后的瞬间引起的:HttpException:请求超时。 我总是发生大约5/100秒。

因此,原因是Android设备连接不良,这种情况很少发生。

答案 2 :(得分:0)

虽然我意识到这个问题已经存在,但问题仍然存在,似乎是由于来自Android设备的PATCH请求发送的格式错误或未终止的实体主体,而不是IIS或.NET问题。

当.NET应用程序挂起几(或多个)秒并最终抛出以下错误时,可以看到问题,如Morten所述:

System.Threading.ThreadAbortException: Thread was being aborted.
   at System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest(IntPtr pHandler, Byte[] pBuffer, Int32 offset, Int32 cbBuffer, Int32& pBytesRead, UInt32 timeout)
   at System.Web.Hosting.IIS7WorkerRequest.ReadEntityCoreSync(Byte[] buffer, Int32 offset, Int32 size, Int64 timeout)
   at System.Web.HttpRequest.GetEntireRawContent()
   at System.Web.HttpRequest.get_InputStream()

当Android设备使用协议相对URL 发出PATCH请求(包含实体主体)时,会发生异常。 如果更改网址以包含协议,则问题就会消失

我已经使用GET,PUT,PATCH,DELETE和OPTIONS动词对此进行了测试,并且发现它只与PATCH一起发生。

我还测试了与Windows 7桌面浏览器(Chrome 41,IE11和Firefox 36)相同的动词组合以及在Android 4.4.2上运行iOS 8.2和Chrome 40的设备,两者都具有协议限定和协议 - 相对的URL。

在所有这些动词/平台/浏览器/协议组合中,我只使用协议相对URL从Android设备发出PATCH请求时抛出了错误。如果未包含实体主体,则不会发生错误。

此外,我首先怀疑它可能与跨源请求有关。但是,在对上述组合进行测试后,我发现请求是跨域还是同一域没有区别。同样,实体主体是JSON还是纯文本也没有区别。所有测试都是使用版本2.1.3中的jQuery&#aajax()方法完成的。

我没有找到如何更好地捕获错误(或者防止它在服务器上发生,可能通过执行一些预处理)的答案,但我认为了解传入的类型会有所帮助请求导致它。