ASP.NET MVC自定义异常过滤器使用案例

目录
  • 一、需求
  • 二、案例
    • 1、创建工具类
      • 1.1、创建日志工具类
      • 1.2、创建网络工具类
    • 2、创建自定义异常类
    • 3、创建控制器
    • 4、测试

在上一篇文章中讲解了自定义异常过滤器,这篇文章会结合工作中的真实案例讲解一下如何使用自定义异常过滤器。

一、需求

本案例要实现的功能需求:在发生异常时记录日志,日志内容包括发生异常的Controller名称、Action名称、使用浏览器类型和版本等。

二、案例

1、创建工具类

首先创建项目中需要使用的工具类。

1.1、创建日志工具类

在案例中使用Log4net来记录日志。首先要添加对Log4net的引用,直接在NuGet里面搜索Log4net,然后安装即可。

日志消息实体类代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MVCCuetomerExcepFilterDemo.Models
{
    /// <summary>
    /// 日志消息实体类
    /// </summary>
    public class LogMessageEntity
    {
        /// <summary>
        /// 操作时间
        /// </summary>
        public DateTime OperationTime { get; set; }
        /// <summary>
        /// Url地址
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        /// 类名
        /// </summary>
        public string Class { get; set; }
        /// <summary>
        /// IP
        /// </summary>
        public string Ip { get; set; }
        /// <summary>
        /// 主机
        /// </summary>
        public string Host { get; set; }
        /// <summary>
        /// 浏览器
        /// </summary>
        public string Browser { get; set; }
        /// <summary>
        /// 操作人
        /// </summary>
        public string UserName { get; set; }
        /// <summary>
        /// 内容
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// 异常信息
        /// </summary>
        public string ExceptionInfo { get; set; }
        /// <summary>
        /// 异常来源
        /// </summary>
        public string ExceptionSource { get; set; }
        /// <summary>
        /// 异常信息备注
        /// </summary>
        public string ExceptionRemark { get; set; }
    }
}

创建日志级别枚举类型,分别对应Log4net中的日志级别,代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;

namespace MVCCuetomerExcepFilterDemo.Models.Enums
{
    /// <summary>
    /// 日志级别
    /// </summary>
    public enum LogLevel
    {
        /// <summary>
        /// 错误
        /// </summary>
        [Description("错误")]
        Error,
        /// <summary>
        /// 警告
        /// </summary>
        [Description("警告")]
        Warning,
        /// <summary>
        /// 信息
        /// </summary>
        [Description("信息")]
        Info,
        /// <summary>
        /// 调试
        /// </summary>
        [Description("调试")]
        Debug
    }
}

创建一个对日志格式进行格式化的类,代码如下:

using MVCCuetomerExcepFilterDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace MVCCuetomerExcepFilterDemo.Util
{
    /// <summary>
    /// 日志格式器
    /// </summary>
    public class LogFormat
    {
        /// <summary>
        /// 生成错误
        /// </summary>
        /// <param name="logMessage">对象</param>
        /// <returns></returns>
        public string ErrorFormat(LogMessageEntity logMessage)
        {
            StringBuilder strInfo = new StringBuilder();
            strInfo.Append("1. 错误: >> 操作时间: " + logMessage.OperationTime + "   操作人: " + logMessage.UserName + " \r\n");
            strInfo.Append("2. 地址: " + logMessage.Url + "    \r\n");
            strInfo.Append("3. 类名: " + logMessage.Class + " \r\n");
            strInfo.Append("4. Ip  : " + logMessage.Ip + "   主机: " + logMessage.Host + "   浏览器: " + logMessage.Browser + "    \r\n");
            strInfo.Append("5. 内容: " + logMessage.Content + "\r\n");
            strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n");
            return strInfo.ToString();
        }
        /// <summary>
        /// 生成警告
        /// </summary>
        /// <param name="logMessage">对象</param>
        /// <returns></returns>
        public string WarnFormat(LogMessageEntity logMessage)
        {
            StringBuilder strInfo = new StringBuilder();
            strInfo.Append("1. 警告: >> 操作时间: " + logMessage.OperationTime + "   操作人: " + logMessage.UserName + " \r\n");
            strInfo.Append("2. 地址: " + logMessage.Url + "    \r\n");
            strInfo.Append("3. 类名: " + logMessage.Class + " \r\n");
            strInfo.Append("4. Ip  : " + logMessage.Ip + "   主机: " + logMessage.Host + "   浏览器: " + logMessage.Browser + "    \r\n");
            strInfo.Append("5. 内容: " + logMessage.Content + "\r\n");
            strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n");
            return strInfo.ToString();
        }
        /// <summary>
        /// 生成信息
        /// </summary>
        /// <param name="logMessage">对象</param>
        /// <returns></returns>
        public string InfoFormat(LogMessageEntity logMessage)
        {
            StringBuilder strInfo = new StringBuilder();
            strInfo.Append("1. 信息: >> 操作时间: " + logMessage.OperationTime + "   操作人: " + logMessage.UserName + " \r\n");
            strInfo.Append("2. 地址: " + logMessage.Url + "    \r\n");
            strInfo.Append("3. 类名: " + logMessage.Class + " \r\n");
            strInfo.Append("4. Ip  : " + logMessage.Ip + "   主机: " + logMessage.Host + "   浏览器: " + logMessage.Browser + "    \r\n");
            strInfo.Append("5. 内容: " + logMessage.Content + "\r\n");
            strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n");
            return strInfo.ToString();
        }
        /// <summary>
        /// 生成调试
        /// </summary>
        /// <param name="logMessage">对象</param>
        /// <returns></returns>
        public string DebugFormat(LogMessageEntity logMessage)
        {
            StringBuilder strInfo = new StringBuilder();
            strInfo.Append("1. 调试: >> 操作时间: " + logMessage.OperationTime + "   操作人: " + logMessage.UserName + " \r\n");
            strInfo.Append("2. 地址: " + logMessage.Url + "    \r\n");
            strInfo.Append("3. 类名: " + logMessage.Class + " \r\n");
            strInfo.Append("4. Ip  : " + logMessage.Ip + "   主机: " + logMessage.Host + "   浏览器: " + logMessage.Browser + "    \r\n");
            strInfo.Append("5. 内容: " + logMessage.Content + "\r\n");
            strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n");
            return strInfo.ToString();
        }
        /// <summary>
        /// 生成异常信息
        /// </summary>
        /// <param name="logMessage">对象</param>
        /// <returns></returns>
        public string ExceptionFormat(LogMessageEntity logMessage)
        {
            StringBuilder strInfo = new StringBuilder();
            strInfo.Append("1. 调试: >> 操作时间: " + logMessage.OperationTime + "   操作人: " + logMessage.UserName + " \r\n");
            strInfo.Append("2. 地址: " + logMessage.Url + "    \r\n");
            strInfo.Append("3. 类名: " + logMessage.Class + " \r\n");
            strInfo.Append("4. 主机: " + logMessage.Host + "   Ip  : " + logMessage.Ip + "   浏览器: " + logMessage.Browser + "    \r\n");
            strInfo.Append("5. 异常: " + logMessage.ExceptionInfo + "\r\n");
            //strInfo.Append("6. 来源: " + logMessage.ExceptionSource + "\r\n");
            //strInfo.Append("7. 实例: " + logMessage.ExceptionRemark + "\r\n");
            strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n");
            return strInfo.ToString();
        }
    }
}

创建日志类,代码如下:

using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MVCCuetomerExcepFilterDemo.Util
{
    /// <summary>
    /// 日志
    /// </summary>
    public class Log
    {
        private ILog logger;
        public Log(ILog log)
        {
            this.logger = log;
        }
        public void Debug(object message)
        {
            this.logger.Debug(message);
        }
        public void Error(object message)
        {
            this.logger.Error(message);
        }
        public void Info(object message)
        {
            this.logger.Info(message);
        }

        public void Warn(object message)
        {
            this.logger.Warn(message);
        }
    }
}

