81

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?

j0k
  • 22,600
  • 28
  • 79
  • 90
cjones26
  • 3,459
  • 1
  • 34
  • 51

6 Answers6

183

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
david.barkhuizen
  • 5,239
  • 4
  • 36
  • 38
Troy Dai
  • 2,071
  • 1
  • 13
  • 7
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);
}
Matt
  • 1,213
  • 14
  • 39
ProVega
  • 5,864
  • 2
  • 36
  • 34
  • 3
    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.WebApi – Kent Fehribach Sep 05 '14 at 01:16
  • 1
    Actually, the HTTP Controllers use should show OnActionExecuting(HttpActionContext httpActionContext) then call base.OnActionExecuting(httpActionContext). OnActionExecuted() is also available. – GarDavis Oct 13 '16 at 17:55
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.

Johnie Karr
  • 2,744
  • 2
  • 35
  • 44
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);
        }
    }
}
AjitChahal
  • 221
  • 2
  • 7
0

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

Baran
  • 1,388
  • 6
  • 16
  • 33
0

My problem was much more simple:

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

bendecko
  • 2,643
  • 1
  • 23
  • 33