Copied to clipboard

Flag this post as spam?

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


  • Henrik Sunesen 84 posts 281 karma points
    Sep 10, 2022 @ 19:56
    Henrik Sunesen
    0

    Umbraco 10 Dependency injection question

    Hi all

    I'm pretty new to DI and haven't worked with it before. I need to be able to call a function that creating some nodes in umbraco without sending all the surfacecontroller parameters:

    public FeedController(IUmbracoContextAccessor umbracoContextAccessor,
             IUmbracoDatabaseFactory databaseFactory,
             ServiceContext services,
             AppCaches appCaches,
             IProfilingLogger profilingLogger,
             IPublishedUrlProvider publishedUrlProvider)
             : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
        {
        }
    
        public async Task<string> DownloadFeed()
        {
            // Do stuff
         }
    

    I've tried to read the documentation, but can't get it through my skull how i can make this work.

    Right now i have my method in a SurfaceController, but i need to run the method en a schedule task setup. And i can't just instantiate a new surfacecontroller object and call the function (i dont have access to send all the parameters when instantiate).

  • Marc Goodson 2157 posts 14431 karma points MVP 9x c-trib
    Sep 13, 2022 @ 08:04
    Marc Goodson
    0

    Hi Henrik

    I think what you need to create is a 'service', an independent piece of code that does your stuff, that can be called from a SurfaceController or from your Scheduled Task.

    It would have a constructor that takes in ONLY the dependencies required to achieve the task - so probably wouldn't need all the dependencies that a SurfaceController needs and so would be easier to create in your Scheduled Task.

    There is quite a good article about Services and Helpers here: https://our.umbraco.com/documentation/implementation/Services/ (that is long but has examples!!! - if you look at how the 'SiteService' works in the example, it shows you how to create an Interface, an implementation of the interface and the registration of the service with dependency injection which allows you to 'inject it' into places like your SurfaceController...

    eg

      public class DownloadingFeedService : IDownloadingFeedService {
    // if your feed needs to query umbraco you'll need the factory to get access to the Umbraco Context
      private readonly IUmbracoContextFactory _umbracoContextFactory;
    
            public DownloadingFeedService(IUmbracoContextFactory umbracoContextFactory)
            {
                _umbracoContextFactory = umbracoContextFactory;
            }
    
            public async Task<string> DoStuff(){
    // do stuff
    }
    
    }
    

    Then in a composer or your StartUp file you can register your service

    builder.Services.AddSingleton<IDownloadingFeedService, DownloadingFeedService>();
    

    Then you'll be able to inject into your SurfaceController:

    private readonly IDownloadFeedService _downloadFeedService;
    public FeedController(IUmbracoContextAccessor umbracoContextAccessor,
             IUmbracoDatabaseFactory databaseFactory,
             ServiceContext services,
             AppCaches appCaches,
             IProfilingLogger profilingLogger,
             IPublishedUrlProvider publishedUrlProvider, IDownloadFeedService downloadFeedService)
             : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
        {
    _downloadFeedService = downloadFeedService;
        }
    
        public async Task<string> DownloadFeed()
        {
           _return await downloadFeedService.DoStuff();
         }
    

    or at least that is the gist of it!

    regards

    Marc

  • Henrik Sunesen 84 posts 281 karma points
    Sep 16, 2022 @ 07:45
    Henrik Sunesen
    0

    Thank you Mark, that helped me a little bit further.

    But i do really need all the surface controller properties. my methods need CRUD access to both content and media sections in Umbraco.

    Maybe I just don't get it. Normaly i call the function from a scheduled task in Plesk (by url). But this new project is hosted on the Umbraco Cloud, and they don't offer this "url scheduled task" option.

    And i can't get my head around the best way to do this :/

  • Roy Berris 89 posts 577 karma points c-trib
    Sep 16, 2022 @ 09:35
    Roy Berris
    1

    Hi, I think you want to inject the IContentService and IMediaService. It doesn't matter if you inject this in to a controller, or a service you've set up yourself.

    https://our.umbraco.com/documentation/Fundamentals/Code/Umbraco-Services/

  • Marc Goodson 2157 posts 14431 karma points MVP 9x c-trib
    Sep 16, 2022 @ 08:48
    Marc Goodson
    1

    Hi Henrik

    If it's a scheduled task you need to run, do you need the scheduling aspect to occur 'outside fo Umbraco'?

    Because you could use the inbuilt RecurringHostedService functionality?

    There is an example here in the docs:

    https://our.umbraco.com/documentation/reference/Scheduling/

    You can see they've injected the IContentService into the task, you can do the same with IMediaService to be able to perform your CRUD

    regards

    marc

  • Henrik Sunesen 84 posts 281 karma points
    Sep 26, 2022 @ 07:43
    Henrik Sunesen
    0

    Hi Marc

    Yes, I want to use the RescurringHostedService. But i'm still a little confused. I have addede the IContentService and IMediaService to the constructor:

    SchedulingUpdateCases : RecurringHostedServiceBase
    
     public SchedulingUpdateCases(
               IRuntimeState runtimeState,
               IContentService contentService,
               IMediaService mediaService,
               IServerRoleAccessor serverRoleAccessor,
               IProfilingLogger profilingLogger,
               ILogger<SchedulingUpdateCases> logger,
               IScopeProvider scopeProvider)
               : base(logger, HowOftenWeRepeat, DelayBeforeWeStart)
            {
                _runtimeState = runtimeState;
                _contentService = contentService;
                _mediaService = mediaService;
                _serverRoleAccessor = serverRoleAccessor;
                _profilingLogger = profilingLogger;
                _logger = logger;
                _scopeProvider = scopeProvider;
    
            }
    

    But I still need access to MediaFileManager and MediaUrlGeneratorCollection (I have access to these in my current surfacecontroller).

  • Marc Goodson 2157 posts 14431 karma points MVP 9x c-trib
    Sep 26, 2022 @ 11:26
    Marc Goodson
    0

    Hi Henrik

    I reckon, that you could inject them too?

    SchedulingUpdateCases : RecurringHostedServiceBase
    
    private readonly _MediaFileManager;
    private readonly _MediaUrlGeneratorCollection;
    
     public SchedulingUpdateCases(
               IRuntimeState runtimeState,
               IContentService contentService,
               IMediaService mediaService,
               IServerRoleAccessor serverRoleAccessor,
               IProfilingLogger profilingLogger,
               ILogger<SchedulingUpdateCases> logger,
               IScopeProvider scopeProvider,
               MediaFileManager mediaFileManager, 
               MediaUrlGeneratorCollection mediaUrlGeneratorCollection) : base(logger, HowOftenWeRepeat, DelayBeforeWeStart)
            {
                _runtimeState = runtimeState;
                _contentService = contentService;
                _mediaService = mediaService;
                _serverRoleAccessor = serverRoleAccessor;
                _profilingLogger = profilingLogger;
                _logger = logger;
                _scopeProvider = scopeProvider;
                _mediaFileManager = mediaFileManager;
                _mediaUrlGeneratorCollection = mediaUrlGeneratorCollection;
    
            }
    

    hopefully...

    regards

    Marc

Please Sign in or register to post replies

Write your reply to:

Draft