创建日志初始化类,代码如下:

using log4net;
using MVCCuetomerExcepFilterDemo.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

namespace MVCCuetomerExcepFilterDemo.Util
{
    /// <summary>
    /// 日志初始化
    /// </summary>
    public class LogFactory
    {
        static LogFactory()
        {
            FileInfo configFile = new FileInfo(HttpContext.Current.Server.MapPath("/XmlConfig/log4net.config"));
            log4net.Config.XmlConfigurator.Configure(configFile);
        }
        public static Log GetLogger(Type type)
        {
            return new Log(LogManager.GetLogger(type));
        }
        public static Log GetLogger(string str)
        {
            return new Log(LogManager.GetLogger(str));
        }
    }
}

最后添加log4net的配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>

  <log4net>
    <!--根配置-->
    <root>
      <!--日志级别:可选值: ERROR > WARN > INFO > DEBUG -->
      <level value="ERROR"/>
      <level value="WARN"/>
      <level value="INFO"/>
      <level value="DEBUG"/>
      <appender-ref ref="ErrorLog" />
      <appender-ref ref="WarnLog" />
      <appender-ref ref="InfoLog" />
      <appender-ref ref="DebugLog" />
    </root>
    <!-- 错误 Error.log-->
    <appender name="ErrorLog" type="log4net.Appender.RollingFileAppender">
      <!--目录路径,可以是相对路径或绝对路径-->
      <param name="File" value="D:\log"/>
      <!--文件名,按日期生成文件夹-->
      <param name="DatePattern" value="/yyyy-MM-dd/&quot;Error.log&quot;"/>
      <!--追加到文件-->
      <appendToFile value="true"/>
      <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]-->
      <rollingStyle value="Composite"/>
      <!--写到一个文件-->
      <staticLogFileName value="false"/>
      <!--单个文件大小。单位:KB|MB|GB-->
      <maximumFileSize value="200MB"/>
      <!--最多保留的文件数,设为"-1"则不限-->
      <maxSizeRollBackups value="-1"/>
      <!--日志格式-->
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message"/>
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="ERROR" />
        <param name="LevelMax" value="ERROR" />
      </filter>
    </appender>

    <!-- 警告 Warn.log-->
    <appender name="WarnLog" type="log4net.Appender.RollingFileAppender">
      <!--目录路径,可以是相对路径或绝对路径-->
      <param name="File" value="D:\log"/>
      <!--文件名,按日期生成文件夹-->
      <param name="DatePattern" value="/yyyy-MM-dd/&quot;Warn.log&quot;"/>
      <!--追加到文件-->
      <appendToFile value="true"/>
      <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]-->
      <rollingStyle value="Composite"/>
      <!--写到一个文件-->
      <staticLogFileName value="false"/>
      <!--单个文件大小。单位:KB|MB|GB-->
      <maximumFileSize value="200MB"/>
      <!--最多保留的文件数,设为"-1"则不限-->
      <maxSizeRollBackups value="-1"/>
      <!--日志格式-->
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message"/>
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="WARN" />
        <param name="LevelMax" value="WARN" />
      </filter>
    </appender>

    <!-- 信息 Info.log-->
    <appender name="InfoLog" type="log4net.Appender.RollingFileAppender">
      <!--目录路径,可以是相对路径或绝对路径-->
      <param name="File" value="D:\log"/>
      <!--文件名,按日期生成文件夹-->
      <param name="DatePattern" value="/yyyy-MM-dd/&quot;Info.log&quot;"/>
      <!--追加到文件-->
      <appendToFile value="true"/>
      <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]-->
      <rollingStyle value="Composite"/>
      <!--写到一个文件-->
      <staticLogFileName value="false"/>
      <!--单个文件大小。单位:KB|MB|GB-->
      <maximumFileSize value="200MB"/>
      <!--最多保留的文件数,设为"-1"则不限-->
      <maxSizeRollBackups value="-1"/>
      <!--日志格式-->
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message"/>
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="INFO" />
        <param name="LevelMax" value="INFO" />
      </filter>
    </appender>

    <!-- 调试 Debug.log-->
    <appender name="DebugLog" type="log4net.Appender.RollingFileAppender">
      <!--目录路径,可以是相对路径或绝对路径-->
      <param name="File" value="D:\log"/>
      <!--文件名,按日期生成文件夹-->
      <param name="DatePattern" value="/yyyy-MM-dd/&quot;Debug.log&quot;"/>
      <!--追加到文件-->
      <appendToFile value="true"/>
      <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]-->
      <rollingStyle value="Composite"/>
      <!--写到一个文件-->
      <staticLogFileName value="false"/>
      <!--单个文件大小。单位:KB|MB|GB-->
      <maximumFileSize value="200MB"/>
      <!--最多保留的文件数,设为"-1"则不限-->
      <maxSizeRollBackups value="-1"/>
      <!--日志格式-->
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message"/>
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <param name="LevelMin" value="DEBUG" />
        <param name="LevelMax" value="DEBUG" />
      </filter>
    </appender>

  </log4net>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
