ControllerのFilterの詳細
前言
前の2篇の书くのは比较的に简単で、ちょうどこのシリーズを书く时私の向いている対象はちょうどAspに接触するのです.Net MVCの友達なので、できるだけ簡単に書きます.だから書く技術の含有量はあまりありません.これらの技術をまとめて、簡単な方法でもっと多くの人によく受け入れてもらうのが私がずっと努力してきた方向です.あとはちょっと複雑なアイテムが!一緒に楽しみましょう!
ここではAspについてご紹介します.Net MVC 3 Filterのいくつかの使い方.グローバルFilter、ActionFilterなどの一般的な使い方を理解し、学ぶことができます.
第一節:Filter知識備蓄
プロジェクトの大きい点はいつも関連するAOPが面と向かっているコンポーネントがありますが、MVC(特に:Asp.Net MVC、以下同じ)プロジェクトの中でActionは実行前または実行後に特殊な操作(例えば認証、ログ、異常、行為の切り取りなど)をしたいと思っています.MVC開発者にこの重複したコードに関心を持って書かせたくないので、AOP切り取りで実現することができます.MVCプロジェクトでは、複雑なAOPを自分で実現することなく、提供されているFilterの特性を直接使用して解決することができます.
Asp.Net MVCには、以下のデフォルトのFilterがあります.
Filter Type
実装インタフェース
じっこうじかん
Default Implementation
Authorization filter
IAuthorizationFilter
すべてのFilterとActionが実行される前に実行
AuthorizeAttribute
Action filter
IActionFilter
アクション実行の前後でそれぞれ実行されます.
ActionFilterAttribute
Result filter
IResultFilter
アクションResultの実行後と実行前
ResultFilterAttribute
Exception filter
IExceptionFilter
filter、またはaction method、またはaction resultが異常を投げ出した場合にのみ実行します.
HandleErrorAttribute
気をつけてNet MVCが提供するActionFilterAttributeのデフォルトでは、IActionFilterとIresultFilterが実装されています.ActionFilterAttributeはAbstractのタイプなので、そのまま使用することはできません.インスタンス化できないため、次の図にActionFilterAttributeの実装を示すように、継承して使用する必要があります.
(図)
したがって、ActionFilterAttributeを実装し、親を直接書き換える方法は次のとおりです.
public
virtual
void
OnActionExecuted(ActionExecutedContext filterContext);
//
Action
public
virtual
void
OnActionExecuting(ActionExecutingContext filterContext);
//
Action
public
virtual
void
OnResultExecuted(ResultExecutedContext filterContext);
//
Result
public
virtual
void
OnResultExecuting(ResultExecutingContext filterContext);
//
Result
その後、Action、Resultが実行される前に、それぞれいくつかの操作を行うことができます.
第二節:ActionFilter実戦
うそをつかないだけで、今すぐ例を作って実際にプレゼンテーションします.
まず、普通のクラスを追加して、直接コードをつけましょう.
public
class
DemoActionAttributeFilter : ActionFilterAttribute
{
public
string
Message {
get
;
set
; }
public
override
void
OnActionExecuted(ActionExecutedContext filterContext)
{ // Action :After Action Excute xxx
filterContext.HttpContext.Response.Write(
@"
<br />After Action Excute
"
+
"
\t
"
+
Message);
base
.OnActionExecuted(filterContext);
}
public
override
void
OnActionExecuting(ActionExecutingContext filterContext)
{ // Action
filterContext.HttpContext.Response.Write(
@"
<br />Before Action Excute
"
+
"
\t
"
+
Message);
base
.OnActionExecuting(filterContext);
}
public
override
void
OnResultExecuted(ResultExecutedContext filterContext)
{ // Result
filterContext.HttpContext.Response.Write(
@"
<br />After ViewResult Excute
"
+
"
\t
"
+
Message);
base
.OnResultExecuted(filterContext);
}
public
override
void
OnResultExecuting(ResultExecutingContext filterContext)
{ // Result
filterContext.HttpContext.Response.Write(
@"
<br />Before ViewResult Excute
"
+
"
\t
"
+
Message);
base
.OnResultExecuting(filterContext);
}
}
このコードを書き終わったら、Actionに戻り、上のマークをつけて次のようにします.
[DemoActionAttributeFilter(Message
=
"
action
"
)]
public
ActionResult Index()
{ //Action
this
.ControllerContext.HttpContext.Response.Write(
@"
<br />Action Excute
"
);
return
Content(
"
Result Excut!
"
);
}
F 5を実行すると、次のようにページに表示されます.
(図)
最終的には,Action実行の前後に我々の書き換えを実行したDemoActionAttributeFilterメソッド,Result実行の前後にも我々のFilterメソッドを実行した.
全体の実行順序は次のとおりです.
Action実行前:OnActionExecutingメソッドが先に実行→Action実行→OnActionExecutedメソッドが実行→OnResultExecutingメソッドが実行→戻るActionRsultのExcuteResultメソッドが実行→OnResultExecutedが実行されます.最終的に表示される効果は、上図のようになります.
爽やかな感じでしょう!ほほほ!
このラベルをControllerに入力すると、DemoActionAttributeFilterはControllerの下のすべてのActionに作用します.たとえば、次のコードを示します.
[DemoActionAttributeFilter(Message
=
"
controller
"
)]
public
class
HomeController : Controller
{
[DemoActionAttributeFilter(Message
=
"
action
"
)]
public
ActionResult Index()
{
this
.ControllerContext.HttpContext.Response.Write(
@"
<br />Action Excute
"
);
return
Content(
"
<br/>Result Excut!
"
);
}
}
では、表示されたページを実行するとどうなるのでしょうか.ControllerのFilterは実行しますか?そのラベルの役割は2回実行されますか?次に、最後の実行結果を下図に示します.
(図)
結果説明:デフォルトでActionにDemoActionAttributeFilterラベルが付けられた後、Controllerにもこのラベルが付けられていますが、Actionのラベルだけが機能しています.
Indexが実行される場合、Filterのメソッドは一度しか実行されませんが、場合によってはControllerのFilterAttributeにもDemoActionAttributeFilterを一度実行させたい場合があります.
では、Controllerの[D e moActionAttributeFilter(Message=「controller」)も機能させるにはどうすればいいのでしょうか.
答えは、D e moActionAttributeFilterクラスの定義に[AttributeUsage(AttributeTargets.All,AllowMultiple=true)]を付けるだけで、「次のクラスの一番上の赤いフォント部分」、つまり複数回実行できるActionになります.コードは次のとおりです.
[AttributeUsage(AttributeTargets.All, AllowMultiple = true
)]
public
class
DemoActionAttributeFilter : ActionFilterAttribute
{
public
string
Message {
get
;
set
; }
public
override
void
OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write(
@"
<br />After Action Excute
"
+
"
\t
"
+
Message);
base
.OnActionExecuted(filterContext);
}
public
override
void
OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write(
@"
<br />Before Action Excute
"
+
"
\t
"
+
Message);
base
.OnActionExecuting(filterContext);
}
public
override
void
OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write(
@"
<br />After ViewResult Excute
"
+
"
\t
"
+
Message);
base
.OnResultExecuted(filterContext);
}
public
override
void
OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write(
@"
<br />Before ViewResult Excute
"
+
"
\t
"
+
Message);
base
.OnResultExecuting(filterContext);
}
}
次に、図のように効果を実行します.
(図)
我々が見た結果は,Controller上のActionFilterがAction上で打ったタグより先に実行されることである.同じくResultがExcuteResultメソッドを実行する前に、Controller上のFilterタグのOnResultExcuteingメソッドを実行します.
最後の実行手順は、Controller上のOnActionExecution→Action上のOnActionExecution→Action実行→Action上のOnActionExecuted→Controller上のOnActionExecuted
これでActionが実行され、スタックに入る順番が表示されます.後はActionがActionResultに戻ってExecuteResultメソッドを実行しますが、実行する前にFilterを実行します.具体的な手順は次のとおりです.
上→ControllerのOnResultExecutionメソッド→Action上のOnResultExecution→ActionがActionResultに戻ってExecuteResultメソッド→Action上のOnResultExecuted実行→Controller上のOnResultExecuted実行→終了
第三節:Gloable Filter実戦
また次の問題も来て、いくつかの共通の方法はすべてのActionが以下を実行する必要があると思っていますが、すべてのControllerでマークするのはつらいです.幸いAsp.Net MVC 3は素晴らしいものをもたらし、グローバルFilterです.どうやってグローバルFilterを登録しますか?答えはGlobalですasaxで.以下のコードを見てみましょう.上記で定義したD e moActionAttributeFilterをグローバルFilterに登録する方法を見てみましょう.上のコード:
public
class
MvcApplication : System.Web.HttpApplication
{
public
static
void
RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(
new
HandleErrorAttribute());
}
public
static
void
RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(
"
{resource}.axd/{*pathInfo}
"
);
routes.MapRoute(
"
Default
"
,
//
Route name
"
{controller}/{action}/{id}
"
,
//
URL with parameters
new
{ controller
=
"
Home
"
, action
=
"
Index
"
, id
=
UrlParameter.Optional }
//
Parameter defaults
);
}
protected
void
Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalFilters.Filters.Add(
new DemoActionAttributeFilter() { Message = "Gloable"
});
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
普通のMVC 2と0のGlobal.asaxの違いは赤い部分のコードです.コードの中で私が定義したDemoActionAttributeFilterのインスタンスをGlobalFiltersに追加したのを見ました.Filtersコレクションでは、次の文がグローバルFilter:RegisterGlobalFilters(GlobalFilters.Filters)を登録します.
これにより、すべてのActionとResultの実行の前後で、私たちのDemoActionAttributeFilterの書き換え方法が呼び出されます.
私たちのdemoを再実行した結果、次のようになりました.
(図)
グローバルなActionが最初に実行され、Controllerの下のFilterが実行され、最後にActionのラベルが実行されます.もちろんこれは、DemoActionAttributeFilterクラスの定義に[AttributeUsage(AttributeTargets.All,AllowMultiple=true)]というタグを付けた上での前提です.そうでなければ、ActionがControllerと同じラベルを付けた場合、ActionのFilterのみが実行されます.
まとめ
この記事では、Filterの使用方法について概ね理解し、グローバルFilterの使用方法についても理解しています.特に、同じFilterが同じActionに繰り返し作用する場合、複数回実行可能なラベルが設定されていない場合、Action上のFilterのみが実行され、ControllerとグローバルFilterはブロックされますが、設定は複数回実行できます.それはまずグローバルFilterを実行し、次にController、次にAction上のFilterを実行します.
原文:http://www.cnblogs.com/fly_dragon/archive/2011/06/15/2081063.html