I would like to use UmbracoHelper to lookup some published content when saving a media node (in order to update some custom properties on the media node), but the question would generally apply to any instance where we have custom event code running and would like to access UmbracoHelper or other services, etc.
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Web;
public class RegisterEventsComposer : ComponentComposer<RegisterEventsComponent>
{
//Events added via RegisterEventsComponent
}
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class RegisterEventsComponent : IComponent
{
private readonly UmbracoHelper _umbracoHelper;
public RegisterEventsComponent(UmbracoHelper umbracoHelper)
{
_umbracoHelper = umbracoHelper;
}
public void Initialize()
{
// ApplicationStarted event in V7: add your events here
//Events
MediaService.Saving += MediaService_Saving;
}
public void Terminate()
{
// called when the Umbraco application shuts down.
MediaService.Saving -= MediaService_Saving;
}
private void MediaService_Saving(IMediaService sender, SaveEventArgs<IMedia> e)
{
foreach (var doc in e.SavedEntities)
{
//By Specific MediaType
switch (doc.ContentType.Alias)
{
case "myMediaTypeAlias":
//Do stuff using _umbracoHelper here
break;
default:
//Nothing
break;
}
}
}
}
This compiles just fine, but when I run the site, it blows up with a boot error:
Server Error in '/' Application.
Boot failed: Umbraco cannot run. See Umbraco's log file for more details.
-> Umbraco.Core.Exceptions.BootFailedException: Boot failed.
-> System.NullReferenceException: Object reference not set to an instance of an object.
at Umbraco.Web.Runtime.WebInitialComposer.<>c.<Compose>b__0_6(IFactory factory) in D:\a\1\s\src\Umbraco.Web\Runtime\WebInitialComposer.cs:line 121
at DynamicMethod(Object[] )
at LightInject.PerContainerLifetime.GetInstance(Func`1 createInstance, Scope scope) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 6169
at LightInject.ServiceContainer.EmitLifetime(ServiceRegistration serviceRegistration, Action`1 emitMethod, IEmitter emitter) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 4656
at LightInject.ServiceContainer.<>c__DisplayClass153_0.<CreateEmitMethodWrapper>b__0(IEmitter ms) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 3856
at LightInject.ServiceContainer.CreateDynamicMethodDelegate(Action`1 serviceEmitter) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 3776
at LightInject.ServiceContainer.CreateDelegate(Type serviceType, String serviceName, Boolean throwError) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 4743
at LightInject.ServiceContainer.CreateDefaultDelegate(Type serviceType, Boolean throwError) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 4705
at LightInject.ServiceContainer.GetInstance(Type serviceType) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 3437
at Umbraco.Core.Composing.ComponentCollectionBuilder.CreateItem(IFactory factory, Type itemType) in D:\a\1\s\src\Umbraco.Core\Composing\ComponentCollectionBuilder.cs:line 33
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Umbraco.Core.Composing.ComponentCollectionBuilder.CreateItems(IFactory factory) in D:\a\1\s\src\Umbraco.Core\Composing\ComponentCollectionBuilder.cs:line 25
at Umbraco.Core.Composing.CollectionBuilderBase`3.CreateCollection(IFactory factory) in D:\a\1\s\src\Umbraco.Core\Composing\CollectionBuilderBase.cs:line 120
at LightInject.PerContainerLifetime.GetInstance(Func`1 createInstance, Scope scope) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 6169
at LightInject.ServiceContainer.EmitLifetime(ServiceRegistration serviceRegistration, Action`1 emitMethod, IEmitter emitter) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 4656
at LightInject.ServiceContainer.<>c__DisplayClass153_0.<CreateEmitMethodWrapper>b__0(IEmitter ms) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 3856
at LightInject.ServiceContainer.CreateDynamicMethodDelegate(Action`1 serviceEmitter) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 3776
at LightInject.ServiceContainer.CreateDelegate(Type serviceType, String serviceName, Boolean throwError) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 4743
at LightInject.ServiceContainer.CreateDefaultDelegate(Type serviceType, Boolean throwError) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 4705
at LightInject.ServiceContainer.GetInstance(Type serviceType) in C:\projects\lightinject\src\LightInject\LightInject.cs:line 3437
at Umbraco.Core.FactoryExtensions.GetInstance[T](IFactory factory) in D:\a\1\s\src\Umbraco.Core\FactoryExtensions.cs:line 23
at Umbraco.Core.Runtime.CoreRuntime.Boot(IRegister register, DisposableTimer timer) in D:\a\1\s\src\Umbraco.Core\Runtime\CoreRuntime.cs:line 187
Though it isn't clearly specified, I assume the issue is that at boot, UmbracoContext isn't ready... or something like that.
If I replace:
...
public RegisterEventsComponent(UmbracoHelper umbracoHelper)
{
_umbracoHelper = umbracoHelper;
}
...
with
...
public RegisterEventsComponent()
{
}
...
The boot error goes away, but of course, I don't have my UmbracoHelper now.
I've also struggled with injecting the UmbracoHelper, especially for methods that might run in background-threads (ie when populating examine-indexes etc).
I've found that the way to go is to use the "IUmbracoContextFactory" and access the content-cache this way, this works in all the places that I've needed access to the cache, custom events, controllers, examine population and also in background-jobs (like when we're using Hangfire to do stuff).
So in our solutions we always use the IContextFactory in any "repository" that needs access to Umbraco to create our domain models.
Utilizing UmbracoHelper in Content/Media events
[Umbraco 8.7.0]
I would like to use UmbracoHelper to lookup some published content when saving a media node (in order to update some custom properties on the media node), but the question would generally apply to any instance where we have custom event code running and would like to access UmbracoHelper or other services, etc.
The summary of the long discussion over here: Using UmbracoHelper in a custom class in v8:
Though EASY, it is generally considered bad form to do this:
So, based on the documentation here: Injecting Services into a Component, I tried to do something better. Here is my code setup:
This compiles just fine, but when I run the site, it blows up with a boot error:
Though it isn't clearly specified, I assume the issue is that at boot, UmbracoContext isn't ready... or something like that.
If I replace:
with
The boot error goes away, but of course, I don't have my UmbracoHelper now.
So, what is the proper way to do this?
Hi!
I've also struggled with injecting the UmbracoHelper, especially for methods that might run in background-threads (ie when populating examine-indexes etc).
I've found that the way to go is to use the "IUmbracoContextFactory" and access the content-cache this way, this works in all the places that I've needed access to the cache, custom events, controllers, examine population and also in background-jobs (like when we're using Hangfire to do stuff).
So in our solutions we always use the IContextFactory in any "repository" that needs access to Umbraco to create our domain models.
There is some info about this in the docs under "Custom Services and Helpers" on the page that you also linked to: https://our.umbraco.com/documentation/Implementation/Services/
Example with your code:
Thanks, Markus! That worked great :-)
is working on a reply...
This forum is in read-only mode while we transition to the new forum.
You can continue this topic on the new forum by tapping the "Continue discussion" link below.