1. ホーム
  2. Web プログラミング
  3. ASP.NET

ASP.NET Core MVC フィルタ

2022-01-14 23:29:07

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 を実装しています。 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 インターフェースは、IFilter インスタンスを作成するためのメソッドを公開しています。その中で 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.
  • のクラスフィルタです。 [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 } } }
  • グローバルフィルター {コード
  • {について コントローラフィルタ {コード

   スコープに基づくデフォルトの並び順を変更するには SampleActionFilter 属性で指定します。例えば TypeFilter をメソッドレベル属性に設定します。

ServiceFilter

この場合、0 より小さい値を指定すると、 このフィルタがグローバルフィルタとクラスレベルフィルタの前に 実行されるようになります: このフィルタがグローバルフィルタとクラスレベルフィルタの前に 実行されるようにするには、以下のようにします。

  • コントローラの IFilterFactory
  • のメソッドフィルタ {コード {を使用します。
  • のグローバルフィルターは IFilter
  • のクラスフィルタです。 IFilterFactory
  • のクラスフィルタです。 IFilterFactory
  • グローバルフィルター {コード
  • {について コントローラフィルタ {コード {を使用します。 メソッドフィルター {コード

{{コード このクラスのメソッドは、すべてのフィルタの前後で常に実行されます。これらのメソッドは CreateInstance インスタンスになります。また、IFilter のソートアルゴリズムに参加することもない。

 3. ミドルウェアの比較

  一般に、フィルタはビジネスとアプリケーションの間の横断的な問題を処理するために使われ、その使い方や機能はミドルウェアによく似ていますが、フィルタによって作用範囲を狭め、ビューの前やモデルバインディングの後など、アプリケーションにとって意味のある場所に挿入することが可能です。フィルタは MVC の一部であり、そのコンテキストとコンストラクタにアクセスすることができます。例えば、要求されたモデルの検証がエラーを発生させた場合に、ミドルウェアがそれを検知してそれに応じて応答することは困難です。

この時点では、この記事の {コード についての詳しい情報は、フィルターについての記事で終わりです。 IFilterFactory