MVC异常处理主要有三种方案:1.基于HandleErrorAttribute重写OnException方法;2.基于Global.apsx添加Application_Error方法;3.直接在Web.Config中配置。现基于上述思路,测试了下面三种自定义错误页面的处理方法(主要侧重于显示异常信息,便于快速找到代码中的异常来源),以便后续查阅。不足之处,还请指教!

1.直接在web.config的<system.web>节点下加入<customErrors mode="On" />,在View/Shared/Error.cshtml中写入异常信息,发生异常时会跳转到该l页面。

  <system.web>
<customErrors mode="On" />
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="" />
</authentication>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages"/>
</namespaces>
</pages>
</system.web>

Web.Config

@model HandleErrorInfo
@{
Layout = null;
} <!DOCTYPE html>
<html>
<head>
<title>Error</title>
</head>
<body>
<p>Message: @Model.Exception.Message</p>
<p>Controller: @Model.ControllerName</p>
<p>Action: @Model.ActionName</p>
<p>Source: @Model.Exception.Source</p>
<p>Exception: @Model.Exception</p>
</body>
</html>

Error.html

2.新建类继承HandleErrorAttribute并重写OnException方法,将异常信息写入日志文件,并跳转到View/Shared/Error.cshtml错误页。直接将该属性作用于某控制器或者注册为全局变量以便于全局适用。

    [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class LogExceptionAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
HandleErrorInfo info = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); Log log = new Log();
log.Write(filterContext); if (!filterContext.ExceptionHandled)
{ filterContext.Result = new ViewResult()
{
ViewName = "/Views/Shared/Error.cshtml",
ViewData = new ViewDataDictionary<HandleErrorInfo>(info)
};
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
}

LogExceptionAttribute

错误页写入异常信息与方法1相同。

   [LogException]
public class HomeController : Controller
{
//
// GET: /Home/ public ActionResult Index()
{
var x=;
string y="x";
ViewBag.t = x / Convert.ToInt32(y);
return View();
}
}

作用于单一控制器

 public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
//new
filters.Add(new LogExceptionAttribute());
} public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
); } protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}

特性注册

3.新建继承于IController的基础控制器,重写OnException方法及写入异常日志文件,其他控制器只需要继承该基础控制器即可。与方法3的区别在于不需要注册全局筛选器取而代之的是控制器的继承。

public class BaseController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
HandleErrorInfo info = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); DateTime dt = DateTime.Now;
string logPath = Server.MapPath("~/Logs/" + dt.ToString("yyyy-MM"));
if (!Directory.Exists(logPath))
{
Directory.CreateDirectory(logPath);
}
string logFilePath = string.Format("{0}/{1}.txt", logPath, dt.ToString("yyyy-MM-dd"));
StreamWriter writer = null;
try
{
writer = new StreamWriter(logFilePath, true, Encoding.UTF8);
writer.WriteLine("------------------------------------------------------------------------------");
writer.WriteLine("出错时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
writer.WriteLine("错误信息:" + filterContext.Exception.Message);
writer.WriteLine("Controller:" + filterContext.Controller);
writer.WriteLine("错误源:" + filterContext.Exception.Source);
writer.WriteLine("堆栈信息:" + filterContext.Exception.StackTrace);
writer.WriteLine("------------------------------------------------------------------------------");
}
catch
{
}
finally
{
if (writer != null)
{
writer.Close();
}
}
base.OnException(filterContext);
filterContext.Result = new ViewResult()
{
ViewName = "/Views/Shared/Error.cshtml",
ViewData = new ViewDataDictionary<HandleErrorInfo>(info)
};
} public ActionResult Error()
{
return View();
}
}

基础控制器实现

 public class HomeController : BaseController
{
//
// GET: /Home/ public ActionResult Index()
{
var x=;
string y="x";
ViewBag.t = x / Convert.ToInt32(y);
return View();
}
}

控制器继承

备注:异常日志记录类

public class Log
{
/// <summary>
/// 异常信息记录
/// </summary>
/// <param name="filterContext"></param>
public void Write(ExceptionContext filterContext)
{
DateTime dt = DateTime.Now;
string logPath = HttpContext.Current.Server.MapPath("~/Logs/" + dt.ToString("yyyy-MM"));
if (!Directory.Exists(logPath))
{
Directory.CreateDirectory(logPath);
}
string logFilePath = string.Format("{0}/{1}.txt", logPath, dt.ToString("yyyy-MM-dd"));
StreamWriter writer = null;
try
{
writer = new StreamWriter(logFilePath, true, Encoding.UTF8);
writer.WriteLine("------------------------------------------------------------------------------");
writer.WriteLine("出错时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
writer.WriteLine("错误信息:" + filterContext.Exception.Message);
writer.WriteLine("Controller:" + filterContext.Controller);
writer.WriteLine("错误源:" + filterContext.Exception.Source);
writer.WriteLine("堆栈信息:" + filterContext.Exception.StackTrace);
writer.WriteLine("------------------------------------------------------------------------------");
}
catch
{
}
finally
{
if (writer != null)
{
writer.Close();
}
}
}
}

Log

4.还可以通过Global.apsx添加Application_Error方法来实现,但实验过程中不怎么喜欢这种方案,故省略。

MVC自定义错误页面的更多相关文章

