Umbraco has several useful APIs and one common misconception is when to use the UmbracoHelper, compared to the ContentTypeService. If you look at the constructor of the Umbraco Helper, it takes an UmbracoContext as a parameter and this is when the first big difference appears. The UmbracoContext, like the normal.NET HTTP Context, works on a per thread basis.
What this means in simple terms is that the UmbracoContext.Current will only be set within a web request. If you need to access data within Umbraco outside of a web request, say in a scheduled task, your search running over async, or an HTTP module, you may run into the issues.
When you need to access Umbraco data outside of a web request, you will need to use the ContentTypeService, like so:
var contentService = ApplicationContext.Current.Services.ContentService; var contentTypeService = ApplicationContext.Current.Services.ContentTypeService;
There are some minor downsides to using ApplicationContext, for one, if you simply need to do read operations on existing data, the ApplicationContext doesn’t check the cache and will request everything from the database, which will be less performant. in 98% of the cases though I don’t think the average Joe would notice anything.
There are a few workarounds if you desperately want to create an Umbraco context outside of a request. First, you could simply try to set the context yourself, like so (to note: make sure you don’t get confused with the defunct Umbraco.Presentation.UmbracoContext though!):
var helper = new UmbracoHelper(Umbraco.Web.UmbracoContext);
If the ContentTypeService or manually creating a context and passing it into a helper, doesn’t fix your issue, then my main bit of advice would be to look at your architecture and see if you can do your work differently. In the extreme case, you could consider manually creating the UmbracoContext yourself, but I don’t recommend this.
var context = new HttpContextWrapper(new HttpContext(new SimpleWorkerRequest("/", string.Empty, new StringWriter()))); UmbracoContext.EnsureContext( context, ApplicationContext.Current, new WebSecurity(context, ApplicationContext.Current), UmbracoConfig.For.UmbracoSettings(), UrlProviderResolver.Current.Providers, false);
The code above works for Umbraco 7.3 onwards and will manually ensure the context is created.
This approach is popular because there is no access to UmbracoContext in the event handlers. However, as shown below, you can pass in the UmbracoHelper when hooking up to GatheringNodeData. This makes calls to the Umbraco XML cache instead, cutting indexing time to just a few seconds.
Umbraco Helper Vs The ContentTypeService