Copied to clipboard

Flag this post as spam?

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


  • Simone Chiaretta 124 posts 488 karma points
    Feb 23, 2017 @ 15:30
    Simone Chiaretta
    0

    Using Unity with WebAPI doesn't work if UmbracoContext is registered as singleton

    I'm bulding some web api to extend the backend of Umbraco. I'm already using Unity and Unity.Mvc to inject depenencies in the views.

    But to extend the approach to backend web api I also had to install the Unity.WebApi package.

    But here I'm encountering some problems. Using the recommended approach of injecting the UmbracoContext.Current as singleton (ContainerControlledLifetimeManager) gives some errors every now and then.

    For example, adding a new node or deleting a node raises an exception

    System.NullReferenceException: Object reference not set to an instance of an object.
    
    at Umbraco.Web.Security.WebSecurity.IsAuthenticated()
       at Umbraco.Web.Security.WebSecurity.ValidateCurrentUser(Boolean throwExceptions)
       at Umbraco.Web.WebApi.UmbracoAuthorizedApiController.get_UmbracoUser()
       at Umbraco.Web.Editors.ContentController.GetEmpty(String contentTypeAlias, Int32 parentId)
    

    But it does work if instead of registering the UmbracoContext.Current as singleton I register it as "per request" (HierarchicalLifetimeManager).

    Since the UmbracoContext.Current just looks inside the HttpContext.Items using one or the other shouldn't be any different.

    Anyone else found issues with this?

    What's the recommended approach by the core team?

    Simone

  • Laurent Lequenne 104 posts 229 karma points
    Feb 24, 2017 @ 14:52
    Laurent Lequenne
    0

    Simone,

            container.RegisterType<UmbracoContext>(
                    new ContainerControlledLifetimeManager(),
                    new InjectionFactory(c => UmbracoContext.Current));
    

    UmbracoContext.Current will be used to create the Singleton object and as it is singleton it will be created only once... the injected value will be the UmbracoContext.Current of your first request.

    The only good reason I think it doesn't break the MVC Unity configuration, is that UmbracoContext.Current reference is not widely used through constructors , or if it used maybe it is used for some global properties that are the same through all requests.

  • Simon Dingley 1219 posts 2777 karma points
    4 days ago
    Simon Dingley
    0

    Did you manage to resolve your issues with this? Everything appears to be working ok for me except when I try to create a new content item via a list view at which point I get the same exception as you. I am using Unity.Mvc5 and Unity.AspNet.WebApi and in the WebActivator class I have the following in the Start() method:

    // Web API
    GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(UnityConfig.Container); ; ;
    // MVC
    DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(UnityConfig.Container));
    
    UnityConfig.RegisterComponents();
    

    And in my UnityConfig class I have the following:

    public static class UnityConfig
    
        private static Lazy<IUnityContainer> container =
            new Lazy<IUnityContainer>(() =>
                {
                    var container = new UnityContainer();
                    return container;
                });
    
        public static IUnityContainer Container => container.Value;
    
        public static void RegisterComponents()
        {
            // Register our type mappings
            RegisterTypes(Container);
        }
    
        public static void RegisterTypes(IUnityContainer container)
        {
            container.RegisterType<UmbracoContext>(new ContainerControlledLifetimeManager(), new InjectionFactory(c => UmbracoContext.Current));
            container.RegisterType<ApplicationContext>(new ContainerControlledLifetimeManager(), new InjectionFactory(c => UmbracoContext.Current));
            container.RegisterType<ServiceContext>(new ContainerControlledLifetimeManager(), new InjectionFactory(c => UmbracoContext.Current));
            container.RegisterType<Umbraco.Web.Mvc.RenderMvcController>(new InjectionConstructor(new ResolvedParameter<UmbracoContext>()));
            container.RegisterType<UmbracoHelper>(new InjectionConstructor(new ResolvedParameter<UmbracoContext>()));
            container.RegisterType<LegacyTreeController>(new InjectionConstructor());
            container.RegisterType<HealthCheckController>(new InjectionConstructor());
            container.RegisterType<UsersController>(new InjectionConstructor());
        }
    }
    
  • Dan Diplo 1165 posts 4140 karma points mvp
    4 days ago
    Dan Diplo
    1

    Like Laurent said, UmbracoContext should be created on a per-request basis, not a lifetime basis. The Umbraco context contains info on the current request, which changes per request. It's equivalent to HttpContext in that regard.

    See https://our.umbraco.org/Documentation/Reference/Common-Pitfalls/

  • Simon Dingley 1219 posts 2777 karma points
    3 days ago
    Simon Dingley
    0

    Thanks Dan, I misunderstood.

    I have replaced:

    container.RegisterType<UmbracoContext>(new ContainerControlledLifetimeManager(), new InjectionFactory(c => UmbracoContext.Current));
    

    with

    container.RegisterType<UmbracoContext>(new PerResolveLifetimeManager(), new InjectionFactory(c => UmbracoContext.Current));
    

    All good so far!

  • Simon Dingley 1219 posts 2777 karma points
    3 days ago
    Simon Dingley
    0

    PerThreadLifetimeManager also seems to work and sounds like it might be more suitable:

    PerThreadLifetimeManager. For this lifetime manager Unity returns, on a per-thread basis, the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects on a per-thread basis. PerThreadLifetimeManager returns different objects from the container for each thread. If you registered a type mapping using configuration or using the RegisterType method, Unity creates a new instance of the registered type the first time the type is resolved in a specified thread, either to answer a call to the Resolve or ResolveAll method for the registered type or to fulfill a dependency while resolving a different type. Subsequent resolutions on the same thread return the same instance.

Please Sign in or register to post replies

Write your reply to:

Draft