Tag Archives: Glass.Mapper

Parameter Templates for Pointing to Content Items

Dynamic Parameter Templates for Pointing to Content Items

Have you ever been in a predicament, in code, where you need to point to an item in the Sitecore content tree?

For instance, you are building a Search Component, and when the user clicks search, you are going to send over the keyword/s in a query string to the Search Results Page for use in processing and displaying the results. In code, I will need that URL in my Search Component in order for me to send over the results. Let’s analyze what our options are on this scenario:

For sake of simplicity, I will leave the null checking and exception handling to you. These are simply options to get ultimately to my point:

Option 1 (Rookie Option):

var searchResultsPage = Sitecore.Context.Database.GetItem("/sitecore/content/Home/Search Results");
var searchPageUrl = LinkManager.GetItemUrl(searchResultsPage);

We can get the item using the path, then get the item URL at that point. However, we NEVER want to do this with content items! If that path changes then now you have a broken Search Component. Just because we can use paths to get items in Sitecore, doesn’t mean it’s a good practice. As a matter of fact, I would consider it bad practice all around, so steer clear of this method.

Option 2 (Better Option):

var searchResultsPage = Sitecore.Context.Database.GetItem(ID.Parse("F6778EA3-1B76-4BBF-AD21-63E9EA847FDE"));
var searchPageUrl = LinkManager.GetItemUrl(searchResultsPage);

A better method to pointing to items is with the ID using the item GUID. Why? Performance reasons. Sitecore will pick that item up faster using the ID. More importantly the ID is tied to that item ONLY and anywhere the Content Editor moves the item, Sitecore will still be able to fetch it, and nothing will break on the Search Component.

Option 3 (Even Better Option):

Typically, in most solutions that I have come across for Sitecore, there is Constants file that has ID’s in the Constants file something like this:

public class ItemIDs
{            
     public const string NewsCategoriesFolder = ID.Parse("{B866EC76-54ED-447D-9AB2-5E05A0699586}");
     public const string SearchResultsPage= ID.Parse("{F6778EA3-1B76-4BBF-AD21-63E9EA847FDE}");
}

As you can see from above there is an item for the News Categories Folder and the Search Results Page. Both of which need to be referenced in code, and the reason why they are in the Constants file. Using the method of putting those ID’s in the Constants file makes it easier to manage those ID’s in one place. When doing so, you can then get your item more clean and like so, in this case the Search Results page:

var searchResultsPage = Sitecore.Context.Database.GetItem(Constants.ItemIDs.SearchResultsPage);
var searchPageUrl = LinkManager.GetItemUrl(searchResultsPage);

If you make a change to the Item ID, then it will make that change across your solution versus having that ID out there in 5 other components you will need to change manually.

Option 4 (Best Option using TDS & Glass.Mapper with Code Generation):

Option 3 is definitely considered a best practice, but what if we can make this even easier to manage dynamically using TDS & Glass.Mapper, and keep ID’s out of the Constants file altogether except for rare circumstances?

Now that you have seen a few ways to point to the item in the Content Tree, let’s discuss Parameter Templates. Parameter templates are a way for you to add fields to your rendering that can help out the Content Editor in their daily Content Editing experience. Below are links to helpful information regarding Parameter Templates:

Now, that you have a good idea of what Parameter Templates are and how to set them up, let’s talk about why we would want to use them as a best practice in components for item pointing.

Parameter templates help to manage the solution while providing a better experience for your Content Editors. We simply create a Parameter Template to be used with the Search Component that has this criteria:

  • Name: Search Results Page
  • Field Type: DropTree
  • Data Source: /sitecore/content/Home/

We create a Standard_Values for the Parameter Template and set it to the Search Results Page by default.

When added to the Search Component, it is by default set to the Search Results page, but if the Content Editor ever wanted to point to an alternative Search Results page (for whatever reason), they now have that option. But more importantly, you bypass having to now add this to the Constants file, if your Parameter Template is strongly typed as one of your Models. Using TDS with Glass.Mapper “Code Generation”, this will allow you to create your Parameter Template for the Search Component, then have it auto-generate the Model in your solution for use where you can then call on the Parameter Template like so using Glass.Mapper (notice Search_Results_Parameter):

var renderingParameters = GetRenderingParameters<Search_Results_Parameter>();
var item = Context.Database.GetItem(ID.Parse(renderingParameters.Search_Results_Page));
var pathInfo = LinkManager.GetItemUrl(item, UrlOptions.DefaultOptions);

The Search Results Parameter is now dynamically generated anytime there is a change in the item in Sitecore. Hence, you never had a need to create the model OR add the item ID/path to the Constants file.

Keep in mind you can still do this without TDS/Glass.Mapper “Code Generation” feature, but then you will need to create a model manually for your Parameter Template. The benefit is that you have given the Content Editor the ability the point to the Search Results page versus having this functionality in code that needs to be changed by a developer, and that is the benefit to the client. To my knowledge, you can also do this same type of “code generation” functionality with Unicorn/Synthesis as well.

