简体   繁体   English

.Net Mvc:如何为Application_Error()引发错误来管理它们?

[英].Net Mvc: How to fire a error for Application_Error() manage them?

I manage all app erros in my Application_Error() in Global.asax : 我在Global.asax的 Application_Error()中管理所有应用程序错误:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();

    Log.LogException(exception);

    Response.Clear();

    HttpException httpException = exception as HttpException;

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Erro");

    if (httpException == null)
    {
        routeData.Values.Add("action", "Index");
    }
    else //It's an Http Exception
    {
        switch (httpException.GetHttpCode())
        {
            case 404:
                //Page not found
                routeData.Values.Add("action", "HttpError404");
                break;
            case 500:
                //Server error
                routeData.Values.Add("action", "HttpError500");
                break;

            // Here you can handle Views to other error codes.
            // I choose a General error template  
            default:
                routeData.Values.Add("action", "General");
                break;
        }
    }

    //Pass exception details to the target error View.
    routeData.Values.Add("error", exception);

    //Clear the error on server.
    Server.ClearError();

    //Avoid IIS7 getting in the middle
    Response.TrySkipIisCustomErrors = true;

    //Call target Controller and pass the routeData.
    IController errorController = new ErroController();
    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}

So, I have a Custom Authorize Attribute in my app that handle Unauthorized Request and I want to redirect to Application_Error() manipulate that instead. 因此,我在我的应用程序中具有一个自定义授权属性,该属性可以处理未经授权的请求,并且我想重定向到Application_Error()处理。

So, I do that: 因此,我这样做:

protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
    if (context.HttpContext.Request.IsAuthenticated)
    {
        throw new HttpException(403, "Forbidden Access.");
    }
    else
    {
        base.HandleUnauthorizedRequest(context);
    }
}

In that way the Application_Error() is called, but it seems ugly to me to call a exception so directly, exist another way? 通过这种方式调用Application_Error() ,但是对我来说直接调用异常似乎很丑,所以存在另一种方式吗? What you think guys? 你觉得男人呢?

You should not raise an exception inside of AuthorizeAttribute because that could lead to performance problems for code that is relying on AuthorizeAttribute to do an authorization check. 您不应在AuthorizeAttribute内部引发异常,因为这可能导致依赖AuthorizeAttribute进行授权检查的代码出现性能问题。 AuthorizeAttribute is meant for checking whether or not Authorization is valid, not for taking action based on this information. AuthorizeAttribute用于检查授权是否有效,而不是根据此信息采取的措施。 That is why the original code doesn't throw an exception directly - it delegates the task to the HttpUnauthorizedResult class. 这就是为什么原始代码不会直接引发异常的原因-它会将任务委托给HttpUnauthorizedResult类。

Instead, you should create a custom handler (similar to the HttpUnauthorizedResult ) to raise the exception. 相反,您应该创建一个自定义处理程序(类似于HttpUnauthorizedResult )以引发异常。 This will cleanly separate the logic of checking authorization and taking an action based on being unauthorized into 2 different classes. 这将把检查授权和基于未授权采取行动的逻辑明确地分为两个不同的类别。

public class HttpForbiddenResult : HttpStatusCodeResult
{
    public HttpForbiddenResult()
        : this(null)
    {
    }

    // Forbidden is equivalent to HTTP status 403, the status code for forbidden
    // access. Other code might intercept this and perform some special logic. For
    // example, the FormsAuthenticationModule looks for 401 responses and instead
    // redirects the user to the login page.
    public HttpForbiddenResult(string statusDescription)
        : base(HttpStatusCode.Forbidden, statusDescription)
    {
    }
}

And then in your custom AuthorizeAttribute, you just need to set the new handler in HandleUnauthorizedRequest. 然后在自定义的AuthorizeAttribute中,只需在HandleUnauthorizedRequest中设置新的处理程序。

protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
    if (context.HttpContext.Request.IsAuthenticated)
    {
        // Returns HTTP 403 - see comment in HttpForbiddenResult.cs.
        filterContext.Result = new HttpForbiddenResult("Forbidden Access.");
    }
    else
    {
        base.HandleUnauthorizedRequest(context);
    }
}

If you need to execute a different action than throwing an HttpException, you should subclass ActionResult and implement the action in the ExecuteResult method or use one of the built-in classes that inherits ActionResult. 如果您需要执行与抛出HttpException不同的操作,则应将ActionResult子类化并在ExecuteResult方法中实现该操作,或使用继承ActionResult的内置类之一。

Because the Unauthorized is not an error by default!!! 因为默认情况下, Unauthorized 不是错误 !!! Just add this method to global.asax 只需将此方法添加到global.asax

    protected void Application_EndRequest(object sender, EventArgs e) {
        if (Context.Response.StatusCode == 401 || Context.Response.StatusCode == 403) {
        // this is important, because the 401 is not an error by default!!!
            throw new HttpException(401, "You are not authorised");
        }
    }

Your code is fine. 您的代码很好。 By default if you call the base.HandleUnauthorizedRequest it throws a 401 exception which is intercepted by the forms authentication module and you get redirected to the login page (which might not be the desired behavior). 默认情况下,如果您调用base.HandleUnauthorizedRequest它将抛出401异常,该异常会被表单身份验证模块拦截,然后您将被重定向到登录页面(这可能不是所需的行为)。 So your approach is correct. 所以你的方法是正确的。

Another possibility is to directly render the corresponding error view if you don't want to go through the Application_Error : 另一种可能性是,如果您不想通过Application_Error ,则直接呈现相应的错误视图:

protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
    if (context.HttpContext.Request.IsAuthenticated)
    {
        context.Result = new ViewResult
        {
            ViewName = "~/Views/Shared/Forbidden.cshtml"
        };
    }
    else
    {
        base.HandleUnauthorizedRequest(context);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM