Episerver: How to set a value on the server side and update the All Properties View?

This article continues the series on Episerver All Properties View with describing how to update a property value on the server side and refresh the view.


The scenario and the code shown in the article is building on top of what is described in one of my latest articles.

This time in my scenario, when dropdown is changed, I want to assign that value to the PetTypeName property on the page. This might not sound like much of a challenge, and it is much easier to do on the frontend, but imagine what else can be done by having this action passed through the server side.

First I added the property that I wanted to update on the server side to the page.

1
2
3
4
5
6
7
8
9
10
11
12
// PetPage.cs
[ContentType(DisplayName = "PetPage", GUID = "317e0860-8466-4817-8c9e-b33e83a297a4", Description = "")]
public class PetPage : PageData
{
// Added code
[Display(Name = "Pet Type Name", GroupName = SystemTabNames.Content, Order = 5)]
public virtual string PetTypeName { get; set; }
// End of added code
[Display(Name = "Pet Type", GroupName = SystemTabNames.Content, Order = 10)]
public virtual PetTypeBlock PetType { get; set; }
}

Next step was to extend the code that registered dropdown chages. The idea was to refesh the All Properties View, and this is done by getting current pageLink and requesting the view for that value. Here is the official documentation. This soulution is not exactly robust, since it uses setTimeout, but I was not able to figure this part out and it worked good enough.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// PetTypeContainer.js
define([
"dojo/_base/declare",
"epi/shell/layout/SimpleContainer"
],
function (
declare,
SimpleContainer
) {
return declare([SimpleContainer], {
petTypeDropdown: null,
addChild: function (child) {
this.inherited(arguments);
if (child.name.indexOf("petType") >= 0) {
this.petTypeDropdown = child;
var self = this;
setTimeout(function () {
self._hideAll();
}, 0);
this.own(this.petTypeDropdown.on("change",
function (petType) {
self._hideAll();
self._updateVisiblePetType(petType);
// Added code
if (self.petTypeDropdown.previousItem === null || self.petTypeDropdown.previousItem !== petType) {
if (self.petTypeDropdown.previousItem) {
setTimeout(function () {
var contextService = epi.dependency.resolve("epi.shell.ContextService");
var currentContext = contextService.currentContext;
var contextParameters = { uri: 'epi.cms.contentdata:///' + currentContext.id };
dojo.publish("/epi/shell/context/request", [contextParameters]);
}, 500);
}
self.petTypeDropdown.previousItem = petType;
}
// End of added code
}));
}
},
_updateVisiblePetType: function (petType) {
$(document).find('input[name*=petType.selectedPetType]').closest('ul').children().eq(petType).show();
},
_hideAll: function () {
$.each([1, 2, 3], function (index, value) {
$(document).find('input[name*=petType.selectedPetType]').closest('ul').children().eq(value).hide();
});
}
});
});

To actually set the new property I used an InitializableModule.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// DefaultPropertyValueInitialization.cs
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class DefaultPropertyValueInitialization : IInitializableModule
{
public void Initialize(InitializationEngine context)
{
ServiceLocator.Current.GetInstance<IContentEvents>().LoadedContent += DefaultPropertyValueInitialization_LoadedContent;
}
public void Uninitialize(InitializationEngine context)
{
}
private void DefaultPropertyValueInitialization_LoadedContent(object sender, ContentEventArgs e)
{
switch (e.Content)
{
case PetPage petPage:
HandlePetPage(e, petPage);
break;
}
}
private static void HandlePetPage(ContentEventArgs e, PetPage petPage)
{
petPage = petPage.CreateWritableClone() as PetPage;
if (petPage != null)
{
petPage.PetTypeName = Enum.GetName(typeof(PetType), int.Parse(petPage.PetType.SelectedPetType));
e.Content = petPage;
}
}
}

As I final step I added an UIDescriptor to default back to All Properties View, but this shouldn’t be required with the latest version of EpiServer, where it defaults to the last used view.

1
2
3
4
5
6
7
8
9
// PetPageUiDescriptor.cs
[UIDescriptorRegistration]
public class PetPageUiDescriptor : UIDescriptor<PetPage>
{
public PetPageUiDescriptor() : base()
{
DefaultView = CmsViewNames.AllPropertiesView;
}
}

By convention both Initializers and Descriptors should be in ProjectRoot\Business folder.

All in all this solved a problem for our project, but it was still a big challenge to figure out the Dojo part.


To take screenshots I use LightShot
To record gifs I use ScreenToGif