I have a question I have been struggling a bit with the last days. I'm trying to understand how the rendering of blocks works in Episerver 7 when working with MVC.
My current setup that actually works is as follows:
I have created a Block Type called "TeaserBlock" which has a couple of properties:
[ContentType(DisplayName = "TeaserBlock", GUID = "571582c4-6b99-4c0a-b000-f62265e312a9", Description = "A Teaser Block for show!")]
public class TeaserBlock : BlockData
{
[Display( GroupName = SystemTabNames.Content, Order = 1)]
public virtual string TeaserHeading { get; set; }
[Display(GroupName = SystemTabNames.Content, Order = 2)]
public virtual string TeaserText { get; set; }
}
To this I have a corresponding partial view in Views/Shared/ called TeaserBlock.cshtml. This one renders the block in view mode I guess?
My biggest problem was to get the "on page edit" to work and after some trying and googling I finally got it to work with the following code:
[TemplateDescriptor(Inherited = true,
Tags = new string[] { RenderingTags.Preview },
TemplateTypeCategory = TemplateTypeCategories.MvcController)]
public class PreviewBlockController : ActionControllerBase, IRenderTemplate<BlockData>
{
public ActionResult Index(BlockData currentBlock)
{
return View(currentBlock);
}
}
After I added a corresponding view to the PreviewBlockController it worked in "on page edit" which was good. It took me quite a while before I realized if the line "TemplateTypeCategory = TemplateTypeCategories.MvcController)" was not there it did not work. Anyone knows why this line is necessary?
Also is there some magic involved when using the Tag "RenderingTags.Preview" ?
Let's say that I have 5 different blocks in my application do I then need 5 different preview controllers and corresponding views to them as well?
What I would like is to have a more general "block preview controller" that could handle all "on page edit" for my blocks. I'm not sure if this is possible however because all Blocks will have different properties and therefore needs individual .cshtml for their preview if the preview will be any meaningful I guess. Or is there some way for me in code to find out what properties that is relevant in the block sent it to my controller so that I can loop over them for example? And with the help of this only need one preview controller and a corresponding view?
Is there any guidelines on how to deal with this in the best way?
Hope anyone can help me understand this concept a bit better, I find it hard to find information for some concepts regarding episerver.
TemplateTypeCategories equals different types of "render template types" supported.
public enum TemplateTypeCategories
{
None = 0,
WebFormsPage = 1,
UserControl = 2,
ServerControl = 4,
WebFormsPartial = 6,
WebForms = 7,
MvcController = 8,
Page = 9,
MvcView = 16,
MvcPartialController = 32,
MvcPartialView = 64,
MvcPartial = 96,
Mvc = 120,
}
Having TemplateTypeCategories.MvcController set will trick EPiServer to load the Block as if it was a normal page, remember that block instances doesn't work exactly as page instances do so we must perform this little trick. Otherwise the block instances will be registered as MvcPartialController's, and that we can't load directly in MVC.
I create my PreviewBlockController's a bit more simple than the ones in AlloyMVC.
using EPiServer.Core;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Framework.Web;
using EPiServer.Web;
using System.Web.Mvc;
using Site.Externwebb.Content.Blocks;
namespace Site.Externwebb.Controllers.Blocks
{
[TemplateDescriptor(Inherited = true,
Tags = new[] { RenderingTags.Preview },
TemplateTypeCategory = TemplateTypeCategories.MvcController)]
public class PreviewBlockController : Controller, IRenderTemplate<BlockData>
{
public ActionResult Index(BlockData currentBlock)
{
var baseType = currentBlock.GetType().BaseType;
if (baseType == typeof(BarkerBlock))
{
return View("Barkers", currentBlock);
}
if (baseType == typeof(SlideshowInlineBlock))
{
return View("Inline", currentBlock);
}
// Standard return (general block controller)
return View("RightColumn", currentBlock);
}
}
}
The views are placed by default in ~/Views/PreviewBlock/xxx.cshtml Here is an example
@using EPiServer.Web.Mvc.Html
@model EPiServer.Core.BlockData
@{
Layout = "~/Views/Shared/Masters/_BlockPreviewMaster.cshtml";
}
@section MainContent{
<div id="rightContent" style="width:300px;">
<div id="rightcolumn">
@{ Html.RenderContentData(Model, false); }
</div>
</div>
}
Good enough and easy to administer.
Good luck.
/ Eric Herlitz