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

一、需求

本案例要实现的功能需求:在发生异常时记录日志,日志内容包括发生异常的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 = ;
} /// <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())
{
// 判断是否勾选了记住我
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())
{
// 判断是否勾选了记住我
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;
} }
}
}

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

MVC过滤器:自定义异常过滤器使用案例的更多相关文章

  1. 第四节:MVC中AOP思想的体现(四种过滤器)并结合项目案例说明过滤器的实际用法

    一. 简介 MVC中的过滤器可以说是MVC框架中的一种灵魂所在,它是MVC框架中AOP思想的具体体现,所以它以面向切面的形式无侵入式的作用于代码的业务逻辑,与业务逻辑代码分离,一经推出,广受开发者的喜 ...

  2. MVC过滤器:自定义异常过滤器

    一.异常过滤器 异常筛选器用于实现IExceptionFilter接口,并在ASP.NET MVC管道执行期间引发了未处理的异常时执行.异常筛选器可用于执行诸如日志记录或显示错误页之类的任务.Hand ...

  3. MVC中的过滤器

    authour: chenboyi updatetime: 2015-05-09 09:30:30 friendly link:   目录: 1,思维导图   2,过滤器种类(图示) 3,全局过滤器 ...

  4. [Asp.net MVC]HandleErrorAttribute异常过滤器

    摘要 在asp.net mvc中除了使用try...catch/finally来处理异常外,它提供了一种通过在Controller或者Action上添加特性的方式来处理异常. HandleErrorA ...

  5. Asp.Net MVC<五>:过滤器

    ControllerActionInvoker在执行过程中除了利用ActionDescriptor完成对目标Action方法本身的执行外,还会执行相关过滤器(Filter).过滤器采用AOP的设计,它 ...

  6. asp.net MVC之 自定义过滤器(Filter) - shuaixf

    一.系统过滤器使用说明 1.OutputCache过滤器 OutputCache过滤器用于缓存你查询结果,这样可以提高用户体验,也可以减少查询次数.它有以下属性: Duration :缓存的时间, 以 ...

  7. ASP.NET MVC 4 (三) 过滤器

    先来看看一个例子演示过滤器有什么用: public class AdminController : Controller { // ... instance variables and constru ...

  8. ASP.NET MVC学习之过滤器篇(2)

    下面我们继续之前的ASP.NET MVC学习之过滤器篇(1)进行学习. 3.动作过滤器 顾名思义,这个过滤器就是在动作方法调用前与调用后响应的.我们可以在调用前更改实际调用的动作,也可以在动作调用完成 ...

  9. asp.net MVC之 自定义过滤器(Filter)

    一.系统过滤器使用说明 1.OutputCache过滤器 OutputCache过滤器用于缓存你查询结果,这样可以提高用户体验,也可以减少查询次数.它有以下属性: Duration:缓存的时间,以秒为 ...

随机推荐

  1. java调用py文件传参执行

    java执行的也是py文件主函数. 传参: String url="*********************"; String[] args1 = new String[] { ...

  2. NLP入门(九)词义消岐(WSD)的简介与实现

    词义消岐简介   词义消岐,英文名称为Word Sense Disambiguation,英语缩写为WSD,是自然语言处理(NLP)中一个非常有趣的基本任务.   那么,什么是词义消岐呢?通常,在我们 ...

  3. 程序员修神之路--redis做分布式锁可能不那么简单

    菜菜哥,复联四上映了,要不要一起去看看? 又想骗我电影票,对不对? 呵呵,想去看了叫我呀 看来你工作不饱和呀 哪有,这两天我刚基于redis写了一个分布式锁,很简单 不管你基于什么做分布式锁,你觉得很 ...

  4. requeests模块响应体属性和方法重新整理

    下面的属性方法都是基于response对象` import requests response = requests.get('url') 一.url 返回值的url 二. text 获得响应体文本信 ...

  5. DevExpress的TreeList实现显示本地文件目录并自定义右键实现删除与重命名文件

    场景 使用DevExpress的TreeList显示本磁盘下文件目录并在树节点上右键实现删除与添加文件. 效果 自定义右键效果 实现 首先在包含Treelist的窗体的load方法中对treelist ...

  6. ansible jinja2模板概述

    目录 ansible jinja2模板概述 ansible jinja2模板使用 基本语法 jinja2模板逻辑判断 ansible jinja2管理nginx ansible jinja2管理kee ...

  7. SQL Server查询数据库近期执行的SQL语句

    SELECT TOP 1000        ST.text AS '执行的SQL语句',       QS.execution_count AS '执行次数',       QS.total_ela ...

  8. hexdump 工具使用 和 .txt 文件的二进制查看

    最近使用txt文件进行数据处理的时候,突然发现txt文件是怎样编码数据的了,它是以二进制来进行存储的吗?为了知道这个情况,我使用hexdump工具进行查看txt文件的二进制形式,并顺道进行学习了hex ...

  9. CPU相关概念

    整部主机的重点在于中央处理器 (Central Processing Unit, CPU),CPU 为一个具有特定功 能的芯片, 里头含有微指令集,如果你想要让主机进行什么特异的功能,就得要参考这颗 ...

  10. Codeforces Round #586 (Div. 1 + Div. 2)

    传送门 A. Cards 记录一下出现的个数就行. Code #include <bits/stdc++.h> #define MP make_pair #define fi first ...