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

时间:2011-01-13 17:08:08

标签: asp.net-mvc asp.net-mvc-3

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

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

2 个答案:

答案 0 :(得分:2)

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

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" };
        }
    }
}

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

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

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

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

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

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;
        }
    }
}

并在Global.asax中:

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

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

答案 1 :(得分:-1)

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

改为写custom authorization filter。您可以提供您想要的任何功能。通常是返回401 HTTP状态代码。