ASP.NETMVC用户友好401错误如何解决?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (18)

404错误一切正常。但是,如何正确显示用户友好的屏幕为401错误?他们通常不会抛出可以在内部处理的异常,Application_Error()而是返回HttpUnauthorizedResult。一种可能的方法是在Application_EndRequest()方法的末尾添加以下代码

if (Context.Response.StatusCode == 401)
{
    throw new HttpException(401, "You are not authorised");
    // or UserFriendlyErrorRedirect(new HttpException(401, "You are not authorised")), witout exception
}

但是在Application_EndRequest()Context.Session == null之内,errorController.Execute()因为它不能使用默认的TempDataProvider而失败。

  // Call target Controller and pass the routeData.
  IController errorController = new ErrorController();
  errorController.Execute(new RequestContext(    
       new HttpContextWrapper(Context), routeData)); // Additional information: The SessionStateTempDataProvider requires SessionState to be enabled.

那么,能否提出一些最佳实践,以便如何在ASP.NET MVC应用程序中使用“用户友好的句柄”401?

提问于
用户回答回答于

看看HandleErrorAttribute。从它的子类或添加您自己的实现,它将处理您感兴趣的所有状态代码。可以使它为每个错误类型返回一个单独的错误视图。

这里是如何创建你的句柄错误异常过滤器的想法。我抛出了大部分内容,只关注我们的要领。绝对看看最初的实现来添加参数检查和其他重要的事情。

public class HandleManyErrorsAttribute : FilterAttribute, IExceptionFilter
{
    public virtual void OnException(ExceptionContext filterContext)
    {
        if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            return;

        Exception exception = filterContext.Exception;

        string viewName = string.Empty;
        object viewModel = null;
        int httpCode = new HttpException(null, exception).GetHttpCode();
        if (httpCode == 500)
        {
            viewName = "Error500View";
            viewModel = new Error500Model();
        }
        else if (httpCode == 404)
        {
            viewName = "Error404View";
            viewModel = new Error404Model();
        }
        else if (httpCode == 401)
        {
            viewName = "Error401View";
            viewModel = new Error401Model();
        }

        string controllerName = (string)filterContext.RouteData.Values["controller"];
        string actionName = (string)filterContext.RouteData.Values["action"];
        filterContext.Result = new ViewResult
        {
            ViewName = viewName,
            MasterName = Master,
            ViewData = viewModel,
            TempData = filterContext.Controller.TempData
        };
        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.StatusCode = httpCode;

        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}

然后用以下属性“修饰”控制器操作:

[HandleManyErrors]
public ActionResult DoSomethingBuggy ()
{
    // ...
}
用户回答回答于

我设法以非常简单的方式解决这个问题。我想为登录用户显示一个自定义页面(“没有权限bla bla ...”)并将未经身份验证的用户重定向到登录页面(默认行为)。所以我实现了一个自定义的AuthorizeAttribute(说CustomAuthorizeAttribute)与HandleUnauthorizedRequest方法覆盖的方式,如果用户通过身份验证,我设置FilterContext参数的Result属性与ViewResult(在共享文件夹中)称为AccessDenied.aspx

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
    {
        base.HandleUnauthorizedRequest(filterContext);
    }
    else
    {
        filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
    }
}

那么你必须改用这个新的属性。

扫码关注云+社区