DEV Community

Cover image for Extending the UmbracoHelper class in Umbraco v8
Tim Geyssens
Tim Geyssens

Posted on

Extending the UmbracoHelper class in Umbraco v8

While setting up an Umbraco site you'll probably end up with some "site settings" that will eather be on a top level node or on a child settings node. Think things like setting up the nav, the footer...

These are items you only set up once a site and want to manage in a global way.

You can of course write a query each time to traverse the tree... but something that v8 makes easy and possible is to extend the UmbracoHelper that is available in your Razor Views.

Imagine that you can simply do @Umbraco.WebSiteSettings.Footer and that you get the data you want (strongly typed). THis is nice and readable and folks without a lot of razor knowledge can also see what is happening...(maybe if a frontend dev needs to do some changes).

Ok let's get started. First of all, to do the stronlgy typed stuff, use Modelbuilders (duh).

I tend to use this config:

Once generated you'll need to include the files in the vs project...

With that in place I now have strongly typed models of my document types...

Next is to get into the DI magic of V8, and build a custom Service

Define an interface (I called mine ISiteService)

It has 2 methods, 1 that fetches a Website doc based on id and one that will fetch the SearchPage doc based on id (both returning strongly typed models generated by ModelsBuilder)

The implementation looks like this

So using the alias of the type. And then looks for the ancestor of the current fed in node id of that alias (since the website will always be at the top of the tree)

For the Searchpage, it first fetched the Website and then looks for the child of the correct alias (since it will be located directly under the website node)

Of course for all of this to work we need to register the custom service

And now we can inject it where we want...

But I'll also create an extension for the UmbracoHelper

Since it is static I can't use the standard constructor approach for injecting my custom service but I can still get to it with

Umbraco.Web.Composing.Current.Factory.GetInstance();

And with all that in place I can now access my service from the Umbraco Helper in views:

Top comments (7)

Collapse
 
dawoe profile image
Dave Woestenborghs • Edited

Hi Tim,

Getting the alias can be done a lot easier... just use Website.ModelTypeAlias

But in fact you don't need it. You can also do this :

website = UmbracoContextReference.UmbracoContext.Content.GetById(id).AncestorOrSelf<Website>();
Enter fullscreen mode Exit fullscreen mode

Personally I also would create a overload for the SiteService methods... where you can pass in a IPublishedContent so you can eliminate the the GetById call.

Collapse
 
timgeyssens profile image
Tim Geyssens

sweet, updating...

Collapse
 
fransdejong profile image
Frans de Jong

I always create a custom viewpage.

The 2 advantages in my opinion are:

  • no messing with static classes so DI is working
  • no confusion about what is Umbraco and what is custom code. The Umbracohelper is the same in every project and the viewpage SiteSettings object contains all the SiteSettings per site.
Collapse
 
timgeyssens profile image
Tim Geyssens

Nice, thanks for sharing!

Collapse
 
mistyn8 profile image
Mike Chambers

I needed a htmlHelper to get the renderedGrid content from

using (UmbracoContextReference umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext())
{
var currentContext = umbracoContextReference.UmbracoContext;
var developments = currentContext.Content.GetByContentType(DevelopmentPage.GetModelContentType()).First();
development.GetGridHtml(htmlHelper, "gridContent", "Bootstrap3-Fluid")
}

I ended up using public static class HtmlExtensions rather than UmbracoHelperExtensions as I didn't need the UmbracoHelper...
If I was to need both, is there a way to get both other than passing the one we haven't extended into the constructor?

Collapse
 
mistyn8 profile image
Mike Chambers

I had just created my own service, and was using Umbraco.Web.Composing.Current.Factory.GetInstance(); in loads of places.. (templates/partials) adding on to the umbracoHelper is so cool!

Would it be worth adding some caching for these ask once and remember globalish settings (dependant on publish)?
Just thinking you could have multiple partials on a single page all requiring to know the website root..
Or is dom traversal in Umbraco performant so don't need to worry?

Collapse
 
timgeyssens profile image
Tim Geyssens

yeah makes sense! But remember it is already using cache, so adding a cache layer on top of cache might have strange results... but can be tweaked :)