在ASP.NET的Web API定义异常处理程序例外启用CORS时,永远达不到顶级水平 [英] Exceptions in ASP.NET Web API custom exception handler never reach top level when CORS is enabled

查看:294
本文介绍了在ASP.NET的Web API定义异常处理程序例外启用CORS时,永远达不到顶级水平的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个自定义Web API全局异常处理程序是这样的:

I have created a custom Web API global exception handler like this:

public class MyGlobalExceptionHandler : ExceptionHandler
{
    public override void Handle(ExceptionHandlerContext context)
    {
        // here I handle them all, no matter sync or not
    }

    public override Task HandleAsync(ExceptionHandlerContext context, 
        CancellationToken cancellationToken)
    {
        // not needed, but I left it to debug and find out why it never reaches Handle() method
        return base.HandleAsync(context, cancellationToken);
    }

    public override bool ShouldHandle(ExceptionHandlerContext context)
    {
        // not needed, but I left it to debug and find out why it never reaches Handle() method
        return context.CatchBlock.IsTopLevel;
    }
}

我注册在我的Global.asax的Application_Start:

I'm registering it in my Global.asax Application_Start:

GlobalConfiguration.Configuration.Services.Replace(typeof(IExceptionHandler),
    new MyGlobalExceptionHandler());

一切运行良好,无论在哪里我扔例外 - 内部控制的方法或在我的自定义属性上面的控制器方法,并不管我把它从AJAX请求或直接从浏览器

Everything worked fine, no matter where I threw exceptions - inside controller methods or in my custom attributes above controller methods, and no matter if I call it from AJAX requests or directly from browser.

但后来有一天,我需要为我的AJAX请求CORS支持。我启用了CORS全球的文章<一中描述href=\"http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors\">Enabling在ASP.NET的Web API 跨域请求

But then one day I needed CORS support for my AJAX requests. I enabled CORS globally as described in the article Enabling Cross-Origin Requests in ASP.NET Web API

var cors = new EnableCorsAttribute("*", "*", "*"); // * is just for debugging purpose
config.EnableCors(cors);

起初一切似乎都OK,CORS和预期一样,服务器响应OPTIONS请求。

At first everything seemed OK, CORS worked as expected, the server responded to OPTIONS request.

但是,当我想检查我的身份验证启动的问题。突然,异常被吞噬,我得到了一个空的JSON {} 响应,而不是我在MyGlobalExceptionHandler的handle()方法创建我的自定义JSON格式例外。

But the problems started when I wanted to check my authentication. Suddenly the exception was swallowed and I got an empty JSON {} response instead of my custom JSON formatted exception which I create in the Handle() method of my MyGlobalExceptionHandler.

调试时,我惊讶地发现,现在Ajax请求ShouldHandle()方法只与IsTopLevel = FALSE调用,从而异常从未冒泡,从来没有达到我的handle()方法。当我禁用CORS,一切工作正常再次(除跨域请求,当然)。

While debugging, I was surprised to find that now for AJAX requests ShouldHandle() method is called only with IsTopLevel = false, thus the exception never bubbles up and never reaches my Handle() method. As soon as I disable CORS, everything works fine again (except cross-domain requests, of course).

为什么IsTopLevel是不正确的,当我使CORS?我应该如何解决这个问题?

<青霉>一更副作用如下。如果CORS被禁用,那么如果我扔内把手任何异常()方法,它到达Global.asax中的Application_Error处理程序。但是,如果我能CORS在我的处理方法抛出异常,这些异常永远也达不到的Application_Error。的

看来,我发现究竟何时发生这种情况。

It seems, I found exactly when this is happening.

如果我扔在当启用CORS控制器方法异常,则CORS根本不踢,不发送的访问控制允许来源头。当浏览器没有接收到首标,它立即破坏该请求和这个破坏似乎也影响异常处理程序 - 它永远不会到达与IsTopLevel =真ShouldHandle()方法。
浏览器和Mozilla像这甚至当我运行从本地HTML文件的AJAX请求我的IIS上的防爆preSS本地主机websiet。

