Action和Filter
Filter在Asp.net MVC中它只能限制于Action,Controller。 继承于ActionFilterAttribute,且可以覆写如下几个重要方法。
1:void OnActionExecuting(ActionExecutingContext):Action执行前的操作
2:void OnActionExecuted(ActionExecutedContext):Action执行后的操作
3:void OnResultExecuting(ResultExecutingContext):解析ActionResult前执行
4:void OnResultExecuted(ResultExecutedContext):解析ActionResult后执行
系统提供的比较常见的Filter:
1:AcceptVerbs
2:ActionName,上面两个都限制了对Action的访问条件;
3:OutputCache,设置缓存;
4:ValidateInput,增加数据验证。
示例:
1:留言簿列表数据:可以这样写,也可以省略[AcceptVerbs(HttpVerbs.Get )],它是个默认值。这种访问是以链接形式访问。
[AcceptVerbs(HttpVerbs.Get )]
public
ActionResult Index()
{
var models
=
inter.FindAllInfo();
return
View(
"
Index
"
, models);
}
2: 当创建一则留言时:我们要用HttpVerbs.Post方式。此时的Action需要在提交表单后才会执行对应的Action。
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult Create(GuestBookInfo model)
{
try
{
inter.Add(model);
var models
=
inter.FindAllInfo();
TempData[
"
TempData
"
]
=
"
已经成功创建
"
;
return
RedirectToAction(
"
Index
"
);
}
catch
(Exception ex)
{
ModelState.AddModelError(
"
ex
"
,ex);
return
View(model);
}
}
3:ActionNameAttribute的用法,和 AcceptVerbsAttribute 方式差不多,如果不指定ActionName,则系统会默认找名称和方法名相同之处的View。
[ActionName (
"
Edit
"
)]
public
ActionResult Edit(
int
id)
自定义Filter:
这里创建一个没有客户端缓存的NoClientCacheAttribute。需要继承ActionFilterAttribute,且重写OnActionExecuting方法。
public
class
NoClientCacheAttribute : ActionFilterAttribute
{
public
override
void
OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext.Current.Response.CacheControl
=
"
No-Cache
"
;
}
}
应用在Action上,特别简单,像C#中的变通特性用法一样。
[NoClientCache]
public
ActionResult Details(
int
id)
AcceptVerbs的工作机制。
第一:AcceptVerbsAttribute类。它继承了ActionMethodSelectorAttribute,重要的方法是重写了基类的IsValidForRequest方法,这也是起过滤作用的地方。
[AttributeUsage(AttributeTargets.Method, AllowMultiple
=
false
, Inherited
=
true
)]
public
sealed
class
AcceptVerbsAttribute : ActionMethodSelectorAttribute
{
//
Fields
[CompilerGenerated]
private
ICollection
<
string
>
<
Verbs
>
k__BackingField;
//
Methods
public
AcceptVerbsAttribute(HttpVerbs verbs);
public
AcceptVerbsAttribute(
params
string
[] verbs);
private
static
void
AddEntryToList(HttpVerbs verbs, HttpVerbs match, List
<
string
>
verbList,
string
entryText);
internal
static
string
[] EnumToArray(HttpVerbs verbs);
public
override
bool
IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo);
//
Properties
public
ICollection
<
string
>
Verbs { [CompilerGenerated]
get
;
private
[CompilerGenerated]
set
; }
}
第二:IsValidForRequest方法:
public
override
bool
IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
if
(controllerContext
==
null
)
{
throw
new
ArgumentNullException(
"
controllerContext
"
);
}
string
httpMethod
=
controllerContext.HttpContext.Request.HttpMethod;
return
this
.Verbs.Contains
<
string
>
(httpMethod, StringComparer.OrdinalIgnoreCase);
}
我们来看这个方法里有一个this.Verbs,它是一个Request.HttpMethod集合。它是如何初始化的呢?我们来看AcceptVerbsAttribute的构造函数。它会同时调用另外一个构造函数public AcceptVerbsAttribute(params string[] verbs)
public
AcceptVerbsAttribute(HttpVerbs verbs) :
this
(EnumToArray(verbs))
{
}
重要的就是下面的EnumToArray方法和AddEntryToList方法,EnumToArray方法负责收集所有的Request.HttpMethod,AddEntryToList方法是把当前访问类型同所有Request.HttpMethod做比较,取出它们的交集。
internal
static
string
[] EnumToArray(HttpVerbs verbs)
{
List
<
string
>
verbList
=
new
List
<
string
>
();
AddEntryToList(verbs, HttpVerbs.Get, verbList,
"
GET
"
);
AddEntryToList(verbs, HttpVerbs.Post, verbList,
"
POST
"
);
AddEntryToList(verbs, HttpVerbs.Put, verbList,
"
PUT
"
);
AddEntryToList(verbs, HttpVerbs.Delete, verbList,
"
DELETE
"
);
AddEntryToList(verbs, HttpVerbs.Head, verbList,
"
HEAD
"
);
return
verbList.ToArray();
}
private
static
void
AddEntryToList(HttpVerbs verbs, HttpVerbs match, List
<
string
>
verbList,
string
entryText)
{
if
((verbs
&
match)
!=
0
)
{
verbList.Add(entryText);
}
}
再回头看下IsValidForRequest方法,就很容易理解这个Filer为什么能够直到过滤的作用了。
总结:利用Filter的特点,我们可以写一些扩展性的内容,例如:压缩页面的Attibute,无缓存的Attibute等等。
注:本文引用:http://www.rainsts.net/article.asp?id=786