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?

6 Answers 6

186

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
Sign up to request clarification or add additional context in comments.

7 Comments

For WebAPI, the System.Web.Http.Mvc filter attribute should be used, correct?
I've been trying to figure out why my ActionFilter doesn't work for the last couple of hours. Thanks Troy! :)
The ActionFilterAttribute for WebApi is in the System.Web.Http.dll assembly.
MVC: System.Web.Http.Mvc --> System.Web.Mvc in some ASP.NET MVC versions
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.
|
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);
}

2 Comments

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
Actually, the HTTP Controllers use should show OnActionExecuting(HttpActionContext httpActionContext) then call base.OnActionExecuting(httpActionContext). OnActionExecuted() is also available.
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.

1 Comment

You should use the HttpClient and HttpServer to set up an internal webserver for unit testing, so it will utilize the entire pipeline.
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);
        }
    }
}

Comments

0

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

Comments

0

My problem was much more simple:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.