开发者

ASP.NET MVC throw and handle error from controller

In m开发者_如何转开发y 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?


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.

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:

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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