In EPiServer CMS 5 you can both build your own Virtual Path Providers (from now on simply VPP) for accessing files as well as change the files properties. In EPiServer CMS 5 R2 it is even possible to add these properties to each Path Provider, so now it's starting to be useful.
In this post, I will create a custom VPP called VirtualPathStartPublishProvider and add a property to all files in that VPP called StartPublishDate and the visitors will not be able to access the file until the start publish date has happend. You will simply get a 404 not found.
Changes in the web.config
This is how we add it in web.config:
1: <virtualPath customFileSummary="~/FileSummary.config">
2: <providers>
3: <clear />
4: <add showInFileManager="true"
5: virtualName="StartPublish Files"
6: virtualPath="~/StartPublishFiles/"
7: bypassAccessCheck="false"
8: indexingServiceCatalog="Web"
9: physicalPath="C:\Inetpub\EPiServerR2\VPP\StartPublishFiles"
10: name="StartPublishFiles"
11: type="EPiServer.StartPublishProvider.VirtualPathStartPublishProvider,
12: EPiServer.Templates.Public"
13: customFileSummary="~/StartPublishProvider.config" />
Let's go over this line by line.
Line 4: showInFileManager="true" is necessery in order to show it at all.
Line 5: Is what it's supposed to be called in the file manager
Line 6: Is what the file path will be
Line 11: The class as well as the assembly (line 12)
Line 13: Where we get our own File summary
File summary
The file summary is a config file with a lot of html in. You can always open the existing FileSummary.config to see some examples. This specialised File summary is a lot smaller, just the StartPublish property.
<root xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<model>
<instance>
<StartPublish />
</instance>
</model>
<table id="id_matrix"
border="0">
<tr>
<td class="EP-tableCaptionCell">
Start publish date [YYYY-MM-DD]
</td>
<td valign="top"
width="100"
height="10">
<div id="id_field1">
<xforms:input ref="StartPublish"
value=""
id="id_field2"
size="40"
class="commonInput" />
</div>
</td>
</tr>
</table>
</root>
Just remeber to add the same name under <model><instance><PROPERTY_NAME /></instance></model> as well in your ref on the xform part.
The Custom Page Provider
We simply load the file and check if it is a unified file. If it is, try and load the property "StartPublish" and make sure the date has passed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Hosting;
using EPiServer.Web.Hosting;
using System.Collections.Specialized;
namespace EPiServer.StartPublishProvider
{ public class VirtualPathStartPublishProvider :
EPiServer.Web.Hosting.VirtualPathVersioningProvider
{ public VirtualPathStartPublishProvider(string name,
NameValueCollection configParameters)
: base(name, configParameters)
{ }
public override VirtualFile GetFile(string virtualPath)
{ // Get the file as always, to get access and versioning and all of that
VirtualFile file = base.GetFile(virtualPath);
// We want to always show it in edit mode and in File manager...
if (IsInFileManager || IsEditOrPreviewMode)
{ return file;
}
// Cast it as a UnifiedFile
UnifiedFile uf = file as UnifiedFile;
// If it is null, then its something else, lets return it as it is...
if (uf != null)
{ // Make sure we have some attributes
if (uf.Summary.Dictionary.Count > 0)
{ // Get our StartPublish attribute
string date = uf.Summary.Dictionary["StartPublish"] as string;
if (!string.IsNullOrEmpty(date))
{ DateTime dt = DateTime.MinValue;
if (DateTime.TryParse(date.Trim(), out dt))
{ // Make sure it is a value in the past
if (dt != DateTime.MinValue && dt < DateTime.Now)
{ return file;
}
}
}
}
return null;
}
return file;
}
/// <summary>
/// Are we in the file manager
/// </summary>
public bool IsInFileManager
{ get
{ HttpRequest request = HttpContext.Current.Request;
Uri referrer = request.UrlReferrer;
return referrer != null
&& referrer.Host == request.Url.Host
&& referrer.Segments[referrer.Segments.Length - 1].Equals("ActionWindow.aspx", StringComparison.InvariantCultureIgnoreCase); }
}
/// <summary>
/// Are we in edit or preview mode
/// </summary>
public static bool IsEditOrPreviewMode
{ get
{ HttpRequest request = HttpContext.Current.Request;
Uri referrer = request.UrlReferrer;
return referrer != null
&& referrer.Host == request.Url.Host
&& referrer.Segments[referrer.Segments.Length - 1].Equals("EditPanel.aspx", StringComparison.InvariantCultureIgnoreCase); }
}
}
}
In reality
We simply add a file, VPP.txt, and set a Start Publish date in the future:
It is then added in our custom VPP:
We then add a link on a page to that file:
And if you then go to view mode and try to click on the link:
You will get a 404 Not found:
But if we change the date to a date in the past:
We will be able to open the file:
Conclusion
This can be very useful, especially after R2 when you can create a summary file per VPP. It feels a little backward to add the properties in a config-file, but I guess it works for now. What I really miss is someway to get EPiServers standard property types in here, so we can get a nice "Select your date" as well as get a "Must enter value" and some validation. But according to EPiServer, no one seems to use this yet, so hopefully this post will get people to start requesting these things.
Credits
A big thank you to Tomas Unestad for actually implementing this in the first place. We had no idea how it worked so it took a few gray hairs...