</configuration>

1.2、创建网络工具类

该工具帮助类用于获取IP、浏览器信息等内容,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Web;

namespace MVCCuetomerExcepFilterDemo.Util
{
    /// <summary>
    /// 网络操作帮助类
    /// </summary>
    public class NetHelper
    {
        #region Ip(获取Ip)

        /// <summary>
        /// 获取Ip
        /// </summary>
        public static string Ip
        {
            get
            {
                var result = string.Empty;
                if (HttpContext.Current != null)
                    result = GetWebClientIp();
                if (string.IsNullOrWhiteSpace(result))
                    result = GetLanIp();
                return result;
            }
        }

        /// <summary>
        /// 获取Web客户端的Ip
        /// </summary>
        private static string GetWebClientIp()
        {
            var ip = GetWebRemoteIp();
            foreach (var hostAddress in Dns.GetHostAddresses(ip))
            {
                if (hostAddress.AddressFamily == AddressFamily.InterNetwork)
                    return hostAddress.ToString();
            }
            return string.Empty;
        }

        /// <summary>
        /// 获取Web远程Ip
        /// </summary>
        private static string GetWebRemoteIp()
        {
            return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
        }

        /// <summary>
        /// 获取局域网IP
        /// </summary>
        private static string GetLanIp()
        {
            foreach (var hostAddress in Dns.GetHostAddresses(Dns.GetHostName()))
            {
                if (hostAddress.AddressFamily == AddressFamily.InterNetwork)
                    return hostAddress.ToString();
            }
            return string.Empty;
        }

        #endregion

        #region Host(获取主机名)

        /// <summary>
        /// 获取主机名
        /// </summary>
        public static string Host
        {
            get
            {
                return HttpContext.Current == null ? Dns.GetHostName() : GetWebClientHostName();
            }
        }

        /// <summary>
        /// 获取Web客户端主机名
        /// </summary>
        private static string GetWebClientHostName()
        {
            if (!HttpContext.Current.Request.IsLocal)
                return string.Empty;
            var ip = GetWebRemoteIp();
            var result = Dns.GetHostEntry(IPAddress.Parse(ip)).HostName;
            if (result == "localhost.localdomain")
                result = Dns.GetHostName();
            return result;
        }

        #endregion

        #region Browser(获取浏览器信息)

        /// <summary>
        /// 获取浏览器信息
        /// </summary>
        public static string Browser
        {
            get
            {
                if (HttpContext.Current == null)
                    return string.Empty;
                var browser = HttpContext.Current.Request.Browser;
                return string.Format("{0} {1}", browser.Browser, browser.Version);
            }
        }

