Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC Action Filters Collection was modified; enumeration operation may not execute

We have this error occurring very frequently in an MVC 5.1.3 application, when it does happen, the user has to refresh the page and it does away, so its an intermittent issue.

We have found it tricky to diagnose as it appears to happen within the framework itself. Any ideas on where to look?

This is the full stack:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Web.Mvc.FilterProviderCollection.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state)
   at System.Web.Mvc.Controller.<BeginExecuteCore>b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TState](AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext)
   at System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TState](AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext)
   at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TState](AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

There has been a similar question asked before: Collection was modified; enumeration operation may not execute, but this was resolved by upgrading to MVC 5, we already on 5.

like image 456
Dan Avatar asked Apr 03 '15 09:04

Dan


1 Answers

As @Erik said in a comment, obviously the collection of filters are being modified during the execution of the requests, where it should only be populated during application start up.

One possibility is that you've registered a custom IFilterProvider which is breaking the code. Here's the source code from where the error occurs (from FilterProviderCollection)

        for (int i = 0; i < providers.Length; i++)
        {
            IFilterProvider provider = providers[i];
            foreach (Filter filter in provider.GetFilters(controllerContext, actionDescriptor))
            {
                filters.Add(filter);
            }
        }

The provider.GetFilter(...) is returning a List which is later modified during enumeration in the FilterProviderCollection's foreach block.

Here's what comes to my mind for you to test:

  • First of all, make sure you're not registering a custom IFilterProvider (either you, or a library you might be using). If so, that is the primary suspect.

  • Look for all usages of GlobalFilterCollection and GlobalFilters class in your code. Any modification to this collection should only be reached from Application_Start in Global.asax or the Startup class (if you're using OWIN)

  • Look for clues where you're creating filters or accessing them.

  • Try upgrading to MVC 5.2. If it's an issue with the framework (which seems unlikely) this may fix it. (I'm using 5.2.2.0 and don't see any similar issues in either development or production)

  • Debug your application, and set a break point in the beginning of Application_BeginRequest and in the controller action. Try to inspect the global filters collection and see if there's any change.

  • Maybe registering a custom IFilterProvider and inspecting the behavior by debugging or logging can be helpful.

like image 172
Iravanchi Avatar answered Nov 16 '22 01:11

Iravanchi