For one of our project we need to call some sublayout in ajax. This allow you to do some pagination or lazy loading and let sitecore resolve the context.
To do that, we will create our own LayoutResolver to respond to our query with only the corresponding rendering.
Our call ajax wll look like:
var url = "http://myurl/myItem?UseAjax=true&PresentationId=BACBFEE1-C0BB-4D8E-BA1A-D9F50CCA5B7F";
$.ajax({
type: 'GET',
url: url
}).done(function (data) {
//Your code
});
We will also need a layout for the ajax queries (in the following code the MY_AJAX_LAYOUT_ID is the id of this layout) and this layout will only contain one placeholder (MY_AJAX_PLACEHOLDER in the code)
Now here is the custom layout resolver (look at the comments into the code):
using System;
using System.Linq;
using System.Web;
using Sitecore.Data.Items;
using Sitecore.Pipelines.HttpRequest;
namespace MyNamespace
{
public class AjaxLayoutResolver : LayoutResolver
{
public override void Process(HttpRequestArgs args)
{
bool useAjax;
//First of all let's check if we are in ajax mode or not if not don't continue
var result = bool.TryParse(HttpContext.Current.Request.Params["UseAjax], out useAjax);
if (!result || !useAjax)
{
return;
}
//The second parameter we need to pass is the PresentationId if not present the query if not valid -> don't continue
var presentationId = HttpContext.Current.Request.Params["PresentationId"];
if (string.IsNullOrEmpty(presentationId))
{
return;
}
//If the current item is null return
if (Sitecore.Context.Item == null)
{
return;
}
//Let's resolve the sublayout
try
{
//Get the list of rendering for the current item
var renderings = Sitecore.Context.Item.Visualization.GetRenderings(Sitecore.Context.Device, false);
//If found
if (renderings != null && renderings.Any())
{
//Get the first rendering corresponding to the requested one
var rendering = renderings.First(sublayout => sublayout.RenderingID.ToString().Equals(presentationId));
if (rendering != null)
{
//Put this rendering into ajax layout
rendering.Placeholder = MY_AJAX_PLACEHOLDER;
var layoutItem = Sitecore.Context.Database.GetItem(MY_AJAX_LAYOUT_ID);
if (layoutItem != null)
{
var layout = new LayoutItem(layoutItem);
Sitecore.Context.Page.FilePath = layout.FilePath;
Sitecore.Context.Page.ClearRenderings();
Sitecore.Context.Page.AddRendering(rendering);
}
}
}
}
catch (Exception exception)
{
Log.Warn("Cannot render this!", this, exception);
}
}
}
}
And of could you need to include this resolver after the existing one by adding this into a .config file in \App_Config\Include\
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<httpRequestBegin>
<processor patch:after="*[@type='Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel']" type="MyNamespace.AjaxLayoutResolver, MyNamespace"/>
</httpRequestBegin>
</pipelines>
</sitecore>
</configuration>