ASP.NET Core MVC フィルタ
I. フィルタの仕組み
異なるフィルタータイプは、パイプラインの異なるステージで実行されるため、それらに付随する独自のシナリオが存在します。作成されるフィルタータイプは、実行されるタスクと、実行されるリクエストのパイプライン上の位置によって選択されます。フィルタはMVCの操作呼び出しパイプライン(フィルタパイプラインと呼ばれることもあります)で実行され、MVCで実行する操作を選択した後、その操作に対するフィルタが実行されます に示すように
パイプライン内の異なる場所で、異なるフィルターが実行されます。認証フィルタのようなフィルタは、パイプラインの前方の位置でのみ実行されます。Action フィルタのような他のフィルタは、以下に示すように、パイプラインの残りの実行の前でも後でも実行することができます。
1. フィルター選択
認可フィルターは、現在要求しているユーザーが認可されているかどうかを判断するために使用されます。
リソースフィルターは、承認後にリクエストを処理する最初のフィルターであり、フィルターパイプラインを離れるときにリクエストに触れる最後のフィルターです。特に、キャッシュを実装したり、フィルタパイプラインを短絡させたりする際に、 パフォーマンスの面で役に立ちます。
オペレーションフィルターは、個々のオペレーションメソッドの呼び出しをラップし、オペレーションに渡されるパラメーターと、オペレーションから返されるオペレーション結果を扱うことができます。
例外フィルターは、MVCアプリケーションで処理されなかった例外にグローバルポリシーを適用するために使用されます。
結果フィルタは、1つの操作結果の実行をラップし、操作の実行に成功した場合に可能な限り実行する。ビューを中心としたロジックの実行や、プログラムの実行を整形するのに適しているはずです。
2. フィルタの実装
すべてのフィルタは、異なるインタフェース定義により、同期および非同期の実装をサポートすることができます。実行されるタスクの種類に応じて、同期または非同期の実装が選択されます。フレームワークの観点からは、これらは互換性があります。
同期フィルタでは
OnStageExecuting
と
OnStageExecuted
メソッドを使用します(例外もあります)。
OnStageExecuting
メソッドは、イベントパイプラインステージの前にステージ名で呼び出されるのに対し
OnStageExecuted
3. フィルタースコープ
フィルターには3段階のスコープがあります。特定の操作に対して特性を使用することができます ( {コード ) を特定のアクションで実行します。また、コントローラ上でフィルタを属性として使用し、コントローラ内のすべてのアクションにその効果を適用させることも可能です。あるいは、グローバルフィルタを登録して、 MVC アプリケーション全体のすべてのアクションに適用させることもできます。
グローバルフィルタを使用する場合、MVCの設定に
public class SampleActionFilter:IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// what to do before the action is executed
}
public void OnActionExecuted(ActionExecutedContext context)
{
//ActionExecuted does something after execution
}
}
で
OnActionExecutionAsync
メソッドが追加されます。
OnActionExecutionAsync
フィルターは、タイプ別またはインスタンス別に追加することができます。インスタンスで追加した場合は、各リクエストでそのインスタンスが使用されます。タイプで追加した場合は、リクエストのたびにインスタンスが作成され、 そのコンストラクタの依存関係はすべて DI で設定されます。
また、フィルターインターフェースの実装を機能として利用することも非常に便利です。フィルター機能は、コントローラや操作メソッドに適用することができます。フレームワークには、機能ベースのフィルタが組み込まれており、それを継承したり、追加でカスタマイズしたりすることができます。たとえば、次のようなフィルタを継承しています。
ActionExecutionDelegate
をオーバーライドします。
{コード
メソッド (レスポンスにメッセージヘッダを追加する) を使用します。
public class SampleAsyncActionFilter: IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// what to do before the action is executed
await next();
// what to do after the action is executed
}
}
機能では、以下のようなパラメータをフィルターに渡すことができます。 コントローラやアクションにこの機能を追加し、そのために必要なHTTPヘッダの名前と値を以下のように指定します。
[AddHeader("Author", "Ruby Lu")] を追加します。 public class HomeController : コントローラ { }
以下のタイプのフィルター・インターフェースは、対応する機能の実装としてカスタマイズすることができます。
- {コード
- {{コード
- {{コード
- {{コード
- {{コード
- {{コード
4. キャンセルとショート
のコンテキストパラメータにResultプロパティを設定することで、フィルタパイプラインの任意の位置でパイプラインを短絡させることができます。{コード
{{コード
Attribute
{{コード
{{コード
Startup
{{コード
{{コード
{{コード
{{コード
{{コード とすると、クラスや操作方法の中で、いくつかの方法で使用することができます。
ConfigureServices
- {{コード
- {{コード 機能の実装
services.AddMvc(options =>
{
options.Filters.Add(typeof(SampleActionFilter));//pass type
Options.Filters.Add(new SampleActionFilter());//register the instance
SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
は、サービスを使用してDIからその依存関係のインスタンスを作成します。一方、ServiceFilterは、DIからフィルターのインスタンスを取得します。
以下はその例です。
ResultFilterAttribute
サービスフィルター
初
OnResultExecuting
で
public class AddHeaderAttribute: ResultFilterAttribute
{
private readonly string _name;
private readonly string _value;
public AddHeaderAttribute(string name, string value)
{
_name = name;
_value = value;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
_name,new string[] { _value });
base.OnResultExecuting(context);
}
}
タイプ
{{コード
{アドヘッダーフィルタウィズディ
();
では、使ってください。
ActionFilterAttribute
ExceptionFilterAttribute
ResultFilterAttribute
FormatFilterAttribute
ServiceFilterAttribute
TypeFilterAttribute
ShortCircuitingResourceFilter
を実装しています。
インターフェースは、IFilter インスタンスを作成するためのメソッドを公開しています。その中で
public class ShortCircuitingResourceFilter:Attribute,IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.Result = new ContentResult() {
Content = "short-circuit"
};
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
II. Configuring filters
The global filter in the
Startup
in Startup /code. Feature-based filters that do not require any dependencies can simply inherit a feature type corresponding to a pre-existing filter. If you want to create a filter that is not globally scoped but requires dependencies from dependency injection, then add to them the
ServiceFilterAttribute
or
TypeFilterAttribute
attribute, so that it can be used for controllers or actions.
1. Dependency injection
The constructor of a filter implemented as a feature and added directly to a controller or operation must not be supplied with dependencies by dependency injection. The reason for this is that the constructor parameters required by the feature must be provided directly by the use. This is a limitation of the feature prototype mechanism.
If a filter requires a dependency from a DI, the
then it can be used in a class or operation method in several ways.
ServiceFilterAttribute
TypeFilterAttribute
IFilterFactory
TypeFilter
で
{{コード
のインターフェイスを使用します。
ServiceFilter
メソッドを実装し、サービスコンテナから指定された型を読み込む。
ConfigureServices
と非常によく似ています。
{コード
(これも IFilterFactory インターフェイスを実装しています) が、DI コンテナから直接型を解決するのではなく、DI コンテナから直接型を解決します。
AddHeaderFilterWithDI
を使用して型をインスタンス化します。
この違いにより
services.AddScoped
参照される型は、使用前にコンテナに登録する必要はありませんが、コンテナによって依存関係が入力されることに変わりはありません。さらに、TypeFilterAttribute は、オプションでその型のコンストラクタ引数を受け付けることができる。
以下は
[ServiceFilter(typeof(AddHeaderFilterWithDI))]
public IActionResult Index()
{
}
デモを行います。
ServiceFilterAttribute
パラメータを必要としないシンプルなフィルターで、DIを介して依存関係を入力する必要があるコンストラクタがある場合、それを継承することができます。
IFilterFactory
独自の名前付き属性クラスとメソッドを使用できるようにする(代わりに
ServiceFilterAttribute
))]). 次のフィルターは、これを実現する方法を示しています。
IFilterFactory
このフィルターは、[
CreateInstance
という構文ではなく、[
TypeFilterAttribute
を実装していること。
ServiceFilterAttribute
インターフェイスを使用します。そのため、クラスやメソッドにフィルタ機能を適用する際に、フィルタの実行順序を指定することができます。デフォルトでは、すべての組み込みフィルタはOrderプロパティが0なので、範囲がセパレータとして使用され、決定要因となります(Orderが0に設定されていない限り)。
の各フィルタは
Microsoft.Extensions.DependencyInjection.ObjectFactory
基底クラスには
TypeFilterAttribute
と
TypeFilterAttribute
メソッドがあります。これらのメソッドは与えられたアクションのためのフィルタをラップし、それぞれ最初と最後に実行されます。どのフィルターにも Order sum が設定されていないと仮定すると、純粋にスコープに基づいた順番は次のようになります。
- コントローラの
[TypeFilter(typeof(AddHeaderAttribute),Arguments =new object[] { "Author","Ruby" })] public IActionResult Index() { return View(); }
{を使用します。
のグローバルフィルタを使用します。
- のクラスフィルタです。
[TypeFilterAttribute(typeof(FilterType
{について
メソッドフィルター
{コード
{を使用します。
{について
のメソッドフィルタ
{コード
{を使用します。
- のクラスフィルタです。
public class SampleActionFilterAttribute:TypeFilterAttribute { public SampleActionFilterAttribute() : base(typeof(SampleActionFilterImpl)) { } private class SampleActionFilterImpl:IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { // what to do before the action is executed } public void OnActionExecuted(ActionExecutedContext context) { //ActionExecuted does something after execution } } }
- グローバルフィルター {コード {について コントローラフィルタ {コード
TypeFilterAttribute.
スコープに基づくデフォルトの並び順を変更するには
SampleActionFilter
属性で指定します。例えば
TypeFilter
をメソッドレベル属性に設定します。
ServiceFilter
この場合、0 より小さい値を指定すると、 このフィルタがグローバルフィルタとクラスレベルフィルタの前に 実行されるようになります: このフィルタがグローバルフィルタとクラスレベルフィルタの前に 実行されるようにするには、以下のようにします。
- コントローラの
IFilterFactory
- のメソッドフィルタ {コード {を使用します。
- のグローバルフィルターは
IFilter
- のクラスフィルタです。
IFilterFactory
- のクラスフィルタです。
IFilterFactory
- グローバルフィルター {コード {について コントローラフィルタ {コード {を使用します。 メソッドフィルター {コード
{{コード
このクラスのメソッドは、すべてのフィルタの前後で常に実行されます。これらのメソッドは
CreateInstance
インスタンスになります。また、IFilter のソートアルゴリズムに参加することもない。
3. ミドルウェアの比較
一般に、フィルタはビジネスとアプリケーションの間の横断的な問題を処理するために使われ、その使い方や機能はミドルウェアによく似ていますが、フィルタによって作用範囲を狭め、ビューの前やモデルバインディングの後など、アプリケーションにとって意味のある場所に挿入することが可能です。フィルタは MVC の一部であり、そのコンテキストとコンストラクタにアクセスすることができます。例えば、要求されたモデルの検証がエラーを発生させた場合に、ミドルウェアがそれを検知してそれに応じて応答することは困難です。
この時点では、この記事の
{コード
についての詳しい情報は、フィルターについての記事で終わりです。
IFilterFactory
関連
-
NET 6の新しい設定オブジェクトConfigurationManagerの紹介
-
ASP.NET Core 6で依存関係を解決する3つの方法
-
NET6新機能 - 暗黙の名前空間参照
-
.NET Coreでオブジェクトプールを使用する
-
NET6新機能 新構造体の最適化
-
NETガベージコレクション GC診断ツール dotnet-gcmon 使用方法
-
swagger uiをasp.net coreに統合する原理
-
Net Core HttpClient処理 レスポンス圧縮の詳細
-
ネットパフォーマンスチューニング - ArrayPool 詳細
-
ASP.NETでのRadioButton(ラジオボタン)の使用について
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ASP.NET CoreでURLを設定する5つの方法
-
30分でわかるコング経由の.NETゲートウェイ
-
.NET開発サーバー アプリケーション管理ツール
-
ASP.NET CoreでCAPの取引詳細を自動で有効にする
-
再起動を伴わないNET5の設定変更は自動的に反映される
-
NET 6 の今後の新機能 暗黙の名前空間参照
-
ASP.NET Coreで複数のサービス実装クラスをインジェクトする方法
-
asp.net core3.1 cookieとjwtのハイブリッド認証による多様な認証ソリューションの実現
-
名前 'xxx' が現在のコンテキストに存在しない エラー解決方法の1つ
-
Application_End イベントをブロックする解決策