下面我们继续之前的ASP.NET MVC学习之过滤器篇(1)进行学习。

3.动作过滤器

顾名思义,这个过滤器就是在动作方法调用前与调用后响应的。我们可以在调用前更改实际调用的动作,也可以在动作调用完成之后更改最终返回的结果,当然很多人一定不太明白这个到底可以干什么,

下面我们举一个比较实际的例子:

相信理解过网站的安全的一定知道跨站请求(CSRF具体可以自行百度,这里我就不去解释了),当然也有解决方案,那就是给页面中增加一个识别码,当页面进行POST请求时,首先判断识别码是否正确,

如果正确则继续进行操作。并且在执行完成之后重新分配一个新的识别码(当然也可以只用一个识别码直到会话结束),这样就可以加大进行跨站请求的难度。而动作过滤器的所处的生命周期刚好符合,

下面我们就开始编写这个过滤器类。

首先我们在Filter文件夹中新建一个ViewMacFilterAttribute类,并且这个类需要继承FilterAttribute,同时还要实现IActionFilter接口:

 namespace MvcStudy.Filter
{
public class ViewMacFilterAttribute : FilterAttribute , IActionFilter
{ public void OnActionExecuted(ActionExecutedContext filterContext)
{
string viewMac = Guid.NewGuid().ToString();
filterContext.HttpContext.Session["vmac"] = viewMac;
filterContext.Controller.ViewBag.ViewMac = viewMac;
} public void OnActionExecuting(ActionExecutingContext filterContext)
{
object viewMac = filterContext.HttpContext.Session["vmac"];
string strMac = filterContext.HttpContext.Request.Form["viewMac"];
filterContext.Result = new HttpNotFoundResult();
if (viewMac != null && strMac != null)
{
if (viewMac.Equals(strMac))
{
filterContext.Result = null;
}
}
}
}
}

这里我们实现了IActionFilter 接口中的OnActionExecuted方法和OnActionExecuting方法,它们分别对应着动作执行结束和动作执行前,通过OnActionExecuting中的代码,我们可以清楚的看到我们首先从Session中获取识别码,然后又从页面中的表单获取客户端的识别码,

这里我们可以看到我们首先默认返回的结果是404,如果比配成功则将Result设置为NULL,如果ResultNULL是会正常调用对应的活动的。接着就是OnActionExecuted方法中的功能,仅仅只是重新分配一个识别码,并且保存进Session中。

注:这种方式会导致一个页面进行了POST请求之后,识别码变换之后。其他页面的提交功能就会失败,所以还要加以ajax去辅助,或者就是一个用户会话分配一个识别码,直到用户会话结束。

有了这个过滤器之后我们就可以进行实际的测试了,首先我们先在Home控制器中写入如下代码,并在Views/Home下新建Index.cshtml以及List.cshtml,其中List.cshtml中的页面如下所示:

 @{
ViewBag.Title = "List";
} <h2>List</h2>
@using(Html.BeginForm())
{
@Html.Hidden("viewMac", (string)ViewBag.ViewMac)
<input type="submit" value="submit" />
}

然后就是Home控制器:

 namespace MvcStudy.Controllers
{
public class HomeController : Controller
{
[MobilResultFilter]
public ActionResult Index()
{ return View();
} public ActionResult List()
{
string viewMac = Guid.NewGuid().ToString();
Session["vmac"] = viewMac;
ViewBag.ViewMac = viewMac;
return View();
} [ViewMacFilter]
[HttpPost]
public ActionResult List(string action)
{
return View();
}
}
}

这里我们可以看到默认的List动作中会分配识别码,而POST请求对应的List方法加上了我们之前写的过滤器,现在我们可以先打开这页面然后提交,会发现只是刷新了,接着我们把List.cshtml中的@Html.Hidden("viewMac", (string)ViewBag.ViewMac) 删去,重新进入这个页面,在点击提交,就能发现出现了404的错误,这样我们就可以防止跨站请求了。

4.结果过滤器

上面讲的仅仅只是动作过滤器,在动作执行完成之后都会返回一个结果,即使到这里了,我们依然可以修改最终的结果,之前在讲路由器部分的时候,曾今举过一个例子,就是根据UserAgent去判断是否为手机,并跳转到对应的控制器下的对应动作。但是很多时候手机页面与PC页面的数据都是一摸一样的,如果像之前那样就会导致重复代码的出现,那么我们就可以利用结果过滤器,在动作执行完成之后,判断是否为手机从而改变最后呈现的视图。

