web-dev-qa-db-fra.com

Comment utiliser les filtres d'action avec injection de dépendance dans ASP.NET CORE?

J'utilise l'injection de dépendance basée sur le constructeur partout dans mon application ASP.NET CORE et j'ai également besoin de résoudre les dépendances dans mes filtres d'action:

public class MyAttribute : ActionFilterAttribute
{
    public int Limit { get; set; } // some custom parameters passed from Action
    private ICustomService CustomService { get; } // this must be resolved

    public MyAttribute()
    {
    }

    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // my code
        ...

        await next();
    }
}

Puis dans le contrôleur:

[MyAttribute(Limit = 10)]
public IActionResult()
{
    ...

Si je mets ICustomService au constructeur, je suis incapable de compiler mon projet. Alors, comment puis-je utiliser des filtres pour obtenir des instances d'interface?

12
James Smith

Si vous souhaitez éviter le motif Service Locator, vous pouvez utiliser DI par injection de constructeur avec un TypeFilter.

Dans votre contrôleur utiliser

[TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[] {10})]
public IActionResult() NiceAction
{
   ...
}

Et votre ActionFilterAttribute n'a plus besoin d'accéder à une instance de fournisseur de service.

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public int Limit { get; set; } // some custom parameters passed from Action
    private ICustomService CustomService { get; } // this must be resolved

    public MyActionFilterAttribute(ICustomService service, int limit)
    {
        CustomService = service;
        Limit = limit;
    }

    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        await next();
    }
}

Pour moi, l'annotation [TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[] {10})] semble gênante. Pour obtenir une annotation plus lisible telle que [MyActionFilter(Limit = 10)], votre filtre doit hériter de TypeFilterAttribute. Ma réponse de Comment puis-je ajouter un paramètre à un filtre d'action dans asp.net? montre un exemple pour cette approche.

16
Ralf Bönning

Vous pouvez utiliser Service Locator:

public void OnActionExecuting(ActionExecutingContext actionContext)
{
     var service = actionContext.HttpContext.RequestServices.GetService<IService>();
}

Notez que la méthode générique GetService<> est une méthode d'extension et réside dans l'espace de noms Microsoft.Extensions.DependencyInjection.

Si vous souhaitez utiliser l'injection de constructeur, utilisez TypeFilter. Voir Comment ajouter un paramètre à un filtre d'action dans asp.net?

2
adem caglin

Vous pouvez utiliser ServiceFilters pour instancier les ActionFilters dont vous avez besoin dans le contrôleur.

Dans le contrôleur:

[ServiceFilter(typeof(TrackingAttribute), Order = 2)]

Vous devez enregistrer TrackingAttribute dans le conteneur de dépendances pour que ServiceFilter puisse le résoudre.

Plus d'informations à ce sujet sur https://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/

1