DEV Community

Xhanti Mda
Xhanti Mda

Posted on

14

Filters with Dependency Injection in ASP.NET CORE

Recently I wanted to add a logger to a custom authorization filter(which was not the best idea) but I didn't want to new up an instance inside the filter, I wanted DI to handle all of that for me.

I did some digging and came across the TypeFilterAttribute, ServiceFilterAttribute and the IFilterFactory.

IFilterFactory

IFilterFactory interface allows you to create an instance of your filter by implementing the CreateInstance method inside your filter.
When MVC invokes a filter, it first tries to cast it to an IFilterFactory. If that cast succeeds, it then calls the CreateInstance method.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class SecurityFilterUsingFactory : Attribute, IAuthorizationFilter, IFilterFactory
{
private IAuthenticationService _authenticationService;
private ILogger _logger;
public SecurityFilterUsingFactory(IAuthenticationService authenticationService, ILogger<string> logger)
{
_authenticationService = authenticationService;
_logger = logger;
}
public bool IsReusable => false;
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
// gets the dependecies from the serviceProvider
// and creates an instance of the filter
return new SecurityFilterUsingFactory(
(IAuthenticationService)serviceProvider.GetService(typeof(IAuthenticationService)),
(ILogger<string>)serviceProvider.GetService(typeof(ILogger<string>)));
}

An example of a filter implementing IFilterFactory

TypeFilter & ServiceFilter

The ServiceFilterAttribute implements the IFilterFactory. IFilterFactory exposes the CreateInstance method for creating an IFilterMetadata instance. The CreateInstance method loads the specified type from the container.
Filters used with the ServiceFilterAttribute need to be registered with the container.

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IMovieService, MovieService>();
services.AddTransient<IAuthenticationService, AuthenticationService>();
//register your filter here
services.AddScoped<SecurityFilter>();
services.AddMvc()
.AddMvcOptions(options =>
{
options.Filters.Add<SecurityFilter>();
options.Filters.Add<SecurityFilterUsingFactory>();
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
view raw Startup.cs hosted with ❤ by GitHub
An example of registering a filter.
[ServiceFilter(typeof(SecurityFilter))]
[HttpGet("api/movies/all")]
public async Task<ActionResult> GetMoviesAsync()
{
return Ok(await _movieService.GetMoviesAsync());
}
An example of how the ServiceFilterAttribute can be used

The TypeFilterAttribute is similar to the ServiceFilterAttribute, but its type isn't resolved directly from the DI container. It instantiates the type by using Microsoft.Extensions.DependencyInjection.ObjectFactory.

This means that types referenced using the TypeFilterAttribute don't need to be registered with the container first and the TypeFilterAttribute can optionally accept constructor arguments for the type.

When using the TypeFilterAttribute, setting IsReusable is a hint that the filter instance may be reused outside of the request scope it was created within. The framework provides no guarantees that a single instance of the filter will be created. Avoid using IsReusable when using a filter that depends on services with a lifetime other than singleton.

[HttpGet("api/movie/{id}")]
[TypeFilter(typeof(SecurityFilterUsingFactory))]
public async Task<ActionResult> GetMovieByIdAsync(int id)
{
if (id <= 0)
return BadRequest();
var movie = await _movieService.GetMovieById(id);
if (movie == null)
return NotFound();
return Ok(movie);
}
An example of how the TypeFilterAttribute can be used

The sample code can be found here

AI Agent image

How to Build an AI Agent with Semantic Kernel (and More!)

Join Developer Advocate Luce Carter for a hands-on tutorial on building an AI-powered dinner recommendation agent. Discover how to integrate Microsoft Semantic Kernel, MongoDB Atlas, C#, and OpenAI for ingredient checks and smart restaurant suggestions.

Watch the video →

Top comments (0)

Jetbrains image

Is Your CI/CD Server a Prime Target for Attack?

57% of organizations have suffered from a security incident related to DevOps toolchain exposures. It makes sense—CI/CD servers have access to source code, a highly valuable asset. Is yours secure? Check out nine practical tips to protect your CI/CD.

Learn more

AWS GenAI LIVE! | May 14, 2025

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️