C#自定义HttpFilter模块完善实例

本文实例讲述了C#自定义HttpFilter模块完善的方法,分享给大家供大家参考。具体实现方法如下:

一、背景

近期由于要针对项目做用户操作日志,但不想在每个方法里去增加代码,写入用户日志。因为这样具体的方法违背职责单一的原则,若后期日志内容格式发生变更,或其他什么需求,该方法代码主要一变在变,故使用HttpModule模块来完成此功能,感兴趣的朋友可以参考:关于HttpHandler与HttpModule的理解和应用方法

经过实际运用与完善,现在可以再次总结下。

二、拦截时机

现在的版本中,拦截的依据是,在每次请求发生的过程中,拦截控制器类请求,重定向http输出流,并分析出Controller与Action,接下来查找是否有方法监控了此控制器,若有,则分析出请求输入参数,与此次请求输出内容,存储在FilterContext中,交给该方法,完成相应逻辑。

由于在最初的写法中,是针对所有的请求进行流的重定向,在asmx下,会遇到问题,只要重定向了,调用服务的客户端会提示400 Http Bad Request 。这个具体的错误原因,还不清楚,但正是由于该错误,让我发现,我之前拦截的时机是错误的,理应放在请求之前,判断是否满足拦截的规则,若满足,则重定向输出流。

三、读取用户名

在Module模块中总会出点问题,最后使用了Cookie记住用户名,并直接定义为FilterContext一个属性。解释下这样做的原因:由于记住用户名的方式有很多,如Session、Cookie,即读取用户名的方式是可变的,所以尽可能将变化的内容在前面解决,这样监听控制器的方法,直接根据该属性获取用户名,否则用户名的读取时机,放在每个监听控制器模块之后,读取方式一旦发生变更,所有的模块都要改变,当然也可以通过继承一个base类来避免这么大的改变。

在这里我想表达的意思是:我们做类似底层库的东西,尽可能稳定,将变化点集中在库本身,这样依赖该库的应用才能稳定。若.net版本更新过程中,API都不稳定,想必我们也不会在去使用它。

四、应用之写入日志

典型例子如下:

代码如下:

[FilterMethod("Login", "Login")]
public void Login(FilterContext context)
{
    //解析输出内容,这里针对要监听的控制器和方法来写的
    var arr = context.OutputBody.Split('|');
    var log = string.Format("userName:{0} password:{1}",arr);
    FilterLog.Log.Info(log);
}

该方法表达的意思是,监控LoginController的Login方法。由于我们需要分析请求输出结果,所以分析的规则,与控制器是强依赖的,控制器的方法是怎么返回数据的,我们此处就要根据规则解析。我在项目中使用的是Json,所以监控的地方都需要Json的反序列化,这里仅仅是一个Demo。

另外一个方法可以监听一个控制器下的多个方法,或者多个控制器。这样是旨在解决有很多Action,输入参数和输出参数都是相同的,可能由于业务不同,仅仅在方法名和内部实现中有不同。

五、应用之更新缓存

首先关于Cache的应用,可以读下此文章,Asp.Net Cache高级用法。

由于此处我没有写例子,先描述我在项目中运用的情况。系统有很多数据字典,在请求该数据字典时,程序首先从数据库加载字典数据,并放入缓存,此时放入缓存有个技巧,设置过期时间,并设置移除缓存前的回调,我们来看看具体的方法定义:

代码如下:

//
// 摘要:
//     将对象与依赖项、到期策略以及可用于在从缓存中移除项之前通知应用程序的委托一起插入到 System.Web.Caching.Cache 对象中。
//
// 参数:
//   key:
//     用于引用对象的缓存键。
//
//   value:
//     要插入到缓存中的对象。
//
//   dependencies:
//     该项的文件依赖项或缓存键依赖项。当任何依赖项更改时,该对象即无效,并从缓存中移除。如果没有依赖项,则此参数包含 null。
//
//   absoluteExpiration:
//     所插入对象将到期并被从缓存中移除的时间。要避免可能的本地时间问题(例如从标准时间改为夏时制),请使用 System.DateTime.UtcNow
//     而不是 System.DateTime.Now 作为此参数值。如果使用绝对到期,则 slidingExpiration 参数必须设置为 System.Web.Caching.Cache.NoSlidingExpiration。
//
//   slidingExpiration:
//     缓存对象的上次访问时间和对象的到期时间之间的时间间隔。如果该值等效于 20 分钟,则对象在最后一次被访问 20 分钟之后将到期并被从缓存中移除。如果使用可调到期,则
//     absoluteExpiration 参数必须设置为 System.Web.Caching.Cache.NoAbsoluteExpiration。
//
//   onUpdateCallback:
//     从缓存中移除对象之前将调用的委托。可以使用它来更新缓存项并确保缓存项不会从缓存中移除。
//
// 异常:
//   System.ArgumentNullException:
//     key、value 或 onUpdateCallback 参数为 null。
//
//   System.ArgumentOutOfRangeException:
//     将 slidingExpiration 参数设置为小于 TimeSpan.Zero 或大于一年的等效值。
//
//   System.ArgumentException:
//     为要添加到 Cache 中的项设置 absoluteExpiration 和 slidingExpiration 参数。- 或 -dependencies
//     参数为 null,absoluteExpiration 参数设置为 System.Web.Caching.Cache.NoAbsoluteExpiration
//     并且 slidingExpiration 参数设置为 System.Web.Caching.Cache.NoSlidingExpiration。
public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);

