Update layout data source references when copying a Sitecore item

Creating a page with faulty data source references

Every once in a while a content editor walks up to me to tell me that a new page does not show the content as expected. When a content editor copies an item to create a new page this usually means the layout references the data sources of the original. When you copy a page, the page is copied together with all underlying item, but the copied item still references the data sources as defined in the source item.

Correcting the data source references when copying a page

Fortunately there is an easy solution to this problem. Jan Hebnes mentions a LayoutDataSourceReferenceUpdater in a blog post some years ago (http://www.sitecore.net/sv-se/learn/blogs/best-practice-blogs/jan-hebnes/posts/2012/09/unsharing-the-layout-field-in-sitecore.aspx).
This piece of code is registered as an item:saved event. When you copy an item all references in the layout field that point to a data source that is a descendant of the item copied are updated to point to the equivalent item under the copied item. I have modified Jan’s gist (https://gist.github.com/janhebnes/3550920) to also support the final layout field.

If you have content editors that sometimes work in the content editor, this might save them (and yourself) a lot of work.

Check out the modified source here: https://github.com/martywoods/Sc.Modules.Events.LayoutDataSourceReferenceUpdater
Available on NuGet: http://www.nuget.org/packages/Sc.Modules.Events.LayoutDataSourceReferenceUpdater/

Tweet about this on TwitterShare on LinkedInShare on Google+Pin on Pinterest

Restore multiple items from sitecore recycle bin using the API

Have you ever messed up and couldn’t be bothered cleaning up in the ‘accepted’ way? I accidentally removed a large number of items from the sitecore media library. Restore the database? Maybe there is a faster way. Fortunately sitecore comes with a recycle bin. Unfortunately the recycle bin is not meant for cleaning up dumb mistakes.

When you delete one item that has subitems, all is great. The deleted item shows up in the recycle bin. When you restore the item, all subitems are restored as well. When the items are deleted one by one, they have to be restored one by one. Fortunately in the sitecore recycle bin you can select multiple items on a page to restore. Unfortunately this is limited to 15 items per page.

sitecore recycle bin

I had to restore 300+ items. To restore these by hand would mean scrolling through numerous pages to restore the items, 15 items at the time. Fortunately the sitecore API provides simple access to the recycle bin. This code on stackoverflow saved me from going through all the items by hand. I modified it so I could restore all items deleted after a certain date where the path started with a certain prefix.

The code to restore items from recycle bin using the sitecore API

using (new SecurityDisabler())
{
    DateTime archiveDate = new DateTime(2015, 9, 8);
    string pathPrefix = "/sitecore/media library";

    // get the recyclebin for the master database
    Sitecore.Data.Archiving.Archive archive = Sitecore.Data.Database.GetDatabase("master").Archives["recyclebin"];

    // get as many deleted items as possible 
    // where the archived date is after a given date 
    // and the item path starts with a given path
    var itemsRemovedAfterSomeDate =
        archive.GetEntries(0, int.MaxValue)
                .Where(entry => 
                    entry.ArchiveDate > archiveDate && 
                    entry.OriginalLocation.StartsWith(pathPrefix)
                ).ToList();

    foreach (var itemRemoved in itemsRemovedAfterSomeDate)
    {
        // restore the item
        archive.RestoreItem(itemRemoved.ArchivalId);
    }
}
Tweet about this on TwitterShare on LinkedInShare on Google+Pin on Pinterest

Organize MVC views like Sitecore renderings with a Razor View Engine

Organise your renderings, organize your views

The nice thing about Sitecore is that is allows you to structure items in a tree. One of the things I like to structure are my renderings. In Sitecore this is not a problem, but I find it difficult to structure the views in my Visual Studio solution.
I like to put renderings that belong to the same functionality together. Renderings I put together are things like views for components used for the Experience Editor, module views, etc. In Sitecore this is easy since you are free to structure the tree as you see fit. The visual studio part is somewhat different. It is easy to structure the controllers folder to match the Sitecore structure. This is also easily done for the views. But when your view is not in the expected folder (/views/controllername/viewname.cshtml), you have to provide a concrete path to the view. If I don’t do this I get this message: The view ‘ViewName’ or its master was not found or no view engine supports the searched locations.

Educating the Razor View Engine

Luckily we can educate the view engine to also look in other locations. We do this by creating our own razor view engine that knows about our other locations and registering it in the global.asax. In this view engine amongst other things you can define in which locations the razor view engine should look when rendering views and partials. By doing this you can have the razor view engine look in these locations and that results in just using the name of a view when returning it from a controller action.

Example

I have created a razor view engine in which I registered some of the other locations I wish to use

public class MyRazorViewEngine : RazorViewEngine
{
  // An array of folders under the /Views folder the View Engine should look
  private readonly string[] _viewPathParts = new[]{
    "Components",
    "Modules",
    "Company/Modules"
  };

  // An array of folders under the folders declared above the View Engine should look
  private readonly string[] _partialPathParts = new[]{
    "Partials",
    "Parts"
  };     

  public MyRazorViewEngine()
  {
    ViewLocationFormats = GetViewLocationFormats();
    PartialViewLocationFormats = GetPartialViewLocationFormats();
  }

  private string[] GetPartialViewLocationFormats()
  {
    var basePath = new[]
    {
        "~/Views/%1/{1}/%2/{0}.cshtml",
        "~/Views/{1}/%2/{0}.cshtml"
    };
    var viewPaths = GetLocationFormats(basePath, "%1", _viewPathParts);
    var paths = GetLocationFormats(viewPaths, "%2", _partialPathParts);

    return paths;
  }

  private string[] GetViewLocationFormats()
  {
    var basePath = new[] { "~/Views/%1/{1}/{0}.cshtml" };
    var paths = GetLocationFormats(basePath, "%1", _viewPathParts);

    return paths;
  }

  private static string[] GetLocationFormats(IEnumerable<string> basePaths, string token, string[] viewPathParts)
  {
    var paths = new List<string>();
    foreach (string basePath in basePaths)
    {
      foreach (string part in viewPathParts)
      {
        paths.Add(basePath.Replace(token, part));
        if (!basePath.Contains(token))
        {
          break;
        }
      }
    }

    return paths.ToArray();
  }
}

This razor view engine add these paths to the ViewLocationFormats
~/Views/Components/{1}/{0}.cshtml
~/Views/Modules/{1}/{0}.cshtml
~/Views/Company/Modules/{1}/{0}.cshtml

This razor view engine add these paths to the PartialViewLocationFormats
“~/Views/Components/{1}/Partials/{0}.cshtml”
“~/Views/Components/{1}/Parts/{0}.cshtml”
“~/Views/Modules/{1}/Partials/{0}.cshtml”
“~/Views/Modules/{1}/Parts/{0}.cshtml”
“~/Views/Company/Modules/{1}/Partials/{0}.cshtml”
“~/Views/Company/Modules/{1}/Parts/{0}.cshtml”
“~/Views/{1}/Partials/{0}.cshtml”
“~/Views/{1}/Parts/{0}.cshtml”

This view engine can be registered in the Global.asax like this.

 protected void Application_Start() { AreaRegistration.RegisterAllAreas(); ViewEngines.Engines.Clear(); // optional ViewEngines.Engines.Add(new MyRazorViewEngine()); RouteConfig.RegisterRoutes(RouteTable.Routes); } 

Result

Using a Razor View Engine like this makes it possible to go from this

return View("~/views/Company/Modules/MyRazorView.cshtml");

to this:

return View("MyRazorView");
The code in this post is inspired by:
http://blog.thekfactor.info/posts/asp-net-mvc-custom-view-engines-using-the-razor-view-engine-as-the-base/
http://theshravan.net/blog/configure-the-views-search-locations-in-asp-net-mvc/
Tweet about this on TwitterShare on LinkedInShare on Google+Pin on Pinterest

Recap day 2 Sitecore symposium Europe

After getting settled in Barcelona and getting a good night sleep, we are ready for SymEU sessions to start. First up is Michael Seifert who give us his view on what an experience is an how important the context is to determine whether an experience is good or bad. Together with Darren Guarnaccia and Mark Floisand Michael showed us some of the new features that will be in the new Sitecore 8 version. At the end everyone was excited to hear what the other sessions would be.

Developer track

As a developer I focus on the developer track and there Lars Nielsen takes us back to when it all started. He explains how Sitecore still makes decisions to implement changes and new features from a technical perspective. Lars is followed by Pieter Brinkman who freshens up our memory about the high level architecture of Sitecore. This is especially useful since 7.5 has some architectural changes because xDb is now the new database that stores all customer data. After a session about Sitecore Commerce connect which allows almost any third party Ecommerce system to connect to Sitecore by Ciaran McAuliffe, there are two session presented by guys I love to hear talking about sitecore: Stephen Pope on Federal Experience Manager and Tim Ward on Skynet.

Federal Experience Manager

Stephen Pope tells an entertaining story about the Federal Experience Manager or FxM for short. FxM allows for a site that is not in Sitecore to be tracked as if it was a normal Sitecore site. All you have to do is register the site in Sitecore and put one javascript tag in the source of the external site. That’s it…just put one script tag in the externals site source code and you’re all set. FxM does not stop at tracking page views. FxM allows you to track events that are fired on the external site and register goals based on those events. With FxM you will also have the possibility to alter the content of the external site in a way that is really close to the native Sitecore way we know from the Page Experience Editor. This will also be a nice feature to use on Sitecore websites that are fully served through a CDN.

Skynet

Tim Ward takes us on a journey along the wonders of testing everything and machine learning. With Skynet there is no excuse not to test changes done in Sitecore. Be it content changes, presentation changes or whatever. Sitecore now make it easy to setup tests and also puts in a gamification element where you can try to predict what effect changes will have. Even though it is hard to keep up with all the info Tim is throwing at us in this short time, some of the main features that stuck with me are versioned layouts and suggested tests.

Sitecore will have presentation settings versioned per language/version. The skynet software is well trained so it can suggest tests/personalization rules based on the clusters, collections and the trends it finds in those.

Can’t wait to learn new stuff tomorrow on the third and final day.

Tweet about this on TwitterShare on LinkedInShare on Google+Pin on Pinterest

Unit testing Sitecore Webforms? It’s possible with the MVP pattern.

As I have described in my previous post about unit testing with Sitecore MVC, unit testing with Sitecore MVC is possible. To make that easy/possible you have to abstract some of the Sitecore classes away into a wrapper. You quickly get used to the fact that the common sitecore classes are abstracted away and you are programming against a wrapper.

One of the perks of MVC as opposed to Webforms development is that is is easy to unit test. This is partially due to the fact that the controls of a Webforms page or control are directly accessed in the code behind. To make a Webforms project more unit testable, you can implement the MVP pattern.

The Model-View-Presenter pattern (or MVP)

I am not stating that is is easy to unit test a Webforms project, but when choosing the right pattern for the job it can be done. The Model-View-Presenter pattern (MVP) is my pattern of choice for this matter. It does a nice job of separating the logic from the presentation. When using the MVP pattern I use the WebformsMVP framework which can be easily installed using Nuget.

Example

I have created a simple example in which I want to have a Usercontrol that contains an image and an image description. If no image is available I want the image to be hidden.

The Model

The model we are using to provide the data to the view looks like this:

public class MediaImageModel
{
    public string Image { get; set; }

    public bool ShowImage
    {
        get { return !string.IsNullOrEmpty(Image); }
    }

    public string ImageDescription { get; set; }
}

The Image property contains the image url.

The Presenter

The presenter manipulates the model and handles the user interaction if necessary which is not the case here.

public class MediaImagePresenter : Presenter<IView<MediaImageModel>>
{
    private readonly ISitecoreContext sitecoreContext;

    public MediaImagePresenter(IView<MediaImageModel> view, ISitecoreContext context)
        : base(view)
    {
        sitecoreContext = context;
        this.View.Load += Load;
    }

    public void Load(object sender, EventArgs e)
    {
        IMediaImageItem model = sitecoreContext.CurrentItem as IMediaImageItem;

        this.View.Model.Image = model.Image.Url;
        this.View.Model.ImageDescription = model.ImageDescription.RenderedValue;
    }
}

The presenter take a view that uses a model of type MediaImageModel. The constructor takes a view which is injected by the WebformsMvp framework. It also takes a context of type ISitecoreContext which is injected using Unity.

this.View.Load

is a method that is fired during the Load event. Since I am still using Synthesis to access the items through generated interface representations of that template, the current item is cast to the IMediaImageItem interface.

The View – codebehind

public partial class MediaImage : MvpUserControl<MediaImageModel>
{}

This control inherits from MvpUserControl which uses a MediaImageModel. Through conventions the WebformsMvp framework links the MediaImagePresenter to the MediaImage control.

The View – markup

<asp:Image runat="server" ID="Image" Visible="<%#Model.ShowImage %>" ImageUrl="<%#Model.Image %>"/>
<asp:Literal runat="server" ID="ImageDescription" Text="<%#Model.ImageDescription %>"/>

The load event in the presenter is fired. After that the public property Model is filled and available in the markup.
All done…except for the unit testing part.

Unit testing

Since we have now separated the logic from the presentation we can determine if the model is filled according to our specifications. to test this I have created three unit tests.

public partial class MediaImage : MvpUserControl<MediaImageModel>
[TestClass()]
public class MediaImagePresenterTests
{
    private Mock<IMediaImageItem> CreateNewMockMediaImageItem(string imageDescription = "", string imageUrl = "")
    {
        var mediaImageItem = new Mock<IMediaImageItem>();

        mediaImageItem.SetupGet(x => x.Image).Returns(new TestImageField(imageUrl));
        mediaImageItem.SetupGet(x => x.ImageDescription).Returns(new TestTextField(imageDescription));
        return mediaImageItem;
    }

    private Mock<IMediaImageView> CreateNewMockMediaImageView()
    {
        return new Mock<IMediaImageView>();
    }

    [TestMethod()]
    public void Load_IMediaImageItemWithEmptyImageUrl_ImageEmptyAndInvisible()
    {
        // Arrange
        Mock<IMediaImageItem> mediaImageItem = CreateNewMockMediaImageItem(imageDescription: "", imageUrl: "");
        Mock<IMediaImageView> view = CreateNewMockMediaImageView();
        view.SetupGet(x => x.Model).Returns(new MediaImageModel());
        SitecoreContext sitecoreContext = new SitecoreContext() { CurrentItem = mediaImageItem.Object };

        // Act
        MediaImagePresenter presenter = new MediaImagePresenter(view.Object, sitecoreContext);
        presenter.Load(null, null);

        // Assert
        Assert.AreEqual("", presenter.View.Model.Image);
        Assert.AreEqual(false, presenter.View.Model.ShowImage);
    }

    [TestMethod()]
    public void Load_IMediaImageItemWithFilledImageUrl_ImageFilledAndVisible()
    {
        // Arrange
        Mock<IMediaImageItem> mediaImageItem = CreateNewMockMediaImageItem(imageDescription: "", imageUrl: "imageurl.jpg");
        Mock<IMediaImageView> view = CreateNewMockMediaImageView();
        view.SetupGet(x => x.Model).Returns(new MediaImageModel());
        SitecoreContext sitecoreContext = new SitecoreContext() { CurrentItem = mediaImageItem.Object };

        // Act
        MediaImagePresenter presenter = new MediaImagePresenter(view.Object, sitecoreContext);
        presenter.Load(null, null);

        // Assert
        Assert.AreEqual("imageurl.jpg", presenter.View.Model.Image);
        Assert.AreEqual(true, presenter.View.Model.ShowImage);
    }

    [TestMethod()]
    public void Load_IMediaImageItemWithImageDescription_ImageDescriptionFilled()
    {
        // Arrange
        Mock<IMediaImageItem> mediaImageItem = CreateNewMockMediaImageItem(imageDescription: "TestImageDescription", imageUrl: "");
        Mock<IMediaImageView> view = CreateNewMockMediaImageView();
        view.SetupGet(x => x.Model).Returns(new MediaImageModel());
        SitecoreContext sitecoreContext = new SitecoreContext() { CurrentItem = mediaImageItem.Object };

        // Act
        MediaImagePresenter presenter = new MediaImagePresenter(view.Object, sitecoreContext);
        presenter.Load(null, null);

        // Assert
        Assert.AreEqual("TestImageDescription", presenter.View.Model.ImageDescription);
    }
}

And there you have it: A unit tested usercontrol that uses the MVP pattern. For simple sites I must say that this approach can make simple things complex. You have to write more code to accomplish the same.
I think that when you want to unit test a Webforms project, you should look into the MVP pattern. When building a new project, I would go with MVC.

Tweet about this on TwitterShare on LinkedInShare on Google+Pin on Pinterest

How to edit field labels for user friendliness with a custom Template Builder

This article was previously posted as How to edit field labels for user friendliness on sitecore.net June 3rd, 2013

Working with Sitecore as a developer is all about servicing the content editor. Content editors need to deliver great content, and as developers we can provide them with solutions that help them do this. Nevertheless, there can be some friction in how information such as content fields are structured by developers and the way this is best presented to content editors. How can we serve both needs easily? Enter the Redhotminute Template Builder.

What the ‘friction’ is about

One of the things that is crucial to a content editor is the label above the field they have to fill in Sitecore. This label should tell them what information should go into the field. At the same time, the developer – if he’s like me – wants to make sure a field name is unique and the name indicates where to find the field within Sitecore.

I do this by prefixing the field names with an abbreviation of the template name. In my case this can result in tittle field names such as ‘doc_page_title’. By default the name of a field is used as the label for the field. This is a nice title to a developer, but it’s gibberish to a content editor.

Displaying the right information

So how can we make sure field labels are optimized in such a way they serve the needs of both the developer as well as the content editor? As described in Oasis’s Mark Ursino’s blog post about Sitecore Item and Field names it is easy to change the field label to display a name other than the field name. The label displays the field name by default, but if we fill the title field then this value is used as the label. This is standard functionality in Sitecore and can be set in the field item itself.

Display the right information

Another feature described in Mark’s post is the use of the Short Description text. This makes it possible to provide the content editor with extra information about the field, for example an image field with the extra information ‘the recommended image dimensions are 120×80 px, PNG’. This field is also set in the field item, but then by changing ribbons and opening dialogs.

Go to the help dialog

Enter a short description

Template Builder to the rescue

Velir’s Tim Braga describes in a post about his Enhanced Template Builder how he added a required checkbox for each field in the template builder. This avoids having to drill down for each field to set the validation options to make the field required. His solution makes it possible to make a field required from the template builder itself. This inspired me to have a look at the template builder myself.

The title field and the short description of a field item enable us to provide the content editor with useful information and have a nice ‘technical’ field name for us developers to work with. But if you have to do this for a template with ten fields, it’s quite a bit of ‘clicking around’. So how can we do this more efficiently? The Redhotminute Template Builder offers the solution.

Smoothing the friction

I have added two columns to the field definitions: Title and Short Description. This allows me to fill in all necessary fields from the template builder. At one glance, I can see and edit all the Titles and Short Descriptions used in a template.

Enter the title and Short description in the template builder

This makes it possible for me to use technical field names. As a developer, I like to use such names for structuring information. At the same time, I can set a label name a content editor understands and provide him or her with extra information such as image requirements if necessary.

See the result in your template

This solutions makes it easy for us developers to use the structured data we want while at the same time displaying information that makes perfect sense to the content editor. This way, we can smooth the friction and effortlessly use the template builder to do what our job is all about in Sitecore: enabling content editors to deliver great content.

The source can be found at Github

The module can be downloaded in the Sitecore Marketplace

Tweet about this on TwitterShare on LinkedInShare on Google+Pin on Pinterest

Unit testing Sitecore MVC? It’s easy when using Synthesis

I have been using Sitecore for a while now, and one of the nice features of the Sitecore API is that it is flexible in presenting field values.

string title = Sitecore.Context.Item["title"];

No matter what type of template you use, if it has a title field, this line of code will work. In fact, this code works even if the template does not have a title field.

Unit testing sitecore using MVC and Synthesis ORM

For a while I have switched from Webforms to MVC. This makes me more conscious of the templates I use, because I now pass a strongly typed model from the controller to the view. I wanted to try an ORM and decide to go with Kam Figy’s Synthesis. It easy to configure, it autogenerates interfaces and concrete classes and it is easily unit testable.

Synthesis generates interfaces and concrete classes based on the templates you include. It is configurable to in- or exclude templates and fields. It is easily installed using Nuget packages and has a Synthesis.Testing package that contains dummy field type implementations to help you write cleaner mocks of Synthesis item types.

After reading Martina Welander’s post on Unit Testing Sitecore MVC we decided to use this as a starting point and combine this with the Synthesis ORM we are using.

Interfaces

First we created interfaces for the parts of the Sitecore.Context we use regularly.

public interface ISiteContextAdapter
{
  IStandardTemplateItem RootItem { get; }
}

public interface ISitecoreContext
{
  IStandardTemplateItem CurrentItem { get; }
  IStandardTemplateItem HomepageItem { get; }
  bool IsPageEditor { get; }
  bool IsPreview { get; }
  ISiteContextAdapter Site { get; }
  IDatabaseAdapter Database { get; }
  RenderingParameters Parameters { get; }
  IStandardTemplateItem DatasourceItem { get; }
  string Placeholder { get; }
}

Instead of returning an Item we chose to return an IStandardTemplateItem. This is the base interface implemented by all template interfaces generated with Synthesis. Instead of the Sitecore.Context.Database we used the IDatabaseAdapter that comes with Synthesis.

Concrete implementation

We created the SitecoreContext class that implements the ISitecoreContext interface. An object of this type is injected in every controller constructor using Dependency Injection. This is where we hook up the coupling with the Sitecore.Context.

public class SiteContextAdapter : ISiteContextAdapter
{
  private readonly SiteContext siteContext;
  private readonly IDatabaseAdapter databaseAdapter;

  public SiteContextAdapter(SiteContext siteContext, IDatabaseAdapter databaseAdapter)
  {
    this.siteContext = siteContext;
    this.databaseAdapter = databaseAdapter;
  }

  public IStandardTemplateItem RootItem{
    get{
      return this.databaseAdapter.GetItem(this.siteContext.RootPath);
    }
  }
}

public class SitecoreContext : ISitecoreContext
{
  private RenderingContext rendering = RenderingContext.CurrentOrNull;

  public IStandardTemplateItem CurrentItem{
    get{
      return Sitecore.Context.Item.AsStronglyTyped();
    }
  }

  public IDatabaseAdapter Database{
    get{
      return new DatabaseAdapter(Sitecore.Context.Database);
    }
  }

  public IStandardTemplateItem DatasourceItem{
    get{
      if (this.rendering != null && this.rendering.Rendering.Item != null)
      {
        return this.rendering.Rendering.Item.AsStronglyTyped();
      }
      return null;
    }
  }

  public IStandardTemplateItem HomepageItem{
    get{
      return this.Database.GetItem(Sitecore.Context.Site.StartPath);
    }
  }

  public ISiteContextAdapter Site{
    get{
      return new SiteContextAdapter(Sitecore.Context.Site, this.Database);
    }
  }

  public bool IsPageEditor{
    get{
      return Sitecore.Context.PageMode.IsPageEditor;
    }
  }

  public bool IsPreview{
    get{
      return Sitecore.Context.PageMode.IsPreview;
    }
  }

  public RenderingParameters Parameters{
    get{
      return this.rendering.Rendering.Parameters;
    }
  }

  public string Placeholder{
    get{
      if (this.rendering != null && this.rendering.Rendering != null)
      {
        return this.rendering.Rendering.Placeholder;
      }
      return null;
    }
  }
}

Fakes implementation

To be able to unit test we also create fake classes to use in our unit tests.

public class FakeSiteContextAdapter : ISiteContextAdapter
{
  public FakeSiteContextAdapter(IStandardTemplateItem rootItem = null)
  {
    this.RootItem = rootItem;
  }

  public IStandardTemplateItem RootItem { get; set; }
}

public class FakeSitecoreContext : ISitecoreContext
{
  public FakeSitecoreContext(IStandardTemplateItem current = null, IStandardTemplateItem home = null, IStandardTemplateItem datasourceItem = null, bool isPageEditor = false, bool isPreview = false, RenderingParameters parameters = null, IDatabaseAdapter database = null, string placeholder = null, ISiteContextAdapter site = null)
  {
    this.CurrentItem = current;
    this.HomepageItem = home;
    this.IsPageEditor = isPageEditor;
    this.IsPreview = isPreview;
    this.Database = database;
    this.DatasourceItem = datasourceItem;
    this.Parameters = parameters;
    this.Placeholder = placeholder;
    this.Site = site;
  }

  public IStandardTemplateItem CurrentItem { get; set; }
  public IDatabaseAdapter Database { get; set; }
  public IStandardTemplateItem DatasourceItem { get; set; }
  public IStandardTemplateItem HomepageItem { get; set; }
  public bool IsPageEditor { get; set; }
  public bool IsPreview { get; set; }
  public RenderingParameters Parameters { get; set; }
  public string Placeholder { get; set; }
  public ISiteContextAdapter Site { get; set; }
}

Implementation Unit Test

Now we are going to write a unit test using the FakeSitecoreContext. This unit test tests the controller action that provides an actionresult of a view that takes a model containing a MetaTitle. We are passing in a mocked item of the MetaInformation template.

[TestMethod]
public void HeaderMetaTitleProvidedTest()
{
  string metaTitle = "My meta title";

  // create a mock item
  var metaInformationItem = new Mock<IMetaInformationItem>();
  metaInformationItem.SetupGet(x => x.MetaTitle).Returns(new TestTextField(metaTitle));

  // setup the fake context
  FakeSitecoreContext sitecoreContext = new FakeSitecoreContext() { CurrentItem = metaInformationItem };

  TagsController controller = new TagsController(sitecoreContext);
  var result = controller.MetaTags() as ViewResult;
  IMetaInformationItem model = result.Model as IMetaInformationItem;

  Assert.IsNotNull(controller);
  Assert.IsNotNull(model);
  Assert.IsTrue(model.MetaTitle.RawValue.Equals(metaTitle));
}

Controller implementation

Al we have to do now is make our unit test pass by actually writing the controller. In the controller we use an object that implements the ISitecoreContext interface. So no tight coupling with the Sitecore.Context. An object of type SitecoreContext is injected using Dependency Injection. Also we use a model that implements the IMetaInformationItem interface generated by Synthesis. This interface is based on the MetaInformation template. This helps us in the view since we have a strongly typed object with all its properties.

public class TagsController : Controller
{
  private ISitecoreContext sitecoreContext;

  public TagsController(ISitecoreContext sitecoreContext)
  {
    this.sitecoreContext = sitecoreContext;
  }

  public ViewResult MetaTags()
  {
    IMetaInformationItem model = sitecoreContext.CurrentItem as IMetaInformationItem;
    return View(model);
  }
}

Result

With the wrapping of the Sitecore.Context and the Dependency Injection in place we can now unit test the results our controller actions give us. We can use the TestFields provided with Synthesis to easily mock our items. We can now develop faster, correct code. Unit testing sitecore  can improve the quality of your code. I wouldn’t have it any other way.

Tweet about this on TwitterShare on LinkedInShare on Google+Pin on Pinterest