NullReferenceException in System.Web.Mvc.FilterProviderCollection.GetFilters

I have an MVC 5 application (.NET 4.5.1) running under Windows 2008 R2 (IIS 7.5)

The following exception occurs periodically when running load tests. Unfortunately, I cannot reproduce locally and am pretty stuck, so I hope the community can have more ideas. (Update: Now you can play under load)

Looking at the source FilterProviderCollection.GetFilters, suppose its possibly a dependent converter - but without additional information, I don't want to just replace the library. He currently uses SimpleInjector.

If this is the case, I assume that this is caused by a reload of the application pool, but failed to confirm this (enabling registration of all reasons for recycling in the application pool gave me nothing useful)

After a long search, I found several links to it, possibly to Glimpse. I confirmed that this is not so. I also split and rebuilt the project to make sure that its not just the inconvenience of updating a package of a nuget package.

Any suggestions as to what might be causing this, or how I can add extra postings to catch more information would be appreciated. Thanks.

Exception information: Exception type: NullReferenceException Exception message: Object reference not set to an instance of an object. 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.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.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) 

Update 1

I managed to find a way to replicate in a test environment:

  • Put a constant load on the application (total 20 virtual users).
  • Manually dispose of the application pool (several times before the failure)

Utilization of an application pool without load does not cause a failure.

More worrying, setting "Disable Overlapped Recycle" to True does not stop them. This, I suggested, will stop any processing problems, as it will completely ruin the workflow before starting a new one.

Update 2

Global.asax and its related configuration do not look (for me) too far from the default templates. See what you think?

  public class MyHttpApplication : HttpApplication { public MyHttpApplication() { SimpleInjectorConfig.InitializeContainer(); //seems to need to be in ctor to support HttpModule dependencies } protected void Application_Start() { MvcHandler.DisableMvcResponseHeader = true; AreaRegistration.RegisterAllAreas(); ViewEngineConfig.RegisterViewEngines(ViewEngines.Engines); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BinderConfig.RegisterGlobalBinders(ModelBinders.Binders); } 

The various XxxConfig classes largely exit the template.

  public static class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new AuthorizeAttribute()); } } public static class SimpleInjectorConfig { /// <summary>Initialize the container and register it as MVC Dependency Resolver.</summary> public static void InitializeContainer() { var container = new Container(); container.Options.AllowResolvingFuncFactories(); RegisterServices(container); container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); container.RegisterMvcIntegratedFilterProvider(); container.RegisterWebApiControllers(GlobalConfiguration.Configuration); //container.Verify(); //see http://bit.ly/YE8OJj for more info DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); } 

Update 3

When I started with overlapped recirculation, I was able to get the following stack trace options.

 [IndexOutOfRangeException: Index was outside the bounds of the array.] System.Collections.Generic.Enumerator.MoveNext() +112 System.Linq.<ConcatIterator>d__71`1.MoveNext() +643 System.Linq.Buffer`1..ctor(IEnumerable`1 source) +520 System.Linq.Enumerable.ToArray(IEnumerable`1 source) +103 System.Web.Mvc.FilterProviderCollection.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +89 System.Web.Mvc.ControllerActionInvoker.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +38 System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +333 System.Web.Mvc.Controller.<BeginExecuteCore>b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +45 System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +111 System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +203 System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +879 System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +154 System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +527 System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +108 System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +111 System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +150 System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +203 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +665 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +12638163 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288 

and

 [IndexOutOfRangeException: Index was outside the bounds of the array.] System.Collections.Generic.Enumerator.MoveNext() +112 System.Linq.<OfTypeIterator>d__aa`1.MoveNext() +344 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +536 System.Linq.Enumerable.ToList(IEnumerable`1 source) +80 SimpleInjector.SimpleInjectorMvcExtensions.RegisterMvcIntegratedFilterProvider(Container container) +271 WebProject.SimpleInjectorConfig.InitializeContainer() in c:\...\App_Start\SimpleInjectorConfig.cs:35 WebProject.MyHttpApplication..ctor() in c:\...\Global.asax.cs:14 ASP.global_asax..ctor() in c:\...\App_global.asax.3szzcx02.0.cs:0 [TargetInvocationException: Exception has been thrown by the target of an invocation.] System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +159 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +256 System.Activator.CreateInstance(Type type, Boolean nonPublic) +127 System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +14259433 System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +200 System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +28 System.Web.HttpRuntime.CreateNonPublicInstance(Type type, Object[] args) +83 System.Web.HttpApplicationFactory.GetNormalApplicationInstance(HttpContext context) +246 System.Web.HttpApplicationFactory.GetApplicationInstance(HttpContext context) +178 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +333 
+6
source share
2 answers

The following line causes problems:

 public MyHttpApplication() { SimpleInjectorConfig.InitializeContainer(); //seems to need to be in c... } 

MyHttpApplication can be called several times, as a result of which several containers are created, each of which tries to register itself as a filter provider using RegisterMvcIntegratedFilterProvider . You need to make sure that only one container instance is created for this application domain, so you only need to call RegisterMvcIntegratedFilterProvider once.

+2
source

First, thanks for Steven for helping me analyze the problem.

It turns out the problem is with the innocuous placement of SimpleInjectorConfig.InitializeContainer.

While the ASP.NET runtime ensures that Application_Start will be called only once, it can create multiple HttpApplications. Having a call to ctor meant that what was supposed to be started when the initialization ended with what it is called a bunch of times when it is processed under load.

 public MyHttpApplication() { SimpleInjectorConfig.InitializeContainer(); //WRONG } 

Moving this object to Application_Start fixes the immediate problem.

 protected void Application_Start() { SimpleInjectorConfig.InitializeContainer(); } 

Given that the call was only in Ctor to support IHttpModule, I also had one more step allowing dependencies to be injected into IHttpModule. HttpModuleMagic works well for this.

0
source

Source: https://habr.com/ru/post/972954/


All Articles