Dependency Injection and Published Content + Culture change (v.8.1)
I'm wondering what the correct / ideal approach would be to use Dependency Injection (DI) now for published content with culture, and especially children change in v8.1
There are a few issues/questions so I hope I explain myself proper and will try to keep it as simple / focused as possible :)
Suppose: I have a custom content service being build using (amongst other things) published content, and I want it to be DI and also minimize logic in the view itself (for example via viewmodels/display templates etc).
This means that the razor helper Umbraco is not available because content will be accessed in a code file, not a razor view.
So I've found a few methods of accessing content, but I'm unsure which is preferred
It seems possible to inject UmbracoHelper directly into my custom class.
This however often seem to run into an isuse where the snapshot is disposed and I suspect it might suffer a bit from the 'singleton' issue of v.7.x?
Via another similar thread I found IUmbracoContextFactory and can access content via
using (var contextFactory = _umbracoContextFactory.EnsureUmbracoContext())
{
var content = _umbracoContextFactory.UmbracoContext.Content.GetAtRoot().OfType<MyType>()?.FirstOrDefault();
}
But the e.g. document.Children(culture) is always empty whereas CultureForAllDomains is populated. But as I understand it, I would then need to manually check if content is available for my given culture?
Or is the content now filtered by culture?
I also saw the IPublishedContentQuery which does seem to work similar to the IUmbracoContextFactory, but the IPublishedContentQuery seems to be inside the UmbracoHelper so I suspect it has the same 'snapshot' issues.
Or is there another and/or simpler way I'm overlooking?
There are some examples of DI that are 'work in progress' in the Umbraco Docs, that might be worth a read through, the most recent version is available here:
Essentially it depends 'a lot' on where your custom C# class will be used...
... if you are ONLY using it from a Controller or View, then you can register your custom c# class in 'Lifetime.Request' scope, and it will be 'safe' to inject the familar IPublishedTypedQuery into the constructor of your custom class to work with the published cache in the same way as you would via UmbracoHelper....
but if you subsequently try to use your custom c# class outside of a HttpRequest eg in a Component/handling an event - then you'll get a boot error on startup...
So if you need your c# class to be called outside of a HttpRequest, then that's when you use the UmbracoContextFactory approach to access the ContentCache... and since this approach works in both scenarios... then although it's a little more involved, means you won't get caught out if you need to use your custom class outside a HttpRequest in the future...
In terms of what is returned by the .Children(string culture = null) extension method on an IPublishedContent item:
Now on the front end of the site, in a view or controller, this should be the culture of the variation the site visitor is requesting, but if your custom code is actioned in a Component or Event, then that default thread culture might be a culture that isn't used on your Umbraco content tree , eg en-US, and so you get no children...
... I am guessing from the source implementation!
Anyway once you have an IPublishedContent item from either of the approaches, Children("en-GB") should return all the UK children variants etc
But it's also possible since this is new in the release of 8.1 that there is a bug...
It would be interesting to see if .Children("*") all children, and whether this contains children with the culture you are seeking which are not returned when you specify the culture...
Anyway, hope this is information of help, even if it perhaps isn't the exact answer to your question!
Dependency Injection and Published Content + Culture change (v.8.1)
I'm wondering what the correct / ideal approach would be to use Dependency Injection (DI) now for published content with culture, and especially children change in v8.1
There are a few issues/questions so I hope I explain myself proper and will try to keep it as simple / focused as possible :)
Suppose: I have a custom content service being build using (amongst other things) published content, and I want it to be DI and also minimize logic in the view itself (for example via viewmodels/display templates etc).
This means that the razor helper Umbraco is not available because content will be accessed in a code file, not a razor view.
So I've found a few methods of accessing content, but I'm unsure which is preferred
It seems possible to inject UmbracoHelper directly into my custom class. This however often seem to run into an isuse where the snapshot is disposed and I suspect it might suffer a bit from the 'singleton' issue of v.7.x?
Via another similar thread I found IUmbracoContextFactory and can access content via
and
But the e.g. document.Children(culture) is always empty whereas CultureForAllDomains is populated. But as I understand it, I would then need to manually check if content is available for my given culture? Or is the content now filtered by culture?
I also saw the IPublishedContentQuery which does seem to work similar to the IUmbracoContextFactory, but the IPublishedContentQuery seems to be inside the UmbracoHelper so I suspect it has the same 'snapshot' issues.
Or is there another and/or simpler way I'm overlooking?
Hi Allan
There are some examples of DI that are 'work in progress' in the Umbraco Docs, that might be worth a read through, the most recent version is available here:
https://github.com/umbraco/UmbracoDocs/blob/512a77c26eaed3e238955a56411d6ba3d0d28b00/Implementation/Services/index.md
Essentially it depends 'a lot' on where your custom C# class will be used...
... if you are ONLY using it from a Controller or View, then you can register your custom c# class in 'Lifetime.Request' scope, and it will be 'safe' to inject the familar IPublishedTypedQuery into the constructor of your custom class to work with the published cache in the same way as you would via UmbracoHelper....
but if you subsequently try to use your custom c# class outside of a HttpRequest eg in a Component/handling an event - then you'll get a boot error on startup...
So if you need your c# class to be called outside of a HttpRequest, then that's when you use the UmbracoContextFactory approach to access the ContentCache... and since this approach works in both scenarios... then although it's a little more involved, means you won't get caught out if you need to use your custom class outside a HttpRequest in the future...
In terms of what is returned by the .Children(string culture = null) extension method on an IPublishedContent item:
https://github.com/umbraco/Umbraco-CMS/blob/3bfd9b71e290354744d677440983ecd06c5c0788/src/Umbraco.Core/PublishedContentExtensions.cs#L103
the logic appears to be if no culture is passed to the method, to use the culture of the current thread in the filtering...
https://github.com/umbraco/Umbraco-CMS/blob/853087a75044b814df458457dc9a1f778cc89749/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs
Now on the front end of the site, in a view or controller, this should be the culture of the variation the site visitor is requesting, but if your custom code is actioned in a Component or Event, then that default thread culture might be a culture that isn't used on your Umbraco content tree , eg en-US, and so you get no children...
... I am guessing from the source implementation!
Anyway once you have an IPublishedContent item from either of the approaches, Children("en-GB") should return all the UK children variants etc
But it's also possible since this is new in the release of 8.1 that there is a bug...
It would be interesting to see if .Children("*") all children, and whether this contains children with the culture you are seeking which are not returned when you specify the culture...
Anyway, hope this is information of help, even if it perhaps isn't the exact answer to your question!
regards
Marc
Also noticed this issue on the issue tracker:
https://github.com/umbraco/Umbraco-CMS/pull/5946
is working on a reply...