WEB API 未捕获 httpException

WEB API httpException is not caught

我有一个 WEB API 应用程序,我们在其中添加一些会话验证逻辑,然后调用基础 SendAsync 方法。

当我们传递包含大于 4MB 行的 byte[] 的请求时 response = await base.SendAsync(request, cancellationToken); 抛出一个 httpException "maximum request length exceeded",这没问题,可以通过 IIS 设置进行管理。令我困扰的是下一步 - 它仍在调用控制器方法,我可以在其中看到此 byte[] 参数设置为 null。控制器方法抛出 ArgumentNullException,这是最终用户得到的。

首先,我不明白为什么控制器方法在 HttpException 之后仍然被调用。更重要的是我如何设法捕获此 HttpException,以便最终用户将看到实际原因,即请求未被处理的原因。 提前谢谢你。

public class SessionIdHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        //some additional logic here
        HttpResponseMessage response;
        try
        {
            response = await base.SendAsync(request, cancellationToken);
        }
        catch (Exception e)
        {
            response = new HttpResponseMessage(HttpStatusCode.Forbidden)
            {
                Content = new StringContent(e.Message, Encoding.UTF8, "application/json")
            };
        }
        finally
        {
            if (signedOnHere)
            {
                Signoff(sessionId);
            }
        }
        return response;
   }
}

What bothers me is that next step - it's still calling controller method, where I can see that this byte[] parameter set to null.

当您调用 base.SendAsync(request, cancellationToken); 时,您实际上是在继续 WebAPI 管道,这最终会导致控制器被调用:

您真正想要的是在将请求发送到控制器之前检查 Content-Length header。为此,您可以为请求的 header 检索它。如果大小超过,您可以 return 一个响应表明,否则,继续管道:

protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, 
            CancellationToken cancellationToken)
{
    // 4MB, perhaps you want to loosen this up a bit as other request
    // characteristics will effect the size.
    const int maxRequestSize = 4194304;

    IEnumerable<string> contentLengthHeader;
    request.Headers.TryGetValues("Content-Length", out contentLengthHeader);

    var contentLength = contentLengthHeader.FirstOrDefault();
    if (contentLength == null)
    {
        //No content-length sent, decide what to do.
    }

    long actualContentlength;
    if (!long.TryParse(contentLength, out actualContentlength))
    {
        // Couldn't parse, decide what to do.
    }

    if (actualContentlength > maxRequestSize)
    {
        // If reached, the content-length of the request was too big. 
        // Return an error response:
        return Task.FromResult(request.CreateErrorResponse(HttpStatusCode.Forbidden,
            string.Format("Request size exceeded {0} bytes", maxRequestSize)));
    }
    return base.SendAsync(request, cancellationToken);
}

如果您不想对 WebAPI 应用程序中的所有控制器进行此检查,您可以 pre-route each DelegatingHandler