        #endregion
    }
}

2、创建自定义异常类

上篇文章中讲过了,要创建自定义异常类,只需要创建一个继承自HandleErrorAttribute的类,并重写OnException方法即可,自定义异常类代码如下:

using MVCCuetomerExcepFilterDemo.Models;
using MVCCuetomerExcepFilterDemo.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCCuetomerExcepFilterDemo.Extension
{
    /// <summary>
    /// 错误日志(Controller发生异常时会执行这里)
    /// </summary>
    public class ExceptionFilters : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            WriteLog(filterContext);
            base.OnException(filterContext);
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.StatusCode = 200;
        }

        /// <summary>
        /// 写入日志(log4net)
        /// </summary>
        /// <param name="context">提供使用</param>
        private void WriteLog(ExceptionContext context)
        {

            if (context == null)
                return;
            var log = LogFactory.GetLogger(context.Controller.ToString());
            Exception Error = context.Exception;
            LogMessageEntity logMessage = new LogMessageEntity();
            logMessage.OperationTime = DateTime.Now;
            logMessage.Url = HttpContext.Current.Request.RawUrl;
            logMessage.Class = context.Controller.ToString();
            logMessage.Ip = NetHelper.Ip;
            logMessage.Host = NetHelper.Host;
            logMessage.Browser = NetHelper.Browser;
            // 这里为了方便直接用默认的,真实案例中不能这样写
            logMessage.UserName = "admin";
            if (Error.InnerException == null)
            {
                logMessage.ExceptionInfo = Error.Message;
            }
            else
            {
                logMessage.ExceptionInfo = Error.InnerException.Message;
            }
            string strMessage = new LogFormat().ExceptionFormat(logMessage);
            log.Error(strMessage);
        }
    }
}

3、创建控制器

控制器里面有一个LogOn登录的方法,代码如下:

using MVCCuetomerExcepFilterDemo.Extension;
using MVCCuetomerExcepFilterDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace MVCCuetomerExcepFilterDemo.Controllers
{
    public class AccountController : Controller
    {
        // GET: Account
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 登录成功显示的视图
        /// </summary>
        /// <returns></returns>
        public ActionResult Welcome()
        {
            return View();
        }

        /// <summary>
        /// 显示登录视图
        /// </summary>
        /// <returns></returns>
        public ActionResult LogOn()
        {
            LogOnViewModel model = new LogOnViewModel();
            return View(model);

        }

        /// <summary>
        /// 处理用户点击登录提交回发的表单
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [ExceptionFilters]
        public ActionResult LogOn(LogOnViewModel model)
        {
            try
            {
                string userName = model.UserName.Trim();
                int password = Convert.ToInt32(model.Password);
                // 用户名是admin,密码是123456表示验证通过
                if (userName.Equals("admin")&&password.Equals(123456))
                {
                    // 判断是否勾选了记住我
                    if (model.RememberMe)
                    {
                        //2880分钟有效期的cookie
                        FormsAuthentication.SetAuthCookie(model.UserName, true);
                    }
                    else
                    {
                        //会话cookie
                        FormsAuthentication.SetAuthCookie(model.UserName, false);
                    }
                    // 跳转到Account控制器的Welcome方法
                    return RedirectToAction("Welcome");
                }
                else
                {
                    return View(model);

                }
            }
            catch (Exception ex)
            {
                // 抛出异常
                throw;
            }

        }
    }
}

4、测试

在控制器代码中,如果输入的用户名是admin,密码是123456就通过,然后显示Welcome视图,如果密码转换失败的时候就记录异常日志。

首先输入正确的用户名和密码:

点击登录,然后显示Welcome视图:

这次输入错误的密码:

再次点击登录,这时查看生成的日志:

