<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Codality &#187; Solution</title>
	<atom:link href="http://blog.najmanowicz.com/category/solution/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.najmanowicz.com</link>
	<description>Code and Effect - solving problem with just enough amount of code - by Adam Najmanowicz</description>
	<lastBuildDate>Mon, 08 Feb 2010 12:01:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Easy Enum property for EPiServer</title>
		<link>http://blog.najmanowicz.com/2009/12/26/easy-enum-property-for-episerver/</link>
		<comments>http://blog.najmanowicz.com/2009/12/26/easy-enum-property-for-episerver/#comments</comments>
		<pubDate>Sat, 26 Dec 2009 19:29:55 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Downloadable]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=160</guid>
		<description><![CDATA[One of the most frequently and eagerly used programming constructs of the Microsoft.Net Framework is Enum. There are several interesting features that make it very compelling to use to for all kinds of dropdowns and checklists: The bounds factor – proper use of Enum type guarantee that the selected value will fall within the constraints [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most frequently and eagerly used programming constructs of the Microsoft.Net Framework is Enum. There are several interesting features that make it very compelling to use to for all kinds of dropdowns and checklists:</p>
<ul>
<li>The bounds factor – proper use of Enum type guarantee that the selected value will fall within the constraints of the allowed value set.</li>
<li>The ability to treat Enums as flags (and compound them into flag sets) as well as a one-of selector. </li>
<li>The ease of use and potentially complete separation of the “Enum value” from the underlying machine type representation that ensures the most efficient memory usage. </li>
</ul>
<p>Surprisingly enough EPiServer as it stands right now does not have an easy facility to turn Enums into properties. To give credit where credit is due, the EPiServer framework provides a nice surrogate that mimic that behaviour to a degree. The relevant property types are:</p>
<ul>
<li><b><a href="http://sdk.episerver.com/library/cms5/html/T_EPiServer_SpecializedProperties_PropertyAppSettingsMultiple.htm">PropertyAppSettingsMultiple</a></b>&#160; &#8211; which “creates check boxes with options that are defined in the AppSettings section in web.config. The name of the property should match the key for the app setting.” </li>
<li><b><a href="http://sdk.episerver.com/library/cms5/html/T_EPiServer_SpecializedProperties_PropertyAppSettings.htm">PropertyAppSettings</a></b>&#160; &#8211; which “creates a drop down list with options that are defined in the AppSettings section in web.config. The name of the property should match the key for the app setting.”</li>
</ul>
<p>You quickly realize though that the properties have some limitations that makes their use a bit less compelling:</p>
<ul>
<li>The properties are not strongly typed </li>
<li>The property entry in AppSettings section has to have the name that matches the property name on the page. </li>
<li>It’s rather poorly documented, Other than relating to this blog entry or <a href="http://antecknat.se/blog/2008/04/18/new-appsettings-and-appsettingsmultiple-in-episerver-cms-5/">Erik’s post documenting</a> it I could not find any other examples on how to use them. (but then again, who needs docs really when we have <a href="http://reflector.red-gate.com/">Reflector</a>) </li>
<li>You cannot have the very same property duplicated on the page since you can only have a single property of a given name per page. So you need to have multiple entries in AppSettings that match the name of each of those properties on your pages. I know… semantics but still… </li>
<li>You are working on strings rather than enums (Did i mention it’s not type safe?) </li>
<li>The values in the AppSettings are stored in a somewhat DLS-y manner (consecutive options are separated from each other with the ‘|’ character, the name and the value are separated with a ‘;’, for example: &lt;add key = &quot;RegionId&quot; value=&quot;First Option;Option1|Default Option;Option2|Disabled Option;Option3&quot; /&gt; ) and I have had on an occasion entered a string there that caused the server to crash.</li>
<li>The values are not translatable, or at least I could not find how to do it and any Reflector digging rendered no results either. </li>
</ul>
<p> <span id="more-160"></span>
</p>
<h2>The solution to the problem:</h2>
<p>The solution that the blog post describes is:</p>
<ul>
<li>Type safe </li>
<li>Supports UI localization </li>
<li>Easy to use in your custom implementation </li>
<li>Flexible in allowing you to switch between the Enum being multi-choice or a single choice solution </li>
<li>fully defined in the code – no need to modify web,config. </li>
</ul>
<p>All you need to do to create your own custom Enum property is declare it.</p>
<pre style="background: white">
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
<span style="color: blue">using</span> Cognifide.EPiserverControls.EnumDropDown;

[<span style="color: #2b91af">PageDefinitionTypePlugIn</span>(DisplayName = <span style="color: #a31515">&quot;Sample Enum Property&quot;</span>)]
<span style="color: blue">public</span> <span style="color: blue">class</span> <span style="color: #2b91af">SampleProperty</span> : <span style="color: #2b91af">PropertyEnumSelector</span>&lt;<span style="color: #2b91af">MySampleEnum</span>&gt;
{
}
</div>
</pre>
<p>That’s it, really!</p>
<p>Now if you want to customize it; obviously you need to provide the information for the property to work with. But let’s stop for a while and think, where does that information belong? </p>
<ul>
<li>The property should worry about the mechanics of editing and the tediousness of persistence of the edited value, it clearly is not the place to specify the link between the Enum type and its human friendly drop down text. </li>
<li>Web.config is for settings, not for describing content types and definitely not to enforce the property names. </li>
<li>So where should the metadata around your Enum type be? How about we put it around the Enum type itself?</li>
</ul>
<pre style="background: white">
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">[<span style="color: #2b91af">Flags</span>]
<span style="color: blue">public</span> <span style="color: blue">enum</span> <span style="color: #2b91af">MySampleEnum</span>
{
  [<span style="color: #2b91af">ValueVisualisation</span>(Name=<span style="color: #a31515">&quot;First Option&quot;</span>, LanguageKey=<span style="color: #a31515">&quot;/enum/first&quot;</span>)]
  Option1,</div>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
  [<span style="color: #2b91af">ValueVisualisation</span>(Name=<span style="color: #a31515">&quot;Default Option&quot;</span>, Selected=<span style="color: blue">true</span>, LanguageKey=<span style="color: #a31515">&quot;/enum/second&quot;</span>)]
  Option2,</div>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
  [<span style="color: #2b91af">ValueVisualisation</span>(Name=<span style="color: #a31515">&quot;Disabled Option&quot;</span>, Enabled=<span style="color: blue">false</span>, LanguageKey=<span style="color: #a31515">&quot;/enum/disabled&quot;</span>)]
  Option3,</div>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
  [<span style="color: #2b91af">ValueVisualisation</span>(Name=<span style="color: #a31515">&quot;Hidden Option&quot;</span>, Hide=<span style="color: blue">true</span>, LanguageKey=<span style="color: #a31515">&quot;/enum/hidden&quot;</span>)]
  Option4,</div>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
  [<span style="color: #2b91af">ValueVisualisation</span>(Name=<span style="color: #a31515">&quot;Fifth Option&quot;</span>, LanguageKey=<span style="color: #a31515">&quot;/enum/fifth&quot;</span>)]
  Option5,</div>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
}</div>
</pre>
<h2>What does all that do?</h2>
<p>The property using an Enum described this way will look the following way in EPiServer:</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/12/SampleEnumPropertyFlags.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="SampleEnumPropertyFlags" border="0" alt="SampleEnumPropertyFlags" src="http://blog.najmanowicz.com/wp-content/uploads/2009/12/SampleEnumPropertyFlags_thumb.png" width="517" height="357" /></a></p>
<p>Let’s get into the what’s happened here as there’s more than catches the eye.</p>
<p>As you can see the enum values are named like they are in the attributes describing them, Default option is selected just like you could have expected by looking at the Selected=<span style="color: blue">true</span> in its attribute. The Enabled=<span style="color: blue">false</span> in the Disabled option results in an option that cannot be changed. The unchangeable option can be both unselected or selected by default. You may want to disable some deprecated options but still show them in the UI as a legacy but for some reason you might not want users to be able to change their value. Option4 is clearly missing, which is intended and specified by the Hide=<span style="color: blue">true</span>, as you might want to hide options that have been removed form the UI and on the same time you don’t want to loose compatibility with a legacy API that uses the option.</p>
<p>Also There is one thing about the first option on the list – <strong>it’s translated!</strong> The mechanism to specify the translation is based on the standard EPiServer localization files that you can find in the “lang” folder in your typical EPiServer installation. The Translation for the property looks like the following</p>
<pre style="background: white">
<div style="font-family: courier new; background: white; color: black; font-size: 8pt"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml</span><span style="color: blue"> </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot;<span style="color: blue"> </span><span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue"> </span><span style="color: red">standalone</span><span style="color: blue">=</span>&quot;<span style="color: blue">yes</span>&quot;<span style="color: blue">?&gt;</span>
<span style="color: blue">&lt;</span><span style="color: #a31515">languages</span><span style="color: blue">&gt;</span>
<span style="color: blue">  &lt;</span><span style="color: #a31515">language</span><span style="color: blue"> </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">English</span>&quot;<span style="color: blue"> </span><span style="color: red">id</span><span style="color: blue">=</span>&quot;<span style="color: blue">en</span>&quot;<span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;</span><span style="color: #a31515">enum</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">first</span><span style="color: blue">&gt;</span>First Option Translated EN<span style="color: blue">&lt;/</span><span style="color: #a31515">first</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;/</span><span style="color: #a31515">enum</span><span style="color: blue">&gt;</span>
<span style="color: blue">  &lt;/</span><span style="color: #a31515">language</span><span style="color: blue">&gt;    </span>
<span style="color: blue">&lt;/</span><span style="color: #a31515">languages</span><span style="color: blue">&gt;</span></div>
</pre>
<p>so you see the value will take its translation key from the LanguageKey=<span style="color: #a31515">&quot;/enum/first&quot;</span>. </p>
<p>Ok, so we have the <b><a href="http://sdk.episerver.com/library/cms5/html/T_EPiServer_SpecializedProperties_PropertyAppSettingsMultiple.htm">PropertyAppSettingsMultiple</a></b> replacement, but what about <b><a href="http://sdk.episerver.com/library/cms5/html/T_EPiServer_SpecializedProperties_PropertyAppSettings.htm">PropertyAppSettings</a></b>?</p>
<p>So here I reach the place where I am not 100% certain whether I took the proper path but I am sure I will hear about it if I didn’t :) The place where the property determines if it’s supposed to allow for multi selection or not is whether the Enum is marked with the [<span style="color: #2b91af">Flags</span>] attribute. Obviously Flags mean that the property is a form of a bit flag and should be able to allow the user to flip the bits independently rather than being the “one-of” type. So once you remove the [<span style="color: #2b91af">Flags</span>] form your enum you’re going to see it rendered the following way:</p>
<p><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/12/SampleEnumPropertyNoFlags.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="SampleEnumPropertyNoFlags" border="0" alt="SampleEnumPropertyNoFlags" src="http://blog.najmanowicz.com/wp-content/uploads/2009/12/SampleEnumPropertyNoFlags_thumb.png" width="517" height="357" /></a></p>
<p>But hey, it’s not a one way trip, if you decide that you want the enum rendered in another type of property and force the opposite behaviour you can always override it in the derived property like follows:</p>
<pre style="background: white">
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">    [<span style="color: #2b91af">PageDefinitionTypePlugIn</span>(DisplayName = <span style="color: #a31515">&quot;Sample Enum Property Checklist&quot;</span>)]
    <span style="color: blue">public</span> <span style="color: blue">class</span> <span style="color: #2b91af">SamplePropertyChecklist</span> : <span style="color: #2b91af">PropertyEnumSelector</span>&lt;<span style="color: #2b91af">MySampleEnum</span>&gt;
    {
        <span style="color: blue">static</span> SamplePropertyChecklist()
        {
            MultiSelectEnum = <span style="color: blue">true</span>;
        }
    }</div>
</pre>
<p>so even if you think my usage of [<span style="color: #2b91af">Flags</span>] is faulty, the damage can be undone :)</p>
<p>Ok, but what about the enums that we have no control over – like enums form libraries. Obviously cannot retrofit attributes into them. Well, true but we still can have all of the control over the property.</p>
<p>Let’s assume for a moment that this is our legacy enum:</p>
<pre style="background: white">
<div style="font-family: courier new; background: white; color: black; font-size: 8pt"><span style="color: blue">public</span> <span style="color: blue">enum</span> <span style="color: #2b91af">MySampleLegacyEnum</span>
{
  Option1,
  Option2,
  Option3,
  Option4,
  Option5,
}</div>
</pre>
<p>You can just do nothing and simply use it in the property but the UI will display the not so nice Option1… names. That can be easily fixed – Again, specifying translation is the easiest way of achieving that goal. An xml for that enum would look like follows:</p>
<pre style="background: white">
<div style="font-family: courier new; background: white; color: black; font-size: 8pt"><span style="color: blue">&lt;?</span><span style="color: #a31515">xml</span><span style="color: blue"> </span><span style="color: red">version</span><span style="color: blue">=</span>&quot;<span style="color: blue">1.0</span>&quot;<span style="color: blue"> </span><span style="color: red">encoding</span><span style="color: blue">=</span>&quot;<span style="color: blue">utf-8</span>&quot;<span style="color: blue"> </span><span style="color: red">standalone</span><span style="color: blue">=</span>&quot;<span style="color: blue">yes</span>&quot;<span style="color: blue">?&gt;</span>
<span style="color: blue">&lt;</span><span style="color: #a31515">languages</span><span style="color: blue">&gt;</span>
<span style="color: blue">  &lt;</span><span style="color: #a31515">language</span><span style="color: blue"> </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">English</span>&quot;<span style="color: blue"> </span><span style="color: red">id</span><span style="color: blue">=</span>&quot;<span style="color: blue">en</span>&quot;<span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;</span><span style="color: #a31515">MySampleLegacyEnum</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">Option1</span><span style="color: blue">&gt;</span>First Option<span style="color: blue">&lt;/</span><span style="color: #a31515">Option1</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">Option2</span><span style="color: blue">&gt;</span>Default Option<span style="color: blue">&lt;/</span><span style="color: #a31515">Option2</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">Option3</span><span style="color: blue">&gt;</span>Disabled Option<span style="color: blue">&lt;/</span><span style="color: #a31515">Option3</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">Option4</span><span style="color: blue">&gt;</span>Hidden Option<span style="color: blue">&lt;/</span><span style="color: #a31515">Option4</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">Option5</span><span style="color: blue">&gt;</span>Fifth Option<span style="color: blue">&lt;/</span><span style="color: #a31515">Option5</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;/</span><span style="color: #a31515">MySampleLegacyEnum</span><span style="color: blue">&gt;</span>
<span style="color: blue">  &lt;/</span><span style="color: #a31515">language</span><span style="color: blue">&gt;  </span>
<span style="color: blue">&lt;/</span><span style="color: #a31515">languages</span><span style="color: blue">&gt;</span></div>
</pre>
<p>The default values can be added by retrofitting the “DefaultValues” list with the elements that you want selected in the scenario where the property is first displayed for editing. You can also modify the inherited AvailableItems list to set the rest of the properties otherwise adjustable by the attributes. </p>
<p>Following is a sample of such retrofitted rules to match our original attribute-defined-enum.</p>
<pre style="background: white">
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">[<span style="color: #2b91af">PageDefinitionTypePlugIn</span>(DisplayName = <span style="color: #a31515">&quot;Sample Legacy Enum Property&quot;</span>)]
<span style="color: blue">public</span> <span style="color: blue">class</span> <span style="color: #2b91af">SampleProperty</span> : <span style="color: #2b91af">PropertyEnumSelector</span>&lt;<span style="color: #2b91af">MySampleLegacyEnum</span>&gt;
{
    <span style="color: blue">static</span> SampleProperty()
    {
        MultiSelectEnum = <span style="color: blue">true</span>;

        <span style="color: green">// Make Option2 a default selected value</span>
        DefaultValues.Add(<span style="color: #2b91af">MySampleLegacyEnum</span>.Option2.ToString());
        AvailableItems.Where(p =&gt; p.Value == <span style="color: #2b91af">MySampleLegacyEnum</span>.Option2.ToString()).First().Selected = <span style="color: blue">true</span>;

        <span style="color: green">//Disable selection of Option3</span>
        AvailableItems.Where(p =&gt; p.Value == <span style="color: #2b91af">MySampleLegacyEnum</span>.Option3.ToString()).First().Enabled = <span style="color: blue">false</span>;

        <span style="color: green">//Remove hidden Option4</span>
        AvailableItems.RemoveAll(p =&gt; p.Value == <span style="color: #2b91af">MySampleLegacyEnum</span>.Option4.ToString());
    }
}</div>
</pre>
<p>The [<a href="http://www.najmanowicz.com/blog_bin/Cognifide.EPiserverControls.EnumDropDown.zip">code for the EnumProperty</a>] as well as [<a href="http://www.najmanowicz.com/blog_bin/Cognifide.EPiserverControls.EnumDropDown.Assembly.zip">the compiled binaries</a>] are available as Open Source and you can incorporate it in your projects as long as the Cognifide namespace is used for the code.</p>
<p>What do you think? Is that going to be useful for you?</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=160&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2009/12/26/easy-enum-property-for-episerver/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Database-based paged EPiServer searches for CMS 5 R2 SP2</title>
		<link>http://blog.najmanowicz.com/2009/07/07/database-based-paged-episerver-searches-for-cms-5-r2-sp2/</link>
		<comments>http://blog.najmanowicz.com/2009/07/07/database-based-paged-episerver-searches-for-cms-5-r2-sp2/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 11:15:25 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[EPiCode]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Microsoft SqlServer]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2009/07/07/database-based-paged-episerver-searches-for-cms-5-r2-sp2/</guid>
		<description><![CDATA[Aparently I have written something on that note before for CMS 4 and it looks like someone still needs it as I got a request for an updated version for it a couple of days ago. So here we go: for the most part the syntax for the call is equivalent to what is was [...]]]></description>
			<content:encoded><![CDATA[<p>Aparently I have written <a href="http://blog.najmanowicz.com/2007/05/21/database-based-paged-episerver-searches/">something on that note before for CMS 4</a> and it looks like someone still needs it as I got a request for an updated version for it a couple of days ago. So here we go:</p>
<p>for the most part the syntax for the call is equivalent to what is was before so go to my previous article regarding that (check out the old article for details). What I’ve added this time around is:</p>
<ul>
<li>the @PropertyName can be declared as ‘%’ if you want to look in all property names </li>
<li>@PropertyType can be –1 if you want to look in all property types otherwise you need to specify type id (this has changed from type name before due to database schema changes) </li>
<li>additionally this version of the stored proc will only look in the Master language Branch, so it will work for the single language pages and for multi-language but for language agnostic properties. (should you require the language to be variable the change is pretty simple – I can send you the updated version by email. </li>
</ul>
<pre class="brush: sql; highlight: [32];">/****** Object:  StoredProcedure [dbo].[PagedSearch]    Script Date: 07/07/2009 12:18:10 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[PagedSearch]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[PagedSearch]
GO

CREATE Procedure PagedSearch
    @Condition varchar(1024),
    @PropertyName varchar(1024),
    @PropertyType int,
    @PageSize int,
    @PageNumber int,
    @Offset int
AS
BEGIN

    DECLARE @RowStart int
    DECLARE @RowEnd int

    SET @RowStart = @PageSize * @PageNumber + @Offset;
    SET @RowEnd = @RowStart + @PageSize + @Offset;

    WITH PageRefs AS
        (SELECT page.pkID as PageId,
            ROW_NUMBER() OVER (ORDER BY pageLang.StartPublish DESC) as RowNumber
            FROM tblPage page, tblProperty propValue, tblPageDefinition propDef, tblPageLanguage pageLang
            WHERE page.pkID = propValue.fkPageID
                AND page.fkMasterLanguageBranchID = pageLang.fkLanguageBranchID
                AND page.pkID = pageLang.fkPageID
                AND propValue.fkPageDefinitionID = propDef.pkID
                AND (@propertyType = -1 or propDef.fkPageDefinitionTypeID = @propertyType) -- is proper type
                AND propDef.Searchable = 1 -- the property is searchable
                AND propValue.String like @Condition -- contains facets
                AND propDef.[Name] like @PropertyName) -- property of proper name
    SELECT PageId
        FROM PageRefs
        WHERE (RowNumber Between @RowStart and @RowEnd) or (@PageSize = 0);
END
GO</pre>
<p>However&#8230; looking how the schema has changed over time, I am not convinced this approach is really the best one for someone who is not prepared to deal with the changes (e.g. you better be able to change the stored procedure based on the schema changes &#8211; or bribe me with pizza and beers for updates :) ).</p>
<p>Additionally this procedure only searches for properties that store their value in Short string field. To make it look into long string you need to Change the highlighted line to.</p>
<pre class="brush: sql;">AND (propValue.LongString like @Condition)</pre>
<p>or alternatively to look in both change it to:</p>
<pre class="brush: sql;">AND ((propValue.String like @Condition) or (propValue.LongString like @Condition))</pre>
<p>Enjoy!</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=143&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2009/07/07/database-based-paged-episerver-searches-for-cms-5-r2-sp2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SoakIE &#8211; a Web Server Stress Tool with a twist</title>
		<link>http://blog.najmanowicz.com/2009/05/10/soakie-a-web-server-stress-tool-with-a-twist/</link>
		<comments>http://blog.najmanowicz.com/2009/05/10/soakie-a-web-server-stress-tool-with-a-twist/#comments</comments>
		<pubDate>Sun, 10 May 2009 14:27:06 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Downloadable]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2009/05/10/soakie-a-web-server-stress-tool-with-a-twist/</guid>
		<description><![CDATA[Last week or so ago a couple of friends in another project in Cognifide has run into a wall while trying to load test their website. the problem was as follows: The website is highly AJAX based – the page merely loads a stub in the initial request but then loads the rest of its [...]]]></description>
			<content:encoded><![CDATA[<p>Last week or so ago a couple of friends in another project in Cognifide has run into a wall while trying to load test their website. the problem was as follows: The website is highly AJAX based – the page merely loads a stub in the initial request but then loads the rest of its data in a dynamic matter therefore a traditional web testing tools are fairly useless. What they tried was to setup a number of Selenium clients to pound the server, but that turned out to be fairly challenging to the machine doing the testing. It was not possible to set up more than 10 clients on a fairly strong machine.</p>
<p>Also there are other limitations like time to wait for the server to timeout and time between clicks, which I am not sure the tool allowed them to adjust. Talking to them I recalled <a href="http://blog.najmanowicz.com/2006/11/17/how-to-get-website-thumbnail-in-c/">a tool for grabbing website thumbnails</a> long time ago. one way for them would be to to make a batch file with it. The tool would grab the sites’ thumbnail and stress it, but they would still have to setup a number of clients. Also it creates and tears down an instance of IE every time, making it’s not optimal for that task.</p>
<p>So a couple of evenings later (and a few back-s and forth-s during the testing sessions) out comes SoakIE:</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/05/soakietest.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="SoakIETest" border="0" alt="SoakIETest" src="http://blog.najmanowicz.com/wp-content/uploads/2009/05/soakietest-thumb.png" width="429" height="387" /></a> </p>
<p> <span id="more-140"></span>
<p align="left">The app uses pretty much the same trick as the <a href="http://blog.najmanowicz.com/2006/11/17/how-to-get-website-thumbnail-in-c/">tool for grabbing website thumbnails</a> but it does so in a nice UI and allows for some rudimentary settings for profiling the traffic:</p>
<p><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/05/soakiesetup.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="SoakIESetup" border="0" alt="SoakIESetup" src="http://blog.najmanowicz.com/wp-content/uploads/2009/05/soakiesetup-thumb.png" width="429" height="387" /></a> </p>
<p>You can select the number of IE instances that will do the clicking, you can select a minimum time between clicks – that is how often any IE instance can click (if it already finished with the previous request). this allows you to simulate clients that will stay a minute on your site and only click after they’ve read the page. Additionally if your application can on an occasion encounter a deadlock or a hang, it allows you to specify the maximum time to live of each request. If the request takes longer than the specified time, the application will “Stop” the request.</p>
<p>One thing that we’ve noticed though is that after a long time of soak tests the IE instances get mighty fat and start to slow down dramatically. Therefore I’ve added a maximum number of clicks an IE instance can perform after which the client will no longer recycle it for more click but will tear it down and create a new IE instance to continue testing.</p>
<p>Naturally the application needs to know what to test. This is specified in the “Test setup&quot; tab in the “URLs to stress:&quot; text box. The URLs will be picked in a round-robin fashion. The first browser will get the first url, the next one will get the second and so on, if the list will get exhausted the browsers will get fed it from beginning. You can theoretically put them in the box with some other text (like pasting it from a Skype window without stripping the message decoration around them) – SoakIE should be smart enough to parse the text and get the URLs out of it.</p>
<p>You can download <a href="http://www.najmanowicz.com/blog_bin/SoakIE.zip">SoakIE here</a></p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=140&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2009/05/10/soakie-a-web-server-stress-tool-with-a-twist/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Advanced Language Manipulation Tool for EPiServer</title>
		<link>http://blog.najmanowicz.com/2009/04/06/advanced-language-manipulation-tool-for-episerver/</link>
		<comments>http://blog.najmanowicz.com/2009/04/06/advanced-language-manipulation-tool-for-episerver/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 15:49:11 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Downloadable]]></category>
		<category><![CDATA[EPiCode]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Microsoft SqlServer]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2009/04/06/advanced-language-manipulation-tool-for-episerver/</guid>
		<description><![CDATA[Have you ever (or have your customers) created and edited a page in one language only to realize that their selected locale was wrong? Have you ever wished you could delete a master language branch of a page&#160; after creating its localized counterpart but you could only delete the newly created slave language instead? Have [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever (or have your customers) created and edited a page in one language only to realize that their selected locale was wrong? Have you ever wished you could delete a master language branch of a page&#160; after creating its localized counterpart but you could only delete the newly created slave language instead? Have a customer ever requested that they could copy a whole branch and you convert it to another language so that they could then translate in-place?</p>
<p>Well I have… and I’m sure I will. And so did Fredrikj on the our #epicode IRC channel ;).</p>
<p>Basically I had the tool that would convert from one language to another, but Fredrikj requested something that would switch master language of a page from one to another. Since I’ve already had some of the work done, I’ve updated the stored procedure I’ve written some time ago and slapped a nice GUI up on it. Here’s the result:</p>
<p>&#160;</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/04/andvancedlanguagetool.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="AndvancedLanguageTool" border="0" alt="AndvancedLanguageTool" src="http://blog.najmanowicz.com/wp-content/uploads/2009/04/andvancedlanguagetool-thumb.png" width="480" height="484" /></a> </p>
<p>What the tool allows you to do is perform either language conversion or master branch switching on a selected page and all of its children (if you choose so).</p>
<p>The stored procedure have been updated to work on CMS5 R2 (will no longer work on R1 – but if you need that functionality, comment here or give me a shout and I’ll create a compatible version for you).</p>
<p>A word of caution though – I take no guarantee whatsoever about its operation. Especially, if you wreck your client’s database with it. I did what I could to prevent some of the obvious problems (like <strong><em>switching</em></strong> to a non existing master or <strong><em>converting</em></strong> to an existing one) but I will not be responsible if it won’t work for you. make a database backup and experiment there before you do any changes on the real data. That said – it works for me, so I think it should also work for you.</p>
<p>You can download the <a title="Episerver Advanced Language Tools" href="http://www.najmanowicz.com/blog_bin/EPiServerLanguageTools.zip" rel="enclosure">archive containing the tool here</a>. unzip it to your EPiServer web application folder keeping the folder structure or the plugin reference will be wrong. Include the *.aspx and the *.cs files in your project and apply the SQL file to your database (The manipulation is performed by a stored procedure located in the file).</p>
<p>Also if you’re performing the change in a load balanced environment, you may need to restart the other servers once you do the changes. I reset the DataFactory cache, but I am not sure it propagates through to other servers.</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=124&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2009/04/06/advanced-language-manipulation-tool-for-episerver/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Get out of my way! &#8230; or the story of file metadata for VirtualPathProvider in EPiServer</title>
		<link>http://blog.najmanowicz.com/2009/03/17/get-out-of-my-way-or-the-story-of-file-metadata-for-virtualpathprovider-in-episerver/</link>
		<comments>http://blog.najmanowicz.com/2009/03/17/get-out-of-my-way-or-the-story-of-file-metadata-for-virtualpathprovider-in-episerver/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 00:18:00 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Internet Information Services]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2009/03/17/get-out-of-my-way-or-the-story-of-file-metadata-for-virtualpathprovider-in-episerver/</guid>
		<description><![CDATA[Immediately after you implement the VirtualPathProvider proxy from my previous post you will notice a one fairly serious lack in it. Namely all the files within that provider will be hiding behind the registration form. That is not cool for a couple of reasons… You may want to keep all of the files in one [...]]]></description>
			<content:encoded><![CDATA[<p>Immediately after you implement the VirtualPathProvider proxy from my previous post you will notice a one fairly serious lack in it. Namely all the files within that provider will be hiding behind the registration form. That is not cool for a couple of reasons…</p>
<ul>
<li>You may want to keep all of the files in one store – being forced to put them into a designated folder is not desired. </li>
<li>You may want to make some file freely available for some time and lock it after a while, or the other way around (e.g. to allow the robots to crawl it initially). having to move them is just silly and defeats the purpose. </li>
</ul>
<p>So how do you discriminate the files that you want locked from those that you want to be publically available, and potentially from those that you want only the logged in users to be able to get?</p>
<h2></h2>
<h2>Specifying the EPiServer File Metadata sweetness</h2>
<p>One of the potential solutions would be to define a special rights group and check for that group for the people that have your “registered” magic-cookie. That however introduces a bogus group, and I would rather like to avoid that. However if you look into the <strong><em>FileSummary.config</em></strong> file that’s located in your web application folder you will find a slightly mysterious content. A bit of hacking reveals that you can actually add your own metadata to the file. For example adding the access rights based on what I’ve established above would look as follows (the content you can already find in the file that comes with the public templates that-we-all-oh-so-love is skipped):</p>
<p><span id="more-120"></span></p>
<pre>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
<span style="color: blue">&lt;</span><span style="color: #a31515">root</span><span style="color: blue"> </span><span style="color: red">xmlns:xforms</span><span style="color: blue">=</span>&quot;<span style="color: blue">http://www.w3.org/2002/xforms</span>&quot;<span style="color: blue"> </span>
<span style="color: blue">      </span><span style="color: red">xmlns:xsi</span><span style="color: blue">=</span>&quot;<span style="color: blue">http://www.w3.org/2001/XMLSchema-instance</span>&quot;<span style="color: blue">&gt;</span>

<span style="color: blue">  &lt;</span><span style="color: #a31515">model</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;</span><span style="color: #a31515">instance</span><span style="color: blue">&gt;</span>
      ...
<span style="color: blue">      &lt;</span><span style="color: #a31515">AccessLevel</span><span style="color: blue"> /&gt;</span>
<span style="color: blue">    &lt;/</span><span style="color: #a31515">instance</span><span style="color: blue">&gt;</span>
<span style="color: blue">  &lt;/</span><span style="color: #a31515">model</span><span style="color: blue">&gt;</span>

  ...
<span style="color: blue">  &lt;</span><span style="color: #a31515">xforms:select1</span><span style="color: blue"> </span><span style="color: red">appearance</span><span style="color: blue">=</span>&quot;<span style="color: blue">full</span>&quot;<span style="color: blue"> </span>
<span style="color: blue">                  </span><span style="color: red">ref</span><span style="color: blue">=</span>&quot;<span style="color: blue">AccessLevel</span>&quot;<span style="color: blue"> </span><span style="color: red">id</span><span style="color: blue">=</span>&quot;<span style="color: blue">id_field51</span>&quot;<span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;</span><span style="color: #a31515">xforms:item</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">xforms:label</span><span style="color: blue">&gt;</span>Unrestricted<span style="color: blue">&lt;/</span><span style="color: #a31515">xforms:label</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">xforms:value</span><span style="color: blue">&gt;</span>Unrestricted<span style="color: blue">&lt;/</span><span style="color: #a31515">xforms:value</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;/</span><span style="color: #a31515">xforms:item</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;</span><span style="color: #a31515">xforms:item</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">xforms:label</span><span style="color: blue">&gt;</span>Requires Registration<span style="color: blue">&lt;/</span><span style="color: #a31515">xforms:label</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">xforms:value</span><span style="color: blue">&gt;</span>RequireRegistration<span style="color: blue">&lt;/</span><span style="color: #a31515">xforms:value</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;/</span><span style="color: #a31515">xforms:item</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;</span><span style="color: #a31515">xforms:item</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">xforms:label</span><span style="color: blue">&gt;</span>Requires CMS Login<span style="color: blue">&lt;/</span><span style="color: #a31515">xforms:label</span><span style="color: blue">&gt;</span>
<span style="color: blue">      &lt;</span><span style="color: #a31515">xforms:value</span><span style="color: blue">&gt;</span>LoggedUserAccess<span style="color: blue">&lt;/</span><span style="color: #a31515">xforms:value</span><span style="color: blue">&gt;</span>
<span style="color: blue">    &lt;/</span><span style="color: #a31515">xforms:item</span><span style="color: blue">&gt;</span>
<span style="color: blue">  &lt;/</span><span style="color: #a31515">xforms:select1</span><span style="color: blue">&gt;</span>
  ...

<span style="color: blue">&lt;/</span><span style="color: #a31515">root</span><span style="color: blue">&gt;</span></div>
</pre>
<p>Great. So what does it look in the file manager now?</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/03/metadataeditor.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="metadata-editor" border="0" alt="metadata-editor" src="http://blog.najmanowicz.com/wp-content/uploads/2009/03/metadataeditor-thumb.png" width="518" height="355" /></a> </p>
<p>Splendid!</p>
<h2>Accessing the metadata</h2>
<p>Now that we gave the user to specify the metadata, we need the VPP to act upon them. For the benefit of automation of parsing I’ve specified the enum defining the access levels as follows:</p>
<pre>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
<span style="color: blue">enum</span> <span style="color: #2b91af">FileAccessLevel</span>
{
    Unrestricted,
    RequireRegistration,
    LoggedUserAccess
}
</div>
</pre>
<p>Now we need to update the GetFile method to discriminate the access levels (I have decorated the core lines with <font color="#ff0000">&#8211;<strong>&gt;</strong></font>) those are the lines that access the meta data based on their format specified in the <strong><em>FileSummary.config</em></strong>.</p>
<pre class="brush: csharp; highlight: [11, 12, 13]">
public override VirtualFile GetFile(string virtualPath)
{
    string handledPath;

    if (TryGetHandledAbsolutePath(virtualPath, out handledPath))
    {
        UnifiedFile file = base.GetFile(virtualPath) as UnifiedFile;

        if (file != null)
        {
            string strAccessLevel = (string) file.Summary.Dictionary["AccessLevel"] ??
                                    FileAccessLevel.RequireRegistration.ToString();
            FileAccessLevel accessLevel = (FileAccessLevel) Enum.Parse(typeof (FileAccessLevel), strAccessLevel);

            bool isLoggedIn = HttpContext.Current.Profile != null &#038;&#038; !HttpContext.Current.Profile.IsAnonymous;
            bool isRegistered = HttpContext.Current.Request.Cookies.AllKeys.Contains(PASS_COOKIE_NAME);
            string email = isRegistered ? HttpContext.Current.Request.Cookies[PASS_COOKIE_NAME].Value :
                (isLoggedIn ? HttpContext.Current.Profile.UserName : "unregistered");

            switch (accessLevel)
            {
                case (FileAccessLevel.Unrestricted):
                    return file;
                    break;
                case(FileAccessLevel.RequireRegistration):
                    if (!isRegistered &#038;&#038; ! isLoggedIn)
                    {
                        HttpContext.Current.Response.Redirect(
                            string.Format(registrationFormUrl,
                                          HttpContext.Current.Server.HtmlEncode(virtualPath)));
                        return null;
                    }
                    return file;
                    break;
                case(FileAccessLevel.LoggedUserAccess):
                    if (isLoggedIn)
                    {
                        return file;
                    }
                    return null;
                    break;
                default:
                    return file;
            }
        }
    }
    return Previous.GetFile(virtualPath);
}
</pre>
<p>Now the user is really in control of what is published to the general public and robots, what is protected with the registration form and what is only available to logged in users. (now you may add more granularity with file rights naturally, this is just a basic setting that an editor without administrative rights can add.</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=120&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2009/03/17/get-out-of-my-way-or-the-story-of-file-metadata-for-virtualpathprovider-in-episerver/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Simple registration for files served by EPiServer</title>
		<link>http://blog.najmanowicz.com/2009/03/12/simple-registration-for-files-served-by-episerver/</link>
		<comments>http://blog.najmanowicz.com/2009/03/12/simple-registration-for-files-served-by-episerver/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 21:01:00 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[.Net Framework]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[EPiCode]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2009/03/12/simple-registration-for-files-served-by-episerver/</guid>
		<description><![CDATA[With the culture of knowledge sharing and open source spreading, everyone races to show they have something valuable that you may want. And while you may not ask for money for your content you may still want to get something in return, say a contact, an email address that’s verified (or not), to keep in [...]]]></description>
			<content:encoded><![CDATA[<p>With the culture of knowledge sharing and open source spreading, everyone races to show they have something valuable that you may want. And while you may not ask for money for your content you may still want to get something in return, say a contact, an email address that’s verified (or not), to keep in touch with the consumer of your content. </p>
<p>Yet a full fledged registration doesn’t seem like a proper thing to do – cluttering your EPiServer user repository with (let’s face it – for a large part fake or temporary email addresses that user create only to get your content).</p>
<p>While there may be a lot of ways to handle that (streaming it through a page Response.WriteFile might seem as one of the more obvious ones), I would like to show you a cleaner, simpler and more elegant way that I’ve come up with.</p>
<p>We really don’t want people to deep link to our files without them knowing the files are from our site, that’s just rude – so hiding them behind an obscure URL wouldn’t work (thus we cannot use the regular file providers). We’ve already establish that we don’t want to log them in, so setting file rights are useless. But I want all the benefits including client-side caching.</p>
<p>Basically the solution boils down to creating a thin layer over the File provider of our choice, in my case the versioning file provider. The only method we need to override in it is <strong>GetFile</strong>. I want to allow downloading for logged in users and I want to allow downloading for all users that have a “magic-cookie” set. If either of the conditions are met, the file just downloads using the underlying provider’s routines including all the logic EPiServer has put for caching and rights. But if neither of the requirements are met, the user is directed to a page of our choice. </p>
<p><span id="more-117"></span></p>
<pre>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt"><span style="color: blue">public</span> <span style="color: blue">override</span> <span style="color: #2b91af">VirtualFile</span> GetFile(<span style="color: blue">string</span> virtualPath)
{
    <span style="color: blue">string</span> handledPath;

    <span style="color: blue">if</span> (TryGetHandledAbsolutePath(virtualPath, <span style="color: blue">out</span> handledPath))
    {
        <span style="color: blue">if</span> ((<span style="color: #2b91af">HttpContext</span>.Current.Profile != <span style="color: blue">null</span> &amp;&amp; !<span style="color: #2b91af">HttpContext</span>.Current.Profile.IsAnonymous) ||
            <span style="color: #2b91af">HttpContext</span>.Current.Request.Cookies.AllKeys.Contains(PASS_COOKIE_NAME))
        {
            <span style="color: blue">return</span> <span style="color: blue">base</span>.GetFile(virtualPath);
        }

        <span style="color: #2b91af">HttpContext</span>.Current.Response.Redirect(
            <span style="color: blue">string</span>.Format(registrationFormUrl,<span style="color: #2b91af">HttpContext</span>.Current.Server.HtmlEncode(virtualPath)));
        <span style="color: blue">return</span> <span style="color: blue">null</span>;
    }
    <span style="color: blue">return</span> Previous.GetFile(virtualPath);
}</div>
</pre>
<p>How you specify that page’s totally up to you, but there is a nice initialization routine called during the Virtual Path Provider loading phase where all of the settings that are specified in your relevant web.config VPP declaration are passed to you, why not use it? What you’ll need define your VPP in the web.config is what follows:</p>
<pre>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
<span style="color: blue">&lt;</span><span style="color: #a31515">add</span><span style="color: blue"> </span><span style="color: red">showInFileManager</span><span style="color: blue">=</span>&quot;<span style="color: blue">true</span>&quot;<span style="color: blue"> </span><span style="color: red">virtualName</span><span style="color: blue">=</span>&quot;<span style="color: blue">CookieEnabled</span>&quot;<span style="color: blue"> </span><span style="color: red">virtualPath</span><span style="color: blue">=</span>&quot;<span style="color: blue">~/CookieEnabled/</span>&quot;<span style="color: blue"> </span>
<span style="color: blue">     </span><span style="color: red">bypassAccessCheck</span><span style="color: blue">=</span>&quot;<span style="color: blue">false</span>&quot;<span style="color: blue"> </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">CookieEnabled</span>&quot;<span style="color: blue"> </span>
<span style="color: blue">     </span><span style="color: red">type</span><span style="color: blue">=</span>&quot;<span style="color: blue">Cognifide.EPiServer.CookieEnabledVirtualPathProvider.CookieEnabledVirtualPathProvider,Cognifide.EPiServer.CookieEnabledVirtualPathProvider</span>&quot;<span style="color: blue"> </span>
<span style="color: blue">     </span><span style="color: red">indexingServiceCatalog</span><span style="color: blue">=</span>&quot;<span style="color: blue">Web</span>&quot;<span style="color: blue"> </span><span style="color: red">physicalPath</span><span style="color: blue">=</span>&quot;<span style="color: blue">C:\vpp\Resources</span>&quot;<span style="color: blue"> </span>
<span style="color: blue">     </span><span style="color: red">RegistrationFormUrl</span><span style="color: blue">=</span>&quot;<span style="color: blue">/File-Asset-Request-Form/?filepath={0}</span>&quot;<span style="color: blue"> /&gt;</span>
</div>
</pre>
<p>
  <br />you can then define your class as:</p>
<pre>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
<span style="color: blue">public</span> <span style="color: blue">class</span> <span style="color: #2b91af">CookieEnabledVirtualPathProvider</span> : <span style="color: #2b91af">VirtualPathVersioningProvider</span>
{
    <span style="color: blue">private</span> <span style="color: blue">const</span> <span style="color: blue">string</span> REGISTRATION_FORM_URL_WEB_CONFIG_PARAM_NAME = <span style="color: #a31515">&quot;RegistrationFormUrl&quot;</span>;
    <span style="color: blue">public</span> <span style="color: blue">const</span> <span style="color: blue">string</span> PASS_COOKIE_NAME = <span style="color: #a31515">&quot;ResourcePass&quot;</span>;
    <span style="color: blue">private</span> <span style="color: blue">string</span> registrationFormUrl;

    <span style="color: blue">public</span> CookieEnabledVirtualPathProvider(<span style="color: blue">string</span> name, <span style="color: #2b91af">NameValueCollection</span> configParameters) :
        <span style="color: blue">base</span>(name, configParameters)
    {
        registrationFormUrl = configParameters[REGISTRATION_FORM_URL_WEB_CONFIG_PARAM_NAME];
    }

    ...

}
</div>
</pre>
<p>So we know now where we want to direct people without a “magic-cookie” who want to get our assets, and how to do it, but how do we finally allow that file to get down to them?</p>
<p>In your page – for the same of simplicity I assume you will be using XForms for gathering the user data, but that really does not matter. When you validate the form data (or get the user to click on a link that you’ve sent them) you just set the “magic” cookie that I called “ResourcePass” to any value and to to expire in some a long amount of time, like a year. So that they can now access your files unrestrained and direct them BACK at the URL they came from – and now the VPP will allow them to just download the file they initially requested:</p>
<pre>
<div style="font-family: courier new; background: white; color: black; font-size: 8pt">
<span style="color: blue">protected</span> <span style="color: blue">void</span> XForm_BeforeSubmitPostedData(<span style="color: blue">object</span> sender, <span style="color: #2b91af">SaveFormDataEventArgs</span> e)
{
    <span style="color: blue">if</span> (!Page.IsValid)
    {
        e.CancelSubmit = <span style="color: blue">true</span>;
    }
    <span style="color: blue">else</span>
    {
        <span style="color: blue">string</span> requestedFile = Request.Params[<span style="color: #a31515">&quot;filepath&quot;</span>];
        <span style="color: #2b91af">HttpCookie</span> cookie = <span style="color: blue">new</span> <span style="color: #2b91af">HttpCookie</span>(<span style="color: #2b91af">CookieEnabledVirtualPathProvider</span>.PASS_COOKIE_NAME, <span style="color: #a31515">&quot;true&quot;</span>);
        cookie.Expires = <span style="color: #2b91af">DateTime</span>.Now.AddYears(1);
        cookie.HttpOnly = <span style="color: blue">true</span>;
        Response.Cookies.Add(cookie);
        <span style="color: blue">if</span> (!<span style="color: blue">string</span>.IsNullOrEmpty(requestedFile))
        {
            Response.Redirect(requestedFile);
        }
    }
}
</div>
</pre>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=117&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2009/03/12/simple-registration-for-files-served-by-episerver/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Merged contacts in gmail rendered uneditable &#8211; the fix</title>
		<link>http://blog.najmanowicz.com/2009/02/28/merged-contacts-in-gmail-rendered-uneditable-the-fix/</link>
		<comments>http://blog.najmanowicz.com/2009/02/28/merged-contacts-in-gmail-rendered-uneditable-the-fix/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 11:43:33 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[GSM]]></category>
		<category><![CDATA[Gmail]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Solution]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2009/02/28/merged-contacts-in-gmail-rendered-uneditable-the-fix/</guid>
		<description><![CDATA[Long story short. Bought G1 lately so I&#8217;ve decided to bring peace to my tormented contact list once and for all. Editing in Gmail is&#8230; adequate. I&#8217;ve been able to import most of my contacts &#8211; naturally countless of those were duplicates as I integrated my mail contact list and my phone contact list. Where [...]]]></description>
			<content:encoded><![CDATA[<p>Long story short. Bought G1 lately so I&#8217;ve decided to bring peace to my tormented contact list once and for all. Editing in Gmail is&#8230; adequate. I&#8217;ve been able to import most of my contacts &#8211; naturally countless of those were duplicates as I integrated my mail contact list and my phone contact list. Where gmail contacts list editing excels is at allowing you to merge those.</p>
<p>It’s incredibly convenient:</p>
<p><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/02/gmail-merge-contacts.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="gmail_merge_contacts" border="0" alt="gmail_merge_contacts" src="http://blog.najmanowicz.com/wp-content/uploads/2009/02/gmail-merge-contacts-thumb.png" width="244" height="90" /></a> </p>
<p>And fairly deadly to the merged contact. Once those contacts are merged and you save them but later try to come back to them to re-edit, I’ve noticed that whenever I select them for editing after that, they don’t pop up for the task, but instead the previously selected contact is being opened for editing. I can see the details of such contact, it synchronizes with the phone perfectly, just the editing won’t work. </p>
<p>Browsing through gmail support groups I’ve found out that a lot of people have this problem but somewhat it eludes Google. People suggest that clearing up cookies or history worked for them. No luck here.</p>
<p>What did the trick though was exporting all of them to the Google CSV:</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2009/02/gmail-merge-contacts2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="gmail_merge_contacts2" border="0" alt="gmail_merge_contacts2" src="http://blog.najmanowicz.com/wp-content/uploads/2009/02/gmail-merge-contacts2-thumb.png" width="573" height="368" /></a> </p>
<p>&nbsp;</p>
<p>Deleting all the contacts and then importing them back. Unfortunately once you do that all the associations they’ve had with the groups that youv’e defined are gone, but at least you can edit them again!</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=116&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2009/02/28/merged-contacts-in-gmail-rendered-uneditable-the-fix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