I have found going this route equates to maximum productivity for the development team once the concept is understood, and helps in manageability of your solution overall. Happy coding!

Exposing Sitecore Item Properties when Using Code Generation with Glass.Mapper

When initially setting up TDS and with Glass.Mapper code generation in your solution, by default you get the initial properties from the Sitecore item:

  • Id – The ID for the item
  • Language – The language for the item
  • Version – The version of the item

However, what if you want something like the item name available to you like you have available when going through the standard Sitecore API? Don’t worry, the Glass.Mapper team has you covered and you can extend the GlassBase and IGlassBase respectively to get you your desired results.

After you got your initial setup of Code Generation setup with TDS, you simply go to your “glassv3header.tt” file and there you can extend the GlassBase/IGlassBase. However, if you start coding in this file you will have no Visual Studio Intellisense, so I actually wrote code in my ViewModel so I could see what was available in the SitecoreInfoType object. Below are a few:

SitecoreInfoType.Name
SitecoreInfoType.DisplayName
SitecoreInfoType.ContentPath

Once you can see what is available via Intellisense you can set them in the “glassv3header.tt” file appropriately when generating the code as such.

public partial interface IGlassBase
{
[SitecoreId]
Guid Id{ get; }


[SitecoreInfo(SitecoreInfoType.Language)]
Language Language{ get; }


[SitecoreInfo(SitecoreInfoType.Version)]
int Version { get; }

}

public abstract partial class GlassBase : IGlassBase
{

[SitecoreId]
public virtual Guid Id{ get; private set;}


[SitecoreInfo(SitecoreInfoType.Language)]
public virtual Language Language{ get; private set; }


[SitecoreInfo(SitecoreInfoType.Version)]
public virtual int Version { get; private set; }


[SitecoreInfo(SitecoreInfoType.Url)]
public virtual string Url { get; private set; }


[SitecoreInfo(SitecoreInfoType.Name)]
public virtual string Name { get; private set; }

}

This will work to get the item name. However, I noticed that ASP.NET MVC when using Html.Helpers with names of “name” will pull in the Item name into the textbox as the value. Hence, I had to change from “Name” to “ItemName” as such and I was back happy coding again and relieved myself of regression testing after making this change. Below is my modification to get the item name property:

[SitecoreInfo(SitecoreInfoType.Name)]
public virtual string ItemName { get; private set; }

Glass.Mapper, TDS, and Code Generation is a phenomenal tool and highly recommended for rapid development with Sitecore. Play around with it and you can get what you need every time. Happy Holidays!

TDS Code Generation Best Practice for Images and Links Using Glass.Mapper

Just a few weeks ago, I ran into an issue with TDS where all the “Image” fields in my solution were not generated correctly by TDS during code generation. Hence, I had hundreds of “Image” fields that had no reference.

If you are not familiar with using TDS for code generation with Glass.Mapper, I would highly recommend you take a look here, as it truly is a phenomenal tool for rapid development by generating models from Sitecore items:

http://www.glass.lu/Mapper/Sc/Tutorials/Tutorial24

I was stumped as to why this might have happened. After taking a look around my Sitecore instance, and getting some tips from the Sitecore Community on Slack in room “TDS”, I was able to find out what the problem was. I had an “ImageBase” base template that was originally setup on a template. However, I inadvertently created another Image field on the template itself with the same field title. Hence, when it came time to code generate, TDS threw up an error, but then couldn’t come back from the code generation “Image” fields issue. Basically, I had hundreds of mis-referenced “Image” fields in my code generated models file.

After speaking with Kamruz Jaman, he gave me a pointer to possibly just explicitly reference the Image object. Great Idea right!? So my solution to this issue was by going into my glassv3item.tt file and searching for Image. Once I found it, I changed it from:

case "image":
    return "Image";
 
case "general link":
case "general link with search":
    return "Link";

to

case "image":
    return "Glass.Mapper.Sc.Fields.Image";

case "general link":
case "general link with search":
    return "Glass.Mapper.Sc.Fields.Link";

I did this for both the Image and Link so if me or my development team ever ran into this issue of double creating a field with the same name, working with bases and the template item, that TDS code generation would not break on the referencing of Image and Link fields. Hence, I consider it a best practice to explicitly reference those fields just for safe measure in all your projects with TDS & Glass.Mapper code generation. Happy coding!

Glass.Mapper Page Editor Support for Children & Items using MVC

Typically, using Glass.Mapper with MVC you can make a field editable by calling the Model that was passed to the View as follows:

@using Glass.Mapper.Sc;
@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<SitecoreSandbox.Models.NavigationViewModel>

<h1>@editable(x => x.Title)</h1>

But what about if you need to make an field editable that is not in the Model such as a Site Settings item field? Glass.Mapper has an overloaded method to pass in any model. Take a look at how I get my Site Settings item by using the “siteModel” variable after it is set to the item as a “Site” model (model generated by TDS code generation):