在上面的代码中,我们在LogOn()方法上面使用了ExceptionFilters这个特性,这样在控制器发生异常的时候就会进入ExceptionFilters自定义异常类,然后记录日志。但是这样有一个问题:使用这种方式要再每个action方法上面都添加该特性,如果action方法比较多,写起来也是很烦的,那么有没有什么好的办法呢?可以在控制器上面添加ExceptionFilters特性,这样就是针对整个控制器里面的action了。那么还有没有更简洁的办法。看App_Start文件夹下面的FilterConfig定义:

using MVCCuetomerExcepFilterDemo.Extension;
using System.Web;
using System.Web.Mvc;

namespace MVCCuetomerExcepFilterDemo
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
    }
}

可以看到这里是添加的HandleErrorAttribute类,如果换成自定义的异常类会如何呢?修改后的FilterConfig文件如下:

using MVCCuetomerExcepFilterDemo.Extension;
using System.Web;
using System.Web.Mvc;

namespace MVCCuetomerExcepFilterDemo
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //filters.Add(new HandleErrorAttribute());
            // 使用自定义异常类
            filters.Add(new ExceptionFilters());
        }
    }
}

AccountController控制器代码修改如下:

using MVCCuetomerExcepFilterDemo.Extension;
using MVCCuetomerExcepFilterDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace MVCCuetomerExcepFilterDemo.Controllers
{
    public class AccountController : Controller
    {
        // GET: Account
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 登录成功显示的视图
        /// </summary>
        /// <returns></returns>
        public ActionResult Welcome()
        {
            return View();
        }

        /// <summary>
        /// 显示登录视图
        /// </summary>
        /// <returns></returns>
        public ActionResult LogOn()
        {
            LogOnViewModel model = new LogOnViewModel();
            return View(model);

        }

        /// <summary>
        /// 处理用户点击登录提交回发的表单
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        // [ExceptionFilters]
        public ActionResult LogOn(LogOnViewModel model)
        {
            try
            {
                string userName = model.UserName.Trim();
                int password = Convert.ToInt32(model.Password);
                // 用户名是admin,密码是123456表示验证通过
                if (userName.Equals("admin")&&password.Equals(123456))
                {
                    // 判断是否勾选了记住我
                    if (model.RememberMe)
                    {
                        //2880分钟有效期的cookie
                        FormsAuthentication.SetAuthCookie(model.UserName, true);
                    }
                    else
                    {
                        //会话cookie
                        FormsAuthentication.SetAuthCookie(model.UserName, false);
                    }
                    // 跳转到Account控制器的Welcome方法
                    return RedirectToAction("Welcome");
                }
                else
                {
                    return View(model);

                }
            }
            catch (Exception ex)
            {
                // 抛出异常
                throw;
            }

        }
    }
}

这样发生异常的时候就会自动进入自定义异常类了,然后记录日志。

