ASP.NET Core MVC에서는 필터(Filters)를 이용해 특정 단계(전역, 컨트롤러, 액션 별로 각각 구성) 전후에 원하는 코드를 실행할 수 있다. 이런 점에 있어서 필터와 미들웨어는 차이점이 있다.
미들웨어는 HttpContext에 액세스할 수 있고 필터는 더 넓은 MVC 컨텍스트에까지 액세스할 수 있다. 즉, 필터는 동작의 범위를 지정할 수 있고, 뷰 처리 직전이나 모델 바인딩 이후 같은 응용 프로그램 내부의 적절한 위치에 삽입이 가능하다. 또한 필터는 MVC의 일부로서 MVC 컨텍스트와 구조에 접근할 수 있다.
요청 실행이 시작되면 미들웨어를 통과하고 미들웨어에서 다른 미들웨어로 요청을 전달하고 결국 미들웨어 요청 후에 MVC 파이프라인으로 들어가 필터를 거치게 된다.
종류 | 설명 |
---|---|
Authorization 필터 | 현재 사용자가 지금 처리 중인 요청에 대한 권한을 부여 받았는지 여부를 판단할 때 사용 |
Resource 필터 | 권한이 부여된 이후에 요청을 처리하는 가장 첫 번째 필터이자, 필터 파이프라인을 빠져 나갈때 요청에 관여할 수 있는 가장 마지막 필터 이 필터는 캐싱을 구현하거나, 성능상의 목적으로 필터 파이프라인을 신속하게 빠져나가야 할 때 특히 유용 |
Action 필터 | 액션 메서드에 대한 호출을 감싸고, 액션으로 전달되는 인자나 반환되는 액션 결과를 조정 |
Exception 필터 | 처리되지 않은 예외에 대한 MVC 응용 프로그램의 전역 정책을 적용할 때 사용 |
Result 필터 | 개별 액션 결과(Action Results)의 실행을 감싸며, 액션 메서드가 정상적으로 실행된 경우에만 실행, 뷰 실행이나 포맷터 실행을 감싸는 로직을 구현하기에 적합한 단계 |
위의 다양한 필터들은 파이프라인의 각기 다른 시점에 실행된다.
Action 필터
액션 메서드가 호출되기 전후에 즉시 실행된다.
Result 필터
액션 결과가 실행되지 전후에 즉시 실행된다.
Exception 필터
다른 필터들이나 액션 메서드, 액션 결과가 예를 던지는 경우에만 실행된다.
필터는 동기 구현과 비동기 구현 모두 작성할 수 있다. 만약 한 클래스에 두 가지 인터페이스를 모두 구현한다면 비동기 메서드만 호출된다.
Authorization 필터
동기 메서드: OnAuthorization
비동기 메서드: OnAuthorizationAsync
Resource 필터
동기 메서드: OnResourceExecuted, OnResourceExecuting
비동기 메서드: OnResourceExecutionAsync
Action 필터
동기 메서드: OnActionExecuted, OnActionExecuting
비동기 메서드: OnActionExecutionAsync
Result 필터
동기 메서드: OnResultExecuted, OnResultExecuting
비동기 메서드: OnResultExecutionAsync
Exception 필터
동기 메서드: OnException
비동기 메서드: OnExceptionAsync
Executing으로 끝나는 메서드는 파이프라인 단계 이전에 호출되고, Executed으로 끝나는 메서드는 파이프라인 단계 이후에 호출된다.
public class SampleActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// do something before the action executes
}
public void OnActionExecuted(ActionExecutedContext context)
{
// do something after the action executes
}
}
비동기 필터는 단일 메서드 하나만 제공되고 메서드 호출 후 대기 중일때 실행 되는 대리자를 구현하면 된다.
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// do something before the action executes
await next();
// do something after the action executes
}
필터는 전역, 컨트롤러, 액션 메서드의 범위로 설정 가능하고 다음과 같은 순서로 동작한다.
순서 | 범위 | 메서드 |
---|---|---|
1 | 전역 | OnActionExecuting |
2 | 컨트롤러 | OnActionExecuting |
3 | 액션 메서드 | OnActionExecuting |
4 | 액션 메서드 | OnActionExecuted |
5 | 컨트롤러 | OnActionExecuted |
6 | 전역 | OnActionExecuted |
전역 범위 설정은 Startup 클래스 또는 program 클래스의 ConfigureServices 메서드에서 MVC를 구성할 때 추가하고, 컨트롤러, 액션 메서드의 필터 사용은 Attributes 형태로 사용된다.
예를 들어, IActionFilter를 상속받아 ActionFilter를 구현한다.
public class SampleActionFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine("OnActionExecuted");
}
public void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine("OnActionExecuting");
}
}
컨트롤러의 Index 액션 메서드를 다음과 같이 수정한다.
public IActionResult Index()
{
Console.WriteLine("Index...");
return View();
}
전역에 설정 하기위해 program 클래스에 다음을 추가한다.
builder.Services.AddMvcCore(options =>
{
options.Filters.Add(new SampleActionFilter());
});
builder.Services.AddScoped<SampleActionFilter>();
웹 어플리케이션을 실행하면 콘솔에 OnActionExecuting -> Index -> OnActionExecuted 순으로 실행된 것을 확인할 수 있다.
컨트롤러 및 액션 메서드에 어트리뷰트로 필터를 정의하기 위해서는 ActionFilterAttribute를 상속받아 구현한다.
public class SampleActionAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine("OnActionExecuted...");
}
public override void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine("OnActionExecuting...");
}
}
컨트롤러에 어트리뷰트를 사용해 필터를 적용한다.
[SampleAction]
public class HomeController : Controller
{
public IActionResult Index()
{
Console.WriteLine("Index...");
return View();
}
}
웹 어플리케이션을 실행하면 전역에 필터를 적용한 결과 동일하다.