Il concetto di filter è presente in fin dalle prime versioni di ASP.NET MVC ed è stato pienamente ereditato anche in ASP.NET Core. Come probabilmente sappiamo, grazie ai filter è possibile aggiungere della logica a una specifica action, a un intero controller o anche a tutta l'applicazione.
Alle volte potremmo avere la necessità di iniettare dipendenze all'interno di un custom filter. Per esempio su un custom Authorize filter, vorremmo avere accesso al database degli utenti per leggere alcune informazioni sul profilo dell'utente stesso, o in un Resource filter vorremmo avere accesso alla cache per verificare se il dato richiesto è presente.
Immaginiamo ad esempio di aver realizzato un filtro simile al seguente, in cui segnaliamo nel log l'inizio e il completamento di una action:
public class LoggerFilter : IActionFilter { private ILogger<LoggerFilter> _logger; public LoggerFilter(ILogger<LoggerFilter> logger) { _logger = logger; } public void OnActionExecuted(ActionExecutedContext context) { _logger.LogDebug($"Action {context.ActionDescriptor.DisplayName} completed"); } public void OnActionExecuting(ActionExecutingContext context) { _logger.LogDebug($"Action {context.ActionDescriptor.DisplayName} starting"); } }
Questa classe necessita di un ILogger<T> come parametro di input. Ovviamente non possiamo definirla come Attribute perchè altrimenti non avremmo modo di fornire questo parametro nel costruttore.
L'alternatica allora è creare un secondo oggetto, che implementi IFilterFactory:
public class LoggerAttribute : Attribute, IFilterFactory { public bool IsReusable => true; public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) { return serviceProvider.GetService<LoggerFilter>(); } }
Questa interfaccia espone un metodo CreateInstance in cui possiamo generare il filtro di cui effettivamente abbiamo bisogno, sfruttando il serviceProvider passato come parametro.
La nostra nuova classe LoggerAttribute eredita effettivamente da Attribute e può essere utilizzata direttamente sul controller o sulla action interessata.
[Route("api/[controller]")] [ApiController] [Logger] public class ValuesController : ControllerBase { ... }
Affinchè tutto funzioni, l'ultimo passaggio è registrare LoggerFilter nell'IoC container di ASP.NET Core all'interno della classe Startup:
public void ConfigureServices(IServiceCollection services) { // .. altro codice qui .. services.AddTransient<LoggerFilter>(); }
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Le novità di .NET 7 e C# 11
Real world .NET Architecture
Recuperare la data di creazione e ultima modifica di un record con Entity Framework Core e le temporal table di SQL Server
Utilizzare l'attributo autofill del CSS
Sfruttare la local cache del browser tramite gli ETag in ASP.NET Core
Gestire il fallimento di uno step in un workflow di GitHub
Usare gateway dedicati con Azure Cosmos DB per migliorare le prestazioni
Eliminare spazio inutilizzato in un Azure Container Registry
Taggare la output cache in base al routing in ASP.NET Core
Gestire la query string nell'output cache di ASP.NET Core
Miglioramenti alla leggibilità delle Media Query con le specifiche di livello 4
Creare automaticamente una pipeline YAML da una sua definizione in Azure DevOps
I più letti di oggi
- 3 metodi JavaScript che ogni applicazione web dovrebbe contenere - Parte 2
- Monitorare i server on-premises con Azure Arc
- Gestire server e pc on premise con Azure Arc
- Taggare la output cache in base al routing in ASP.NET Core
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!