Whenever you need to modify an entity that Umbraco stores in the database, there are a number of service APIs available to help you. This means that you can create, update and delete any of the core Umbraco entities directly from your custom code.
Accessing the Umbraco services
Services are typically defined using interfaces. Umbraco has them in the Umbraco.Cms.Core.Services namespace, while the specific implementations can be found under the Umbraco.Cms.Core.Services.Implement namespace. To use the service APIs you must first access them. Owing to the built-in dependency injection (DI) in ASP.NET Core, configured services are made available throughout Umbraco's codebase. This can be achieved via injecting the specific service you require - the service type or an interface.
Access via a Controller
If you are accessing Umbraco services inside your own controller class, you can add the Umbraco services that you need as constructor parameters. An instance of every service will be provided at runtime from the service container and by saving each one to a local field, you can make use of them within the scope of your class:
Inside a Razor View template, you can make use of a service injection into a view using the @inject directive. It works similarly to adding a property to the view, and populating the property using DI:
If for instance we wish to subscribe to notifications on one of the services, we'd do so in a Composer C# class, where you will add a custom NotificationHandler. In this custom NotificationHandler we would inject the service we need into the public constructor of the class and Umbraco's underlying dependency injection framework will do the rest.
In this example we will wire up to the ContentService 'Saved' event, and create a new folder in the Media section whenever a new LandingPage is created in the content section to store associated media. Therefore we will need the MediaService available to create the new folder.
usingSystem.Linq;usingUmbraco.Cms.Core;usingUmbraco.Cms.Core.Events;usingUmbraco.Cms.Core.Models;usingUmbraco.Cms.Core.Notifications;usingUmbraco.Cms.Core.Services;namespaceUmbraco.Cms.Core.Events{publicclassCustomNotificationHandler:INotificationHandler<ContentSavedNotification> { // access to the MediaService by injectionprivatereadonlyIMediaService _mediaService;privatereadonlyIRuntimeState _runtimeState;publicCustomNotificationHandler(IMediaService mediaService,IRuntimeState runtimeState) { _mediaService = mediaService; _runtimeState = runtimeState; }publicvoidHandle(ContentSavedNotification notification) {if (_runtimeState.Level!=RuntimeLevel.Run) {return; }foreach (var contentItem innotification.SavedEntities) { // if this is a new landing page create a folder for associated media in the media sectionif (contentItem.ContentType.Alias=="landingPage") { // we have injected in the mediaService in the constructor for the component see above.bool hasExistingFolder =_mediaService.GetByLevel(1).Any(f =>f.Name==contentItem.Name);if (!hasExistingFolder) { // let's create one (-1 indicates the root of the media section)IMedia newFolder =_mediaService.CreateMedia(contentItem.Name,-1,"Folder");_mediaService.Save(newFolder); } } } } }}
Custom Class example
When you are creating your own custom class, in order to make use of the dependency injection framework, you need to register the ICustomNewsArticleService service with the concrete type CustomNewsArticleService. The AddScoped() method registers the service with the lifetime of a single request.
There are several different ways that you can achieve the same outcome:
Especially recommended when creating Umbraco packages as you won't have access to the Startup class, instead you can achieve the same as above by using a custom Composer which gives you access to the IUmbracoBuilder.