下面我们继续在Filter文件夹下新建一个MobilResultFilterAttribute类,并且这个类依然要继承FilterAttribute,同时还要实现IResultFilter接口,实现代码如下:

 namespace MvcStudy.Filter
{
public class MobilResultFilterAttribute : FilterAttribute , IResultFilter
{ public void OnResultExecuted(ResultExecutedContext filterContext)
{ } public void OnResultExecuting(ResultExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.UserAgent.Contains("Android"))
{
((ViewResult)filterContext.Result).ViewName = "List";
}
}
}
}

为了能够以最简单的方式说明,所以笔者仅仅判断了UserAgent是否含有Android,如果含有就修改最终的视图名称,这样我们就可以通过注解属性的方式实现,而不需要放在控制器中或者在动作中进行判断。

下面我们依然要以测试为主,我们还是使用Home控制器:

         [MobilResultFilter]
public ActionResult Index()
{ return View();
}

首先我们通过正常的方式访问,然后让Chrome模拟手机进行访问,这个时候我们就可以发现最终的页面会是List而不是Index了

上面的3和4我们都要自己去继承对应的接口,同时还要继承FilterAttribute类,其实ASP.NET MVC中已经为我们写好了一个默认的类,就是ActionFilterAttribute,我们源码中的定义:

 public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IresultFilter

它已经继承了FilterAttribute,同时也实现了IActionFilterIResultFilter接口,这样可以可以少记一些关键的名称。

5.无注解属性过滤与全局过滤器

通过之前的几点,大家可以发现我们都是使用注解属性的方式进行过滤,其他我们也可以直接在控制器中实现,比如下面的代码:

 namespace MvcStudy.Controllers
{
public class HomeController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
} protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
} protected override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
} protected override void OnException(ExceptionContext filterContext)
{
base.OnException(filterContext);
} protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
} protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
base.OnResultExecuting(filterContext);
} [MobilResultFilter]
public ActionResult Index()
{ return View();
} public ActionResult List()
{
string viewMac = Guid.NewGuid().ToString();
Session["vmac"] = viewMac;
ViewBag.ViewMac = viewMac;
return View();
} [ViewMacFilter]
[HttpPost]
public ActionResult List(string action)
{
return View();
}
}
}

我们可以看到控制器中其实已经实现了上面所有的接口,当然我建议使用注解属性,这样可以尽量的分离关注点,控制器的代码会很杂乱。

