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()
};
}
}
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:
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
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
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:
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.
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
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.
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'
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?
In GetAll, _productService is always null
Hi David
What if you register your service with the interface??
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:
but just wondering why you had it?
regards
marc
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
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
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
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 workHi 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
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 ofUmbraco.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 writingcomposition.Register<IService, Service>()
would not suggestUmbraco.Core
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...
do you reckon that's clearer?
regards
Marc
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.
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!
Thanks all., problem resolved with the missing namespace being added in.
is working on a reply...