Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Mark Owen 10 posts 102 karma points
    Oct 12, 2018 @ 16:11
    Mark Owen
    0

    User section of back-office fails when using custom dependency injection framework after version 7.7

    Original post name: "NullReferenceException after Umbraco 7.12.3 upgrade due to User section"

    Edit 2:

    So I have renamed this post as I believe I have now identified the problem causing the issue below. It appears that around Umbraco 7.7 some parts of Umbraco have begun relying on an internal dependency injection, contrary to this post: https://our.umbraco.com/documentation/reference/using-ioc

    I proved this by removing our existing dependency injection setup and the backoffice began working as expected. Specifically I removed setting our dependency resolver as the current resolver:

    DependencyResolver.SetResolver(...);
    

    I require getting both a custom dependency injection framework and Umbraco's working together.

    Edit 1:

    Having dug into this some more I've found that other sections don't go anywhere near the code above that causes the NullReferenceException.

    The other sections skip this code entirely, two calls above, in Umbraco.Web.Editors.SectionController due to the fact that they "have dashboards" in the following code on lines 39 - 54:

            var hasDashboards = false;
            IEnumerable<Tab<DashboardControl>> dashboardsForSection;
            if (dashboards.TryGetValue(section.Alias, out dashboardsForSection))
            {
                if (dashboardsForSection.Any())                    
                    hasDashboards = true;
            }
    
            if (hasDashboards == false)
            {
                //get the first tree in the section and get it's root node route path
                var sectionTrees = appTreeController.GetApplicationTrees(section.Alias, null, null).Result;
                section.RoutePath = sectionTrees.IsContainer == false || sectionTrees.Children.Count == 0
                    ? sectionTrees.RoutePath 
                    : sectionTrees.Children[0].RoutePath;
            }
    

    The dashboards appear to be based on the contents of the Dashboard.config file and I have noticed that the are no entries in there for "area" users, but this also seems to be the case in the files directly from the Umbraco package.

    Does this help anyone with any ideas?

    Original post:

    We've recently upgraded from Umbraco 7.6.12 to 7.12.3 and found that the CMS area of Umbraco fails to load as follows:

    Failed to load Umbraco CMS

    The following errors can be found in the network tab/console:

    GET https://***/umbraco/backoffice/UmbracoApi/Section/GetSections 500 (Internal Server Error)
    GET https://***/umbraco/ysod 404 (Not Found)
    

    Looking into the logs this is the error:

        2018-10-12 16:52:06,304 [P20804/D3/T10] ERROR Umbraco.Web.Editors.SectionController - Unhandled controller exception occurred
    System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
       at Umbraco.Web.Trees.ApplicationTreeExtensions.TryLoadFromControllerTree(ApplicationTree appTree, String id, FormDataCollection formCollection, HttpControllerContext controllerContext)
       at Umbraco.Web.Trees.ApplicationTreeController.<GetRootForSingleAppTree>d__2.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at Umbraco.Web.Trees.ApplicationTreeController.<GetApplicationTrees>d__0.MoveNext()
    

    After several rounds of changing the config files for Umbraco I found that disabling the user section in trees.config resolves the issue, but obviously I need to solve the Users section.

    <!--Users-->
      <add initialize="false" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, umbraco" />
    

    I tried debugging this issue in Umbraco and found that the issue is around line 185 in Umbraco.Web.Trees.ApplicationTreeExtensions.

    var instance = (TreeController)DependencyResolver.Current.GetService(foundControllerTree);
    instance.ControllerContext = controllerContext;
    

    The problem here is that the DependencyResolver doesn't return any result for when foundControllerTree is Umbraco.Web.Trees.UserTreeController leading to a NullReferenceException on the next line.

    We do setup our own DependencyResolver in the custom code we have written, so I suspect the problem is around that, but as it's never caused us any problems with any other areas of Umbraco now, we are unsure why it would now or how to resolve it.

    I've noticed a similar/the same problem popping up a couple of other times in this forum, with people seemingly fixing their problems by making a change in their dependency injection frameworks, but no one has posted an actual solution. In case it is useful the dependency injection framework we are using is SimpleInjector.

    Any ideas welcome.

    Thanks, Mark

  • Mark Owen 10 posts 102 karma points
    Oct 19, 2018 @ 10:43
    Mark Owen
    102

    I resolved this in the end by writing a multi-tenant dependency resolver class and using this.

    Multi-tenant dependency resolver (based on answer here: https://stackoverflow.com/questions/15842827/is-it-possible-to-have-multiple-dependency-resolvers-in-asp-net-mvc-3):

     public class MultiTenantDependencyResolver : IDependencyResolver
      {
        private readonly IEnumerable<IDependencyResolver> _dependencyResolvers;
    
        public MultiTenantDependencyResolver(
          IEnumerable<IDependencyResolver> dependencyResolvers)
        {
          _dependencyResolvers = dependencyResolvers;
        }
    
        public object GetService(Type serviceType)
        {
          return _dependencyResolvers
            .Select(dependencyResolver => dependencyResolver.GetService(serviceType))
            .FirstOrDefault(service => service != null);
        }
    
        public IEnumerable<object> GetServices(Type serviceType)
        {
          return _dependencyResolvers
            .SelectMany(dependencyResolver => dependencyResolver.GetServices(serviceType));
        }
      }
    

    Code to use it:

      if (DependencyResolver.Current != null)
      {
        DependencyResolver.SetResolver(new MultiTenantDependencyResolver(new List<IDependencyResolver>
        {
          myDependencyResolver,
          DependencyResolver.Current
        }));
      }
      else
      {
        DependencyResolver.SetResolver(myDependencyResolver);
      }
    
  • Gordon Saxby 1444 posts 1855 karma points
    Jul 04, 2019 @ 10:19
    Gordon Saxby
    0

    Thank you very much for this post - I had the same issue after upgrading to 7.7.13. The above code has solved it for me too.

Please Sign in or register to post replies

Write your reply to:

Draft