• MVC自定义错误页面


      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="2880" />
        </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=1;
                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=1;
                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方法来实现,但实验过程中不怎么喜欢这种方案,故省略。

  • 相关阅读:
    微信小程序 生命周期
    ftp uploadFileAction(重要)
    java FTP 上传下载删除文件
    httpsession
    db2 blob EMPTY_BLOB()
    java blob
    java session getCreationTime()
    eclipse 查看源代码
    java file类
    Vue.js 和 MVVM 小细节
  • 原文地址:https://www.cnblogs.com/fuxuyang/p/7364430.html
Copyright © 2020-2023  润新知