我在ASP.NET MVC网站in a way like suggests this post中实现了错误处理。
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应用程序中使用“用户友好句柄”?
感谢。
答案 0 :(得分:14)
查看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 ()
{
// ...
}
答案 1 :(得分:6)
我设法以一种非常简单的方式解决了这个问题。我想为登录用户显示一个自定义页面(“你没有权限bla bla ...”)并将未经身份验证的用户重定向到登录页面(默认行为)。 所以我实现了一个自定义AuthorizeAttribute(比如说CustomAuthorizeAttribute),其HandleUnauthorizedRequest方法被覆盖,如果用户被认证,我将filterContext参数的Result属性设置为一个名为AccessDenied.aspx的ViewResult(在Shared文件夹中)
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
}
}
然后你必须使用这个新属性。 问候。
答案 2 :(得分:0)
如果您正在使用ASP.NET MVC,那么您很可能使用IIS,那么为什么不设置IIS以使用该Web应用程序/虚拟目录的自定义401错误页面?
答案 3 :(得分:-1)
在我的一个项目中,我使用uvita中的代码。
我有 ASP.NET MVC2 ,我在没有登录页面的情况下使用 Active Directory 身份验证。 我有一个使用网站母版页的 NoAuth.aspx 页面,整合了网络应用程序布局。
这是web.config。
<system.web>
<authentication mode="Windows" />
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
<providers>
<clear />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider"
applicationName="/" />
</providers>
</roleManager>
</system.web>
新类CustomAutorizeAttribute
using System.Web.Mvc;
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
filterContext.Result = new ViewResult { ViewName = "NoAuth"};
}
}
}
和控制器
[CustomAuthorize(Roles = "ADRole")]
public class HomeController : Controller
{
public HomeController()
{
}
}