web-dev-qa-db-fra.com

Async OnActionExecuting dans ActionFilterAttribute d'ASP.NET Core

ActionFilterAttribute d'ASP.NET Core a:

public virtual void OnActionExecuting(ActionExecutingContext context);
public virtual void OnActionExecuted(ActionExecutedContext context);
public virtual Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next);

J'ai besoin d'une version asynchrone de OnActionExecuting, qui n'existe pas.

Cependant, j'ai le sentiment que je peux utiliser OnActionExecutionAsync à la place, car il a également un argument de ActionExecutingContext.

Ai-je raison de dire que malgré leur nom, ils se déclenchent au même moment du processus?

De plus, que dois-je faire avec l'argument next? Une fois que j'ai fini mes affaires, dois-je simplement appeler await next()?

Est-ce que c'est ça? Je ne suis pas sûr car je ne trouve pas de documents pour cela.

17
grokky

Les filtres asynchrones fonctionnent un peu différemment: exécutez d'abord le code qui doit être exécuté avant l'action, appelez next() pour la logique réelle, puis ajoutez le code à exécuter après l'action.

public async Task OnActionExecutionAsync(ActionExecutingContext context, 
                                         ActionExecutionDelegate next)
{

    // logic before action goes here

    await next(); // the actual action

    // logic after the action goes here
}

La documentation est ici: https://docs.Microsoft.com/en-us/aspnet/core/mvc/controllers/filters#implementation

37
jeroenh

Les filtres asynchrones ont toujours la priorité sur les implémentations de filtres synchrones.

Selon le Docs :

  • Il est conseillé d'implémenter la version synchrone ou asynchrone d'une interface de filtre , pas les deux. Le runtime vérifie d'abord si le filtre implémente l'interface asynchrone, et si c'est le cas, il l'appelle. Sinon, il appelle la ou les méthodes de l'interface synchrone. Si les interfaces asynchrones et synchrones sont implémentées dans une seule classe, seule la méthode async est appelée.

Cependant, vous pouvez réussir à avoir les deux. Par exemple:

public class TimestampFilter : IActionFilter, IAsyncActionFilter 
{    
    public void OnActionExecuting(ActionExecutingContext context)    
    {         
        context.ActionDescriptor.RouteValues["timestamp"] = DateTime.Now.ToString();    
    }

    public void OnActionExecuted(ActionExecutedContext context)    
    {         
        var ts = DateTime.Parse(context.ActionDescriptor. RouteValues["timestamp"]).AddHours(1).ToString();        
        context.HttpContext.Response.Headers["X-EXPIRY-TIMESTAMP"] = ts;    
    }

     public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    
    {        
        this.OnActionExecuting(context);        
        var resultContext = await next();
        this.OnActionExecuted(resultContext);    
    }
 }

0
A. Nadjar