The documentation for v7 and IoC doesn't apply to v8. Is it as simple as implementing IComposer, and then registering the types we need? What about the controllers and the API pieces as well?
You can indeed just implement IUserComposer to register your types with the DI container and then they will be injected when needed.
Small example:
using Umbraco.Core;
using Umbraco.Core.Composing;
public class SomeComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IServiceOne, ServiceOne>();
composition.Register<IServiceTwo, ServiceTwo>();
}
}
And then in your ApiController:
using Umbraco.Web.WebApi;
public class SomeApiController : UmbracoApiController
{
private readonly IServiceOne _serviceOne;
private readonly IServiceTwo _serviceTwo;
public SomeApiController(IServiceOne serviceOne, IServiceTwo serviceTwo)
{
_serviceOne = serviceOne;
_serviceTwo = serviceTwo;
}
// API methods here as usual
}
Hi Daniël, i installed umbraco 8.1.3 and i'm trying to configure dependecy injection following this post, but not work.
Me code is:
Controller:
public class ContactController : UmbracoApiController
{
private readonly IContactService contactService;
public ContactController(IContactService contactService)
{
this.contactService = contactService;
}
[HttpPost]
public void Post([FromBody]ContactDto request)
{
this.contactService.Register(request);
}
}
Service:
public interface IContactService
{
void Register(ContactDto contact);
}
public class ContactService : IContactService
{
public ContactService()
{
}
public void Register(ContactDto contact)
{
//Implement
}
}
DI Config:
public class ApplicationComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.RegisterFor<IContactService, ContactService>();
}
}
Error:
"Message": "An error has occurred.",
"ExceptionMessage": "An error occurred when trying to create a controller of type 'ContactController'. Make sure that the controller has a parameterless public constructor.",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "Unable to resolve type: MySite.Controllers.ContactController, service name: ",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at LightInject.ServiceContainer.CreateDelegate(Type serviceType, String serviceName, Boolean throwError) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4748\r\n at LightInject.ServiceContainer.CreateDefaultDelegate(Type serviceType, Boolean throwError) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4705\r\n at LightInject.ServiceContainer.TryGetInstance(Type serviceType) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 3493\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "Unresolved dependency [Target Type: MySite.Controllers.ContactController], [Parameter: contactService(IServices.Contacts.IContactService)], [Requested dependency: ServiceType:IServices.Contacts.IContactService, ServiceName:]",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at LightInject.ServiceContainer.EmitConstructorDependency(IEmitter emitter, Dependency dependency) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4163\r\n at LightInject.ServiceContainer.EmitConstructorDependencies(ConstructionInfo constructionInfo, IEmitter emitter, Action`1 decoratorTargetEmitter) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4120\r\n at LightInject.ServiceContainer.EmitNewInstanceUsingImplementingType(IEmitter emitter, ConstructionInfo constructionInfo, Action`1 decoratorTargetEmitMethod) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4081\r\n at LightInject.ServiceContainer.EmitNewInstance(ServiceRegistration serviceRegistration, IEmitter emitter) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4038\r\n at LightInject.ServiceContainer.CreateDynamicMethodDelegate(Action`1 serviceEmitter) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 3777\r\n at LightInject.ServiceContainer.CreateInstanceDelegateIndex(Action`1 emitMethod) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4693\r\n at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)\r\n at LightInject.ServiceContainer.EmitLifetime(ServiceRegistration serviceRegistration, Action`1 emitMethod, IEmitter emitter) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4664\r\n at LightInject.ServiceContainer.<>c__DisplayClass153_0.<CreateEmitMethodWrapper>b__0(IEmitter ms) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 3856\r\n at LightInject.ServiceContainer.CreateDynamicMethodDelegate(Action`1 serviceEmitter) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 3777\r\n at LightInject.ServiceContainer.CreateDelegate(Type serviceType, String serviceName, Boolean throwError) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4743",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "Missing public constructor for Type: IServices.Contacts.IContactService",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at LightInject.MostResolvableConstructorSelector.Execute(Type implementingType) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 5558\r\n at LightInject.TypeConstructionInfoBuilder.Execute(Registration registration) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 5719\r\n at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)\r\n at LightInject.ServiceContainer.EmitNewInstance(ServiceRegistration serviceRegistration, IEmitter emitter) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4028\r\n at LightInject.ServiceContainer.<>c__DisplayClass153_0.<CreateEmitMethodWrapper>b__0(IEmitter ms) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 3856\r\n at LightInject.ServiceContainer.<>c__DisplayClass153_0.<CreateEmitMethodWrapper>b__0(IEmitter ms) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 3856\r\n at LightInject.ServiceContainer.EmitConstructorDependency(IEmitter emitter, Dependency dependency) in C:\\projects\\lightinject\\src\\LightInject\\LightInject.cs:line 4158"
}
}
}
You are using RegisterFor(), but you are looking for the Register() method instead, which is a built-in extension method in the Umbraco.Core namespace (hence my example has the using Umbraco.Core; line). I see in your referenced StackOverflow that you have added this extension method yourself but that is not necessary as it is provided by Umbraco.
I have some pre-existing DI code using Autofac in an umbraco 7 project, and looking for the equivalent best practice in umbraco 8. It sounds like ‘Compositions’ is what I should port the code to.
Is this correct or am i missing something. all the stuff i seen online suggest i dont need to use the typeof wrapper but i cant get it to work without it?
Make sure to include using Umbraco.Core; at the top of your file. The Register<T>(IService, Service) method and some others are defined as extension methods in the Umbraco.Core namespace.
Umbraco 8 and IoC
The documentation for v7 and IoC doesn't apply to v8. Is it as simple as implementing IComposer, and then registering the types we need? What about the controllers and the API pieces as well?
Thanks
Not sure about the IOC stuff, but im pretty sure controllers are all the same
You can indeed just implement
IUserComposer
to register your types with the DI container and then they will be injected when needed.Small example:
And then in your ApiController:
Thanks! At least I was close ;)
very good!
Hi Daniël, i installed umbraco 8.1.3 and i'm trying to configure dependecy injection following this post, but not work. Me code is:
Controller:
Service:
DI Config:
Error:
Can you help me? Thanks
i found the issue. I explain that here
Hi Mauri,
You are using
RegisterFor()
, but you are looking for theRegister()
method instead, which is a built-in extension method in theUmbraco.Core
namespace (hence my example has theusing Umbraco.Core;
line). I see in your referenced StackOverflow that you have added this extension method yourself but that is not necessary as it is provided by Umbraco.Hi Chris,
and maybe this blogpost helps you out a bit as well: https://www.perplex.nl/en/blog/2019/umbraco-v8-changes-for-developers/
Cheerio,
Jeffrey
Great article... thanks!
Hi Chris! Were you able to make it work? I'm in the exact same point and I can't make mine work. Any suggestions?
Yup! I just implemented my own IUserComposer.
hi Jeffrey
thanks for that blog post – that’s very helpful for me too.
Do you know what DI container this is using - Is it LightInject? I suspect the umbraco doc https://our.umbraco.com/documentation/reference/using-ioc saying IoC isn’t used in the v8 core is out of date?
I have some pre-existing DI code using Autofac in an umbraco 7 project, and looking for the equivalent best practice in umbraco 8. It sounds like ‘Compositions’ is what I should port the code to.
Thanks
Andrew
Hi Andrew
That article is for v7. Umbraco 8 uses LightInject.
hi - does anyone know of a blog or thread explaining the various composition methods in a bit more detail / real world examples etc?
thanks
In 8.5.3 i have to use Register like this
composition.Register(typeof(IMyService), typeofMyService));
Is this correct or am i missing something. all the stuff i seen online suggest i dont need to use the typeof wrapper but i cant get it to work without it?
Hi Perry,
Make sure to include
using Umbraco.Core;
at the top of your file. TheRegister<T>(IService, Service)
method and some others are defined as extension methods in theUmbraco.Core
namespace.is working on a reply...