webentwicklung-frage-antwort-db.com.de

Wie Verwenden von Aktionsfiltern mit Abhängigkeitseinspritzung in ASP.NET CORE?

Ich benutze überall in meiner ASP.NET CORE-Anwendung die Konstruktorbasierte Abhängigkeitsinjektion und muss auch Abhängigkeiten in meinen Aktionsfiltern auflösen:

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();
    }
}

Dann im Controller:

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

Wenn ich ICustomService in den Konstruktor stecke, kann ich mein Projekt nicht kompilieren. Wie kann ich also Schnittstelleninstanzen im Aktionsfilter abrufen?

12
James Smith

Wenn Sie das Service Locator-Muster vermeiden möchten, können Sie DI durch Konstruktorinjektion mit einem TypeFilter verwenden.

In Ihrem Controller verwenden

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

Und Ihr ActionFilterAttribute muss nicht mehr auf eine Dienstanbieterinstanz zugreifen.

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();
    }
}

Für mich scheint die Annotation [TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[] {10})] umständlich zu sein. Um eine lesbarere Annotation wie [MyActionFilter(Limit = 10)] zu erhalten, muss Ihr Filter von TypeFilterAttribute erben. Meine Antwort von Wie füge ich einem Aktionsfilter in asp.net einen Parameter hinzu? zeigt ein Beispiel für diesen Ansatz.

16
Ralf Bönning

Sie können Service Locator verwenden:

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

Beachten Sie, dass die generische Methode GetService<> eine Erweiterungsmethode ist und sich im Namensraum Microsoft.Extensions.DependencyInjection befindet.

Wenn Sie die Konstruktorinjektion verwenden möchten, verwenden Sie TypeFilter. Siehe Wie füge ich einen Parameter zu einem Aktionsfilter in asp.net hinzu?

2
adem caglin

Sie können ServiceFilters verwenden, um die benötigten ActionFilters im Controller zu instanziieren.

Im Controller:

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

Sie müssen TrackingAttribute im Abhängigkeitscontainer registrieren, damit der ServiceFilter es auflösen kann.

Lesen Sie mehr darüber unter https://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/