#How to register your own dependencies

1 messages · Page 1 of 1 (latest)

terse lichen
#

Can someone please tell me how to register a class so it can be injected because these docs aren't working for me at all. I think they are written for experts rather than people that want to learn, but I may be wrong:
https://docs.umbraco.com/umbraco-cms/reference/using-ioc

I have a static helper class I wish to inject into a surface controller to use it's methods but I think I need to register it first. So trying to work out from the docs how to do that and failing miserably. I'm happy with the concept of DI and can do it all day long with Umbraco services, but registering my own is the issue here.

Cobbling instructions together from the Vendr DI page I tried adding:-

services.AddTransient<Helpers>(); to ConfigureServices in startup.cs but that just gives me:

Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Web.Core.Services.Helpers Lifetime: Transient ImplementationType: Web.Core.Services.Helpers': Unable to resolve service for type 'Umbraco.Cms.Core.Models.PublishedContent.IPublishedContent' while attempting to activate 'Web.Core.Services.Helpers'.)

So I have:

Namespace: myProj.Core.Services
Class: Helpers (with various methods)

Then what?

Thanks.

Inversion of Control/Dependency Injection in Umbraco

lethal jackal
#

How's your helper class looking in terms of constructors?

terse lichen
#
    private readonly IPublishedContent _publishedContent;
    private readonly IPublishedContentQuery _contentQuery;

    public Helpers(IPublishedContent publishedContent, IPublishedContentQuery contentQuery) {
        _publishedContent = publishedContent;
        _contentQuery = contentQuery;
    } 
    
    public IPublishedContent? GetMemorialListNode() {
            
        IPublishedContent? siteRoot = _contentQuery.ContentAtRoot().FirstOrDefault();
        var memorialListNode = siteRoot?.FirstChild<MemorialListPage>();
            
        return memorialListNode;
    }
    
}```
#

This is the first of what I expect to be half a dozen helper methods. It's just trying to find the listing container so I can add content nodes underneath it.

raven lance
#

Remove the IPublishedContent from the constructor, as it can't be injected.

viscid egret
#

The reason behind Dan's answer being: a dependency injection container can only produce services of types that are explicitly registered during startup. A class that you register may only take a dependency on another type if that other type is registered in the container as well. IPublishedContent is not registered in the container: it is produced by methods on the Umbraco context, therefore you cannot take dependency on IPublishedContent.

terse lichen
jaunty flume
#

You can inject an IUmbracoContextAccessor to get access to that

#

You'll need an if statement to get access to the context itself, e.g.

if (umbracoContextAccessor.TryGetUmbracoContext(out var umbracoContext))
{
    [... code here]
}
terse lichen
#

Thanks for that. Using the docs (https://docs.umbraco.com/umbraco-cms/reference/querying/umbraco-context) I now have this, but no idea what Problem is meant to be so it's a bit inelegant around there, but it works.

    
    private readonly IUmbracoContextAccessor _umbracoContextAccessor;

    public Helpers(IUmbracoContextAccessor umbracoContextAccessor)
    {
        _umbracoContextAccessor = umbracoContextAccessor;
    }  
    
    public IPublishedContent GetMemorialListNode() {
        
        if (_umbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext? context) == false) {
            return null; //this.Problem("unable to get content");
        }

        if (context.Content == null) {
            return null; //this.Problem("Content Cache is null");
        } 
        
        IPublishedContent? siteRoot = context.Content.GetAtRoot().FirstOrDefault();
        var memorialListNode = siteRoot?.FirstChild<MemorialListPage>();
            
        return memorialListNode;
    }
}```

The UmbracoContext is a helpful service provided on each request to the website

jaunty flume
#

Awesome :)

#

When it comes to IoC, I find the thing to remember is when you're injecting things they're going to usually stay the same through the whole process, so you don't want to inject things that are going to change at some point - pass in stuff like IPublishedContent and queries and the like as method parameters, and inject services and helper classes like this

terse lichen
#

I should also mention the actual registration has been done like this:-

        {
            services.AddUmbraco(_env, _config)
                .AddBackOffice()
                .AddWebsite()
                .AddSlimsy()
                .AddComposers()
                .Build();

            services.AddTransient<Helpers>();
        }```
terse lichen
jaunty flume
#

You should inject them, sorry