@using Glass.Mapper.Sc;
@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<SitecoreSandbox.Models.NavigationViewModel>
 
@{ var siteModel = new SitecoreContext().GetItem<SitecoreSandbox.Models.Site.Site>(SitecoreSandbox.Helpers.Configuration.GetSettingsItem().ID.Guid); }

<a href="/">
     @RenderImage(siteMdoel, x => x.Site_Logo)
</a>

Also, you can make the children of an item editable by using a BeginEditFrame method in Glass.Mapper. Again, only the Model.Children are available to the View via the passed in Model (NavigationViewModel which was created in another post where I talk about using ViewModels), but I want the children to be editable to my Content Editors. I can accomplish this as follows:

@using Glass.Mapper.Sc; 
@inherits Glass.Mapper.Sc.Web.Mvc.GlassView<SitecoreSandbox.Models.NavigationViewModel> 

<ul>                 
    @foreach (SitecoreSandbox.Models.Site.Navigation.Navigation_Item navigationItem in Model.Children)                 
    {                     
        using (BeginEditFrame(navigationItem.Url))                     
        {                         
            <li>                             
               @(RenderLink(navigationItem, x => x.Link, isEditable: true))
            </li>                     
        }                  
    }             
</ul>

Glass.Mapper and TDS Code Generation are a great tool for your toolbox, and here is just a bit more knowledge to pass along when using Glass.Mapper and MVC to ensure Page Editor support. Happy coding!

Using ViewModels in MVC with TDS code generation and Glass.Mapper

So, first and foremost, I want to thank the guys over at Hedgehog Development for developing this wonderful tool TDS (Team Development for Sitecore) for the Sitecore community. In my experience, it is not just a handy tool in the toolbag, it’s now become a way of life and is on my best practices list where I just don’t see myself ever developing without it (unless I have to…boo!). There are many features, but the one I love the most is the ability to do code generation utilizing Glass.Mapper as the ORM. What might take you days to develop models for your Sitecore templates depending on how many templates are in the Content Tree, takes only minutes with TDS code generation. This is definitely a time saver for your development team, and once you have developed with it before, and try to build out models in MVC on your own, you will quickly realize you were spoiled with TDS code generation. It’s definitely a return on investment in terms of saved development time for your development firm and I highly recommend!

Ok, so now down to the main reason I am putting up this post, which is using ViewModels in MVC to help gain additional functionality with Glass.Mapper. After getting everything setup with TDS and code generation, I proceeded to start on my development efforts and needed to get the datasource of a component on my home page, then get the children of that datasource and use those items (Navigation_Item) in my NavigationComponent to render out my navigation. Since, I generated the classes, I needed to create a ViewModel class and inherit from my Navigation_Folder like so:

using Glass.Mapper.Sc.Configuration.Attributes;
using System.Collections.Generic;
 
namespace SitecoreSandbox.Models
{
    public class NavigationViewModel : Site.Navigation.Navigation_Folder
    {
        [SitecoreChildren]
        public virtual IEnumerable<Site.Navigation.Navigation_Item> Children { get; set        ; }
    }
}

Using this ViewModel I can inherit all the properties of the Item AND create additional functionality such as getting the children of the Navigation_Folder now. Glass.Mapper makes this so easy for us. However, be sure to add the [SitecoreChildren] configuration attribute! Otherwise, the Children property will always come back “null” and you will be scratching your head as to what is wrong. Here is more on children if you are interested.

Now, I just get the datasource from my Navigation Component using my NavigationController making sure I inherit from GlassController:

using Glass.Mapper.Sc.Web.Mvc;
using System.Web.Mvc;
 
namespace SitecoreSandbox.Controllers
{
    public class NavigationController : GlassController
    {
        public Models.NavigationViewModel Model { get; set; }
 
        public ActionResult Navigation()
        {
            Model = this.GetDataSourceItem<Models.NavigationViewModel>();
            return View(Model);
        }
    }
}

Then I pass my NavigationViewModel over to my View and I can iterate through the Navigation_Items that are children of my Navigation_Folder to render my navigation:

@using Sitecore.Mvc
@using Sitecore.Mvc.Presentation
@using Glass.Mapper.Sc;
@model SitecoreSandbox.Models.NavigationViewModel
 
<ul>
    @foreach (SitecoreSandbox.Models.Site.Navigation.Navigation_Item navigationItem in Model.Children)
    {
       <li class="mainNavItem"><a href="@navigationItem.Link.Url">@navigationItem.Link.Text</a></li>
    }
</ul>

So, you can see you can use a ViewModel to gain the additional functionality you need while still using TDS code generation and Glass.Mapper.  Overall, TDS code generation, Glass.Mapper, and ViewModels in MVC will have you doing your Sitecore development like a BOSS in no time! Happy coding!