I am trying to swap partial views on my home page layout via jquery. I have 3 tabs which when clicked, would load their respective partial view into a placeholder on the main layout.

In my controller file, I have created 3 ActionView methods (for each partial view), and also button click code using Jquery, but I keep getting a 404 error when I click a link, so something's going wrong somewhere.

Controller file

using iehp.EventCalendar.Models;
using Sitecore;
using Sitecore.Data;
using Sitecore.Mvc.Controllers;
using System;
using System.Linq;
using System.Web.Mvc;

namespace iehp.Controllers
{
    public class EventCalendarController : SitecoreController
    {
        public ActionResult EventCalendarCtrl()
        {
            //read config file & get parentGuid values
            var communityGuid = Sitecore.Configuration.Settings.GetSetting("communityEventCalendarFolderGuid");
            var communityResultsQty = Sitecore.Configuration.Settings.GetSetting("communityResultsQty");

            var healthGuid = Sitecore.Configuration.Settings.GetSetting("healthEventCalendarFolderGuid");
            var healthResultsQty = Sitecore.Configuration.Settings.GetSetting("healthResultsQty");

            int communityResultsQtyTemp = Int32.Parse(communityResultsQty);
            int healthResultsQtyTemp = Int32.Parse(healthResultsQty);

            //init Sitecore db 
            Database database = Context.Database;

            var model = new EventViewModel();
            model.Item = database.GetItem(communityGuid);
            model.Community = model.Item.Children.ToList();

            model.Item2 = database.GetItem(healthGuid);
            model.Health = model.Item2.Children.ToList();

            //trunicate list to resultsQty from config
            ViewBag.communityList = model.Community.Where(x => x.Fields["Active"] != null && x.Fields["Active"].Value == "1").Take(communityResultsQtyTemp);
            ViewBag.healthList = model.Health.Where(x => x.Fields["Active"] != null && x.Fields["Active"].Value == "1").Take(healthResultsQtyTemp);

            return PartialView("/Views/Components/_FADEventCalendarCtrl.cshtml", model);
        }

        public ActionResult UrgentTabCtrl()
        {
            //read config file & get parentGuid values
            var urgentTab1Guid = Sitecore.Configuration.Settings.GetSetting("urgentTab1EventCalendarFolderGuid");
            var urgentTab1ResultsQty = Sitecore.Configuration.Settings.GetSetting("urgentTab1ResultsQty");

            var urgentTab2Guid = Sitecore.Configuration.Settings.GetSetting("urgentTab2EventCalendarFolderGuid");
            var urgentTab2ResultsQty = Sitecore.Configuration.Settings.GetSetting("urgentTab2ResultsQty");

            int urgentTab1ResultsQtyTemp = Int32.Parse(urgentTab1ResultsQty);
            int urgentTab2ResultsQtyTemp = Int32.Parse(urgentTab2ResultsQty);

            //init Sitecore db 
            Database database = Context.Database;

            var model = new EventViewModel();
            model.Item3 = database.GetItem(urgentTab1Guid);
            model.UrgentTab1 = model.Item3.Children.ToList();

            model.Item4 = database.GetItem(urgentTab2Guid);
            model.UrgentTab2 = model.Item4.Children.ToList();

            //trunicate list to resultsQty from config

            ViewBag.urgentTab1List = model.UrgentTab1.Where(x => x.Fields["Active"] != null && x.Fields["Active"].Value == "1").Take(urgentTab1ResultsQtyTemp);
            ViewBag.urgentTab2List = model.UrgentTab2.Where(x => x.Fields["Active"] != null && x.Fields["Active"].Value == "1").Take(urgentTab2ResultsQtyTemp);

            return PartialView("/Views/Components/_UCEventCalendarCtrl.cshtml", model);
        }

        public ActionResult PharmacyTabCtrl()
        {
            //read config file & get parentGuid values
            var pharmacyTab1Guid = Sitecore.Configuration.Settings.GetSetting("pharmacyTab1EventCalendarFolderGuid");
            var pharmacyTab1ResultsQty = Sitecore.Configuration.Settings.GetSetting("pharmacyTab1ResultsQty");

            var pharmacyTab2Guid = Sitecore.Configuration.Settings.GetSetting("pharmacyTab2EventCalendarFolderGuid");
            var pharmacyTab2ResultsQty = Sitecore.Configuration.Settings.GetSetting("pharmacyTab2ResultsQty");

            int pharmacyTab1ResultsQtyTemp = Int32.Parse(pharmacyTab1ResultsQty);
            int pharmacyTab2ResultsQtyTemp = Int32.Parse(pharmacyTab2ResultsQty);

            //init Sitecore db 
            Database database = Context.Database;

            var model = new EventViewModel();  
            model.Item5 = database.GetItem(pharmacyTab1Guid);
            model.PharmacyTab1 = model.Item5.Children.ToList();

            model.Item6 = database.GetItem(pharmacyTab2Guid);
            model.PharmacyTab2 = model.Item6.Children.ToList();

            //trunicate list to resultsQty from config
            ViewBag.pharmacyTab1List = model.PharmacyTab1.Where(x => x.Fields["Active"] != null && x.Fields["Active"].Value == "1").Take(pharmacyTab1ResultsQtyTemp);
            ViewBag.pharmacyTab2List = model.PharmacyTab2.Where(x => x.Fields["Active"] != null && x.Fields["Active"].Value == "1").Take(pharmacyTab2ResultsQtyTemp);

            return PartialView("/Views/Components/_PharmEventCalendarCtrl.cshtml", model);
        }
    }
}

