Sitecore MVC have 2 types of renderings: View Rendering, Controller Action Rendering. To be simple - controller action is only some logic that fill data to model and transfer it to view.
You can use Razor view engine to render rendering view:
public string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View,
ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
To render Controller Action Rendering you can use same code, but return model that is filled by your logic.
If you need to use Sitecore rendering view engine wrapper and render View Rendering(or Controller Action Rendering) go through all Sitecore processors (e.g. GlassMapper get model, render other renderings in placeholders) - it is much more complex. You can take a look on this example. It was done to render one rendering and transfer it via AJAX and don't lose personalization, rendering parameters, datasource, nested renderings in placeholders:
if (rendering != null)
{
args.PageDefinition.Renderings.Remove(rendering);
//Put this rendering into ajax layout
rendering.Placeholder = Constants.Strings.AjaxPlaceholderKey;
rendering.LayoutId = new Guid(Constants.IDs.AjaxEmptyLayout);
var layout = renderings.First(x => x.RenderingType == "Layout");
if (layout != null)
{
args.PageDefinition.Renderings.Remove(layout);
for ( int i=0; i< args.PageDefinition.Renderings.Count; i++)
{
args.PageDefinition.Renderings[i].Placeholder =
args.PageDefinition.Renderings[i].Placeholder.Split('/').Last();
args.PageDefinition.Renderings[i].LayoutId =
new Guid(Constants.IDs.AjaxEmptyLayout);
}
layout.LayoutId = new Guid(Constants.IDs.AjaxEmptyLayout);
var getRedererArgs = new GetRendererArgs(new Rendering());
getRedererArgs.LayoutItem =
Sitecore.Context.Database.GetItem(Constants.IDs.AjaxEmptyLayout);
if (rendering.Renderer is Sitecore.Mvc.Presentation.ControllerRenderer)
{
RouteValueDictionary routeValueDictionary = new RouteValueDictionary();
foreach (var key in HttpContext.Current.Request.QueryString.AllKeys.Select(x=> x.ToString()))
{
routeValueDictionary.Add(key, HttpContext.Current.Request.QueryString[key]);
}
((Presentation.ControllerRenderer)rendering.Renderer).routeValueDictionary = routeValueDictionary;
}
layout.Renderer = PipelineService.Get().RunPipeline<GetRendererArgs, Renderer>(PipelineNames.GetRenderer, getRedererArgs, a => a.Result);
args.PageDefinition.Renderings.Add(layout);
args.PageDefinition.Renderings.Add(rendering);
}
}
You can adopt this code to be used not inside ActionResult, but not via Sitecore processor.
Also, I think that you can take a look on Sitecore FxM implementation as there is used same approach (code via ILSpy reflector):
public string GetRenderingHtml(Guid id, string uniqueId, string placeholder, string dataSource = "")
{
RenderingItem item = RenderingItem.GetItem(new ID(id), this.sitecoreContext.Database.Database, false);
if (item == null)
{
return string.Empty;
}
if (string.IsNullOrEmpty(placeholder))
{
return string.Empty;
}
if (string.IsNullOrEmpty(uniqueId))
{
return string.Empty;
}
string[] array = placeholder.TrimStart(new char[]
{
'/'
}).Split(new char[]
{
'/'
});
if (array.Length <= 0)
{
return string.Empty;
}
string text = array[0];
if (this.sitecoreContext.Database.GetItem(text) == null)
{
return string.Empty;
}
string result;
try
{
if (item.IsMvcRendering())
{
result = this.GenerateRenderingHtml(id, uniqueId, placeholder, text, dataSource);
}
else
{
result = this.GenerateSublayoutHtml(id, uniqueId, placeholder, text, dataSource);
}
}
catch (ItemNotFoundException ex)
{
throw this.HandleError(ex);
}
catch (Exception ex2)
{
throw this.HandleError(ex2);
}
return result;
}
Conclusion, there are two ways:
- Make your views simpler(render from model, don't use a lot of
Sitecore extensions) to have ability to use Razor rendering view
engine.
- Write your own code, you have as examples 2 implementations(GitHub
or Sitecore Federated Experience Manager). Your solution will be complex, but will be suitable almost for every rendering.