到此这篇关于ASP.NET MVC自定义异常过滤器使用案例的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET Core 过滤器中使用依赖注入知识点总结

    如何给过滤器ActionFilterAttribute也用上构造函数注入呢? 一般自定义的过滤器直接用特性方式标识就能使用 [ContentFilter] 因为构造函数在使用的时候要求传参,然后我们可以使用这个 ServiceFilter 在ASP.NET Core里,我们可以使用ServiceFilter来完成这个需求. ServiceFilter允许我们解析一个已经添加IoC容器的服务,因此我们需要把ContentFilter注册一下. services.AddScoped<ContentF

  • ASP.NET Core MVC 过滤器的使用方法介绍

    过滤器的作用是在 Action 方法执行前或执行后做一些加工处理.使用过滤器可以避免Action方法的重复代码,例如,您可以使用异常过滤器合并异常处理的代码. 过滤器如何工作? 过滤器在 MVC Action 调用管道中运行,有时称为过滤器管道.MVC选择要执行的Action方法后,才会执行过滤器管道: 实现 过滤器同时支持同步和异步两种不同的接口定义.您可以根据执行的任务类型,选择同步或异步实现. 同步过滤器定义OnStageExecuting和OnStageExecuted方法,会在管道特定

  • ASP.NET MVC授权过滤器用法

    过滤器 过滤器(Filter)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,并不是每个请求都会响应内容,只有那些有特定权限的用户才能响应特定的内容.过滤器理论上有以下功能: 判断登录与否或者用户权限. 决策输出缓存. 防盗链. 防蜘蛛. 本地化与国际化设置. 实现动态Action(做权限管理系统经常用到). 1.使用方式一 第一种方法是在Controller或Action上面直接使用Authorize特性,不设置特性的任何属性.看下面的截图: 从上面的截图中可

  • ASP.NET Core MVC中过滤器工作原理介绍

    过滤器的作用是在 Action 方法执行前或执行后做一些加工处理.使用过滤器可以避免Action方法的重复代码,例如,您可以使用异常过滤器合并异常处理的代码. 过滤器如何工作? 过滤器在 MVC Action 调用管道中运行,有时称为过滤器管道.MVC选择要执行的Action方法后,才会执行过滤器管道: 实现 过滤器同时支持同步和异步两种不同的接口定义.您可以根据执行的任务类型,选择同步或异步实现. 同步过滤器定义OnStageExecuting和OnStageExecuted方法,会在管道特定

  • ASP.NET Core MVC 过滤器(Filter)

    目录 一.过滤器如何工作 1.选择过滤器 2.实现过滤器 3.过滤器作用域 4.取消和短路 二.配置过滤器 1.依赖注入 2.排序 3.对比中间件 一.过滤器如何工作 不同的过滤器类型在管道中的不同阶段执行,因此具有各自的与其场景.根据需要执行的任务以及需要执行的请求管道中的位置,选择要创建的过滤器类型.过滤器在 MVC 操作调用管道中运行,有时也称为过滤管道,在 MVC 中选择要执行的操作后,执行操作上的过滤器,如图: 不同的过滤器在管道内的不同位置执行.像授权过滤器这样的过滤器只在管道中靠前

  • ASP.NET MVC异常过滤器用法

    我们平常在程序里面为了捕获异常,会加上try-catch-finally代码,但是这样会使得程序代码看起来很庞大,在MVC中我们可以使用异常过滤器来捕获程序中的异常,如下图所示: 使用了异常过滤器以后,我们就不需要在Action方法里面写Try -Catch-Finally这样的异常处理代码了,而把这份工作交给HandleError去做,这个特性同样可以应用到Controller上面,也可以应用到Action方面上面. 注意: 使用异常过滤器的时候,customErrors配置节属性mode的值

  • ASP.NET MVC自定义异常过滤器

    一.异常过滤器 异常筛选器用于实现IExceptionFilter接口,并在ASP.NET MVC管道执行期间引发了未处理的异常时执行.异常筛选器可用于执行诸如日志记录或显示错误页之类的任务.HandleErrorAttribute类是异常筛选器的一个示例. 先来看看HandleErrorAttribute类的定义: #region 程序集 System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364

  • ASP.NET MVC缓存过滤器用法

    缓存过滤器用来输出页面缓存,其用法如下图所示: 注意: Duration:表示缓存多少秒;VaryByParam:表示缓存是否随地址参数而改变.OutputCache除了可以定义在Action方法上面以外,还可以定义在控制器上面. 演示示例: 新建一个MVC应用程序,添加一个名为Cache的控制器,Cache控制器的Index方法里面将当前时间输出到页面中,Cache控制器定义如下: using System; using System.Collections.Generic; using Sy

  • 在Asp.Net Core中使用ModelConvention实现全局过滤器隔离

    从何说起 这来自于我把项目迁移到Asp.Net Core的过程中碰到一个问题.在一个web程序中同时包含了MVC和WebAPI,现在需要给WebAPI部分单独添加一个接口验证过滤器 IActionFilter ,常规做法一般是写好过滤器后给需要的控制器挂上这个标签,高级点的做法是注册一个全局过滤器,这样可以避免每次手动添加同时代码也更好管理.注册全局过滤器的方式为: services.AddMvc(options => { options.Filters.Add(typeof(AccessCon

  • ASP.NET MVC自定义异常过滤器使用案例

    目录 一.需求 二.案例 1.创建工具类 1.1.创建日志工具类 1.2.创建网络工具类 2.创建自定义异常类 3.创建控制器 4.测试 在上一篇文章中讲解了自定义异常过滤器,这篇文章会结合工作中的真实案例讲解一下如何使用自定义异常过滤器. 一.需求 本案例要实现的功能需求:在发生异常时记录日志,日志内容包括发生异常的Controller名称.Action名称.使用浏览器类型和版本等. 二.案例 1.创建工具类 首先创建项目中需要使用的工具类. 1.1.创建日志工具类 在案例中使用Log4net

  • ASP.NET MVC授权过滤器用法

    过滤器 过滤器(Filter)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,并不是每个请求都会响应内容,只有那些有特定权限的用户才能响应特定的内容.过滤器理论上有以下功能: 判断登录与否或者用户权限. 决策输出缓存. 防盗链. 防蜘蛛. 本地化与国际化设置. 实现动态Action(做权限管理系统经常用到). 1.使用方式一 第一种方法是在Controller或Action上面直接使用Authorize特性,不设置特性的任何属性.看下面的截图: 从上面的截图中可

  • Asp.Net MVC学习总结之过滤器详解

     一.过滤器简介 1.1.理解什么是过滤器 1.过滤器(Filters)就是向请求处理管道中注入额外的逻辑.提供了一个简单而优雅的方式来实现横切关注点. 2.所谓的过滤器(Filters),MVC框架里面的过滤器完全不同于ASP.NET平台里面的Request.Filters和Response.Filter对象,它们主要是实现请求和响应流的传输.通常我们所说的过滤器是指MVC框架里面的过滤器. 3.过滤器可以注入一些代码逻辑到请求处理管道中,是基于C#的Attribute的实现.当负责调用Act

  • ASP.NET MVC自定义操作过滤器

    目录 一.操作过滤器 1.定义 2.案例 2.1.创建自定义操作过滤器 2.2.新建控制器 二.结果过滤器 1.定义 2.案例 三.案例 1.记录操作 1.1.创建实体类 1.2.创建日志类 1.3.修改操作过滤器类 2.实现权限控制功能 一.操作过滤器 1.定义 操作过滤器用于实现IActionFilter接口以及包装操作方法执行.IActionFilter接口声明两个方法:OnActionExecuting和OnActionExecuted.OnActionExecuting在操作方法之前运

  • ASP.NET MVC自定义授权过滤器

    目录 一.授权过滤器 二.示例 1.添加对应实体类 2.添加测试数据 3.新建继承类 4.添加Account控制器 5.修改配置文件 6.添加授权控制器 三.测试 测试Welcome 四.总结 一.授权过滤器 授权过滤器用于实现IAuthorizationFilter接口和做出关于是否执行操作方法(如执行身份验证或验证请求的属性)的安全策略.AuthorizeAttribute类继承了IAuthorizationFilter接口,是授权过滤器的示例.授权过滤器在任何其他过滤器之前运行. 如果要自

  • 详解ASP.NET MVC 常用扩展点:过滤器、模型绑定

    一.过滤器(Filter) ASP.NET MVC中的每一个请求,都会分配给对应Controller(以下简称"控制器")下的特定Action(以下简称"方法")处理,正常情况下直接在方法里写代码就可以了,但是如果想在方法执行之前或者之后处理一些逻辑,这里就需要用到过滤器. 常用的过滤器有三个:Authorize(授权过滤器),HandleError(异常过滤器),ActionFilter(自定义过滤器),对应的类分别是:AuthorizeAttribute.Han

随机推荐