在ASP.NET MVC中,我视图中最好的显示未处理的exception是什么?
我在web.config中有以下内容:
我有一个
[HandleError]
在我的HomeController类的顶部。 为了测试,我创建和操作只是抛出一个exception。 。 它重定向到我的
ErrorController/Index
方法,但当它到达我的视图绑定到HandleErrorInfo我的模型为null所以我不知何故失去了对错误的引用。
我确信它与错误在重定向中丢失有关,所以我想看看我是否遗漏了一些东西,如果有人有建议我可以有一个显示Stacktrace和错误消息的视图。
我可以看到误解。 您想要执行MVC
并redirect
到控制器操作。
但defaultRedirect
本身就是一种Web Form
约定,因而受到限制。 当您重定向到另一个控制器时,您将丢失HttpContext
,从而丢失HandleErrorInfo
对象
您的[HandleError]
属性需要View
来指示其错误消息。 按照上面的例子,我假设您有一个ErrorController
的Views/Error
文件夹,并且在其中有一个Index
视图。 如果您希望Filter Context将HandleErrorInfo
对象发送到该视图,
试试这个语法:
[HandleError(View="~/Views/Error/Index")] Public class HomeController : Controller
但是Logging呢?!?!?
我怀疑你的意图不仅仅是向用户显示错误堆栈。 事实上,我怀疑你根本没有这样的意图。 我怀疑你的真正目的是记录你的错误(可能是数据库)并向你的用户显示一些淡淡的消息。
到目前为止我所解释的是“ 在我看来,什么是最好的方式来展示未处理的例外 ”。 [HandleError]
属性适用[HandleError]
。
但是当您想要进入下一步(记录错误)时,您有以下几种选择:
1) 覆盖基本控制器的On Exception方法 ; 创建自己的inheritance自MVC Controller类的Controller,但覆盖On Exception方法。 此方法可与[HandleError]属性一起使用
2) 创建自定义exception处理程序创建自己的exception处理程序,记录错误。 然后,您的exception处理程序可以调用View of choice或者可以与[HandleError(order=2)]
一起使用,因为filter属性可以采用优先顺序的order参数。
Nitin Sawant询问错误视图的样子。 该
@model System.Web.Mvc.HandleErrorInfo Exception details
Controller: @Model.ControllerName
Action: @Model.ActionName
Exception: @Model.Exception
我做了类似于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库中的有用东西的扩展方法。 有了这个,我不需要任何error handling属性,customErrors配置或自定义filter。 相反,扩展方法将记录错误详细信息,然后调用适当的视图,或者:
- 拒绝访问
- 未找到
- 内部服务器错误
使这项工作的扩展方法代码是:
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(); 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 { /// /// Page not found /// /// public ActionResult Http404() { return View(); } /// /// All other errors /// /// protected override void HandleUnknownAction(string actionName) { // in case detailed exception is required. var ex = (Exception) RouteData.Values["ex"]; return View(); } }
您可以为每个http代码添加不同的视图。 只需实施行动Http {Code}