Why is my ASP.NET Web API ActionFilterAttribute OnActionExecuting not firing?
Asked Answered
M

6

82

I'm trying to implement what's seen here: http://www.piotrwalat.net/nhibernate-session-management-in-asp-net-web-api/ but I'm having an issue with my NhSessionManagementAttribute.

I've set breakpoints on my OnActionExecuting(HttpActionContext actionContext) to see whether the function was ever being called -- it wasn't.

I double-checked my global.asax.cs file & found I am in fact registering the ActionFilter with:

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

I have also decorated both my controller class itself, as well as its actions with the attribute to no avail:

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

Why would this action filter not be firing any of the events within?

Mountaineering answered 20/10, 2012 at 21:11 Comment(0)
A
184

If you're working in a project contains both MVC and WebAPI assembilies, could you check what's the namespace your ActionFilterAttribute's namespace. It's fairly confusing cause there are two ActionFilterAttributes under both:

  • WebAPI: System.Web.Http.Filters
  • MVC: System.Web.Http.Mvc
Arrogant answered 21/10, 2012 at 6:12 Comment(7)
For WebAPI, the System.Web.Http.Mvc filter attribute should be used, correct?Geisler
I've been trying to figure out why my ActionFilter doesn't work for the last couple of hours. Thanks Troy! :)Dabchick
The ActionFilterAttribute for WebApi is in the System.Web.Http.dll assembly.Nickola
Mate you saved a lot of time for me. Cheers.Afterward
MVC: System.Web.Http.Mvc --> System.Web.Mvc in some ASP.NET MVC versionsTimehonored
I'm still confused. For WebAPI why is System.Web.Http.Filters.ActionFilterAttribute not the appropriate choice? The answer just says to check the namespace and states that there are two. It doesn't explain why you would not use the WebAPI one.Fillin
It seems that the biggest differenence is webapi is authAsync, mvc is notVelvetvelveteen
I
39

The answer above definitely helped me - to save others some time... here is explicitly the difference.

Standard MVC Controllers use:

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

OData HTTP Controllers use:

// System.Web.Http.Filters;
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    base.OnActionExecuted(actionExecutedContext);
}
Invidious answered 26/3, 2013 at 3:35 Comment(2)
And the System.Web.Http.Filters is for WebApi as well. If using Ninject it is important to note that the Filter bindings are in different libraries for Mvc versus Http as well. Mvc - Ninject.Web.Mvc WebApi/Http - Ninject.Web.WebApiStoneblind
Actually, the HTTP Controllers use should show OnActionExecuting(HttpActionContext httpActionContext) then call base.OnActionExecuting(httpActionContext). OnActionExecuted() is also available.Tribulation
A
7

For anyone else who comes across this, ActionFilterAttribute will not fire when calling YourController.YourAction from your UnitTest.

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

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

    //Some Assertions
}

In the TestMethod above, any ActionFilterAttributes on YourController.YourAction will not be called. However; if you call YourController.YourAction from a browser, your ActionFilterAttribute will be called.

This is true for at least WebApi, but I don't know if it applies to MVC.

Armand answered 25/6, 2015 at 18:2 Comment(1)
You should use the HttpClient and HttpServer to set up an internal webserver for unit testing, so it will utilize the entire pipeline.Peripeteia
I
2

Here is the complete Implementation:

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);
        }
    }
}
Importune answered 4/2, 2016 at 12:2 Comment(0)
M
0

For WebApi, you should install Microsoft.AspNet.WebApi.Core from nuget. For MVC you can use System.Web.MVC.

Memory answered 7/3, 2016 at 22:33 Comment(0)
H
0

My problem was much more simple:

Check your Controller is decorated with <actionPreProcessActivitiesAttribute()> _

Hauge answered 22/6, 2017 at 9:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.