How it works
Episerver supports context-sensitive client components. Context could be the current page that the user is working with. Because components are loosely coupled, the context service object is responsible for handling the current context. To get hold of the current context you could simply do this:
JavaScript
var contextService = epi.dependency.resolve("epi.shell.ContextService");
var currentContext = contextService.currentContext;
The context service on the client interacts with the server to resolve context for the selected page/block/entity. The actual properties on the context object depends on the type of context being displayed but a few properties are available for all context:
uri |
The key uniquely identifying the entity in context. |
previewUrl |
The URL on which the entity can be displayed in the editing UI. |
data |
The values of the entity in context. |
type |
The type of data for this context. This information is derived from the uri. |
id |
The id of the data for this context. This information is derived from the uri. |
Context on the server implements the IClientContext interface and is serialized to the client.
Example: epi.cms.contentdata Context
JavaScript
{
"parentLink":"4",
"customViewType":"",
"language":"en",
"publicUrl":"/MaintAlloy/Alloy-Track/",
"capabilities":
{
"languageSettings":true,
"securable":true,
"dynamicProperties":true,
"isFolder":false,
"isPage":true,
"contentResources":true,
"language":true,
"isBlock":false
},
"languageContext":
{
"isTranslationNeeded":false,
"language":"en",
"isPreferredLanguageAvailable":true,
"preferredLanguage":"en",
"reason":1,
"warning":null,
"hasTranslationAccess":true
},
"hasSiteChanged":false,
"fullHomeUrl":"http://localhost/MaintAlloy/EPiServer/CMS/Home",
"versionedUrl":"",
"dataType":"epi.cms.page",
"uri":"epi.cms.contentdata:///8_8",
"previewUrl":"/MaintAlloy/EPiServer/CMS/Alloy-Track,,8_8/?id=8_8&epieditmode=true",
"data":null,
"name":"Alloy Track",
"requestedUri":"epi.cms.contentdata:///8",
"versionAgnosticUri":"epi.cms.contentdata:///8"
}
The ContentDataContext class is serialized to produce this client context.
Using _ContextMixin to access context in components
To simplify interaction with the context you can implement a mix-in that provides access to the context from a component.
JavaScript
define("epi-cms/component/PageVersions", [
"epi/shell/_ContextMixin"
], function (_ContextMixin) {
return dojo.declare("epi.cms.component.PageVersions", [_ContextMixin], {
constructor: function(){
dojo.when(this.getCurrentContext(), function(context){
console.log("we have context: ", context);
});
}
}
});
The _ContextMixin extends the class with a the following methods:
getCurrentContext() |
Returns an available context or a deferred object that resolves to the context when it is available. |
currentContext |
The currently loaded context. This may be null. |
contextChanged(context, callerData) |
Overridable method called when the context changes. Components should check that the context is not null and may look at context.type to determine whether they can work with a given context. |
contextChangeFailed(previousContext, callerData) |
Overridable method called when loading the context fails for any reason. |
Changing the current context
If you need to change the current context, publish a message to the /epi/shell/context/request channel with parameters for the new context as the data. A URI parameter property is required to determine which type of context to load. The following example changes the current context to an Episerver CMS ContentData object:
JavaScript
var pageLink = "5_135";
var contextParameters = { uri: 'epi.cms.contentdata:///' + pageLink };
dojo.publish("/epi/shell/context/request", [contextParameters]);
Listening to changes to the current context using subscription
Without using _ContextMixin, you can subscribe to context changes using the dojo pub/sub infrastructure. If you want to react to a context change, subscribe to the /epi/shell/context/changed message:
JavaScript
startup: function () {
this.subscribe("/epi/shell/context/changed", this._contextChanged);
},
_contextChanged: function (newContext) {
if (!newContext) {
return;
}
}
Implementing a context resolver on the server
To provide context for a certain type of entities you can implement the following context resolver interfaces.
- Resolve a known reference using URI.
- Query context on a specific URL.
The following example shows a context resolver that performs both these tasks:
C#
[ServiceConfiguration(typeof(IUrlContextResolver))]
[ServiceConfiguration(typeof(IUriContextResolver))]
public class CmsFileContextResolver : IUriContextResolver, IUrlContextResolver
{
private VirtualPathProvider _vpp;
public CmsFileContextResolver(VirtualPathProvider vpp)
{
SortOrder = 123;
_vpp = vpp;
}
public string Name
{
get { return "epi.cms.unifiedfile"; }
}
public bool TryResolveUri(Uri uri, out IClientContext instance)
{
instance = ResolvePath("~" + uri.LocalPath);
return instance != null;
}
public bool TryResolveUrl(Uri url, out IClientContext instance)
{
instance = ResolvePath(url.LocalPath);
return instance != null;
}
private IClientContext ResolvePath(string path)
{
var file = _vpp.GetFile(path) as UnifiedFile;
if (file == null)
{
return null;
}
return new Models.UnifiedFileContext
{
Uri = new Uri("epi.file.unifiedfile://" + VirtualPathUtilityEx.ToAppRelative(file.VirtualPath).TrimStart('~')),
Data = new
{
file.VirtualPath,
},
PreviewUrl = file.VirtualPath
};
}
public int SortOrder { get; set; }
}
Querying for a new context by URL
Context resolvers that implement the IUrlContextResolver interface are queried when you load a URL in the preview frame. Publish a message to programmatically change the context to the context associated with a URL, as shown in the following example.
JavaScript
var contextParameters = { url: someUnknownUrl.toString() };
dojo.publish("/epi/shell/context/request", [contextParameters, { sender: this }]);
When an editor navigates from one context to another or the same, Episerver keeps the history of every step through the ContextHistory and BackContextHistory classes on the client side (both are internal to Episerver).
As a developer, you can clear the current context (and close the related view), and go back to the previous context. This is usually the case when you want to close or cancel a view related to the current context and go back.
For example, in the Project Overview, there is a close button. Clicking this button means clearing all Project context history and going back to the previous context.
You can achieve the same thing with the contextNavigation object on client side. This is a static object on the client side, exposing a method "back". It clears the history of the current context and then goes to the previous context.
Do you find this information helpful? Please log in to provide feedback.