web-dev-qa-db-fra.com

Pourquoi mon API ActionFilterAttribute OnActionExecuting de l'API Web ASP.NET ne se déclenche-t-elle pas?

J'essaie de mettre en œuvre ce qui est vu ici: http://www.piotrwalat.net/nhibernate-session-management-in-asp-net-web-api/ mais j'ai un problème avec ma NhSessionManagementAttribute .

J'ai défini des points d'arrêt sur ma OnActionExecuting(HttpActionContext actionContext) pour voir si la fonction a déjà été appelée - ce n'était pas le cas.

J'ai vérifié deux fois mon fichier global.asax.cs et j'ai constaté que je suis en train d'enregistrer la ActionFilter avec: 

GlobalConfiguration.Configuration.Filters.Add(new NhSessionManagementAttribute());

J'ai également décoré à la fois ma classe de contrôleur elle-même, ainsi que ses actions avec l'attribut en vain:

public class ClientsController : ApiController {
    static readonly ClientRepository repository = new ClientRepository();

    [NhSessionManagement]
    public IEnumerable<Client> GetAllClients() {
        return repository.GetAll();
    }

    [NhSessionManagement]
    public Client GetClient(int id) {
        Client client = repository.Get(id);
        if (client == null) {
            throw new HttpResponseException(
                new HttpResponseMessage(HttpStatusCode.NotFound)
            );
        }
        return client;
    }
}

Pourquoi ce filtre d'action ne déclenche-t-il aucun des événements qu'il contient?

66
slashp

Si vous travaillez dans un projet contenant à la fois des associations MVC et WebAPI, pouvez-vous vérifier quel est l'espace de noms de votre espace de noms ActionFilterAttribute. C'est assez déroutant car il y a deux ActionFilterAttributes sous les deux:

  • WebAPI: System.Web.Http.Filters
  • MVC: System.Web.Http.Mvc
139
Troy Dai

La réponse ci-dessus m'a définitivement aidé - sauver du temps aux autres ... voici la différence explicite.

Les contrôleurs MVC standard utilisent:

// System.Web.Mvc
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    base.OnActionExecuting(filterContext);
}

Les contrôleurs HTTP OData utilisent:

// System.Web.Http.Filters;
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    base.OnActionExecuted(actionExecutedContext);
}
31
ProVega

ActionFilterAttribute ne se déclenchera pas lors de l'appel de YourController.YourAction à partir de votre UnitTest.

[TestMethod]
public void RevokeSiteAdmin_SessionOver()
{
    FakeDbContext db = new FakeDbContext();

    YourController controller = new YourController(db);
    var result = controller.YourAction();

    //Some Assertions
}

Dans la méthode Test ci-dessus, aucun ActionFilterAttributes sur YourController.YourAction ne sera appelé. Toutefois; Si vous appelez YourController.YourAction depuis un navigateur, votre ActionFilterAttribute sera appelé.

Ceci est vrai au moins pour WebApi, mais je ne sais pas si cela s'applique à MVC.

4
Johnie Karr

Voici l'implémentation complète:

public class AllowCrossSiteJsonAttribute : System.Web.Mvc.ActionFilterAttribute
{
    public override void OnActionExecuted(System.Web.Mvc.ActionExecutedContext filterContext)
    {
        if (filterContext.HttpContext != null && filterContext.HttpContext.Response != null && filterContext.HttpContext.Request != null && filterContext.HttpContext.Request.UrlReferrer != null)
        {
            var allowedCrossDomains = TypeSafeConfigurationManager.GetValueString("allowedCrossDomains", "none");
            var allowedHosts = allowedCrossDomains.Split(',');

            var requestHost =  filterContext.HttpContext.Request.UrlReferrer.GetLeftPart(UriPartial.Authority);
            if (allowedHosts.Contains(requestHost.ToLower()))
            {
                filterContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", requestHost);
            }
        }

        base.OnActionExecuted(filterContext);
    }
}
public class AllowCrossSiteJsonForWebApiAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null && actionExecutedContext.Request != null &&
            actionExecutedContext.Request.Headers.Referrer != null)
        {
            var allowedCrossDomains = TypeSafeConfigurationManager.GetValueString("allowedCrossDomains", "none");
            var allowedHosts = allowedCrossDomains.Split(',').ToList();

            var requestHost = actionExecutedContext.Request.Headers.Referrer.GetLeftPart(UriPartial.Authority);

            if (allowedHosts.Contains(requestHost.ToLower()))
            {
                actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", requestHost);
            }

            base.OnActionExecuted(actionExecutedContext);
        }
    }
}
1
AjitChahal

Mon problème était beaucoup plus simple:

Vérifiez que votre contrôleur est décoré avec <actionPreProcessActivitiesAttribute()> _

0
bendecko

Pour WebApi, vous devez installer Microsoft.AspNet.WebApi.Core de nuget . Pour MVC, vous pouvez utiliser System.Web.MVC.

0
Baran