Copied to clipboard

Flag this post as spam?

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


  • David Houghton 7 posts 95 karma points
    1 week ago
    David Houghton
    0

    Dependency Injection/Composition in back office

    I'm trying to register some custom services, and have them injected into aback office plugin controller, however the constructor in my controller (ProductDetailsApiController) with params never seems to be hit, only the paramaterless constructor gets called.

    I'm thinking that Umbraco isn't set up for DI/IOC into the back office, and I'm banging my head against a brick wall...

    Can anybody shed any light please?

     public class ProductComposer : IUserComposer
    {
        public void Compose(Composition composition)
        {
            composition.Register(typeof(ProductService));
        }
    }
    
    
    
     [PluginController("Store")]
    public class ProductDetailsApiController : UmbracoAuthorizedJsonController
    {
        private readonly IProductService _productService;
    
        public ProductDetailsApiController() { }
        public ProductDetailsApiController(
            IProductService productService)
        {
            _productService = productService;
        }
    
        public JsonNetResult GetAll()
        {            
            return new JsonNetResult
            {
                Data = _productService.GetProducts()
            };
        }
    }
    

    In GetAll, _productService is always null

  • Marc Goodson 1080 posts 7275 karma points MVP 4x c-trib
    1 week ago
    Marc Goodson
    0

    Hi David

    What if you register your service with the interface??

    using Umbraco.Core;
    using Umbraco.Core.Composing;
    using Umbraco8.Services;
    
        namespace Umbraco8.Composers
        {
            public class ProductComposer : IUserComposer
            {
                public void Compose(Composition composition)
                {
       // if your service makes use of the current UmbracoContext, eg AssignedContentItem - register the service in Request scope
                // composition.Register<IProductService, ProductService>(Lifetime.Request);
                // if not then it is better to register in 'Singleton' Scope
                composition.Register<IProductService, ProductService>(Lifetime.Singleton);
                }
            }
        }
    

    since your constructor is expecting an IProductService

    Also what is your intention for the empty constructor?

    In theory you could wire up the service in the parameterless constructor:

    _productService = Current.Factory.GetInstance<IProductService>()
    

    but just wondering why you had it?

    regards

    marc

  • David Houghton 7 posts 95 karma points
    1 week ago
    David Houghton
    0

    Hi Marc,

    Since posting last night, having played around with it a bit more, if I change the constructor parameter to accept ProductService as opposed to IProductService, everything now work as expected.

    With regards to the parameterless constructor, LightInject was throwing errors when it was not present, but the above change resolved that issue as well, so now removed.

    I was originally composing against the interface as you have suggested, however this is were the problem may be. I'm on v 8.5.3, and I actually don't have the Register method available to me which is strange as looking at the docs and your reply, it most definitely should. I only have RegisterFor

    Screenshot attached

    composition

  • Marc Goodson 1080 posts 7275 karma points MVP 4x c-trib
    1 week ago
    Marc Goodson
    100

    Hi David

    Yes, essentially whatever you 'register' should be what is passed into the constructor! so it would work that way around too!

    The Register method 'you do not have' is an extension method in the Umbraco.Core namespace

    so I reckon if you add

    using Umbraco.Core
    

    to the top of your ProductComposer then you should be able to use it to register the service for the interface, as in the example and the docs!

    crosses fingers

    regards

    marc

  • Perry Cope 13 posts 123 karma points
    1 week ago
    Perry Cope
    0

    Had this problem too is this documented anywhere that the namespace is needed? its really confusing it being an extension in Umbraco.core easy to miss the difernce between

    composition.Register<IProductService, ProductService>()

    and

    composition.Register(IProductService, ProductService) which doesnt work

  • Marc Goodson 1080 posts 7275 karma points MVP 4x c-trib
    1 week ago
    Marc Goodson
    0

    Hi Perry

    The bit about registering dependencies in the documentation does include the namespace Umbraco.Core in the example:

    https://our.umbraco.com/Documentation/Reference/Using-Ioc/#registering-dependencies

    but you are right there is no specific warning to tell you to use the namespaces in the example in your implementations, and that Register 'lives there', and it's made more confusing by having the reference to Doccers?

    Do you think it's enough to remove the 'Doccers' bit from the sample to make it more obvious of the Umbraco dependencies required in the sample? or do you think it would be helpful to have a 'warning' node under the example explaining the Register extensions in the example is part of Umbraco.Core namespace

    In the Reference documentation, if you search for 'Register' you'd need to be expecting it to be an Extension method to find the definition:

    https://our.umbraco.com/apidocs/v8/csharp/api/Umbraco.Core.RegisterExtensions.html

    I put together this page here:

    https://our.umbraco.com/Documentation/Implementation/Services/

    to try to give as many examples as possible for using DI in Umbraco and tried to include the correct namespaces at the top of the examples, but again, the docs are always changing, so any thoughts to make them clearer would be ace, or you can edit a page and raise a PR.

    regards

    Marc

  • Perry Cope 13 posts 123 karma points
    1 week ago
    Perry Cope
    0

    Your right it is there, and i think the code sample is fine as is

    Personally id say a warning explaining composition.Register<IService, Service>() is an extension of Umbraco.Core

    The reason being is that Umbraco.Core is well Core its used almost everywhere your doing stuff with Umbraco, and there is no real indication here that core contains an extension method.

    e.g in visual studio if i was to implement IUserComposer manually it would auto suggest importing Umbraco.Core.Composing; but writing composition.Register<IService, Service>() would not suggest Umbraco.Core

  • Marc Goodson 1080 posts 7275 karma points MVP 4x c-trib
    1 week ago
    Marc Goodson
    1

    Hi Perry

    Updated! I've mentioned the register extension method is from Umbraco.Core

    https://our.umbraco.com/Documentation/Reference/Using-Ioc/#registering-dependencies

    and have added a 'tip' box too say remember to add as using statements...

    enter image description here

    do you reckon that's clearer?

    regards

    Marc

  • Perry Cope 13 posts 123 karma points
    1 week ago
    Perry Cope
    0

    Nice tip Personally i think The tip can go under the first Code Block, Dependency Injection is pretty common thing developers come across so didn't need to read anything past the first block as i just needed to know where i register my dependencies.

  • Marc Goodson 1080 posts 7275 karma points MVP 4x c-trib
    1 week ago
    Marc Goodson
    1

    Yes, I updated the introducing sentence so it mentions the namespace 'from the getgo'

    To register your own dependencies to the container you need to do so in a composer (Read more about composers and components) using the 'Register' extension method from 'Umbraco.Core'

    Hope that helps for future devs!

  • David Houghton 7 posts 95 karma points
    1 day ago
    David Houghton
    0

    Thanks all., problem resolved with the missing namespace being added in.

Please Sign in or register to post replies

Write your reply to:

Draft