<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Martin Helgesen</title><link href="http://world.optimizely.com" /><updated>2011-01-16T18:30:46.0000000Z</updated><id>https://world.optimizely.com/blogs/Martin-Helgesen/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Chain of data fetching</title><link href="https://world.optimizely.com/blogs/Martin-Helgesen/Dates/2011/1/Chain-of-data-fetching/" /><id>&lt;p&gt;I’m sure you are familiar with the EPiServer feature that allows a page to fetch data from another page. A webeditor can easily enable this feature in edit mode, and this works fine.&lt;/p&gt;  &lt;p&gt;But what about a page that fetches data from a page that fetches data from another page? In this case we have a chain of 3 pages in inheritance. What does EPiServer do about this?&lt;/p&gt;  &lt;p&gt;Let’s try:&lt;/p&gt;  &lt;ul style=&quot;width: 406px; height: 350px&quot;&gt;   &lt;li&gt;Page A&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Heading – “Base Page”&lt;/li&gt;      &lt;li&gt;MainBody – “Base Page Body”&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Page B&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Heading – “Company Page”&lt;/li&gt;      &lt;li&gt;MainBody – empty&lt;/li&gt;      &lt;li&gt;Fetches data from Page A&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Page C&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Heading – “Department Page”&lt;/li&gt;      &lt;li&gt;MainBody – empty&lt;/li&gt;      &lt;li&gt;Fetches data from Page B&lt;/li&gt;   &lt;/ul&gt;     &lt;/ul&gt;  &lt;p&gt;When showing Page B the MainBody propertys value will be “Base Page Body”. However, when showing Page C the MainBody property will be empty. &lt;/p&gt;  &lt;p&gt;Let’s say you want to set up a site for a big company with subcompnaies and departments. 3 chains. And the top company want to distribute pages to the subcompanies with company guidelines that can be overridden. And, likewise, the subcompanies want to distribute those pages to the departments.&lt;/p&gt;  &lt;p&gt;One way of getting this to work is to have chains of data-fetching. In our example, this means that Page C’s MainBody would not be empty when shown. It would have shown data from Page A.&lt;/p&gt;  &lt;p&gt;The solution to this is to implement your own GetPropertyHandler. Using reflector, I fetched the code for EPiServer’s default property handler, and modified it:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;kwrd&quot;&gt;namespace&lt;/span&gt; EPiServer.Custom.Handlers
{
    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; PropertyHandlers
    {
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; PropertyData DefaultPropertyHandler(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; name, PropertyDataCollection properties)
        {
            PropertyData data = properties.Get(name);
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (data != &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;)
            {
                &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (!data.IsNull || data.IsMetaData)
                {
                    &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; data;
                }

            }
            PropertyData data3 = FetchDataFrom(name, properties);
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; ((data3 != &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;) &amp;amp;&amp;amp; (data3.Value != &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;))
            {
                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; data3;
            }
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; (DynamicPropertyCache.DynamicPropertyFinder.FindDynamicProperty(name, properties) ?? data);
        }

        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; PropertyData FetchDataFrom(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; name, PropertyDataCollection properties)
        {
            PropertyData data = properties.Get(&lt;span class=&quot;str&quot;&gt;&amp;quot;PageShortcutType&amp;quot;&lt;/span&gt;);
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (((data == &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;) || (data.Value == &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;)) || (((PageShortcutType)data.Value) != PageShortcutType.FetchData))
            {
                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;;
            }
            data = properties.Get(&lt;span class=&quot;str&quot;&gt;&amp;quot;PageShortcutLink&amp;quot;&lt;/span&gt;);
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (data == &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;)
            {
                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;;
            }
            PageReference pageLink = (PageReference)data.Value;
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (!PageReference.IsValue(pageLink))
            {
                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;;
            }
            &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; languageBranch = properties.Get(&lt;span class=&quot;str&quot;&gt;&amp;quot;PageLanguageBranch&amp;quot;&lt;/span&gt;).Value &lt;span class=&quot;kwrd&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt;;
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; GetPropertyFromPage(pageLink, languageBranch, name);
        }

        &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; PropertyData GetPropertyFromPage(PageReference fetchPageLink, &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; languageBranch, &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; propertyName)
        {
            PageData page;
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt;.IsNullOrEmpty(languageBranch))
            {
                page = DataFactory.Instance.GetPage(fetchPageLink);
            }
            &lt;span class=&quot;kwrd&quot;&gt;else&lt;/span&gt;
            {
                page = DataFactory.Instance.GetPage(fetchPageLink, LanguageSelector.Fallback(languageBranch, &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;));
            }
            PropertyData data2 = page.Property.Get(propertyName);
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (((data2 != &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;) &amp;amp;&amp;amp; !data2.IsLanguageSpecific) &amp;amp;&amp;amp; (data2.Value == &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;))
            {
                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; DataFactory.Instance.GetPage(page.PageLink, LanguageSelector.MasterLanguage()).Property.Get(data2.Name);
            }
&lt;font style=&quot;background-color: #ffff00&quot;&gt;            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt;.Compare(propertyName, &lt;span class=&quot;str&quot;&gt;&amp;quot;MainBody&amp;quot;&lt;/span&gt;, StringComparison.OrdinalIgnoreCase) == 0)
            {
                var data3 = FetchDataFrom(propertyName, page.Property);
                &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (data3 != &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;)
                {
                    &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; data3;
                }&lt;/font&gt;
            }
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; data2;
        }
     

    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;As you can see from the code, this fetch data logic is recursive as long as the property is named “MainBody”.&lt;/p&gt;

&lt;p&gt;And then, you have hook up this handler in Global.asax Application_Start method:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        &lt;span class=&quot;kwrd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;void&lt;/span&gt; Application_Start(Object sender, EventArgs e)
        {
            XFormControl.ControlSetup += &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; EventHandler(XForm_ControlSetup);
            PropertyDataCollection.GetHandler = EPiServer.Custom.Handlers.PropertyHandlers.DefaultPropertyHandler;
        }&lt;/code&gt;&lt;/pre&gt;

&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;I guess there are other ways of solving chains of inheritance, feedback is very welcome &lt;img style=&quot;border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none&quot; class=&quot;wlEmoticon wlEmoticon-smile&quot; alt=&quot;Smilefjes&quot; src=&quot;/link/00043480c63f43ec84a52c87906a433e.png&quot; /&gt;&lt;/p&gt;</id><updated>2011-01-16T18:30:46.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Access Control with the new Visitor Groups feature</title><link href="https://world.optimizely.com/blogs/Martin-Helgesen/Dates/2011/1/Access-Control-with-the-new-Visitor-Groups-feature/" /><id>&lt;p&gt;Just a quick follow-up from my previous post &lt;a href=&quot;http://world.episerver.com/Blogs/Martin-Helgesen/Dates/2010/11/Virtual-Roles-and-access-control-in-EPiServer/&quot;&gt;Virtual-Roles-and-access-control-in-EPiServer&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;In that situation I had to solve a problem for a customer where certain endusers (not authenticated) should have access to more pages than other users. These users could be identified from an IP-range.&lt;/p&gt;  &lt;p&gt;The solution then was to implement a Virtual Role and every user that matched a specific IP-range gained that role automatically. Then the webeditors could set access rights on pages based on this role.&lt;/p&gt;  &lt;p&gt;With the new EPiServer CMS 6 R2 feature “Visitor Groups” this could be done in another way. With a little help from Magnus excellent post &lt;a href=&quot;http://world.episerver.com/Blogs/Magnus-Paulsson/Dates/2010/12/Building-custom-criteria-for-Visitor-groups-in-CMS-6-R2/&quot;&gt;Building-custom-criteria-for-Visitor-groups-in-CMS-6-R2/&lt;/a&gt; I created a custom criterion “IPAddress” for the Visitor Groups and then the webeditors can define as many groups they want to based on an IP range match.&lt;/p&gt;  &lt;p&gt;Her is my criterion:&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt; &lt;font size=&quot;1&quot;&gt;[VisitorGroupCriterion(
        Category = &lt;span class=&quot;str&quot;&gt;&amp;quot;User Criteria&amp;quot;&lt;/span&gt;,
        DisplayName = &lt;span class=&quot;str&quot;&gt;&amp;quot;IPAddress&amp;quot;&lt;/span&gt;,
        Description = &lt;span class=&quot;str&quot;&gt;&amp;quot;Criterion that matches type and version of the user&#39;s browser&amp;quot;&lt;/span&gt;,
        LanguagePath = &lt;span class=&quot;str&quot;&gt;&amp;quot;/shell/cms/visitorgroups/criteria/ipaddresscriterion/ipaddress&amp;quot;&lt;/span&gt;)]
    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; IPCriterion : CriterionBase&amp;lt;IPModel&amp;gt;
    {
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;bool&lt;/span&gt; IsMatch(System.Security.Principal.IPrincipal principal,
                                     HttpContextBase httpContext)
        {
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; IsInRange(httpContext.Request.UserHostAddress);
        }


        &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;bool&lt;/span&gt; IsInRange(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; clientIpAddress)
        {
            &lt;span class=&quot;kwrd&quot;&gt;byte&lt;/span&gt;[] clientIP = IPAddress.Parse(clientIpAddress).GetAddressBytes();
            &lt;span class=&quot;kwrd&quot;&gt;byte&lt;/span&gt;[] mask = IPAddress.Parse(Model.Mask).GetAddressBytes();
            &lt;span class=&quot;kwrd&quot;&gt;byte&lt;/span&gt;[] ip = IPAddress.Parse(Model.Address).GetAddressBytes();
            &lt;span class=&quot;kwrd&quot;&gt;bool&lt;/span&gt; isequal = &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;;
            &lt;span class=&quot;kwrd&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;kwrd&quot;&gt;int&lt;/span&gt; i = 0; i &amp;lt; ip.Length; i++)
                &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; ((clientIP[i] &amp;amp; mask[i]) != (ip[i] &amp;amp; mask[i]))
                {
                    isequal = &lt;span class=&quot;kwrd&quot;&gt;false&lt;/span&gt;;
                    &lt;span class=&quot;kwrd&quot;&gt;break&lt;/span&gt;;
                }
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; isequal;
        }&lt;/font&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;And the model looks like:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt; &lt;font size=&quot;1&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; IPModel : IDynamicData, ICloneable
    {
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; EPiServer.Data.Identity Id { get; set; }
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;object&lt;/span&gt; Clone()
        {
            var model = (IPModel)&lt;span class=&quot;kwrd&quot;&gt;base&lt;/span&gt;.MemberwiseClone();
            model.Id = Identity.NewIdentity();
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; model;
        }

        [DojoWidget(            
       DefaultValue = &lt;span class=&quot;str&quot;&gt;&amp;quot;127.0.0.1&amp;quot;&lt;/span&gt;,
       LabelTranslationKey = &lt;span class=&quot;str&quot;&gt;&amp;quot;/shell/cms/visitorgroups/criteria/ipaddresscriterion/ipaddress&amp;quot;&lt;/span&gt;,
       AdditionalOptions = &lt;span class=&quot;str&quot;&gt;&amp;quot;{ selectOnClick: true }&amp;quot;&lt;/span&gt;),
       Required]
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; Address { get; set; }

        [DojoWidget(
       DefaultValue = &lt;span class=&quot;str&quot;&gt;&amp;quot;255.255.255.0&amp;quot;&lt;/span&gt;,
       LabelTranslationKey = &lt;span class=&quot;str&quot;&gt;&amp;quot;/shell/cms/visitorgroups/criteria/ipaddresscriterion/mask&amp;quot;&lt;/span&gt;,
       AdditionalOptions = &lt;span class=&quot;str&quot;&gt;&amp;quot;{ selectOnClick: true }&amp;quot;&lt;/span&gt;),
       Required]
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; Mask { get; set; }&lt;/font&gt;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;Now it looks like this in the Admin mode:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/link/ec8ffdaf841b4daea025d7998aa77dbe.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;visitorgroups&quot; border=&quot;0&quot; alt=&quot;visitorgroups&quot; src=&quot;/link/336871f6a0d84b1a9fd9c3cdea69870c.png&quot; width=&quot;577&quot; height=&quot;238&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</id><updated>2011-01-02T11:04:17.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Virtual Roles and access control in EPiServer</title><link href="https://world.optimizely.com/blogs/Martin-Helgesen/Dates/2010/11/Virtual-Roles-and-access-control-in-EPiServer/" /><id>&lt;p&gt;In some scenarios in EPiServer you may need to create your own logic for accessing specific pages.    &lt;br /&gt;This can be done in several ways, but one of them is to implement your own Virtual Role. EPiServer default includes a set of virtual roles which are being used frequently.&lt;/p&gt;  &lt;p&gt;Let’s say you have an open webportal in your company, no need to log in. And one department in the company, located in another part of the world, should see a set of pages (and its children), while the rest of the company should not. This department has specific IP addresses so we can recognize a request from this specific department from the IP address.&lt;/p&gt;  &lt;p&gt;One solution would be to create a virtual role that compares the request IP to a set of pre-defined IP ranges (e.g from a config file). Let’s call this role “Employee”. you have to register it in web.config like this (added to the bottom after the default roles):&lt;/p&gt;  &lt;p&gt;&amp;lt;virtualRoles replacePrincipal=&amp;quot;true&amp;quot;&amp;gt;    &lt;br /&gt;&amp;lt;providers&amp;gt;     &lt;br /&gt;&amp;lt;add name=&amp;quot;Administrators&amp;quot; type=&amp;quot;EPiServer.Security.WindowsAdministratorsRole, EPiServer&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;lt;add name=&amp;quot;Everyone&amp;quot; type=&amp;quot;EPiServer.Security.EveryoneRole, EPiServer&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;lt;add name=&amp;quot;Authenticated&amp;quot; type=&amp;quot;EPiServer.Security.AuthenticatedRole, EPiServer&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;lt;add name=&amp;quot;Anonymous&amp;quot; type=&amp;quot;EPiServer.Security.AnonymousRole, EPiServer&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;lt;add name=&amp;quot;Creator&amp;quot; type=&amp;quot;EPiServer.Security.CreatorRole, EPiServer&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;lt;add name=&amp;quot;Employee&amp;quot; type=&amp;quot;YourType, YourAssembly&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;lt;/providers&amp;gt;     &lt;br /&gt;&amp;lt;/virtualRoles&amp;gt;&lt;/p&gt;  &lt;p&gt;Then you have to create the implementation of the class. Inherit from the &lt;strong&gt;EPiServer.Security.VirtualRoleProviderBase&lt;/strong&gt;class. Here is a class that compares the requests IP address:&lt;/p&gt;  &lt;pre lang=&quot;javascript&quot;&gt;public class EmployeeRole : EPiServer.Security.VirtualRoleProviderBase
    {
        public override bool IsInVirtualRole(IPrincipal principal, object context)
        {
            var clientIpAddress = HttpContext.Current.Request.UserHostAddress;
            var validAddresses = new System.Xml.XmlDocument();
            validAddresses.Load(System.Web.HttpContext.Current.Server.MapPath(&amp;quot;/ipaddresses.config&amp;quot;));
            var isequal = validAddresses.SelectNodes(&amp;quot;//IPSet/ip&amp;quot;).Cast().Any(node =&amp;amp;gt; IsInRange(clientIpAddress, node));
            return isequal;
        }&amp;#160;&amp;#160; private static bool IsInRange(string clientIpAddress, XmlNode node)
        {
            byte[] clientIP = IPAddress.Parse(clientIpAddress).GetAddressBytes();
            byte[] mask = IPAddress.Parse(node.Attributes[&amp;quot;mask&amp;quot;].Value).GetAddressBytes();
            byte[] ip = IPAddress.Parse(node.Attributes[&amp;quot;address&amp;quot;].Value).GetAddressBytes();
            bool isequal = true;
            for (int i = 0; i &amp;amp;lt; ip.Length; i++)
                if ((clientIP[i] &amp;amp;amp; mask[i]) != ip[i])
                {
                    isequal = false;
                    break;
                }
            return isequal;
        }
    }&lt;/pre&gt;

&lt;p&gt;There you are finished creating your role! 
  &lt;br /&gt;But how do you assign this role read-rights to a specific page and its subpages? Do it in edit mode. But first, you have to create a new group with the same name as the role you just created. EPi will then automatically associate this group with your created Virtual Role. 

  &lt;br /&gt;After this, you can just add access rights for the group “Employee” to the pages in EPi you want.&lt;/p&gt;</id><updated>2010-11-30T15:38:14.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>