每个请求错误处理策略
Per Request Error Handling Policy
我正在尝试按照 this 2013 guide 设置每个请求的错误处理策略。
- 如果是本地请求,显示错误信息。
- 如果当前用户在IT组,则显示错误信息。
- 对于其他人,不要显示错误。
我的代码:
public class PerRequestErrorPolicyDelegatingHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Properties[HttpPropertyKeys.IncludeErrorDetailKey] = new Lazy<bool>(() =>
{
// CHECK USER
var identity = request.GetRequestContext().Principal as ClaimsPrincipal;
return identity != null && identity.Identity.IsAuthenticated && identity.IsInRole("IT");
});
return base.SendAsync(request, cancellationToken);
}
}
它被注册为第一个处理程序:
public static void Configure(HttpConfiguration http)
{
http.MessageHandlers.Add(new PerRequestErrorPolicyDelegatingHandler());
...
}
我的网站 Api 托管在 Owin 上,但我没有看到相关的 Owin 代码,所以我省略了它。为了测试,我正在使用这个控制器:
[AllowAnonymous]
[RoutePrefix("api/sandbox")]
public class SandboxApiController : ApiController
{
[HttpPost, Route("test")]
public IHttpActionResult Test()
{
throw new InvalidOperationException($"you screwed up. Local: {RequestContext.IsLocal}, IT: {User.IsInRole("IT")}");
}
}
在本地,我总是得到错误信息,延迟加载代码(表示为"CHECK USER")从不执行,所以我不知道如何调试它。
部署到服务器,无论是否经过身份验证,我都不会收到任何错误信息。
我的 web.config 中没有自定义错误配置。
我做错了什么?
我认为我正在遵循的指南太旧而不再相关,而是遵循了这种方法。它更简单,而且有效。
我们将 ExceptionResult
替换为一个新的,我们在其中指定是否应包含详细信息。我们从现有结果中复制其他依赖项。
public class PerUserErrorDetailExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
var exResult = context.Result as ExceptionResult;
if (!context.CatchBlock.IsTopLevel || exResult == null)
return;
var identity = context.RequestContext.Principal as ClaimsPrincipal;
var showErrorDetail = identity != null
&& identity.Identity.IsAuthenticated
&& identity.IsInRole("IT");
context.Result = new ExceptionResult(
exResult.Exception,
showErrorDetail,
exResult.ContentNegotiator,
exResult.Request,
exResult.Formatters);
}
}
在其他地方,在 Web Api 配置中:
public static void Configure(HttpConfiguration http)
{
http.Services.Replace(typeof(IExceptionHandler), new PerUserErrorDetailExceptionHandler());
}
我正在尝试按照 this 2013 guide 设置每个请求的错误处理策略。
- 如果是本地请求,显示错误信息。
- 如果当前用户在IT组,则显示错误信息。
- 对于其他人,不要显示错误。
我的代码:
public class PerRequestErrorPolicyDelegatingHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Properties[HttpPropertyKeys.IncludeErrorDetailKey] = new Lazy<bool>(() =>
{
// CHECK USER
var identity = request.GetRequestContext().Principal as ClaimsPrincipal;
return identity != null && identity.Identity.IsAuthenticated && identity.IsInRole("IT");
});
return base.SendAsync(request, cancellationToken);
}
}
它被注册为第一个处理程序:
public static void Configure(HttpConfiguration http)
{
http.MessageHandlers.Add(new PerRequestErrorPolicyDelegatingHandler());
...
}
我的网站 Api 托管在 Owin 上,但我没有看到相关的 Owin 代码,所以我省略了它。为了测试,我正在使用这个控制器:
[AllowAnonymous]
[RoutePrefix("api/sandbox")]
public class SandboxApiController : ApiController
{
[HttpPost, Route("test")]
public IHttpActionResult Test()
{
throw new InvalidOperationException($"you screwed up. Local: {RequestContext.IsLocal}, IT: {User.IsInRole("IT")}");
}
}
在本地,我总是得到错误信息,延迟加载代码(表示为"CHECK USER")从不执行,所以我不知道如何调试它。
部署到服务器,无论是否经过身份验证,我都不会收到任何错误信息。
我的 web.config 中没有自定义错误配置。
我做错了什么?
我认为我正在遵循的指南太旧而不再相关,而是遵循了这种方法。它更简单,而且有效。
我们将 ExceptionResult
替换为一个新的,我们在其中指定是否应包含详细信息。我们从现有结果中复制其他依赖项。
public class PerUserErrorDetailExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
var exResult = context.Result as ExceptionResult;
if (!context.CatchBlock.IsTopLevel || exResult == null)
return;
var identity = context.RequestContext.Principal as ClaimsPrincipal;
var showErrorDetail = identity != null
&& identity.Identity.IsAuthenticated
&& identity.IsInRole("IT");
context.Result = new ExceptionResult(
exResult.Exception,
showErrorDetail,
exResult.ContentNegotiator,
exResult.Request,
exResult.Formatters);
}
}
在其他地方,在 Web Api 配置中:
public static void Configure(HttpConfiguration http)
{
http.Services.Replace(typeof(IExceptionHandler), new PerUserErrorDetailExceptionHandler());
}