1

来自 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)

4

3 回答 3

2

我会推荐以下

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

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

于 2013-10-23T12:57:14.983 回答
1

我们最终发现该异常实际上是由另一个异常引发不久之后引发的:HttpException:请求超时。我总是出现大约 5/100 秒的后者。

因此,原因是 Android 设备上的连接不良,这是有道理的,因为它很少发生。

于 2013-10-24T09:41:33.163 回答
0

虽然我意识到这个问题已经过时,但问题仍然存在,并且似乎是由于PATCH来自 Android 设备的请求发送的格式错误或未终止的实体主体,而不是 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 请求(包含实体主体)时,会发生异常。如果 URL 更改为包含协议,问题就会消失

我已经用 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 还是纯文本也没有区别。所有测试都是使用 jQuery 2.1.3 版本中的 .ajax() 方法完成的。

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

于 2015-03-19T05:55:38.223 回答