If I throw an exception in a controller method when CORS is enabled, then CORS doesn't kick in at all and does not send the Access-Control-Allow-Origin header. When the browser doesn't receive the header, it immediately disrupts the request and this disruption seems to affect also the exception handler - it never reaches ShouldHandle() method with IsTopLevel = true. Chrome and Mozilla act like this even when I run AJAX request from a local html file to my websiet on IIS Express localhost.

但是现在的情况是IE 11的不同。当我打开HTML文件存在,它首先要求我的权限启用脚本。我同意后,再IE 11忽略了一个事实,有没有CORS头$​​ P $ psent,它不会破坏请求,因此我的异常处理程序接收IsTopLevel = true并且能够返回定制错误响应。

But the situation is different on IE 11. When I open the html file there, it first asks me permissions to enable scripts. After I agree, then IE 11 ignores the fact that there are no CORS headers present and it doesn't disrupt the request, thus my exception handler receives IsTopLevel = true and is able to return a customised error response.

我想,这应该是固定在Web API的核心 - 即使我抛出异常,CORS应该还是能踢和发送它的头文件,所以浏览器接受响应。我创建了一个最小的测试用例应用程序,我将它发送到ASP.NET团队codePLEX。
链接到测试项目。 (该项目zip文件将被标记,只需点击下载,而忽略该文件夹中的所有其他文件)

I guess, this should be fixed in the Web API core - even if I throw exceptions, CORS should still be able to kick in and send its headers, so the browser accepts the response. I have created a minimal test case application and I'll send it to the ASP.NET Team on CodePlex. Link to the test project. (the project zip file will be marked, just click Download and ignore all the other files in that folder)

推荐答案

我已经找到问题的根源。

I have found the source of confusion.

看来,通过的WebAPI默认使用此异常处理程序:

It seems, WebAPI by default is using this exception handler:

<一个href=\"https://aspnetwebstack.$c$cplex.com/SourceControl/latest#src/System.Web.Http/ExceptionHandling/DefaultExceptionHandler.cs\">https://aspnetwebstack.$c$cplex.com/SourceControl/latest#src/System.Web.Http/ExceptionHandling/DefaultExceptionHandler.cs

和它已经从建议的异常处理在这篇文章中主要区别:

and it has major differences from the suggested exception handling in this article:

<一个href=\"http://www.asp.net/web-api/overview/web-api-routing-and-actions/web-api-global-error-handling\">http://www.asp.net/web-api/overview/web-api-routing-and-actions/web-api-global-error-handling

请参见附录:基地班详细信息,在默认的异常基类code中给出。

see chapter "Appendix: Base Class Details", where the code of default exception base class is given.

在它检查 IsOutermostCatchBlock 的例子(现在似乎被移动到 exceptionContext.CatchBlock.IsTopLevel )看它是否是时候来处理异常。当CORS启用时,这样的方法将不会对我上述原因的工作。 ASP.NET小组说,这种行为是设计使然,他们不会改变任何东西。

In the example it checks for IsOutermostCatchBlock (which now seems to be moved to exceptionContext.CatchBlock.IsTopLevel) to see if it's time to handle the exception. When CORS is enabled, such approach won't work for the reasons I described above. ASP.NET team said, this behavior is by design and they won't change anything.

我希望有人经历会写一个上最新的文章与做异常处理有和没有CORS的正确方法的说明。

I hope someone experienced will write an up-to-date article with instructions for doing exception handling the right way with and without CORS.

目前我看到两种方法可以解决这在我的code:

Currently I see two ways to work around this in my code:


  • 不继承 System.Web.Http.ExceptionHandling.ExceptionHandler 我的自定义异常处理程序,但实施 IExceptionHandler 直接

  • don't inherit my custom exception handler from System.Web.Http.ExceptionHandling.ExceptionHandler but implement IExceptionHandler directly

如果从 System.Web.Http.ExceptionHandling.ExceptionHandler 继承,覆盖
ShouldHandle方法并返回真正总是因为 CatchBlock.IsTopLevel 可能永远不会有真正值。

if inheriting from System.Web.Http.ExceptionHandling.ExceptionHandler, override ShouldHandle method and return true always because CatchBlock.IsTopLevel might never have true value.

我都尝试apporaches,他们似乎很好地工作。

I tried both apporaches and they seem to work fine.

这篇关于在ASP.NET的Web API定义异常处理程序例外启用CORS时,永远达不到顶级水平的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