8

My WebApi filter method OnActionExecuted is being called twice. My filter (I make it as simple as possible):

   public class NHibernateActionFilter : ActionFilterAttribute
   { 
        //  [Inject]
        //   public ISessionFactoryProvider sessionFactoryProvider { get; set; }
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
           var a = 5;
           var b = a;
           //new BaseSessionProvider(sessionFactoryProvider).EndContextSession();
        }
    }

My setup:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        //http://stackoverflow.com/questions/9521040/how-to-add-global-asp-net-web-api-filters
        FilterConfig.RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
    }

    public class FilterConfig
    {

        public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
        {
             filters.Add(new NHibernateActionFilter());
        }
     }

In debugger I catch OnActionExecuted twice with the same actionExecutedContext. Why?

UPD

Controller
public class BankSmsController : ApiController
{
         [AcceptVerbs(HttpVerbs.Get)]
         public int GetTest()
         {
             return 1;
         }
}
Daniel Little
  • 15,641
  • 10
  • 66
  • 89
Andrew Kalashnikov
  • 2,785
  • 5
  • 31
  • 55

3 Answers3

8

I have a suspicion, that this strange behavior can be fixed by either overriding AllowMultiple property of filter and returning false, or applying AttributeUsage attribute with AllowMultiple set to false too (this influences on default implementation of AllowMultiple property of filter.

At least in our project this helped (we have filters injected via Autofac).

Mikhail Brinchuk
  • 647
  • 6
  • 16
3

This might be caused due to a registration of a custom filter provider. When you do this, you need to unregister the default one. Otherwise, if you are getting the usual filters in your custom one, they will be registered twice and consequently, executed twice.

Code should be something like this:

// remove default action filter provider
var defaultFilterProvider = config.Services.GetFilterProviders().Single(provider => provider is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(IFilterProvider), defaultFilterProvider);

// add custom filter provider
config.Services.Add(typeof(IFilterProvider), new CustomFilterProvider(container));

As have been said, AllowMultiple to false is a hack since .net is clever enough to only execute once a filter even if it has been registered several times. Also, there are scenarios where you do need this to be true.

jbernal
  • 706
  • 1
  • 11
  • 27
  • Thanks for this code but i coundn't able to find FilterProvider with ActionDesctiptorFilterProvider type it give me error Sequence contains no matching element – Niraj Trivedi Jan 29 '18 at 00:51
  • Depends on the actual application configuration, but all matching filters should be removed/replaced: `config.Services.RemoveAll(typeof(System.Web.Http.Filters.IFilterProvider), provider => provider is ActionDescriptorFilterProvider);` – Eugene Y. Nov 14 '18 at 02:12
2

For me, I had specified the filter twice. In my IOC config file I had

builder.Register(c => new SelectListFilter(c.Resolve<ClientManager>()))
        .AsActionFilterFor<Controller>()
        .InstancePerRequest();
        .RegisterFilterProvider();

And then in filterConfig I had

filters.Add(DependencyResolver.Current.GetService<IActionFilter>());

I removed the line from filterConfig and everything was better.

Fabian N.
  • 3,570
  • 2
  • 20
  • 44
Andy V
  • 907
  • 10
  • 16