EditHint in MVC
Describes how to use EditHint to trigger a full page refresh in edit view, when changing the value of a specific property.
When you work with Optimizely content data in MVC (model-view-controller), the view does not have to take the content data object as the view model. The received content data populates a view model that the view uses when a page loads.
When a view uses a view model instead of the content data object, the edit view is unaware of connections between the properties on the view model and the properties on the content data object. This means that you cannot update parts of the page when you change the content in the form edit view. However, you can use helper methods to display the correct data on the preview window. The following sections describe each helper method.
Property connections
The GetEditHints extension method lets you connect a view model property to a content data property. Located in EPiServer.Web.Mvc, use it on the ViewData property in the controller. This method returns a class that handles two collections on the ViewData object.
AddConnection on the class uses expressions to get the view model property and the content data property, which should be connected. Use the ViewData object to set connections between properties by casting ViewData[EPiServer.Web.Mvc.ViewDataKeys.PropertyConnections to IList<EditHint>, and adding edit hints to the collection.
When you want to display the property (with a connection to a content data property) in the view, use the Html.PropertyFor extension method in the EPiServer.Web.Mvc.Html namespace. This creates a wrapping element around the property with attributes that connect to the content data property.
By default, the wrapping element is a div, but you can change the element by adding CustomTag to the list in additionalViewData (new { CustomTag = "span" }) in the overloads of PropertyFor that contain additionalViewData.
If you cannot use a wrapping element in edit view, use the EditAttributes extension method instead. This writes the attributes for connecting the element to a property on the content data object.
Make connections between properties directly in the view by using the Html.PropertyFor extension with the EditHint overload. Set the ContentDataPropertyName on the EditHint object to connect to the view data property.
When you use Html.PropertyFor, edit view automatically connects a view model property with the same name as the content data object property.
Full refresh properties
Some content data properties cannot have a one-to-one relation with a property on the view model. These properties need a full page refresh to render a correct preview.
For example, a ShowBanner property displays a banner on the page if the property is set to true. Because it can affect many elements on the page, it requires a full refresh to render correctly.
To add a property to the full refresh list, use the GetEditHints extension method in EPiServer.Web.Mvc. This returns a class that handles two collections on the ViewData object: connections between the view model properties and the content data properties, and properties that need a full refresh.
AddFullRefreshFor on the class uses expressions to get the property from the content data object, which is added to the list. Use the ViewData object to set a property to the full refresh list by casting ViewData[EPiServer.Web.Mvc.ViewDataKeys.FullRefreshProperties] to IList<EditHint>, and adding an edit hint to the collection with the ContentDataPropertyName set to the property name.
Render the collection somewhere on the page using the Html.FullRefreshPropertiesMetaData() extension method. This method also has an overload that takes an array of property names. Use the overload with the string array to add property names for full refresh. The default method adds the properties in the ViewData collection.
Html.BeginEditSection
The BeginEditSection and EndEditSection extension methods work like EditAttributes by adding attributes that are needed for editing.
Use the methods when you add attributes to a property containing nested properties (such as a block) or render a property that can be nested (such as a partial view for a block). BeginEditSection ensures that only the outer property gets edit hints when there are nested properties.
When you render a block, the block property gets edit hints, while the individual properties within the block do not get edit hints.
Html.EditAttributes
The EditAttributes extension methods add attributes to an existing element. These attributes connect the content in the element to a property on the content data object in edit view by specifying the content data object property to which the element connects.
Html.FullRefreshPropertiesMetaData
The Html.FullRefreshPropertiesMetaData() extension has a parameterless method (default) and an overload that takes an array of property names. The default method adds the properties in the ViewData collection for a full refresh. The overload with the string array adds only the property names in the array for full refresh.
Html.PropertyFor
The Html.PropertyFor methods wrap Html.DisplayFor to create connections between view model properties and content data properties in edit mode. In view mode, PropertyFor directly calls DisplayFor. In edit view, a wrapping element is created around the property that contains a connection to a content data property (if a connection exists).
By default, the wrapping element is a div, but you can change the element by adding editepielementname to the list in additionalViewData (new { editepielementname = "span" }) in the overloads of PropertyFor that contain additionalViewData.
EditHint example
The following example contains a page type, a controller, a model view, and a view.
public class EditHintSample: PageController<EditSamplePage> {
public ActionResult Index(EditSamplePage currentPage) {
var model = new EditSampleViewModel {
Heading = currentPage.MyText,
Body = currentPage.MainBody,
SecondaryBody = currentPage.SecondaryBody,
BannerUrl = currentPage.BannerUrl.ToString(),
ShowBanner = currentPage.ShowBanner,
TextBlock = currentPage.TextBlock
};
// Get the edit hint collections
var editingHints = ViewData.GetEditHints<EditSampleViewModel,EditSamplePage>();
// Adds a connection between 'Heading' in view model and 'MyText' in content data.
editingHints.AddConnection(m => m.Heading, p => p.MyText);
// Add the property 'ShowBanner' to the collection of properties which requires full refresh of the page.
editingHints.AddFullRefreshFor(p => p.ShowBanner);
return View(model);
}
}
public class EditSampleViewModel {
public string Heading {
get;
set;
}
public string BannerUrl {
get;
set;
}
public XhtmlString Body {
get;
set;
}
public XhtmlString SecondaryBody {
get;
set;
}
public virtual bool ShowBanner {
get;
set;
}
public virtual EditSampleBlock TextBlock {
get;
set;
}
}
[ContentType]
public class EditSampleBlock: BlockData {
public virtual string Heading {
get;
set;
}
public virtual XhtmlString Body {
get;
set;
}
}
[ContentType]
public class EditSamplePage: PageData {
public virtual string MyText {
get;
set;
}
public virtual XhtmlString MainBody {
get;
set;
}
public virtual XhtmlString SecondaryBody {
get;
set;
}
public virtual Url BannerUrl {
get;
set;
}
public virtual bool ShowBanner {
get;
set;
}
public virtual EditSampleBlock TextBlock {
get;
set;
}
}Razor view engine:
@model AlloyTemplates.Controllers.EditSampleViewModel
@{
Layout = null;
}
@Html.FullRefreshPropertiesMetaData()
<h1 @Html.EditAttributes(m => m.Heading)>@Model.Heading</h1>
@if (Model.ShowBanner)
{
<div @Html.EditAttributes(m => m.BannerUrl)>
<img src="@Model.BannerUrl"/>
</div>
}
@Html.PropertyFor(m => m.Body, new EPiServer.Web.Mvc.EditHint() { ContentDataPropertyName = "MainBody" } )
@Html.PropertyFor(m => m.SecondaryBody)
@Html.BeginEditSection("div", p => p.TextBlock)
@Html.Partial("TextBlock", Model.TextBlock )
@Html.EndEditSection("div")Updated 17 days ago
