Search code examples
model-view-controllerhyperlinksitecoresitecore-mvcsitecore-exm

Render a list of links in my Component MVC Sitecore


I am having some difficulties in understanding how to display links in a Sitecore EXM email component.

I am using Sitecore MVC Controller Rendering. I am essentially trying to duplicate the Main Section component that comes as default with the Sitecore EXM platform.

So to start with I have a controller MainSectionMVCController.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestSitecore.Repositories;

namespace TestSitecore.Controllers
{
    public class MainSectionMVCController : Controller
    {
        // GET: MainSectionMVC
        public ActionResult Index()
        {
            var repository = new MainSectionMVCRepository();
            var mainSectionMVC = repository.GetMainSectionMVC();

            var mainSectionMVCViewModel = repository.GetMainSectionMVCViewModel(mainSectionMVC);

            return View(mainSectionMVCViewModel);
        }
    }
}

I have a repository MainSectionMVCRepository.cs:

using Sitecore.Links;
using Sitecore.Mvc.Presentation;
using Sitecore.Web.UI.WebControls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TestSitecore.Models;
using TestSitecore.Models.MVCEmailModels;
using Sitecore.Data.Items;
using Sitecore.Collections;

namespace TestSitecore.Repositories
{
    public class MainSectionMVCRepository
    {
        public MainSectionMVC GetMainSectionMVC()
        {
            var mainSectionMVC = new MainSectionMVC();
            var rendering = RenderingContext.Current.Rendering;
            var dataSource = rendering.Item;

            mainSectionMVC.Title = new HtmlString(FieldRenderer.Render(dataSource, Constants.FIELD_TITLE));
            mainSectionMVC.Text = new HtmlString(FieldRenderer.Render(dataSource, Constants.FIELD_TEXT));
            mainSectionMVC.Image = new HtmlString(FieldRenderer.Render(dataSource, Constants.FIELD_IMAGE));

            mainSectionMVC.Links = GetLinks(dataSource);

            return mainSectionMVC;
        }

        private List<Item> GetLinks(Item dataSource)
        {            
            List<Item> links = new List<Item>();

            // I need to get access the the Links that are attached to the datasource item ???? How to do this

            return links;
        }

        public MainSectionMVCViewModel GetMainSectionMVCViewModel(MainSectionMVC mainSectionMVC)
        {
            var viewModel = new MainSectionMVCViewModel();
            var rendering = RenderingContext.Current.Rendering;
            //viewModel.Background = rendering.Parameters["Background"];
            viewModel.ContextItem = PageContext.Current.Item;
            viewModel.MainSectionMVC = mainSectionMVC;

            return viewModel;
        }
    }
}

and a model MainSectionMVC.cs:

using Sitecore.Data.Items;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestSitecore.Models.MVCEmailModels
{
    public class MainSectionMVC
    {
        public HtmlString Title { get; set; }
        public HtmlString Image { get; set; }
        public HtmlString Text { get; set; }

        public List<Item> Links { get; set; }

    }
}

I have a ViewModel MainSectionMVCViewModel.cs:

using Sitecore.Data.Items;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestSitecore.Models.MVCEmailModels
{
    public class MainSectionMVCViewModel
    {
        public MainSectionMVC MainSectionMVC { get; set; }
        public string Background { get; set; }
        public Item ContextItem { get; set; }

    }
}

and finally I have a Index.cshtml that is linked to the Index action of the controller:

@using Sitecore.Mvc
@using Sitecore.Data.Items
@using Sitecore.Web.UI.WebControls;
@using TestSitecore.Models
@using TestSitecore.Models.MVCEmailModels

@model MainSectionMVCViewModel

<div class="highlight">
    <div class="row">
        <div class="col-md-2 col-lg-2"></div>
        <div class="col-md-5 col-lg-5">
            <h2>@Model.MainSectionMVC.Title</h2>
        </div>
        <div class="col-md-3 col-lg-3" style="align-content: center">
            @Model.MainSectionMVC.Image
        </div>
        <div class="col-md-2 col-lg-2"></div>
    </div>
    <div class="row">
        <div class="col-md-8 col-lg-8">
            <h2>@Model.MainSectionMVC.Text</h2>
        </div>
        <div class="col-md-4 col-lg-4"></div>
    </div>
    <div class="row">
        <!--DISPLAY THE LINKS HERE-->
    </div>
</div>

My issue is how to populate the list of links in my Repository and then render the output on my component.

Looking at the Template from the Link Item in Sitecore reveals that the data definition contains 2 fields, Text and Destination.

So I assume that the Text field is used as display text for the link and the destination is actually the ItemPath/ItemID.

I have tried using var children = dataSource.GetChildren(); This gets me the all children of the parent Item (Main Section). Currently only Links can be child items of the Main Section Item, but this may change if the component template is modified.

I struggled to find a suitable way to test if the child items were Links. So any tips on testing Item types would be appreciated also.

Any Ideas?


Solution

  • So after a lot of wrong turns and woes I finally managed to find the solution. I guess I was missing some important understanding of the Sitecore HTML helper class.

    So for those of you that are having a similar issue in understanding here is how I solved the issue.

    Inside my MainSectionMVCRepository class I complete the GetLinks() method like so:

    private List<Item> GetLinks(Item item)
    {
        ChildList children = item.GetChildren();
        List<Item> links = new List<Item>(children.Count);
    
        foreach (Item link in children)
        {
            links.Add(link);
        }
    
        return links;
    }
    

    And then inside my Index.cshtml file I render the links with the following code:

     @{  if (Model.MainSectionMVC.Links.Count > 0)
        {
            <ul>
                @foreach (Item link in @Model.Links)
                {
                    <li>
                        @Html.Sitecore().BeginField("Destination", link, new { haschildren = true })
                        @Html.Sitecore().Field("Text", link)
                        @Html.Sitecore().EndField()
                    </li>
                }
            </ul>
        }
    }
    

    I pretty happy with the result. The Links are displayed and editable in the page editor when rendered this way.

    Displaying Links

    Hope this helps anyone else having similar issues :D