This project is read-only.

Couldn't use OutputCache in MVC Application

Dec 17, 2014 at 8:08 AM
We use SImple Injector in our MVC - Application, when we activate the Output Cache (using the OutputCache-Attribute) we receive the following Error. The application code inside the controller-action in question is not being hit and there is no parameter being passed to the controller-action.
Static property requires null instance, non-static property requires non-null instance.
Parameter name: expression

Stacktrace:
   at System.Linq.Expressions.Expression.Property(Expression expression, PropertyInfo property)
   at SimpleInjector.Advanced.PropertyInjectionHelper.<>c__DisplayClass5.<BuildPropertyInjectionExpressions>b__3(<>f__AnonymousType1`2 pair)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at SimpleInjector.Advanced.PropertyInjectionHelper.BuildPropertyInjectionExpressions(ParameterExpression targetParameter, PropertyInfo[] properties, ParameterExpression[] dependencyParameters)
   at SimpleInjector.Advanced.PropertyInjectionHelper.BuildPropertyInjectionDelegateInternal(PropertyInfo[] properties)
   at SimpleInjector.Advanced.PropertyInjectionHelper.BuildPropertyInjectionDelegate(PropertyInfo[] properties)
   at SimpleInjector.Advanced.PropertyInjectionHelper.BuildPropertyInjectionExpression(Expression expression, PropertyInfo[] properties)
   at SimpleInjector.Advanced.PropertyInjectionHelper.BuildPropertyInjectionExpression(Container container, Type implementationType, PropertyInfo[] properties, Expression expressionToWrap)
   at SimpleInjector.PropertyInjector.BuildDelegate()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at System.Lazy`1.get_Value()
   at SimpleInjector.PropertyInjector.Inject(Object instance)
   at SimpleInjector.Container.InjectProperties(Object instance)
   at SimpleInjector.Integration.Web.Mvc.SimpleInjectorLegacyFilterProvider.GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   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 Web.Core.Controllers.DefaultController.BeginExecuteCore(AsyncCallback callback, Object state) in e:\git\DealerNet\Web\Web.Core\Controllers\DefaultController.cs:line 112
   at System.Web.Mvc.Controller.<BeginExecute>b__14(AsyncCallback asyncCallback, Object callbackState, Controller controller)
   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.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState)
Our Configuration of Simple Inejector is the following:
    //create the DI-container
        public static void Compose()
        {
            Injection.Global = new Container();

            //Injection.Global.RegisterMvcControllers(typeof(MvcSiteMapProvider.SiteMaps).Assembly);
            Injection.Global.RegisterMvcControllers(Assembly.GetExecutingAssembly());
            Injection.Global.RegisterMvcAttributeFilterProvider();

            InitializeContainer(Injection.Global);

            //Injection.Global.Verify();//TODO: remove this for production (creates an instance of every type)

            DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(Injection.Global));
        }


        private static void InitializeContainer(Container container)
        {
            container.RegisterSingle<ILoginRepository, LoginDao>();
            container.RegisterSingle<IPersonDao, KtmWebServicePersonDao>();
            container.RegisterSingle<IDownloadCenterDao, KtmDownloadCenterDao>();

            // Setup configuration of DI (required)
            MvcSiteMapProviderContainerInitializer.SetUp(container);

            // Setup global sitemap loader (required)
            MvcSiteMapProvider.SiteMaps.Loader = container.GetInstance<ISiteMapLoader>();

        }
Dec 17, 2014 at 8:20 AM
Which version of Simple Injector are you using?

By looking at the stack trace I can see that the SimpleInjectorLegacyFilterProvider is called. This means that the error occurs while trying to use the (legacy) Container.InjectProperties method on a MVC filter attribute. Can you show the code for the filter attribute that is causing this? It shouldn't be very hard for you to figure out which filter attributes are applied to this controller action. By commenting out the attributes one by one, you can find out which attribute is causing this.
Dec 17, 2014 at 8:25 AM
we are using version 2.5.2.
we already tried disabling the filters one-by-one. the attribute that is causing the problem is the outputcache-attribute which is included in the asp.net mvc framework.
Dec 17, 2014 at 8:59 AM
The code of the MVC filter attributte can be found here:
https://searchcode.com/codesearch/view/25097638/
Dec 17, 2014 at 9:28 AM
This is probably a bug in the Container.InjectProperties method. In this case you are out of luck while using the RegisterMvcAttributeFilterProvider. Both the Container.InjectProperties method and RegisterMvcAttributeFilterProvider extension method are made deprecated (read here and here) since version 2.6 and this not only means that we advise not using it, but it also means that bugs in that part of the API are not fixed.

The best solution is to move away from implicit property injection and the use of the deprecated RegisterMvcAttributeFilterProvider. This page explains how to change your code. Basically this means using the new RegisterMvcIntegratedFilterProvider extension method, override the default property selection behavior and mark the properties on your filter attributes that need injection with an attribute. This prevent Simple Injector from trying to inject anything in places other than that you specified explicitly (such as the OutputCacheAttribute). This also prevents a range of other errors as explained here.

If you have any questions, please let me know.
Marked as answer by dot_NET_Junkie on 12/25/2014 at 2:39 PM
Dec 17, 2014 at 1:01 PM
Thank you very much for the prompt and appropriate response.
Now everything works as desired.