NullReferenceException at System.Web.Mvc.FilterProviderColle

本文关键字:Mvc FilterProviderColle Web System at NullReferenceException | 更新日期: 2023-09-27 18:15:08

我有一个MVC 5应用程序。. NET 4.5.1)在Windows 2008 R2 (IIS 7.5)上运行

运行负载测试时,定期抛出以下异常。不幸的是,我不能在本地复制,我被困住了,所以我希望社区可以有更多的想法。(更新:现在已经能够在负载下复制)

查看FilterProviderCollection的源代码。GetFilters暗示它可能是依赖解析器——但是没有更多的信息,我不愿意简单地替换库。目前使用的是SimpleInjector。

如果是这样的话,我猜是由应用程序池回收引起的,但还不能确认这一点(启用日志记录应用程序池中回收的所有原因给我没有任何有用的东西)

经过多次搜索,我确实找到了一些参考资料,它可能是一瞥。我已经确认不是这样的。我还对项目进行了剥离和重建,以帮助获得信心,这不仅仅是一个奇怪的内核包升级。

关于可能导致它的任何建议,或者我如何添加额外的日志记录以捕获更多信息将不胜感激。谢谢。

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)

更新1

我已经能够找到一种在测试环境中复制的方法:

  1. 在应用程序上设置恒定负载(少至20个虚拟用户)
  2. 手动回收应用程序池(重复直到触发失败)

在不加载的情况下回收应用程序池似乎不会触发故障。

更令人担忧的是,将"禁用重叠回收"设置为True并不能阻止它们发生。我原以为这样做会阻止任何回收问题,因为它会在启动新进程之前完全关闭工作进程。

更新2

全球。Asax和相关的配置看起来(对我来说)与默认模板相差不大。看看你是怎么想的?

    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);
            }

各种各样的XxxConfig类几乎都不在模板中。

    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);
            }

更新3

在关闭重叠回收的情况下运行时,我能够获得以下变体堆栈跟踪:

[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

[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

NullReferenceException at System.Web.Mvc.FilterProviderColle

下面这行给你造成了麻烦:

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

可以多次调用MyHttpApplication,这会导致创建多个容器,每个容器都尝试使用RegisterMvcIntegratedFilterProvider将自己注册为过滤器提供程序。你应该确保只有一个容器实例是为该应用程序域创建的,所以你只需要调用RegisterMvcIntegratedFilterProvider一次。

首先,感谢Steven帮忙分析这个问题。

原来问题是由于SimpleInjectorConfig.InitializeContainer的无害放置。

而ASP。. NET运行时确保Application_Start只被调用一次,它可以创建多个httpapplication。在actor中调用意味着应该一次运行的初始化最终在负载下回收时被调用了很多次。

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

把这个移到Application_Start可以解决当前的问题。

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

考虑到调用仅在支持IHttpModule的tor中,我还采取了进一步的步骤,使依赖项被注入到IHttpModule的。