Take advantage of dependency injection to make your action methods in ASP.NET Core lean, clean, and maintainable Credit: Thinkstock Filters enable you to execute code at certain stages of the request processing pipeline. An action filter is a filter that is executed before or after the execution of an action method. By using action filters, you can make your action methods lean, clean, and maintainable. There are several filters available for action methods, each of which corresponds to a different stage of the request processing pipeline. You can read more about action filters in my earlier article here. In this article we’ll discuss how we can work with dependency injection in action filters in ASP.NET Core 3.1. To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here. Create an ASP.NET Core 3.1 MVC project in Visual Studio 2019 First off, let’s create an ASP.Net Core project in Visual Studio 2019. Assuming Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new ASP.Net Core project in Visual Studio. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “ASP.NET Core Web Application” from the list of templates displayed. Click Next. In the “Configure your new project” window, specify the name and location for the new project. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences. Click Create. In the “Create a New ASP.NET Core Web Application” window shown next, select .NET Core as the runtime and ASP.NET Core 3.1 (or later) from the drop-down list at the top. Select “Web Application (Model-View-Controller)” as the project template to create a new ASP.NET Core MVC application. Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we won’t be using those features here. Ensure that Authentication is set to “No Authentication” as we won’t be using authentication either. Click Create. Following these steps should create a new ASP.Net Core MVC project in Visual Studio 2019. We’ll use this project in the sections below to illustrate the use of dependency injection in action methods in ASP.NET Core 3.1. Use the RequestServices.GetService method in ASP.NET Core 3.1 Although it’s not a recommended practice, an easy way to retrieve a service that has been added to the service collection is by using the RequestServices.GetService method. Assuming that you have added a service named CustomService to your services container, you can use the following code to retrieve the service instance. public override void OnActionExecuting(ActionExecutingContext context) { var customService = context.HttpContext.RequestServices. GetService(typeof(CustomService)); //Write your code here _logger.LogWarning("Inside OnActionExecuting method..."); base.OnActionExecuting(context); } Use the ServiceFilter attribute in ASP.NET Core 3.1 A better practice is to take advantage of the ServiceFilter attribute — it can be applied at the controller or the action level. Here is the syntax for using this attribute. [ServiceFilter(typeof(typeof YourActionFilter))] Below we’ll learn how to leverage the ServiceFilter attribute for dependency injection in action filters. Create a custom ActionFilterAttribute class in ASP.NET Core 3.1 Let’s create a custom ActionFilterAttribute class and use it as a ServiceFilter. To create a custom action filter in ASP.NET Core 3.1, you should create a class that extends the ActionFilterAttribute class as shown in the code snippet given below. Note that the ActionFilterAttribute class implements the IActionFilter, IAsyncActionFilter, IResultFilter, IAsyncResultFilter, and IOrderedFilter interfaces. public class CustomActionFilter : ActionFilterAttribute { private readonly ILogger _logger; public CustomActionFilter(ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger("CustomActionFilter"); } public override void OnActionExecuting(ActionExecutingContext context) { _logger.LogWarning("Inside OnActionExecuting method..."); base.OnActionExecuting(context); } public override void OnActionExecuted(ActionExecutedContext context) { _logger.LogWarning("Inside OnActionExecuted method..."); base.OnActionExecuted(context); } public override void OnResultExecuting(ResultExecutingContext context) { _logger.LogWarning("Inside OnResultExecuting method..."); base.OnResultExecuting(context); } public override void OnResultExecuted(ResultExecutedContext context) { _logger.LogWarning("Inside OnResultExecuted method..."); base.OnResultExecuted(context); } } Register a custom action filter in ASP.NET Core 3.1 In ASP.NET Core you can add services to the services container easily. Dependency injection is not only a first-class citizen in ASP.NET Core, but support for dependency injection is built-in. Hence you can inject both framework services and application services easily. You can use any of the following methods to add your services using dependency injection in ASP.NET Core. AddTransient AddScoped AddSingleton You can learn more about dependency injection and what each of these methods does from my earlier article here. Next, you must register the custom filter so that it can be used as a ServiceType. The following code snippet illustrates how this can be achieved. public void ConfigureServices(IServiceCollection services) { services.AddScoped<CustomActionFilter>(); services.AddControllersWithViews(); } Use a custom action filter in the controller in ASP.NET Core 3.1 You can take advantage of the ServiceFilter attribute to inject dependencies in your controller or your controller’s action methods. Here is the syntax for using the ServiceFilter attribute. [ServiceFilter(typeof(MyCustomFilter))] The code snippet below shows how you can apply the custom action filter to an action method in a controller class named HomeController. Note how the ServiceFilter attribute has been used. public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } [ServiceFilter(typeof(CustomActionFilter))] public IEnumerable<string> Get() { _logger.LogInformation("Inside HttpGet action method..."); return new string[] { "Joydip", "Michael", "Anand", "Steve" }; } } Set the execution order of the action filters in ASP.NET Core 3.1 You can even set the execution order of the action filters. The action filters that have a higher execution order will be executed later in the execution cycle. The usual execution order of action filters is as follows: OnActionExecuting method of Global action filter OnActionExecuting method of Controller action filter OnActionExecuting method of Action filter Action method OnActionExecuted method of Action filter OnActionExecuted method of Controller action filter OnActionExecuted method of Global action filter You can set the execution order of an action filter individually. The code snippet below shows how you can achieve this. [ServiceFilter(typeof(CustomActionFilter), Order = 2)] public IEnumerable<string> Get() { _logger.LogInformation("Inside HttpGet action method..."); return new string[] { "Joydip", "Michael", "Anand", “Steve” }; } When you execute your application, you’ll observe that the CustomActionFilter is executed after the Global action filter is executed. Use the TypeFilter attribute in ASP.NET Core 3.1 You can also use type filters to inject dependencies into action filters. The ServiceFilter attribute works nicely for dependencies that are resolved via the IoC (inversion of control) container. TypeFilter works much the same way as ServiceFilter but doesn’t need to be registered with the services container. Moreover, type filters can also be used to pass additional parameters to the action filter. The following code snippet illustrates how TypeFilter can be used. [TypeFilter(typeof(CustomFilter), Arguments = new object[] {"This is a string parameter"})] [HttpGet("")] public IEnumerable<string> Get() { _logger.LogInformation("Inside HttpGet action method..."); return new string[] { "Joydip", "Michael", "Anand" }; } Use global action filters in ASP.NET Core 3.1 You can also apply filters globally by adding your action filter to the Filters collection of the IServiceCollection instance as shown in the code snippet given below. { services.AddControllers(config => { config.Filters.Add<CustomFilter>(); }).SetCompatibilityVersion(CompatibilityVersion.Version_3_0); } This enables you to apply the filter to every action method of every controller in your project. One of the biggest benefits of dependency injection is that it allows you to build applications that are loosely coupled. When working with your controllers and their action methods you might often need to inject filters that modify the way those actions are executed. ASP.NET Core 3.1 allows you to do this easily. How to do more in .NET Core: How to use in-memory caching in ASP.NET Core Advanced versioning in ASP.NET Core Web API How to use dependency injection in ASP.NET Core How to use async and await in .NET Core How to consume an ASP.NET Core Web API using RestSharp How to consume a WCF SOAP service in ASP.NET Core How to improve the performance of ASP.NET Core applications Testing with the InMemory provider in Entity Framework Core How to work with logging in ASP.NET Core How to use MediatR in ASP.NET Core How to use System.Threading.Channels in .NET Core More advanced AutoMapper examples in .NET Core How to work with session state in ASP.NET Core How to use Nancy in ASP.NET Core How to implement rate limiting in ASP.NET Core How to implement global exception handling in ASP.NET Core Web API How to use IHostedService in ASP.NET Core How to work with cookies in ASP.NET Core How to use Autofac in ASP.NET Core How to upload files in ASP.NET Core MVC How to use URL Rewriting Middleware in ASP.NET Core How to handle null values in ASP.NET Core MVC How to work with worker services in ASP.NET Core How to use Elmah for error logging in ASP.NET Core How to implement health checks in ASP.NET Core How to use Glimpse in ASP.NET Core How to use Swagger in ASP.NET Core How to implement global exception handling in ASP.NET Core MVC How to use conditional middleware in ASP.NET Core How to use Azure Application Insights in ASP.NET Core How to use NCache in ASP.NET Core How to return data from ASP.NET Core Web API How to use response caching middleware in ASP.NET Core How to schedule jobs using Quartz.NET in ASP.NET Core How to enable CORS in ASP.NET Core How to use session storage in ASP.NET Core Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos