如何在ASP.NET MVC4中捕获Web API中的表单授权错误

时间:2013-11-28 16:54:08

标签: asp.net-mvc asp.net-mvc-4 asp.net-web-api

ASP.NET / Mono MVC4 Web API v.1应用程序。

API控制器正在使用表单授权,并使用标准[授权]进行修饰 属性。 如果授权失败,则标准api错误消息

<Error>
<Message>Authorization has been denied for this request.</Message>
</Error>

发生。 如何通过写入日志文件来识别此错误。 返回给调用者shoudl的错误消息保持不变。 如何添加额外的代码,这可以用整个http编写此错误消息 请求标题和正文以记录文件?

我添加了问题

中的代码

How do I log ALL exceptions globally for a C# MVC4 WebAPI app?

How to catch undefined api method calls in ASP.NET MVC4 Web API

但是没有抓住错误。

如何捕捉所有错误?

更新

代码需要在Windows 2003服务器中运行。 我从回答中尝试了代码但得到了编译错误

Predefined type 'System.Runtime.CompilerServices.IAsyncStateMachine' is not defined or imported

Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

如何在W2003服务器中运行int?

1 个答案:

答案 0 :(得分:7)

您可以实现此目的的一种方法是编写DelegatingHandler以在将响应发送回客户端之前拦截响应,然后记录有关返回错误的请求的信息。

public class RepsonseInterceptor : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        LogResponse(request, response);

        return response;
    }

    public void LogResponse(HttpRequestMessage request, HttpResponseMessage response)
    {
        HttpStatusCode status = response.StatusCode;
        //Catch the status codes you want to Log
        if (status == HttpStatusCode.NotFound || status == HttpStatusCode.Unauthorized || status == HttpStatusCode.InternalServerError)
        {
            //Do Logging Stuff here
            //with the Request and Response
        }
    }
}

然后将其添加到Global.asax.cs中的Application_Start:

GlobalConfiguration.Configuration.MessageHandlers.Add(new ResponseInterceptor());

编辑:

如果您不想为所有路由执行处理程序,可以将它作为Per-Route消息处理程序添加到您想要的路由而不是全局路由,如下所示:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional },
    constraints: null,
    handler: new ResponseInterceptor()
    );

如果您使用的是.NET Framework 4.0,则需要更改处理程序的SendAsync方法,如下所示:

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    return base.SendAsync(request, cancellationToken)
      .ContinueWith(task =>
      {
          var response = task.Result;
          LogResponse(request, response);
          return response;
       });
}

我认为如果你能从请求和响应对象中获取记录所需的所有信息,那么使用这个MessageHandler是合理的,尽管我还没有对此进行全面测试。