November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
Note: This topic has no later version.
This document describes how you create page templates in EPiServer CMS, through using ASP.NET Web Forms or MVC. Both are fully valid to use.
Create a page template in Visual Studio as follows:
When the strongly typed page type template is used, the template will automatically be registred as a supported template for the specified page type (T). To make the template supported for all page types in the system, EPiServer.Core.PageData can be used as the generic type (T).
The [TemplateDescriptor] attribute can be used on templates to add metadata to the template. The attribute can also be used to set the template as the default template for the page data. For more information about the TemplateDescriptor attribute see the Attributes article.
It is possible to use several [TemplateDescriptor] attributes on the same template, to specify several page types which will have the template as an supported render. When the template are strongly typed, the ModelType type must be derived from the generic type. When two page types should use one template, the multi-attribute functionality can be used by setting the generic type to PageData and add two [TemplateDescriptor] attributes, which specifies the types in the ModelType property.
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAnnotations;
using EPiServer.Framework.DataAnnotations;
using EPiServer.SpecializedProperties;
using EPiServer.Web;
[ContentType]
public class MyPage : PageData
{
public virtual XhtmlString MainBody { get; set; }
public virtual PageList MainList { get; set; }
}
[TemplateDescriptor(Name = "My template", Description = "My first template", Path = "~/templates/MyTemplate.aspx", Default = true)]
public partial class MyTemplate : TemplatePage<MyPage>
{ }
Create a block template in Visual Studio as follows:
The template will automatically be registered as a supported template for the specified block type (T). To make the template supported for all block types in the system, EPiServer.Core.BlockData can be used as the generic type (T).
The [TemplateDescriptor] attribute can be used on controls to add meta data to the template. The attribute can also be used to set the control as the default template for the block data. The attribute, which exists in the EPiServer.Framework.DataAnnotations namespace, contains the following properties:
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAnnotations;
using EPiServer.Framework.DataAnnotations;
using EPiServer.SpecializedProperties;
using EPiServer.Web;
[ContentType(DisplayName = "A page list", Description = "A block of properties needed to display a page list")]
public class PageList : BlockData
{
public virtual PageReference Root { get; set; }
public virtual int Count { get; set; }
public virtual string Heading { get; set; }
}
[TemplateDescriptor(Name = "My block control", Description = "My first block control", Path = "~/templates/MyBlockControl.ascx", Default = true)]
public partial class MyBlockControl : BlockControlBase<PageList>
{ }
If you want to render an MVC view for a page type, create a controller which inherits from EPiServer.Web.Mvc.PageController<T>, where T is your page type. This controller will be called for the page type, if it is chosen as the render for the page type. To render EPiServer CMS properties you use the Html.PropertyFor extension method. This method will call another view, which has the same name as the property type you are about to render. For EPiServer built-in properties, we have created views which will render the properties. An example of a view:
public class AcmeStandardPageController : PageController<MyStandardPage>
{
public ActionResult Index()
{
return View();
}
}
[ContentType]
public class MyStandardPage : PageData
{
public virtual string MyText { get; set; }
}
An alternative to use Html.PropertyFor is to use the HTML helpers in the EPiServer.Web.Mvc.Html namespace. Those helpers will be called through Html.DisplayFor, but can also be used directly.
You can make a dynamic content plug-in to support MVC in the following ways:
The first option is to create a display template with the same name as the dynamic content plug-in. For the DynamicPageProperty plug-in, the name would be “DynamicPageProperty.ascx” or “DynamicPageProperty.cshtml”. The view will take the dynamic content plug-in as the view model, and render the dynamic content in view mode. In the example “DdsViewerDynamicContent”, we have created a simple dynamic content, and a razor view for rendering the content.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.DynamicContent;
using EPiServer.PlugIn;
using EPiServer.Data.Dynamic;
using EPiServer.Core;
namespace CodeSamples.Additional_Content.HowTo
{
/// <summary>
/// Dynamic content showing the first 100 items in a Dynamic Data Store.
/// A specific editor is used to select store.
/// </summary>
[GuiPlugIn(Url = "~/EPiServer/DynamicContent/DdsViewerDynamicContentEdit.ascx", Area = PlugInArea.DynamicContent)]
public class DdsViewerDynamicContentUsingRazor : IDynamicContentBase
{
/// <summary>
/// Gets and sets the selected store
/// </summary>
public string State
{
get;
set;
}
/// <summary>
/// This property is not used, because a specific editor is used.
/// </summary>
public PropertyDataCollection Properties
{
get { return null; }
}
/// <summary>
/// Gets the first 100 hits from the selected store
/// </summary>
public IEnumerable<PropertyBag> Top100
{
get
{
return DynamicDataStoreFactory.Instance.GetStore(State).ItemsAsPropertyBag().Take(100).ToList();
}
}
}
}
@using CodeSamples.Additional_Content.HowTo
@model DdsViewerDynamicContent
<h2>Store: @Model.State</h2>
<table>
@if (@Model.Top100.Count() > 0) {
<tr>
@foreach (string column in @Model.Top100.First().Keys)
{
<th>@column</th>
}
</tr>
}
@foreach (var propertyBag in @Model.Top100)
{
<tr>
@foreach (var value in propertyBag.Values) {
<td>@value</td>
}
</tr>
}
</table>
The second option is to let the plug-in implement the interface System.Web.Mvc.IView, which is exactly what the DynamicPageProperty does. The interface only contains the method Render, with a ViewContext object and a TextWriter.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.DynamicContent;
using EPiServer.PlugIn;
using EPiServer.Data.Dynamic;
using System.IO;
using System.Web.Mvc;
using EPiServer.Core;
namespace CodeSamples.Additional_Content.HowTo
{
/// <summary>
/// Dynamic content showing the first 100 items in a Dynamic Data Store.
/// A specific editor is used to select store.
/// </summary>
[GuiPlugIn(Url = "~/EPiServer/DynamicContent/DdsViewerDynamicContentEdit.ascx", Area = PlugInArea.DynamicContent)]
public class DdsViewerDynamicContentUsingIView : IDynamicContentBase, System.Web.Mvc.IView
{
/// <summary>
/// Gets and sets the selected store
/// </summary>
public string State
{
get;
set;
}
/// <summary>
/// This property is not used, because a specific editor is used.
/// </summary>
public PropertyDataCollection Properties
{
get { return null; }
}
/// <summary>
/// Gets the first 100 hits from the selected store
/// </summary>
public IEnumerable<PropertyBag> Top100
{
get
{
return DynamicDataStoreFactory.Instance.GetStore(State).ItemsAsPropertyBag().Take(100).ToList();
}
}
/// <summary>
/// Renders the data received from the selected store
/// </summary>
/// <param name="context">The context.</param>
/// <param name="writer">The writer.</param>
public void Render(ViewContext context, TextWriter writer)
{
foreach (PropertyBag propertyBag in Top100)
{
foreach (var value in propertyBag)
{
writer.Write(value);
}
}
}
}
}
If it exists a display template with the same name as the dynamic content plug-in, and the plug-in implements IView, the display template will be called, and the system will not care about the IView implementation.
To render an XForm property on a page, the HTML helper methods Property and RenderPropertyXForm can be used in the view. The Property method will use the default behavior, while the RenderPropertyXForm takes the name of the property, and an XFormParameters class as parameters. The XFormParameters parameter is optional, and can be used to override the default settings.
The most important properties on the XFormParameters class are SuccessAction and FailedAction. When those properties are not set, default views for succeded and failed posts will be used. By changing those properties to Success for the SuccessAction and Failed for FailedAction, the action Success or Failed will be called in the controller, depending if a validation error occured when posting the form. The methods Success and Failed must than be created in the controller to make it work.
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="EPiServer.XForms.Util" %>
<section id="form">
<%--<% Html.EnableClientValidation(); %>--%>
<%: Html.ValidationSummary() %>
<% Html.RenderPropertyXForm("XForm", new XFormParameters() { SuccessAction = "Success", FailedAction = "Failed" }); %>
<%--<%: Html.Property("XForm") %> --%>
</section>
For EPiServer CMS to be able to match a requested URL to a controller, the EPiServer.Web.HierarchicalUrlRewriteProvider class must be in use. In a newly installed site that is the default URL rewrite provider, but in the case of an upgrade you must change the configuration manually.
You can render an MVC view for a block type in the following ways:
To render EPiServer CMS properties you use the procedure as you do on pages that is described above.
It is possible to require certain client resources to be rendered on the page in specific area. Please see Managing client resources in EPiServer CMS section for more information about requirements for templates to support this functionality.
Last updated: Mar 31, 2014