Jquery

$("#urgentTab").on("click", function () {
    $.get('@Url.Action("EventCalendar","UrgentTabCtrl")', {}, function (response) {
        $("#eventCalendarBlock").html(response);
            });
        });

What I'm hoping / expecting will happen when I click the #urgentTab link is that the #eventCalendarBlock div will get replaced with the new partial view.

However what actually happens is that I get an xhr 404 error that reads like this.

http://[domain name]/@Url.Action(%22EventCalendar%22,%22UrgentTabCtrl%22)

Update

It's come to my attention that my attempt to do this might be correct, however as I'm trying it in regular MVC, Sitecore's MVC is slightly different, hence why it's not working.

I've also learned that there are a couple of ways either through routing, or returning a json object that could make this work, but I haven't been able to find a complete enough example of either to adapt to my environment.

Thanks!

up vote 2 down vote accepted

As there are many ways to solve this issue, I ended up using a combo of modifying my controller code and pulling in the view through an ajax call.

Here's the final solution.

Controller

[HttpGet]
    public ActionResult MethodName()
    {
       ...controller code goes here...
       return PartialView("/path/to/partialView.cshtml", obj); 
    }

Jquery

$("#linkID").on("click", function () {
        $.ajax({
            type: "GET",
            url: '/api/sitecore/{controller name}/{action}',
            contentType: "application/json; charset=utf-8",
            cache: false,
            beforeSend: function () {
                $('#loading').show();
            },
            complete: function () {
                $('#loading').hide();
            },
            success: function (data) {
                $("#divtoDisplayPartial").html(data);
            },
            error: function (request, status, error) {
                console.log(request.responseText);
            }
        });
    });

Replace the {controller name} with the name of your controller from your controller file and replace the {action} with the name of your action(method).

I also included an animated gif spinner in my #loading div, which is a nice to have while the view is loading.

A big thanks to @ksbecker over at the sitecore slack community for helping me effort this solution.

  • Is your site multilingual? As a heads up, I remember doing something similar and it seemed like the language did not persist from the page to the request to the controller so I added a parameter for that. – Teeknow Apr 17 at 18:20
  • It will be in the future, but at the moment I'm not thinking about that.. however perhaps I should based on your comment, so thanks for putting that out there. :) – Nick Apr 17 at 18:49

This doesn't map 100% to what you want, but I normally wrap this in a WebApi controller and within that, call this code which renders HTML from a View Rendering:

using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
using Sitecore.Data.Items;
using Sitecore.Mvc.Common;
using Sitecore.Mvc.Controllers;
using Sitecore.Mvc.Pipelines;
using Sitecore.Mvc.Pipelines.Response.RenderRendering;
using Sitecore.Mvc.Presentation;

public class RenderingHelper
{
    public string RenderViewRendering(string pathOrId, object model = null)
    {
        if (pathOrId == null)
        {
            throw new ArgumentNullException(nameof(pathOrId));
        }

        var renderingItemInner = Sitecore.Context.Database.GetItem(pathOrId);
        if (renderingItemInner == null)
        {
            throw new ArgumentException("Item not found with path or id: " + pathOrId);
        }

        var pageContext = new PageContext
        {
            RequestContext = HttpContext.Current.Request.RequestContext
        };

        ContextService.Get().Push(pageContext);

        var rend = new Rendering
        {
            RenderingItem = new RenderingItem(renderingItemInner),
            Model = model
        };

        using (var stringWriter = new StringWriter())
        {
            ContextService.Get().Push(GetViewContext(rend, stringWriter));
            PipelineService.Get().RunPipeline("mvc.renderRendering", new RenderRenderingArgs(rend, stringWriter));
            return stringWriter.ToString();
        }
    }

    private static ViewContext GetViewContext(Rendering rend, TextWriter writer)
    {
        var contContext = new ControllerContext(HttpContext.Current.Request.RequestContext, new SitecoreController());
        HttpContext.Current.Request.RequestContext.RouteData.Values["controller"] = "Sitecore";
        IView view = new RenderingView(rend);
        return new ViewContext(contContext, view, new ViewDataDictionary(rend.Model), new TempDataDictionary(), writer);
    }
}

I've pieced together this code from several sources, and Googling around quickly maybe even from this site, but I'm afraid I've forgotten who deserves the credit. I also don't have the code which deals with Controller Renderings.

  • Thank you for that Steve.. I'd like to study your answer in depth, but for now, I ended up going the ajax route to solve the issue. – Nick Apr 17 at 16:10
  • This is code I use in ajax requests. But please do let us (and future Googlers) know here how you solved it? – Steve McGill Apr 17 at 16:12

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.