  1. ASP.NET MVC 自定义错误页面心得

    自定义错误页面的目的,就是为了能让程序在出现错误/异常的时候,能够有较好的显示体验. 所以,首先要先了解,我们可以在哪里捕获异常. 当程序发生错误的时候,我们可以在两个地方捕获: Global里面的A ...

  2. MVC 自定义 错误页面

    很多时候,我们需要自定义错误页面,用来当发生异常后引导用户进入一个比较友好的错误页面. 在这里,我归结一下我常用的2个方案 1   通过Global.asax 文件来处理异常信息(这个不管是 MVC ...

  3. 在ASP.NET MVC自定义错误页面

    异常处理跳转页面 第一步,在项目的Web.config文件中找到节点<system.web> 在此节点下添加配置(Error为定义的控制器也可以多添加些error标签用于区分不同的错误) ...

  4. Asp.net MVC 自定义错误页面以及return HttpNotFound遇到的问题

    今天在处理mvc 项目404和500页面时,发现我以前比较喜欢用的Return HttpNotFound()没有跳转到我在webconfig中配置的自定义404页面,而且也不会去执行Global中的A ...

  5. Spring MVC自定义错误页面

    在web.xml中添加: <error-page(其他属性404...省略咯)> <location>/error</location> </error-pa ...

  6. .net mvc 自定义错误页面

    1.Global.asax.cs中,加入如下代码 protected void Application_Error(Object sender, EventArgs e) { Exception ex ...

  7. ASP.NETMVC自定义错误页面真的简单吗?

    Note:文章前半部分翻译自 http://benfoster.io/blog/aspnet-mvc-custom-error-pages ,着急的可直接看总结~ 如果你在设置asp.net mvc自 ...

  8. 自定义错误页面mvc用法

    原谅我这个新手,对大神们来说这么简单的问题,竟折腾了我一个上午,仅此文章做个记录,供以后备用. 自定义错误页面(custom error pages)在asp.net webform里的配置请看htt ...

  9. ASP.NET Core中显示自定义错误页面

    在 ASP.NET Core 中,默认情况下当发生500或404错误时,只返回http状态码,不返回任何内容,页面一片空白. 如果在 Startup.cs 的 Configure() 中加上 app. ...

随机推荐

  1. laravel中的validate验证的使用案例:

    第一个是设置,第二个是直接调用.

  2. DataTable RowFilter 过滤数据

    用Rowfilter加入过滤条件 eg: string sql = "select Name,Age,Sex from UserInfo"; DataTable dt = Data ...

  3. 【dlbook】优化

    [神经网络优化的挑战] 一.病态: 虽然学习率很小,而且梯度大,但是由于Hessian阵的病态,二次项比一次项还要大,梯度下降事实上并不一定能下降,反而有可能上升.因此需要将学习率调低. 表现:梯度很 ...

  4. zookeeper的c API 单线程与多线程问题 cli_st和cli_mt

    同样的程序,在centos和ubuntu上都没有问题,在solaris上问题却多多,据说是solaris管理更加严格. zookeeper_init方法,在传入一个错误的host也能初始化出一个非空的 ...

  5. Quartz创建多个不同名字的scheduler实例

    _http://my.oschina.net/laiweiwei/blog/122280 需求创建多个不同的Scheduler实例,每个实例自主启动.关闭 问题 如果直接用 SchedulerFact ...

  6. Gradle2.0用户指南翻译——第一章. 介绍

    翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2 ...

  7. React Native组件(三)Text组件解析

    相关文章 React Native探索系列 React Native组件系列 前言 此前介绍了最基本的View组件,接下来就是最常用的Text组件,对于Text组件的一些常用属性,这篇文章会给出简单的 ...

  8. jquery.treetable.js

    html:   <table class="table table-hover table-responsive main-list" id="columntabl ...

  9. 数据库备份mysqldump

    |--好友说:有些知识就是石头,走上这条路就没法绕过,就是牙齿啃碎了也要把它啃下来. ------------------------------------------ 针对当前备份做一个总结记忆: ...

  10. Typescript : 遍历Array的方法:for, forEach, every等

    方法一,for…of 这个貌似是最常用的方法,angular 2中HTML语法绑定也是要的这种语法. let someArray = [1, "string", false]; f ...