C# 未捕获WEB API httpException
我有一个WEB API应用程序,我们在其中添加了一些会话验证逻辑,然后调用基本SendAsync方法 当我们传递包含大于4MB的字节[]的请求时,lineC# 未捕获WEB API httpException,c#,asp.net-web-api,asp.net-web-api2,C#,Asp.net Web Api,Asp.net Web Api2,我有一个WEB API应用程序,我们在其中添加了一些会话验证逻辑,然后调用基本SendAsync方法 当我们传递包含大于4MB的字节[]的请求时,lineresponse=wait base.SendAsync(请求,取消令牌)抛出httpException“超出最大请求长度”,这是正常的,可以通过IIS设置进行管理。困扰我的是下一步——它仍然在调用controller方法,我可以看到这个byte[]参数设置为null。控制器方法抛出ArgumentNullException,这是最终用户得到的
response=wait base.SendAsync(请求,取消令牌)代码>抛出httpException“超出最大请求长度”,这是正常的,可以通过IIS设置进行管理。困扰我的是下一步——它仍然在调用controller方法,我可以看到这个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;
}
}
公共类sessiondHandler:DelegatingHandler
{
受保护的覆盖异步任务SendAsync(
HttpRequestMessage请求,
取消令牌(取消令牌)
{
//这里有一些额外的逻辑
HttpResponseMessage响应;
尝试
{
response=wait base.sendaync(请求、取消令牌);
}
捕获(例外e)
{
响应=新的HttpResponseMessage(HttpStatusCode.Forbidden)
{
Content=newstringcontent(例如,Message,Encoding.UTF8,“应用程序/json”)
};
}
最后
{
如果(签名人)
{
签核(sessionId);
}
}
返回响应;
}
}
困扰我的是下一步——它仍然在呼叫控制器
方法,我可以看到这个byte[]参数设置为null
当您调用base.SendAsync(请求、取消令牌)时代码>,您实际上是在继续WebAPI管道,这将最终导致调用控制器:
实际上,您需要在将请求发送到控制器之前检查内容长度
标题。您可以通过为请求的标头检索它来实现这一点。如果大小超过,则可以返回一个响应,指示继续管道:
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);
}
受保护的覆盖任务SendAsync(
HttpRequestMessage请求,
取消令牌(取消令牌)
{
//4MB,也许您希望像其他请求一样将其放宽一点
//特性会影响尺寸。
常量int maxRequestSize=4194304;
IEnumerable contentLengthHeader;
request.Headers.TryGetValues(“内容长度”,out contentLengthHeader);
var contentLength=contentLengthHeader.FirstOrDefault();
if(contentLength==null)
{
//未发送内容长度,请决定要执行的操作。
}
长实际内容长度;
如果(!long.TryParse(contentLength,out实际contentLength))
{
//无法分析,无法决定要执行的操作。
}
如果(实际内容长度>最大请求大小)
{
//如果达到,则请求的内容长度太大。
//返回错误响应:
返回Task.FromResult(request.CreateErrorResponse(HttpStatusCode.Forbidden),
Format(“请求大小超过了{0}字节”,maxRequestSize));
}
返回base.sendaync(请求、取消令牌);
}
如果您不希望对WebAPI应用程序中的所有控制器进行此检查,您可以。您提到的控制器方法是什么?这是不是Signoff(sessionId)?
除非我被误解,否则这不是默认的try catch finally
行为吗?不,控制器方法不是直接从上面的代码调用的。它是AddDocument方法,请求中描述了它,上面的代码拦截了它一段时间,以便检查会话。@mattytommo,默认行为是什么意思?因为我没弄错,任务通常会抛出aggreateeexception。在这里,我从对base.SendAsync方法的调用中抛出了两个异常,我只得到了最后一个异常。我希望有一个不是聚合,就是先发生的。谢谢你,@Yuval Itzzakov,但我不想在后台的某个地方用.NET代码为我检查请求长度,从而复制逻辑。此外,如果我使用常量const int maxRequestSize=4194304;然后有人更改IIS设置,这将导致不正确的行为。@Olga这只是为了演示。如果愿意,您可以从IIS配置的设置中读取此内容。好的,但无论如何,它将复制逻辑。好吧,我想,如果没有其他事情出现,我最终会这么做的。非常感谢。