ASP.NET MVC从控制器抛出并处理错误

时间:2022-10-09 23:22:01

In my controller, for lets say edit user. In my controller, I check if the user has rights to edit then I'd like to throw some kind of authentication or prohibited error which would lead to an error page.

在我的控制器中,让我们说编辑用户。在我的控制器中,我检查用户是否有权编辑然后我想抛出某种身份验证或禁止的错误,这将导致错误页面。

Is there some way to do this rather than creating a controller and action just for error? What is the correct way to do this?

有没有办法做到这一点,而不是仅为错误创建控制器和操作?这样做的正确方法是什么?

2 个解决方案

#1


2  

Here's an example of a custom authorize attribute you could use:

以下是您可以使用的自定义授权属性的示例:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // if the user is not authenticated render the AccessDenied view
            filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
        }
    }
}

and then decorate your controller action with this attribute:

然后用这个属性装饰你的控制器动作:

[CustomAuthorizeAttribute]
public ActionResult SomeAction() 
{ 
    ...
}

There's one caveat with this approach you should be aware of. If the user is not authorized the server sends 200 status code which is not very SEO friendly. It would be better to send 401 status code. The problem is that if you are using Forms Authentication there's a custom module that gets appended to the ASP.NET execution pipeline and whenever the server sends 401 status code it is intercepted and automatically redirected to the login page. This functionality is by design and is not bug in ASP.NET MVC. It has always been like this.

你应该注意这种方法有一点需要注意。如果用户未被授权,则服务器发送200状态代码,该代码不是非常友好的SEO。发送401状态代码会更好。问题是,如果您使用表单身份验证,则会有一个自定义模块附加到ASP.NET执行管道,每当服务器发送401状态代码时,它就会被截获并自动重定向到登录页面。此功能是设计使然,不是ASP.NET MVC中的错误。它一直都是这样的。

And as a matter of fact there is a way to workaround this unpleasant situation:

事实上,有一种方法可以解决这种不愉快的情况:

You could modify the custom authorization filter like so:

您可以像这样修改自定义授权过滤器:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // if the user is not authenticated render the AccessDenied view
            filterContext.HttpContext.Items["unauthorized"] = true;
        }
    }
}

and in Global.asax:

在Global.asax中:

protected void Application_EndRequest()
{
    if (Context.Items.Contains("unauthorized"))
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
        Context.Server.Transfer("~/401.htm");
    } 
}

Now that's better. You get 401 status code with a custom error page. Nice.

现在那更好了。您将获得具有自定义错误页面的401状态代码。尼斯。

#2


-1  

Since your authorization is based per user (I suppose the correct process is each user can only edit their own data) you can't use provided Authorize filter.

由于您的授权基于每个用户(我认为正确的过程是每个用户只能编辑自己的数据),因此您无法使用提供的授权过滤器。

Write a custom authorization filter instead. You can provide whatever functionality you'd like. The usual is to return a 401 HTTP status code.

请改为编写自定义授权过滤器。您可以提供您想要的任何功能。通常是返回401 HTTP状态代码。

#1


2  

Here's an example of a custom authorize attribute you could use:

以下是您可以使用的自定义授权属性的示例:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // if the user is not authenticated render the AccessDenied view
            filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
        }
    }
}

and then decorate your controller action with this attribute:

然后用这个属性装饰你的控制器动作:

[CustomAuthorizeAttribute]
public ActionResult SomeAction() 
{ 
    ...
}

There's one caveat with this approach you should be aware of. If the user is not authorized the server sends 200 status code which is not very SEO friendly. It would be better to send 401 status code. The problem is that if you are using Forms Authentication there's a custom module that gets appended to the ASP.NET execution pipeline and whenever the server sends 401 status code it is intercepted and automatically redirected to the login page. This functionality is by design and is not bug in ASP.NET MVC. It has always been like this.

你应该注意这种方法有一点需要注意。如果用户未被授权,则服务器发送200状态代码,该代码不是非常友好的SEO。发送401状态代码会更好。问题是,如果您使用表单身份验证,则会有一个自定义模块附加到ASP.NET执行管道,每当服务器发送401状态代码时,它就会被截获并自动重定向到登录页面。此功能是设计使然,不是ASP.NET MVC中的错误。它一直都是这样的。

And as a matter of fact there is a way to workaround this unpleasant situation:

事实上,有一种方法可以解决这种不愉快的情况:

You could modify the custom authorization filter like so:

您可以像这样修改自定义授权过滤器:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // if the user is not authenticated render the AccessDenied view
            filterContext.HttpContext.Items["unauthorized"] = true;
        }
    }
}

and in Global.asax:

在Global.asax中:

protected void Application_EndRequest()
{
    if (Context.Items.Contains("unauthorized"))
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
        Context.Server.Transfer("~/401.htm");
    } 
}

Now that's better. You get 401 status code with a custom error page. Nice.

现在那更好了。您将获得具有自定义错误页面的401状态代码。尼斯。

#2


-1  

Since your authorization is based per user (I suppose the correct process is each user can only edit their own data) you can't use provided Authorize filter.

由于您的授权基于每个用户(我认为正确的过程是每个用户只能编辑自己的数据),因此您无法使用提供的授权过滤器。

Write a custom authorization filter instead. You can provide whatever functionality you'd like. The usual is to return a 401 HTTP status code.

请改为编写自定义授权过滤器。您可以提供您想要的任何功能。通常是返回401 HTTP状态代码。