关于全局过滤器,唯一的区别就是我们需要在FilterConfig类中的RegisterGlobalFilters方法中使用filters.add增加上面我们所写的过滤器即可,并没有太大的特殊(FilterConfig在App_Start,在ASP.NET MVC 4以上才有这个文件

6.内建过滤器

关于内建过滤器我们这里就列举出来以下,因为上手很快。

RequireHttps   强迫对动作使用Https协议

OutputCache   缓存一个动作方法的输出

ValidateInput   与安全有关的授权过滤器

AsyncTimeout/NoAsyncTimeout  用于异步控制器

ChildActionOnly 只能作为子操作进行调用

到此为止关于过滤器部分就结束了。

下面是之前的前面ASP.NET MVC学习连载:

ASP.NET MVC学习之路由器篇(1)

ASP.NET MVC学习之路由器篇(2)

ASP.NET MVC学习之路由器篇(3)

ASP.NET MVC学习之控制器篇

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

ASP.NET MVC学习之过滤器篇(2)的更多相关文章

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

    一.前言 继前面四篇ASP.NET MVC的随笔,我们继续向下学习.上一节我们学习了关于控制器的使用,本节我们将要学习如何使用过滤器控制用户访问页面. 二.正文 以下的示例建立在ASP.NET MVC ...

  2. ASP.NET MVC学习之控制器篇扩展性

    原文:ASP.NET MVC学习之控制器篇扩展性 一.前言 在之前的一篇随笔中已经讲述过控制器,而今天的随笔是作为之前的扩展. 二.正文 1.自定义动作方法 相信大家在开发过程一定会遇到动作方法的重名 ...

  3. ASP.NET MVC学习之控制器篇

    一.前言 许久之后终于可以继续我的ASP.NET MVC连载了,之前我们全面的讲述了路由相关的知识,下面我们将开始控制器和动作的讲解. ASP.NET MVC学习之路由篇幅(1) ASP.NET MV ...

  4. ASP.NET MVC学习之视图篇(2)

    继ASP.NET MVC学习之视图(1)学习 4.HTML辅助器 虽然在ASP.NET MVC中我们已经摆脱了ASP.NET的控件,但是对于页面中需要循环标签的情况依然还是存在,可能很多人认为用for ...

  5. ASP.NET MVC学习之控制器篇(二)

    原文链接:http://www.asp.net/learn/mvc/ 这篇教程探索了ASP.NET MVC控制器(controller).控制器动作(controller action)和动作结果(a ...

  6. ASP.NET MVC学习之视图篇(1)

    一.前言 不知道还有多少读者从第一篇开始一直学习到如今,笔者也会一直坚持将ASP.NET MVC的学习完美的结束掉,然后开始写如何配合其他框架使用ASP.NET MVC的随笔.当然笔者后面的随笔如果没 ...

  7. ASP.NET MVC学习之路由篇(3)

    根据路由输出链接 既然是网站开发自然少不了链接,我们已经学会了强大的路由,但是还缺少一步就是能够将这些路由的路径输出到页面,下面我们就开始学习如何输出路由路径. 首先我们的路由注册部分如下所示: 1 ...

  8. ASP.NET MVC学习之路由篇(2)

    7.解决与物理路径的冲突 当发送一个请求至ASP.NET MVC时,其实会检查网站中存不存在这个请求的物理路径文件,如果存在的话,就会直接将这个物理文件返回.但是有时候我们需要它执行控制器的某个方法, ...

  9. ASP.NET MVC学习之路由篇(1)

    1.基本路由 RouteConfig.cs: 1 public class RouteConfig 2 { 3 public static void RegisterRoutes(RouteColle ...

随机推荐

  1. ArcGIS生成根据点图层生成等值面并减小栅格锯齿的操作步骤

    一.打开ArcMAP并加载上相应的点图层和边界面图层 二.ArcToolbox--Spatial Analyst工具--差值分析--克里金法(根据不同的情况选择不同的算法,这次的处理实际上使用的是样条 ...

  2. TabCtrl的基本用法

    MFC TabCtrl控件的使用方法及思路 1.建立基于Dialog的应用程序 2.添加TabCtrl控件,并关联变量 3.建立TabCtrl中存放的Dialog子对话框若干,并关联类 4.在Tabc ...

  3. tcl使用笔记

    tcl语法网站:http://www.tcl.tk/man/tcl8.5/TclCmd/contents.htm 1)拷贝文件 set PRJ_HDL_DIR "../prj/hdl&quo ...

  4. 【过程改进】10分钟进阶Nuget

    目录 nuget初识 nuget本地包 nuget解决依赖冲突 nuget是什么 .net版的maven(java)? 如果你用过windows的chocolatey,mac的homebrew或许更容 ...

  5. CSS背景图拉伸自适应尺寸,全浏览器兼容

    突然有人问我这个问题,说网上CSS filter的方法在非IE浏览器下不奏效.思考之后,问题之外让我感慨万千啊,很多我们所谓的难题,都会随着时代的发展迎刃而解,或被新的问题所取代. 当CSS背景图片拉 ...

  6. 循序渐进Python3(三) -- 1 -- 内置函数

    对函数有了一定了解之后,我们来看看Python的内置函数.下图是Python所有的内置函数,共68个.

  7. cmd.ExecuteReader(CommandBehavior.CloseConnection)

    有些开发人员坚持认为,如果您设置 CommandBehavior.CloseConnection 选项,则 DataReader 及其相关联的连接会在 DataReader 完成数据读取时自动关闭.这 ...

  8. AngularJS学习---Routing(路由) & Multiple Views(多个视图) step 7

    1.切换分支到step7,并启动项目 git checkout step- npm start 2.需求: 在步骤7之前,应用只给我们的用户提供了一个简单的界面(一张所有手机的列表),并且所有的模板代 ...

  9. python py生成为pyc文件

    生成单个pyc文件 python就是个好东西,它提供了内置的类库来实现把py文件编译为pyc文件,这个模块就是 py_compile 模块. 使用方法非常简单,如下所示,直接在idle中,就可以把一个 ...

  10. SublimeText为啥选择Python开发extension

    真正优秀的软件是靠优秀的程序员开发出来的,反过来也一样,优秀的语言,平台,工具只有在优秀的程序员的手中才能显现出它的威力. 比如,Jon Skinner开发的SublimeText.桌面应用一般支持二 ...