use umbracohelper in a model extension?
# help-with-umbraco
s
Hi, not sure if I'm approaching this right. I have an extended model that needs information from the umbraco helper. I need to feed it a piece of content from the global > settings content node. This worked on version 8 but I can't seem to get it to work in version 13. The original code is:
Copy code
namespace Umbraco.Web.PublishedModels
{
    public partial class PropertyBanner
    {

        public static List<SelectListItem> ScottishRegions => GetRegions("Scotland");
        public static List<SelectListItem> EnglishRegions => GetRegions("England");
        public static List<SelectListItem> Regions => ScottishRegions.Union(EnglishRegions).ToList();

        private static List<SelectListItem> GetRegions(string country)
        {
            var helper = Composing.Current.UmbracoHelper;
            var settings = helper.GetSettings();
            var regionsSelectList = settings.RegionsRoot.Children.Cast<Region>()
                .Where(r => r.Country == country).Select(r => new SelectListItem { Text = r.RegionName, Value = r.ReapitId }).ToList();
            return regionsSelectList;
        }
    }
}
I've tried to replicate the behaviour on 13 but I'm honestly stuck. Any help is appreciated!
l
First of all, I think you should reconsider how your project is set up. You want your services to be injected by dependency injection and avoid exactly what you want to do here. Having said that, you can probably use the StaticServiceProvider: https://www.andybutland.dev/2022/03/service-location-in-umbraco-9.html
s
Watch out, models get cached when you least expect it. If I were you, I'd create a static class extending the the Umbraco helper, so you have either
GetRegions(this PropertyBanner propertyBanner, UmbracoHelper umbracoHelper, string country)
or
GetRegions(this UmbracoHelper umbracoHelper, PropertyBanner propertyBanner, string country)
and then have
ScottishRegions(this PropertyBanner propertyBanner, UmbracoHelper umbracoHelper
and so forth
s
I think the thing is I got it to here in Umbraco 13:
Copy code
using Microsoft.AspNetCore.Mvc.Rendering;
using Galbraith.Services;
using Galbraith.Extensions;
using Umbraco.Cms.Web;

namespace Umbraco.Cms.Web.Common.PublishedModels
{
    public partial class PropertyBanner
    {
        private static UmbracoHelper umbraco;
        public static List<SelectListItem> ScottishRegions => GetRegions("Scotland");
        public static List<SelectListItem> EnglishRegions => GetRegions("England");
        public static List<SelectListItem> Regions => ScottishRegions.Union(EnglishRegions).ToList();
        private static List<SelectListItem> GetRegions(string country)
        {
            UmbracoHelper umbracoHelper = umbraco;
            var settings = umbracoHelper.GetSettings();
            var regionsSelectList = settings.RegionsRoot.Children.Cast<Region>().Where(r => r.Country == country).Select(r => new SelectListItem { Text = r.RegionName, Value = r.ReapitId }).ToList();
            return regionsSelectList;
        }
    }
}
I just can't work out what step I'm missing... Is it just that I need to extract the regions function from the model and run it elsewhere? If so then I'm not sure how this worked in v8
s
You can't inject the umbraco Helper like that. You can use the StaticServiceProvider, but I would not do it like this. Safer to take it outside of the model, as ModelsBuilder will cache the values of ScottishRegions, EnglishRegions and Regions, regardless off changes to the nodes you select in your GetRegions() method
s
I see! Thanks for the tips, I'll try changing it up and see how far I get 🙂
k
If you're not using Controllers currently, you may want to do that. Controllers provide a way to do stuff earlier in the pipeline, and maybe it would be easier for you to compose all the data needed there, and pass it down to your views. Then it wouldn't be up to your models to do it. Controllers aren't usually needed in Umbraco but we use them for situations like these.
j
If you don't want to rearchitecture/change your logic then method injection is a fine appraoch for situations like these...
Copy code
csharp
public static List<SelectListItem> GetScottishRegions(UmbracoHelper helper) => GetRegions(helper, "Scotland");

private static List<SelectListItem> GetRegions(UmbracoHelper helper, string country)
{
var settings = helper.GetSettings();
...
}
Though a good question is, do you need a helper at all? As you're currently inside an IPublishedContent, can you use the navigation properties to get the settings or RegionsRoot node?
i.e.
this.AncestorOrSelf<HomePage>().FirstChild<SiteSettings>()
etc.
8 Views