我在我的web.config以下:
<customErrors mode="On" defaultRedirect="Error">
<error statusCode="404" redirect="Error/NotFound" />
</customErrors>
我有一个
[HandleError]
在我的HomeController类的顶部。 为了测试,我创建并简单地抛出一个异常动作。 。 并重定向到我
ErrorController/Index
方法,但是当它到达我的观点,其结合HandleErrorInfo我的模型为空,所以我莫名其妙地失去了参考错误。
我相信它有事情做与重定向,所以我想看看,如果我失去了一些东西错误迷路,如果任何人有意见,我可以有一个观点,显示堆栈跟踪和错误消息。
我可以看到误解。 你想要做的MVC
的事情, redirect
到一个控制器的动作。
但是defaultRedirect
本身就是一个Web Form
约定,因此限制了。 您重定向到另一个控制器的那一刻,你将失去你HttpContext
,从而失去你HandleErrorInfo
对象
你的[HandleError]
属性需要View
指导其错误消息。 通过你上面的例子去,我假设你有一个Views/Error
的文件夹为您ErrorController
,并在其中你有一个Index
视图。 如果你想你的过滤器上下文的发送HandleErrorInfo
对象这一观点,
试试这个语法:
[HandleError(View="~/Views/Error/Index")]
Public class HomeController : Controller
但是,我们记录?!?!?
我怀疑你的意图不仅仅是显示错误堆栈给用户更多 。 事实上,我怀疑你有没有这样的打算都没有。 我怀疑你的真正目的是记录自己的错误(可能为db),并显示一些刺激性的消息,你的用户是什么。
我到目前为止已经解释的是“ 什么是最好的[办法]显示未处理的在我看来例外 ”。 在[HandleError]
属性是好了点。
但是,当你要移动到下一个步骤(记录错误),你有几种选择:
1) 重写您的基本控制器的有关异常的方法 ; 创建自己的Controller
从MVC控制器类继承,但覆盖在例外情况的方法。 这种方法可以与[的HandleError]属性一起使用
2) 创建一个自定义异常处理程序创建自己的异常处理程序是记录错误。 然后,您的异常处理程序可以调用选择的视图,或者可以结合工作[HandleError(order=2)]
,因为过滤器属性可以采取施加优先的顺序的参数。
尼廷张以芳问一个错误观点是什么样子。 该
@model System.Web.Mvc.HandleErrorInfo
<h2>Exception details</h2>
<p> Controller: @Model.ControllerName </p>
<p> Action: @Model.ActionName </p>
<p> Exception: @Model.Exception </p>
我做类似的东西maxlego负责处理所有的错误(不只是那些在控制器与属性的HandleError发生)。
我MvcApplication类(在的global.asax.cs)有这样的:
public class MvcApplication : HttpApplication
{
// usual stuff here...
protected void Application_Error(object sender, EventArgs e)
{
Server.HandleError(((MvcApplication)sender).Context);
}
}
上面的代码使用扩展方法从有用的东西我的MVC库。 有了这个地方,我不需要任何的错误处理的属性,配置的customErrors或自定义过滤器。 相反,扩展方法将记录错误的详细信息,然后调用适当的视图,或者:
扩展方法的代码,使这项工作是:
public static class HttpServerUtilityExtensions
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static void HandleError(this HttpServerUtility server, HttpContext httpContext)
{
var currentController = " ";
var currentAction = " ";
var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (currentRouteData != null)
{
if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
currentController = currentRouteData.Values["controller"].ToString();
if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
currentAction = currentRouteData.Values["action"].ToString();
}
var exception = server.GetLastError();
Logger.ErrorException(exception.Message, exception);
var controller = DependencyResolver.Current.GetService<ErrorController>();
var routeData = new RouteData();
var action = "InternalServerError";
if (exception is HttpException)
{
var httpEx = exception as HttpException;
switch (httpEx.GetHttpCode())
{
case 404:
action = "NotFound";
break;
case 401:
action = "AccessDenied";
break;
}
}
httpContext.ClearError();
httpContext.Response.Clear();
httpContext.Response.StatusCode = exception is HttpException ? ((HttpException)exception).GetHttpCode() : 500;
httpContext.Response.TrySkipIisCustomErrors = true;
routeData.Values["controller"] = "Error";
routeData.Values["action"] = action;
controller.ViewData.Model = new HandleErrorInfo(exception, currentController, currentAction);
((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
}
请注意,上述使用NLOG用于记录错误的详细信息,但可以很容易地改变以支持别的东西。 此外,解决ErrorController此方法时,尊重您的IoC容器。
我已经使用这个一小段代码向用户显示处理的错误页面。 无论页面不存在或出现了其他一些错误。
void Application_Error(object sender, EventArgs e)
{
// this value can be fetched from config or depend on DEBUG smybol
if (!handleErrors)
return;
var error = Server.GetLastError();
var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;
if (code == 404)
{
// do something if page was not found. log for instance
}
else
{
// collect request info and log exception
}
// pass exception to ErrorsController
Request.RequestContext.RouteData.Values["ex"] = error;
// execute controller action
IController errorController = new ErrorsController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), Request.RequestContext.RouteData));
}
和错误控制器是这个样子。 如果您需要详细的例外,它是通过访问的RouteData
public class ErrorsController : Controller
{
/// <summary>
/// Page not found
/// </summary>
/// <returns></returns>
public ActionResult Http404()
{
return View();
}
/// <summary>
/// All other errors
/// </summary>
/// <param name="actionName"></param>
protected override void HandleUnknownAction(string actionName)
{
// in case detailed exception is required.
var ex = (Exception) RouteData.Values["ex"];
return View();
}
}
您可以为每个HTTP代码添加不同的看法。 刚刚实施的行动HTTP {}代码