仔细看看onUpdateCallback参数的描述:从缓存中移除对象之前将调用的委托。可以使用它来更新缓存项并确保缓存项不会从缓存中移除。

我在把数据字典放入缓存的同时传递读取缓存的委托,这样在主动移除缓存或者缓存过期时都将再次调用此委托,将数据字典再次放入缓存。所以一旦数据字典发生了变更,如增删改,那么就主动将字典缓存移除,它就可以自动更新过来,是不是很方便呢。

区别于写操作日志,不过是处理逻辑发生了变化,他们都需要请求的输入和输出。

六、其他

1.由于使用HttpModule来完成此功能,如需正常运行,需要在WebConfig中注册该模块。详见Demo。

2.项目中使用了Log4Net记录文本日志,并可以根据功能分类。详见:Log4Net日志分类维护。

完整实例代码点击此处本站下载。

希望本文所述对大家的C#程序设计有所帮助。

(0)

相关推荐

  • C#中HttpWebRequest的用法详解

    本文实例讲述了C#中HttpWebRequest的用法.分享给大家供大家参考.具体如下: HttpWebRequest类主要利用HTTP 协议和服务器交互,通常是通过 GET 和 POST 两种方式来对数据进行获取和提交.下面对这两种方式进行一下说明: GET 方式: GET 方式通过在网络地址附加参数来完成数据的提交,比如在地址 http://www.jb51.net/?hl=zh-CN 中,前面部分 http://www.jb51.net表示数据提交的网址,后面部分 hl=zh-CN 表示附

  • C#使用IHttpModule接口修改http输出的方法

    本文实例讲述了C#使用IHttpModule接口修改http输出的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.Linq; using System.Web; //修改http输出先建个类这个类作为模块mould就要实现接口 namespace 修改_HTTP_输出 { public class MyMould:IHttpModule //实现接口 { //点击实现接口就会

  • 基于C#实现一个最简单的HTTP服务器实例

    本文详细分析了基于C#实现一个最简单的HTTP服务器的方法.分享给大家供大家参考.具体如下: 一.简介 本文用C#实现了一个最简单的HTTP服务器类,你可以将它嵌入到自己的项目中,或者也可以阅读代码来学习关于HTTP协议的知识. 二.背景 高性能的WEB应用一般都架设在强大的WEB服务器上,例如IIS, Apache, 和Tomcat.然而,HTML是非常灵活的UI标记语言,也就是说任何应用和后端服务都可以提供HTML的生成支持.在这个小小的例子中,像IIS,. Apache这样的服务器消耗的资

  • C#中使用HttpDownLoadHelper下载文件实例

    本文实例讲述了C#使用HttpDownLoadHelper下载文件的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; using System.Threading; namespace ProjectWenDangManage.Framework {     /// <sum

  • C#实现HTTP协议迷你服务器(两种方法)

    本文以两种稍微有差别的方式用C#语言实现HTTP协议的服务器类,之所以写这些,也是为了自己能更深刻了解HTTP底层运作. 要完成高性能的Web服务功能,通常都是需要写入到服务,如IIS,Apache Tomcat,但是众所周知的Web服务器配置的复杂性,如果我们只是需要一些简单的功能,安装这些组件看起来就没多大必要.我们需要的是一个简单的HTTP类,可以很容易地嵌入到简单的Web请求的服务,加到自己的程序里. 实现方法一: .net框架下有一个简单但很强大的类HttpListener.这个类几行

  • C#模拟Http与Https请求框架类实例

    本文实例讲述了C#模拟Http与Https请求框架类.分享给大家供大家参考. 具体实现方法如下: 复制代码 代码如下: using System.Text; using System.Net; using System.IO; using System.Text.RegularExpressions; using System.Security.Cryptography.X509Certificates; using System.Net.Security; namespace WebReque

  • C#发送HttpPost请求来调用WebService的方法

    复制代码 代码如下: void UpdateContactSign()        {           string ServerPage ="http://localhost/WebService/MyService.asmx";            try            {                //ServerPage += "?op=TangramAction";                ServerPage += "

  • C#自定义HttpFilter模块完善实例

    本文实例讲述了C#自定义HttpFilter模块完善的方法,分享给大家供大家参考.具体实现方法如下: 一.背景 近期由于要针对项目做用户操作日志,但不想在每个方法里去增加代码,写入用户日志.因为这样具体的方法违背职责单一的原则,若后期日志内容格式发生变更,或其他什么需求,该方法代码主要一变在变,故使用HttpModule模块来完成此功能,感兴趣的朋友可以参考:关于HttpHandler与HttpModule的理解和应用方法 经过实际运用与完善,现在可以再次总结下. 二.拦截时机 现在的版本中,拦

  • 详解Python import方法引入模块的实例

    详解Python import方法引入模块的实例 在Python用import或者from-import或者from-import-as-来导入相应的模块,作用和使用方法与C语言的include头文件类似.其实就是引入某些成熟的函数库和成熟的方法,避免重复造轮子,提高开发速度. python的import方法可以引入系统的模块,也可以引入我们自己写好的共用模块,这点和PHP非常相似,但是它们的具体细节还不是很一样.因为php是在引入的时候指明引入文件的具体路径,而python中不能够写文件路径进

  • JS仿iGoogle自定义首页模块拖拽特效的方法

    本文实例讲述了JS仿iGoogle自定义首页模块拖拽特效的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999

  • Android自定义竖排TextView实现实例

    Android自定义竖排TextView实现实例 前言: 之前做联系人模块的时候遇到一个左侧索引控件,里面的字符都是竖直方向上排列的.当时这个控件是用一个图片代替的.现在想来如果索引的字符变更了,那么就得重新更换图片了,感觉很麻烦.今天通过一个自定义TextView实现类似的功能.先上效果图: 汉字和英文字符都可以竖直排列.结合联系人界面,可以将左侧的索引改成联系人的姓氏. 上代码: 测试用的Activity. public class MainActivity extends Activity

  • python定时任务 sched模块用法实例

    这篇文章主要介绍了python定时任务 sched模块用法实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 通过sched模块可以实现通过自定义时间,自定义函数,自定义优先级来执行函数. schedule = sched.scheduler( time.time,time.sleep) schedule是一个对象,叫什么名字都可以. schedule.enter(delay,priority,action,arguments) delay:第

  • Node.js API详解之 repl模块用法实例分析

    本文实例讲述了Node.js API详解之 repl模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 repl repl(交互式解释器) 模块提供了一种"读取-求值-输出"循环(REPL)的实现,它可作为一个独立的程序或嵌入到其他应用中. 可以通过以下方式使用它: const repl = require('repl'); Node.js 自身也使用 repl 模块为执行 JavaScript 代码提供交互接口. 可以通过不带任何参数(或使用 -i 参数)地执行

  • Flask中sqlalchemy模块的实例用法

    一.安装 $ pip install flask-sqlalchemy 二.配置 配置选项列表 : SQLALCHEMY_NATIVE_UNICODE | 可以用于显式禁用原生 unicode 支持.当使用 不合适的指定无编码的数据库默认值时,这对于 一些数据库适配器是必须的(比如 Ubuntu 上某些版本的 PostgreSQL ).| | SQLALCHEMY_POOL_SIZE | 数据库连接池的大小.默认是引擎默认值(通常 是 5 ) | | SQLALCHEMY_POOL_TIMEOU

  • matplotlib绘制鼠标的十字光标的实现(自定义方式,官方实例)

    matplotlib在widgets模块提供Cursor类用于支持十字光标的生成.另外官方还提供了自定义十字光标的实例. widgets模块Cursor类源码 class Cursor(AxesWidget): """ A crosshair cursor that spans the axes and moves with mouse cursor. For the cursor to remain responsive you must keep a reference

  • 举例说明自定义C++异常处理的实例

    举例说明自定义C++异常处理的实例 例1:自定义一个继承自excepton的异常类myException C++标准中,定义在<stdexcept>中的任何异常类都派生自exception Class,本例也只是简单地由exception继承,在try段抛出一个异常并捕捉.代码如下: /*++ test.cpp version:1.0 decript:define a exception class named myException derived from base class excep

  • Spark自定义累加器的使用实例详解

    累加器(accumulator)是Spark中提供的一种分布式的变量机制,其原理类似于mapreduce,即分布式的改变,然后聚合这些改变.累加器的一个常见用途是在调试时对作业执行过程中的事件进行计数. 累加器简单使用 Spark内置的提供了Long和Double类型的累加器.下面是一个简单的使用示例,在这个例子中我们在过滤掉RDD中奇数的同时进行计数,最后计算剩下整数的和. val sparkConf = new SparkConf().setAppName("Test").setM

随机推荐