Home » Customization » Inject Dependencies Into Sitecore MVC Razor Views Using a SitecoreHelper Extension Method

Inject Dependencies Into Sitecore MVC Razor Views Using a SitecoreHelper Extension Method

Sitecore Technology MVP 2016
Sitecore MVP 2015
Sitecore MVP 2014

Enter your email address to follow this blog and receive notifications of new posts by email.

Tweets

Error: Twitter did not respond. Please wait a few minutes and refresh this page.

Last week before the Christmas holiday break, I came up with a solution similar to what I am going to show here except that I had used the Simple Injector Dependency Injection framework in that solution (if you would like me to add a blog post on that approach, please let me know in a comment).

I wanted a “quick and dirty” solution — well, I guess this is really in the eye of the beholder on whether the following is a good idea or not, but I’m throwing it out there just in case it helps out someone — where I could inject a dependency into an MVC Razor view via an HtmlHelper extension method, and in that solution, I used this approach for injecting an object instance which grabs values from a Sitecore Dictionary Domain. I am going to recreate this solution here though using the Sitecore Configuration Factory (we’re all not using Simple Injector in our solutions but the Sitecore Configuration Factory is available to all of us via the Sitecore API).

I first defined the following interface for class instances which return a value for a given dictionary entry key:

using Sitecore.Globalization;

namespace Sitecore.Sandbox.Dictionaries
{
    public interface ITranslator
    {
        string Text(string key, params object[] parameters);

        string Text(TranslateOptions options, string key, params object[] parameters);
    }
}

The following class implements the interface above:

using Sitecore.Diagnostics;
using Sitecore.Globalization;

namespace Sitecore.Sandbox.Dictionaries
{
    public class DomainDictionaryTranslator : ITranslator
    {
        public string Domain { get; set; }

        public virtual string Text(string key, params object[] parameters)
        {
            AssertDomainDictionary();
            Assert.ArgumentNotNullOrEmpty(key, "key");
            return Translate.TextByDomain(Domain, key, parameters);
        }

        public virtual string Text(TranslateOptions options, string key, params object[] parameters)
        {
            AssertDomainDictionary();
            Assert.ArgumentNotNullOrEmpty(key, "key");
            return Translate.TextByDomain(Domain, options, key, parameters);
        }

        protected virtual void AssertDomainDictionary()
        {
            Assert.IsNotNullOrEmpty(Domain, "The Domain must be set!");
        }
    }
}

Client code of the class above must supply the Domain name for the Sitecore Dictionary via the Domain property on the class.

Client code can then use either Text method by supplying a key for the lookup — both methods just delegate to the corresponding static methods defined on the Sitecore.Globalization.Translate class.

We now need classes that serve as Factories. I created the following interface for such classes:

namespace Sitecore.Sandbox.Helpers.Sitecore
{
    public interface IFactory
    {
        T CreateObject<T>(string configPath, bool assert) where T : class;
    }
}

The following class implements the above interface, and basically has one method that delegates to the static CreateObject() method on the Sitecore.Configuration.Factory class:

using Sitecore.Configuration;

namespace Sitecore.Sandbox.Helpers.Sitecore
{
    public class ConfigurationFactory : IFactory
    {
        public T CreateObject<T>(string configPath, bool assert) where T : class
        {
            return Factory.CreateObject(configPath, assert) as T;
        }
    }
}

Now, we need an extension method on the Sitecore.Mvc.Helpers.SitecoreHelper class — this lives in Sitecore.Mvc.dll — so that we can leverage the code defined above (check out Sitecore MVP Kevin Brechbühl’s blog post where he talks about this approach as well as another):

using Sitecore.Configuration;
using Sitecore.Diagnostics;
using Sitecore.Mvc.Helpers;

namespace Sitecore.Sandbox.Helpers.Sitecore
{
    public static class ConfigurationFactoryHelper
    {
        private static IFactory ConfigurationFactory { get; set; }

        static ConfigurationFactoryHelper()
        {
            ConfigurationFactory = CreateFactory();
        }

        public static T CreateObject<T>(this SitecoreHelper sitecoreHelper, string configPath, bool assert) where T : class
        {
            return ConfigurationFactory.CreateObject<T>(configPath, assert);
        }

        private static IFactory CreateFactory()
        {
            IFactory factory = Factory.CreateObject("configurationFactory", true) as IFactory;
            Assert.IsNotNull(factory, "The configurationFactory must be defined in configuration!");
            return factory;
        }
    }
}

We are instantiating an instance of the ConfigurationFactory class defined above via the Sitecore Configuration Factory, and then setting it on a static property in this class — all members and methods on this class must be static since it contains extension methods.

The CreateObject() method just delegates to the ConfigurationFactory class instance’s CreateObject() method and returns its value.

I then glued everything together using the following Sitecore patch configuration file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <configurationFactory type="Sitecore.Sandbox.Helpers.Sitecore.ConfigurationFactory, Sitecore.Sandbox" singleInstance="true" />
    <domainDictionaryTranslator type="Sitecore.Sandbox.Dictionaries.DomainDictionaryTranslator, Sitecore.Sandbox" singleInstance="true">
      <Domain>MyCoolDictionary</Domain>
    </domainDictionaryTranslator>
  </sitecore>
</configuration>

Let’s see this in action!

First, we need a Dictionary Domain. I created one with the following folder with entries:

label-one-dictionary

label-two-dictionary

Now, we new a Razor view to make this work. I created the following, and mapped it to my home page’s presentation details:

@using Sitecore.Mvc;
@using Sitecore.Sandbox.Helpers.Sitecore
@using Sitecore.Sandbox.Dictionaries

@{
    var translator = Html.Sitecore().CreateObject<ITranslator>("domainDictionaryTranslator", true);
    if (translator == null)
    {
        return;
    }

    var labelOne = translator.Text("mycooldictionary.somelabels.labelone");
    var labelTwo = translator.Text("mycooldictionary.somelabels.labeltwo");
    if (string.IsNullOrWhiteSpace(labelOne) && string.IsNullOrWhiteSpace(labelTwo))
    {
        return;
    }
}

<div>
    @if (!string.IsNullOrWhiteSpace(labelOne))
    {
        <h2>@labelOne</h2>
    }

    @if (!string.IsNullOrWhiteSpace(labelTwo))
    {
        <h2>@labelTwo</h2>
    }
</div>

After building and deploying, I navigated to my home page. As you can see, the dictionary entry values display:

dictionary-values-displayed

If you have any thoughts on this, please drop a comment.

Advertisements

2 Comments

  1. Nice post.. I have one thought like if we can write like @Html().Sitecore().Translate().Text(“mydomain.mycooldictionary.somelabels.labeltwo”); if would be more clean to write and understand. I have seen such approach in Orchard CMS they use @T(“mylabel”); ..

  2. Betty says:

    Looks more like Service Location rather than Injection, although that probably just means you’re 1 more pipeline away from actual injection and the removes the need to call Html.Sitecore().CreateObject in the view.

Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: