Была изменена коллекция фильтров действий MVC; операция перечисления может не выполняться
Эта ошибка возникает очень часто в приложении MVC 5.1.3, когда это происходит, пользователь должен обновить страницу, и она уходит, поэтому ее проблема прерывистая.
Мы обнаружили, что это сложно диагностировать, поскольку, как представляется, это происходит в самой структуре. Любые идеи о том, где искать?
Это полный стек:
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)
Ранее был задан аналогичный вопрос: Коллекция была изменена; операция перечисления не может выполняться, но это было разрешено путем обновления до MVC 5, мы уже на 5.
Ответы
Ответ 1
Как отмечает @Erik в комментарии, очевидно, что сбор фильтров изменяется во время выполнения запросов, где он должен быть заполнен только во время запуска приложения.
Одна из возможностей заключается в том, что вы зарегистрировали пользовательский IFilterProvider
, который разбивает код. Здесь исходный код, из которого происходит ошибка (из FilterProviderCollection
)
for (int i = 0; i < providers.Length; i++)
{
IFilterProvider provider = providers[i];
foreach (Filter filter in provider.GetFilters(controllerContext, actionDescriptor))
{
filters.Add(filter);
}
}
provider.GetFilter(...)
возвращает List
, который позже изменен во время перечисления в блоке FilterProviderCollection
foreach
.
Вот что приходит мне на ум, чтобы проверить:
-
Прежде всего, убедитесь, что вы не регистрируете пользовательский IFilterProvider
(либо вы, либо библиотеку, которую вы можете использовать). Если это так, это основной подозреваемый.
-
Посмотрите на все применения классов GlobalFilterCollection
и GlobalFilters
в вашем коде. Любые изменения в этой коллекции должны достигаться только от Application_Start
в классе Global.asax или Startup
(если вы используете OWIN)
-
Ищите подсказки, где вы создаете фильтры или получаете доступ к ним.
-
Попробуйте перейти на MVC 5.2. Если это проблема с каркасом (что кажется маловероятным), это может исправить это. (Я использую 5.2.2.0 и не вижу подобных проблем в разработке или производстве)
-
Отлаживайте приложение и устанавливайте точку прерывания в начале Application_BeginRequest
и в действии контроллера. Попробуйте проверить коллекцию глобальных фильтров и посмотреть, есть ли какие-либо изменения.
-
Может быть, может быть полезно зарегистрировать пользовательский IFilterProvider
и проверить поведение путем отладки или ведения журнала.