作成者: Rick Anderson
RazorページフィルターIPageFilterは、IAsyncPageFilterRazor ページハンドラーの実行前後にRazorページでコードを実行することを可能にします。 Razor ページ フィルターは、個々のページ ハンドラー メソッドに適用できない点を除き、 ASP.NET Core MVC アクション フィルターと似ています。
Razor ページ フィルター:
- ハンドラー メソッドが選択された後、モデル バインドが発生する前にコードを実行します。
- モデル バインドが完了した後、ハンドラー メソッドの実行前にコードを実行します。
- ハンドラー メソッドの実行後にコードを実行します。
- ページまたはグローバルに実装できます。
- 特定のページ ハンドラー メソッドには適用できません。
- 依存関係挿入 (DI) によってコンストラクターの依存関係を設定できます。 詳細については、「 ServiceFilterAttribute」 と 「TypeFilterAttribute」を参照してください。
ページ コンストラクターとミドルウェアでは、ハンドラー メソッドが実行される前にカスタム コードの実行が有効になりますが、ページ フィルター Razor のみが HttpContext とページへのアクセスを有効にします。 ミドルウェアは HttpContextにアクセスできますが、"ページ コンテキスト" にはアクセスできません。 フィルターには、FilterContextへのアクセスを提供するHttpContext派生パラメーターがあります。 ページ フィルターのサンプルを次に示します。応答にヘッダーを追加する フィルター属性を実装 します。コンストラクターやミドルウェアでは実行できません。 ページのインスタンスとモデルへのアクセスを含むページ コンテキストへのアクセスは、 Razor ページのフィルター、ハンドラー、または本文を実行する場合にのみ使用できます。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
Razor ページ フィルターには、グローバルまたはページ レベルで適用できる次のメソッドが用意されています。
同期メソッド:
- OnPageHandlerSelected : ハンドラー メソッドが選択された後、モデル バインドが発生する前に呼び出されます。
- OnPageHandlerExecuting : モデル バインドが完了した後、ハンドラー メソッドが実行される前に呼び出されます。
- OnPageHandlerExecuted : ハンドラー メソッドの実行後、アクションの結果の前に呼び出されます。
非同期メソッド:
- OnPageHandlerSelectionAsync : ハンドラー メソッドが選択された後、モデル バインドが発生する前に非同期的に呼び出されます。
- OnPageHandlerExecutionAsync : モデル バインドが完了した後、ハンドラー メソッドが呼び出される前に非同期的に呼び出されます。
フィルター インターフェイスの同期と非同期バージョンの両方ではなく、いずれかを実装します。 フレームワークはまず、フィルターが非同期インターフェイスを実装しているかどうかを確認し、実装されている場合はそれを呼び出します。 そうでない場合は、同期インターフェイスのメソッドを呼び出します。 両方のインターフェイスが実装されている場合は、非同期メソッドのみが呼び出されます。 同じ規則がページ内のオーバーライドに適用され、両方ではなく、同期バージョンまたは非同期バージョンのオーバーライドが実装されます。
Razor ページ フィルターをグローバルに実装する
次のコードは、 IAsyncPageFilterを実装します。
public class SampleAsyncPageFilter : IAsyncPageFilter
{
private readonly IConfiguration _config;
public SampleAsyncPageFilter(IConfiguration config)
{
_config = config;
}
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
var key = _config["UserAgentID"];
context.HttpContext.Request.Headers.TryGetValue("user-agent",
out StringValues value);
ProcessUserAgent.Write(context.ActionDescriptor.DisplayName,
"SampleAsyncPageFilter.OnPageHandlerSelectionAsync",
value, key.ToString());
return Task.CompletedTask;
}
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context,
PageHandlerExecutionDelegate next)
{
// Do post work.
await next.Invoke();
}
}
上記のコードでは、 ProcessUserAgent.Write は、ユーザー エージェント文字列で動作するユーザー指定のコードです。
次のコードは、SampleAsyncPageFilter クラスのStartupを有効にします。
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddMvcOptions(options =>
{
options.Filters.Add(new SampleAsyncPageFilter(Configuration));
});
}
次のコードは、AddFolderApplicationModelConventionを呼び出して、SampleAsyncPageFilter 内のページにのみを適用します。
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages(options =>
{
options.Conventions.AddFolderApplicationModelConvention(
"/Movies",
model => model.Filters.Add(new SampleAsyncPageFilter(Configuration)));
});
}
次のコードは、同期 IPageFilterを実装します。
public class SamplePageFilter : IPageFilter
{
private readonly IConfiguration _config;
public SamplePageFilter(IConfiguration config)
{
_config = config;
}
public void OnPageHandlerSelected(PageHandlerSelectedContext context)
{
var key = _config["UserAgentID"];
context.HttpContext.Request.Headers.TryGetValue("user-agent", out StringValues value);
ProcessUserAgent.Write(context.ActionDescriptor.DisplayName,
"SamplePageFilter.OnPageHandlerSelected",
value, key.ToString());
}
public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
{
Debug.WriteLine("Global sync OnPageHandlerExecuting called.");
}
public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
{
Debug.WriteLine("Global sync OnPageHandlerExecuted called.");
}
}
次のコードは、 SamplePageFilterを有効にします。
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddMvcOptions(options =>
{
options.Filters.Add(new SamplePageFilter(Configuration));
});
}
ページ フィルターを実装するためには、フィルターメソッドをオーバーライドしてください。
次のコードは、非同期 Razor ページ フィルターをオーバーライドします。
public class IndexModel : PageModel
{
private readonly IConfiguration _config;
public IndexModel(IConfiguration config)
{
_config = config;
}
public override Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
Debug.WriteLine("/IndexModel OnPageHandlerSelectionAsync");
return Task.CompletedTask;
}
public async override Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context,
PageHandlerExecutionDelegate next)
{
var key = _config["UserAgentID"];
context.HttpContext.Request.Headers.TryGetValue("user-agent", out StringValues value);
ProcessUserAgent.Write(context.ActionDescriptor.DisplayName,
"/IndexModel-OnPageHandlerExecutionAsync",
value, key.ToString());
await next.Invoke();
}
}
フィルター属性を実装する
組み込みの属性ベースのフィルター OnResultExecutionAsync フィルターをサブクラス化できます。 次のフィルターは、応答にヘッダーを追加します。
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
namespace PageFilter.Filters
{
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 });
}
}
}
次のコードは、 AddHeader 属性を適用します。
using Microsoft.AspNetCore.Mvc.RazorPages;
using PageFilter.Filters;
namespace PageFilter.Movies
{
[AddHeader("Author", "Rick")]
public class TestModel : PageModel
{
public void OnGet()
{
}
}
}
ブラウザー開発者ツールなどのツールを使用してヘッダーを調べます。
[応答ヘッダー] の下に author: Rick が表示されます。
順序 のデフォルト設定をオーバーライドする 手順については、該当箇所を参照してください。
フィルターからフィルター パイプラインを短絡する手順については、「 キャンセルとショートサーキット 」を参照してください。
フィルター属性を承認する
Authorize 属性は、PageModelに適用できます。
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace PageFilter.Pages
{
[Authorize]
public class ModelWithAuthFilterModel : PageModel
{
public IActionResult OnGet() => Page();
}
}
作成者: Rick Anderson
RazorページフィルターIPageFilterは、IAsyncPageFilterRazor ページハンドラーの実行前後にRazorページでコードを実行することを可能にします。 Razor ページ フィルターは、個々のページ ハンドラー メソッドに適用できない点を除き、 ASP.NET Core MVC アクション フィルターと似ています。
Razor ページ フィルター:
- ハンドラー メソッドが選択された後、モデル バインドが発生する前にコードを実行します。
- モデル バインドが完了した後、ハンドラー メソッドの実行前にコードを実行します。
- ハンドラー メソッドの実行後にコードを実行します。
- ページまたはグローバルに実装できます。
- 特定のページ ハンドラー メソッドには適用できません。
コードは、ページ コンストラクターまたはミドルウェアを使用してハンドラー メソッドを実行する前に実行できますが、 Razor ページ フィルターのみが HttpContextにアクセスできます。 フィルターには、FilterContextへのアクセスを提供するHttpContext派生パラメーターがあります。 たとえば、 フィルター属性の実装 サンプルでは、コンストラクターやミドルウェアでは実行できないヘッダーを応答に追加します。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
Razor ページ フィルターには、グローバルまたはページ レベルで適用できる次のメソッドが用意されています。
同期メソッド:
- OnPageHandlerSelected : ハンドラー メソッドが選択された後、モデル バインドが発生する前に呼び出されます。
- OnPageHandlerExecuting : モデル バインドが完了した後、ハンドラー メソッドが実行される前に呼び出されます。
- OnPageHandlerExecuted : ハンドラー メソッドの実行後、アクションの結果の前に呼び出されます。
非同期メソッド:
- OnPageHandlerSelectionAsync : ハンドラー メソッドが選択された後、モデル バインドが発生する前に非同期的に呼び出されます。
- OnPageHandlerExecutionAsync : モデル バインドが完了した後、ハンドラー メソッドが呼び出される前に非同期的に呼び出されます。
Note
両方ではなく、同期バージョンまたは非同期バージョンのフィルター インターフェイス を 実装します。 フレームワークはまず、フィルターが非同期インターフェイスを実装しているかどうかを確認し、実装されている場合はそれを呼び出します。 そうでない場合は、同期インターフェイスのメソッドを呼び出します。 両方のインターフェイスが実装されている場合は、非同期メソッドのみが呼び出されます。 同じ規則がページ内のオーバーライドに適用され、両方ではなく、同期バージョンまたは非同期バージョンのオーバーライドが実装されます。
Razor ページ フィルターをグローバルに実装する
次のコードは、 IAsyncPageFilterを実装します。
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace PageFilter.Filters
{
public class SampleAsyncPageFilter : IAsyncPageFilter
{
private readonly ILogger _logger;
public SampleAsyncPageFilter(ILogger logger)
{
_logger = logger;
}
public async Task OnPageHandlerSelectionAsync(
PageHandlerSelectedContext context)
{
_logger.LogDebug("Global OnPageHandlerSelectionAsync called.");
await Task.CompletedTask;
}
public async Task OnPageHandlerExecutionAsync(
PageHandlerExecutingContext context,
PageHandlerExecutionDelegate next)
{
_logger.LogDebug("Global OnPageHandlerExecutionAsync called.");
await next.Invoke();
}
}
}
上記のコードでは、 ILogger は必要ありません。 サンプルでは、アプリケーションのトレース情報を提供するために使用されます。
次のコードは、SampleAsyncPageFilter クラスのStartupを有効にします。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(new SampleAsyncPageFilter(_logger));
});
}
次のコードは、完全な Startup クラスを示しています。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PageFilter.Filters;
namespace PageFilter
{
public class Startup
{
ILogger _logger;
public Startup(ILoggerFactory loggerFactory, IConfiguration configuration)
{
_logger = loggerFactory.CreateLogger<GlobalFiltersLogger>();
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(new SampleAsyncPageFilter(_logger));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc();
}
}
}
次のコードはAddFolderApplicationModelConventionを呼び出して、SampleAsyncPageFilter 内のページにのみを適用します。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddFolderApplicationModelConvention(
"/subFolder",
model => model.Filters.Add(new SampleAsyncPageFilter(_logger)));
});
}
次のコードは、同期 IPageFilterを実装します。
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace PageFilter.Filters
{
public class SamplePageFilter : IPageFilter
{
private readonly ILogger _logger;
public SamplePageFilter(ILogger logger)
{
_logger = logger;
}
public void OnPageHandlerSelected(PageHandlerSelectedContext context)
{
_logger.LogDebug("Global sync OnPageHandlerSelected called.");
}
public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
{
_logger.LogDebug("Global sync PageHandlerExecutingContext called.");
}
public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
{
_logger.LogDebug("Global sync OnPageHandlerExecuted called.");
}
}
}
次のコードは、 SamplePageFilterを有効にします。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(new SamplePageFilter(_logger));
});
}
ページ フィルターを実装するためには、フィルターメソッドをオーバーライドしてください。
次のコードは、同期 Razor ページ フィルターをオーバーライドします。
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace PageFilter.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public string Message { get; set; }
public void OnGet()
{
_logger.LogDebug("IndexModel/OnGet");
}
public override void OnPageHandlerSelected(
PageHandlerSelectedContext context)
{
_logger.LogDebug("IndexModel/OnPageHandlerSelected");
}
public override void OnPageHandlerExecuting(
PageHandlerExecutingContext context)
{
Message = "Message set in handler executing";
_logger.LogDebug("IndexModel/OnPageHandlerExecuting");
}
public override void OnPageHandlerExecuted(
PageHandlerExecutedContext context)
{
_logger.LogDebug("IndexModel/OnPageHandlerExecuted");
}
}
}
フィルター属性を実装する
組み込みの属性ベースのフィルター OnResultExecutionAsync フィルターをサブクラス化できます。 次のフィルターは、応答にヘッダーを追加します。
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
namespace PageFilter.Filters
{
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 });
}
}
}
次のコードは、 AddHeader 属性を適用します。
[AddHeader("Author", "Rick")]
public class ContactModel : PageModel
{
private readonly ILogger _logger;
public ContactModel(ILogger<ContactModel> logger)
{
_logger = logger;
}
public string Message { get; set; }
public async Task OnGetAsync()
{
Message = "Your contact page.";
_logger.LogDebug("Contact/OnGet");
await Task.CompletedTask;
}
}
順序 のデフォルト設定をオーバーライドする 手順については、該当箇所を参照してください。
フィルターからフィルター パイプラインを短絡する手順については、「 キャンセルとショートサーキット 」を参照してください。
フィルター属性を承認する
Authorize 属性は、PageModelに適用できます。
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace PageFilter.Pages
{
[Authorize]
public class ModelWithAuthFilterModel : PageModel
{
public IActionResult OnGet() => Page();
}
}
ASP.NET Core