Last week I spendt a lot of hours converting one of the EPiCode modules (the MultiPageProperty) to EPiServer CMS 5.
Here are some of the lessons I learned.
References
First step is replacing EPiServer references.
Note that we will need 3 EPiServer references (while only EPiServer.dll in 4.6x):
- EPiServer
- EPiServer.Configuration
- EPiServer.Web.WebControls
Build errors
The majority of the build errors refers to namespace changes and to functionality that has been removed from EPiServer.Global.
Excample:
- EPiServer.Web.WebControls replaces EPiServer.WebControls
- ResolveUrl("~/") replaces EPiServer.Global.EPConfig.RootDir
- EPiServer.LanguageManager.Instance replaces EPiServer.Global.EPLang
- DataFactory.Instance replaces EPiServer.Global.EPDataFactory
New model for Property Types
From the CMS 5 SDK:
In EPiServer CMS, presentation logic has been removed from PropertyData and classes inheriting from PropertyData. They are still responsible for providing a default user interface through the method EPiServer.Core.PropertyData.CreatePropertyControl that returns a control implementing EPiServer.Core.IPropertyControl. This Interface implements properties and methods that make it possible to load and save data for the properties that are being edited.
In other words, all custom properties need to be rebuildt to fit the new model.
Example:
[PageDefinitionTypePlugIn(DisplayName = "MultiPage")]
[Serializable]
public class PropertyMultiPage :
EPiServer.Core.PropertyLongString
{
}
public class MultiPageControl :
EPiServer.Web.PropertyControls.PropertyStringControl
{
}
CreateChildControls() in 4.x becomes:
- case "edit" --> CreateEditControls()
- case "default" --> CreateDefaultControls()
- validation --> ApplyEditChanges()
EPiServer Javascript and dialogs
By now the project will build successfully. You may think you're almost done, but this is when it gets interesting.
The core functionality in the MultiPageProperty relies on javascript to open custom dialogs which in turn opens EPiServer dialogs.
Another fact is that the way modal dialogs are created and opened in EPiServer is changing.
Previous versions of EPiServer made use of Microsoft Internet Explorer specific code, most of these functions were located in /Util/javascript/common.js.
The new scripting model is recommended in order to be able to open the dialogs in other browsers such as FireFox.
Create a modal dialog
To create a modal dialog in UI we use the EPi.Dialog object and especially the EPi.CreateDialog() function located in /UI/javascript/system.js.
The EPi.Dialog class also needs /UI/javascript/system.aspx and /Util/javascript/episerverscriptmanager.js to be registered as well.
Example:
<script type='text/javascript'
src="<%= EPiServer.UriSupport.
ResolveUrlFromUtilBySettings("javascript/episerverscriptmanager.js") %>">
</script>
<script type='text/javascript'
src="<%= EPiServer.UriSupport.
ResolveUrlFromUIBySettings("javascript/system.js") %>" >
</script>
<script type='text/javascript'
src="<%= EPiServer.UriSupport.
ResolveUrlFromUIBySettings("javascript/system.aspx") %>" >
</script>
Note the use of EPiServer.UriSupport.ResolveUrl..() methods to ensure correct paths to the UI and Util folders.
Let use the example of opening the EpiServer FileManager dialog.
Prior to CMS 5 the javascript code would be similar to this excample:
function SelectImageLink(myControlId)
{
var url = '/<%= EPiServer.Global.EPConfig.EditDir %>FileManagerBrowser.aspx';
var returnvalue;
var linkAttributes = new Object();
returnValue = OpenDialog(url, linkAttributes, 445, 412);
if (returnValue != undefined && returnValue != 0)
{
var myCtrl = document.all[myControlId];
myCtrl.value = returnValue;
}
}
Using the new scripting model in CMS 5:
function SelectImageLink(myControlId)
{
// Pass the page or parent page id to the popup.
// Will be used in page browser dialog
var pageId =
'<%= Page.Request.QueryString["pageid"] != null ?
Page.Request.QueryString["pageid"] : "0" %>';
var parentPageId =
'<%= Page.Request.QueryString["parentId"] != null ?
Page.Request.QueryString["parentId"] : "0" %>';
// The file manager needs the folder id in order
// to show or create the "Page Files" directory.
var folderId =
'<%= Page.Request.QueryString["folderId"] != null ?
Page.Request.QueryString["folderId"] :
Page.Request.QueryString["pageid"] %>';
var url =
'<%= EPiServer.UriSupport.
ResolveUrlFromUIBySettings("edit/FileManagerBrowser.aspx") %>?id='
+ pageId + '&parent=' +
parentPageId + '&folderid=' + folderId;
var selectedfile =
'<%= LinkItem.ImageLink == null ? "" : LinkItem.ImageLink.URL %>';
url += '&selectedfile=' + selectedfile;
var linkAttributes = new Object();
var dialogArguments = linkAttributes;
var features = {width: 600, height: 412};
var callbackArguments = new Object();
callbackArguments.myControlId = myControlId;
/* opens the filemanagerbrowser dialog */
EPi.CreateDialog(
url,
OnFileDialogClosed,
callbackArguments,
dialogArguments,
features);
}
/* function called after file browser dialog has returned and closed*/
function OnFileDialogClosed(returnValue, callbackArguments)
{
if (returnValue != undefined && returnValue != 0)
{
var myCtrl = document.getElementById(callbackArguments.myControlId);
myCtrl.value = returnValue;
}
}
Let's look at the parameters
url
Path to the file to open in a dialog, required.
Note that the location of many of the EPiServer dialogs has changed in CMS 5.
callbackMethod
Function | null.
In the callbackMethod you write the name of the javascript function you want to execute when the dialog is closed.
This function is passed two arguments. The first is the returnValue of the dialog, the second is the callbackArguments described next.
callbackArguments
Variant | null.
Variant that specifies arguments to use in the callbackMethod when returning/closing the dialog.
Use this parameter to pass a value of any type to callbackMethod. E.g. the id of the control that should be updated with the returnValue.
dialogArguments
Variant | null.
Variant that specifies the arguments to use when displaying the dialog.
Use this parameter to pass a value of any type to the dialog.
features
Optional. Object that specifies the dialogs position and size in pixels, if the window should be resizable and if it should allow scrolling.
Example: {width: 400, height: 300}. Position is centered in opening window.
Get hold of a control
Using document.all[""] is not allowed in FireFox.
//4.6x
document.all["Id"]
//CMS 5
document.getElementById["Id"]
Set returnvalues and close dialog
window.returnValue = linkReturnValues;
window.close();
EPi.GetDialog().Close(linkReturnValues);
Using id as a queryparameter
The EPiServerFriendlyUrlRewriteProvider will by default remove id's from the url of webforms that don't match an EPiServer template.
As of now, the provider does not include support to turn off the Provider on a specific template.
Simplest solution is to rename the queryparameter in our custom dialog, similar to this MultipageSelector.aspx?pageid=21&epslanguagebranch=...