ViewModels
A view model is an object that can be rendered in a view - a Razor template. The view model represents an entity such as a page or a paragraph and has been optimized for rendering in front end.
Since view models are objects with strongly typed properties you will be able to use intellisense in e.g. Visual Studio and easily find the values available to you (Figure 1.1).
Some of the key advantages to using ViewModels are:
- Workflow / Intellisense
Regular razor templates use a key/value collection where the view model templates are served a typed object with properties. The view model will make it possible to get full intellisense when working with templates in Visual Studio. You no longer have to rely as much on documentation or DwTemplateTags/@TemplateTags() to find out what information is available. - Feedback
A regular razor templates will fail silently if you misspell a property, since it is a simple lookup like this: @GetValue(“DwPageName”). In contrast, the rendering engine will give you immediate feedback (an error message) if you misspell the name of a view model property. - Performance
View model templates are easier to optimize, particularly regarding the parsing and rendering process. Therefore you should see some performance improvements when using view model templates, compared to other types of templates.
There are two different base ViewModels available to you:
- PageViewModel
- ParagraphViewModel
They inherit a number of other viewmodels, such as the CartViewModel used for rendering shopping cart information. Both of these base ViewModels are described in more detail below.
Using a view model template
In order to use a ViewModel, the template must inherit from ViewModelTemplate and should specify a model that is valid in the context where the template is used - e.g. page or paragraph - at the top of the template:
You will then have access to all properties of the ViewModel via @Model - as in the example below.
Please note that - unlike for TemplateTags - you need not remember these properties or look them up anywhere, with a proper setup you will have access to code-hinting and other Intellisense features.
PageViewModel
When rendering a page layout you must use the PageViewModel:
Content placeholders are defined in the following manner:
A placeholder can take the following parameters:
Parameter |
Required |
Comments |
Id |
Yes |
Unique id of a layout container. |
Title |
No |
Friendly name of the layout container which is displayed in the administration (defaults to the value of Id). |
Settings |
No |
Additional settings that specifies how the content should be rendered. |
The placeholder settings available to you are:
Property |
Description |
Default value |
Possible values |
Default |
Whether new content should be placed in this container by default (page edit). |
False |
True or False |
Sort |
Controls the sorting in administration (page edit). |
0 |
1-99 |
Template |
The template that should be used for items in this container. |
|
Any valid paragraph template. Must be placed in /Templates/Paragraph, /Templates/Designs/Paragraph or /Templates/Designs/DesignName/Paragraph |
A very simple page layout template could look like this:
You can explore the PageViewModel further in the API documentation.
ParagraphViewModel
When rendering a paragraph you must use the ParagraphViewModel.
This view model gives you access to all basic properties of the current paragraph – e.g. the Text, Image, ImageAlt, and any app module output:
You can explore the ParagraphViewModel in more detail in the API documentation.
As usual, GetValue() returns the field value as an untyped object which only really advisable if you don't know what you're trying to retrieve, e.g. if you loop through all fields and you don't know which fields will be available.
Under normal circumstances it is advisable to use the appropriate method instead, which alsoallows you to use all the lovely type-appropriate C# methods:
Example: Rendering a Date field using GetValue or GetDateTime
Method |
Example |
Result |
GetValue |
@Model.Item.GetValue("Date") |
01-11-2016 14:35:09 |
GetDateTime |
@Model.Item.GetDateTime("Date").ToString("s") |
2016-11-01T14:35:09 |
GetDateTime | @Model.Item.GetDateTime("Date").Year | 2016 |
Example: Rendering a File field using GetValue or GetFile
Method |
Example |
Result |
GetValue |
<div>@Model.Item.GetValue("File")</div> |
<div>Dynamicweb.Frontend.FileViewModel</div> |
GetFile |
<div>@Model.Item.GetFile("File").Path</div> |
<div>/Files/Images/logo.png</div> |
Items in ViewModels
Some ViewModels will expose an item property which will give you an instance of the ItemViewModel, e.g.
- PageViewModel.Item (Item based pages)
- PageViewModel.PropertyItem (Page Properties items)
- PageViewModel.Area.Item (Website Properties items)
- ParagraphViewModel.Item (Item based paragraphs)
The ItemViewModel gives you access to a collection of item fields - and the following methods for retrieving field values directly:
Method |
Return type |
Use with item field type |
Comment |
GetBoolean |
Boolean |
Check box |
|
GetDateTime |
DateTime |
Date, Date and time |
|
GetDouble |
Double |
Decimal number |
|
GetInt32 |
Int32 |
Integer number |
|
GetInt64 |
Int64 |
|
|
GetString |
String |
Text, Rich text, Color |
|
GetFile |
FileViewModel |
File |
You use the GetFile() method whenever you’ve used an item field of the type File: Item.GetFile("Image").Path |
GetFiles |
IList<FileViewModel> |
Folder |
|
GetGeolocation |
GeolocationViewModel |
Geolocation |
|
GetItem |
ItemViewModel |
Item type, Link to item |
You have a shared item type called Font which contains all sort of font settings. This item type is used in your website settings – so to retrieve the value from the FontFamily field: Model.Area.Item.GetItem("Font").GetString("FontFamily”); |
GetItems |
IList<ItemViewModel> |
Item relation list |
You use the GetItems() method if you have used an item field of the type Item relation list – this is the only way to retrieve values from item relation lists: |
GetUsers |
IList<UserViewModel> |
User |
|
GetValue |
untyped object |
Any |
Examples:
Standard template methods
The following standard template methods and features can be used in ViewModel templates:
Property |
Used in |
Comments |
@ContentPlaceholder() |
Master templates |
Used to specify where to merge in page template content |
@MasterPageFile(“master.cshtml”) |
Page templates |
Used to specify which Master file to use for this page template |
@Include(…) |
Everywhere |
|
@IncludeFile(…) |
Everywhere |
|
@GetPageIdByNavigationTag("TagName") |
Everywhere |
Returns the first area page with the specified navigationtag. If no page is found, 0 is returned |
@RenderItem(…) |
Everywhere |
|
@RenderItemList(…) |
Everywhere |
|
@RenderItemCreationForm(…) |
Everywhere |
|
@RenderNavigation(…) |
Everywhere |
|
@SnippetStart(…) @SnippetEnd(…) @RenderSnippet(…) |
Everywhere |
|
@Translate(…) |
Everywhere |
Extension Methods
If the properties of the ViewModel is not enough – if you need more data – you can sometimes use an extension method to retrieve that data. Extension methods are typically available when you occasionally need to fetch complex data but adding the data directly to the ViewModel would lead to too much of a performance hit. In that sense you can think of extension methods as a sort of mid-point between adding more properties to the ViewModel and using the API.
To use an extension method:
- Find the extension method using the API documentation
- Add the appropriate namespace to the relevant template
- Use the extension method(s)
Currently it’s a little bit hard to know which extension methods are available – the only option is to browse the API documentation – but we hope to improve on this in the future.
Example 1: GetProductGroup()
For example – the NavigationTreeViewModel has an extension method for fetching product group properties. This is useful in edge-cases where you need to fetch data such as group assets, the group description, or the name of a product category applied to the group – things which can be useful in e.g. a mega-menu but not a normal navigation.
To use this extension method:
- Open the API documentation and locate the GetProductGroup() method (Dynamicweb.Ecommerce.ProductCatalog.NavigationTreeViewNodeExtensions)
- Add @using Dynamicweb.Ecommerce.ProductCatalog to the template where you want to use the method – in this case this is likely a navigation template of some sort
- You can now use the extension method in your code, as in the example below:
Example 2: IsProductInCart()
The ProductViewModel contains an extension method – IsProductInCart() – which is used to check if the product is in a specific order context cart. This can be useful when you want to check if a product is in for instance a quote cart, or a weekly or monthly cart.
To use this extension method:
- Open the API documentation and locate the IsProductInCart() method
- Add @using Dynamicweb.Ecommerce.ProductCatalog to the template where you want to use the method – this could be a product details template
- You can now use the extension method in your code, as in the example below: