ASP.NET Core에서 Razor Pages를 위한 필터 메서드
작성자: Rick Anderson
Razor 페이지 필터 IPageFilter 및 IAsyncPageFilter는 Razor Pages가 Razor 페이지 처리기 실행 전후에 코드를 실행하도록 허용합니다. Razor 페이지 필터는 개별 페이지 처리기 메서드에 적용할 수 없다는 점을 제외하고는 ASP.NET Core MVC 작업 필터와 유사합니다.
Razor 페이지 필터:
- 처리기 메서드를 선택한 후 모델 바인딩이 발생하기 전에 코드를 실행합니다.
- 모델 바인딩이 완료된 후 처리기 메서드가 실행되기 전에 코드를 실행합니다.
- 처리기 메서드가 실행된 후 코드를 실행합니다.
- 한 페이지에 또는 전역으로 구현할 수 있습니다.
- 특정 페이지 처리기 메서드에는 적용할 수 없습니다.
- 생성자 종속성이 DI(종속성 주입)를 통해서 채워질 수 있습니다. 자세한 내용은 ServiceFilterAttribute 및 TypeFilterAttribute를 참조하세요.
페이지 생성자 및 미들웨어는 처리기 메서드가 실행되기 전에 사용자 지정 코드를 실행할 수 있지만 Razor 페이지 필터를 통해서만 HttpContext 및 페이지에 액세스할 수 있습니다. 미들웨어는 HttpContext
에 액세스할 수 있지만 "페이지 컨텍스트"에는 액세스할 수 없습니다. 필터에는 HttpContext
에 대한 액세스를 제공하는 FilterContext 파생 매개 변수가 있습니다. 다음은 페이지 필터 에 대한 샘플입니다. 응답에 헤더를 추가하는 필터 특성을 구현합니다. 생성자 또는 미들웨어로는 수행할 수 없는 작업입니다. 페이지의 인스턴스 및 페이지의 모델에 대한 액세스를 포함하는 페이지 컨텍스트에 대한 액세스는 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
는 사용자 에이전트 문자열에 작동하는 사용자 제공 코드입니다.
다음 코드는 Startup
클래스의 SampleAsyncPageFilter
를 활성화합니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddMvcOptions(options =>
{
options.Filters.Add(new SampleAsyncPageFilter(Configuration));
});
}
다음 코드는 AddFolderApplicationModelConvention을 호출하여 SampleAsyncPageFilter
를 /Movies의 페이지에만 적용합니다.
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 페이지 필터 구현
다음 코드는 비동기 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
이 표시됩니다.
순서 재정의에 대한 지침은 기본 순서 재정의를 참조하세요.
필터에서 필터 파이프라인을 단락(short-circuit)시키는 지침은 취소 및 단락을 참조하세요.
권한 부여 필터 특성
권한 부여 특성은 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 및 IAsyncPageFilter는 Razor Pages가 Razor 페이지 처리기 실행 전후에 코드를 실행하도록 허용합니다. Razor 페이지 필터는 개별 페이지 처리기 메서드에 적용할 수 없다는 점을 제외하고는 ASP.NET Core MVC 작업 필터와 유사합니다.
Razor 페이지 필터:
- 처리기 메서드를 선택한 후 모델 바인딩이 발생하기 전에 코드를 실행합니다.
- 모델 바인딩이 완료된 후 처리기 메서드가 실행되기 전에 코드를 실행합니다.
- 처리기 메서드가 실행된 후 코드를 실행합니다.
- 한 페이지에 또는 전역으로 구현할 수 있습니다.
- 특정 페이지 처리기 메서드에는 적용할 수 없습니다.
페이지 생성자 또는 미들웨어를 사용하여 처리기 메서드를 실행하기 전에 코드를 실행할 수 있지만 페이지 필터만 Razor 액세스할 수 HttpContext있습니다. 필터에는 HttpContext
에 대한 액세스를 제공하는 FilterContext 파생 매개 변수가 있습니다. 예를 들어 필터 특성 구현 샘플은 생성자 또는 미들웨어로 수행할 수 없는 응답에 헤더를 추가합니다.
Razor 페이지 필터는 전역 또는 페이지 수준에서 적용할 수 있는 다음과 같은 메서드를 제공합니다.
동기 메서드:
- OnPageHandlerSelected : 처리기 메서드를 선택한 후 모델 바인딩이 발생하기 전에 호출됩니다.
- OnPageHandlerExecuting : 모델 바인딩이 완료된 후 처리기 메서드가 실행되기 전에 호출됩니다.
- OnPageHandlerExecuted : 처리기 메서드가 실행된 후 작업 결과 전에 호출됩니다.
비동기 메서드:
- OnPageHandlerSelectionAsync : 처리기 메서드를 선택한 후 모델 바인딩이 발생하기 전에 비동기적으로 호출됩니다.
- OnPageHandlerExecutionAsync : 모델 바인딩이 완료된 후 처리기 메서드가 호출되기 전에 비동기적으로 호출됩니다.
참고 항목
필터 인터페이스의 동기 또는 비동기 버전 중 하나를 구현합니다. 프레임워크는 먼저 필터가 비동기 인터페이스를 구현하는지를 확인하고 그렇다면 이를 호출합니다. 그렇지 않으면 동기 인터페이스의 메서드를 호출합니다. 두 인터페이스가 구현되는 경우 비동기 메서드만 호출됩니다. 페이지의 재정의에 동일한 규칙이 적용되며, 재정의의 동기 또는 비동기 버전 중 하나만 구현합니다.
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 필요하지 않습니다. 이는 샘플에서 애플리케이션에 대한 추적 정보를 제공하는 데 사용됩니다.
다음 코드는 Startup
클래스의 SampleAsyncPageFilter
를 활성화합니다.
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
를 /subFolder의 페이지에만 적용합니다.
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 페이지 필터 구현
다음 코드는 동기 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;
}
}
순서 재정의에 대한 지침은 기본 순서 재정의를 참조하세요.
필터에서 필터 파이프라인을 단락(short-circuit)시키는 지침은 취소 및 단락을 참조하세요.
권한 부여 필터 특성
권한 부여 특성은 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
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기