<?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>Fredrik Haglund's blog</title>
	<atom:link href="http://blog.fredrikhaglund.se/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.fredrikhaglund.se</link>
	<description>Chatter about EPiServer, ASP.NET, CSS and Web Development.</description>
	<lastBuildDate>Wed, 10 Mar 2010 22:42:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Configuration Management and EPiServer CMS 6</title>
		<link>http://blog.fredrikhaglund.se/blog/2010/03/10/configuration-management-and-episerver-cms-6/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2010/03/10/configuration-management-and-episerver-cms-6/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 20:00:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[CM]]></category>
		<category><![CDATA[Configuration Management]]></category>
		<category><![CDATA[EPIServer 6]]></category>
		<category><![CDATA[episerver.config]]></category>
		<category><![CDATA[episerver.datastore]]></category>
		<category><![CDATA[episerver.shell]]></category>
		<category><![CDATA[EPiServerFramework.config]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2010/03/10/configuration-management-and-episerver-cms-6/</guid>
		<description><![CDATA[This blog post is based on the experience of upgrading one EPiServer CMS 5 project and creating a new one from scratch based on a release candidate of EPiServer CMS 6 and things may change before the release. 
New configuration files
Web.config contained a lot of settings for EPiServer CMS that is now split into several [...]]]></description>
			<content:encoded><![CDATA[<p>This blog post is based on the experience of upgrading one EPiServer CMS 5 project and creating a new one from scratch based on a release candidate of EPiServer CMS 6 and things may change before the release. </p>
<h3>New configuration files</h3>
<p><em>Web.config</em> contained a lot of settings for EPiServer CMS that is now split into several files. Unfortunately another 250 lines of configuration is also added increasing the burden to manage the configuration.</p>
<h4>EPiServerFramework.config</h4>
<p>This file contains mapping between host header name and site and default language. This information was previously located in <em>configuration/episerver/sites/site/siteHosts</em>-tag.</p>
<p>Notice that the EpiServer framework automatically updates this file with machine specific information which makes it harder to put under version control but EPiServer will work even if the file is read-only (you get some exceptions in the log files and maybe temporary version of the files). </p>
<p>It is needed by all developers, staging and QA so one strategy could be to put it on version control directly or check-in a file with another name or location copy it during the post build event.</p>
<h4>episerver.config</h4>
<p>This is basically everything previously located in <em>configuration/episerver</em>-tag in <em>web.config</em>. It is connected using the configSource attribute in the same way as <em>connectionStrings.config</em>-file.</p>
<p>It contains the same information as before except that <em>siteHosts</em>-tag is migrated to <em>EPiServerFramework.config</em>-file.</p>
<p>In addition to the paths in <em>configuration/episerver/virtualPath/providers/add</em>-tag another machine specific attribute has been added on the <em>site</em>-tag called <em>licenseFilePath</em>. </p>
<p>This file must be put under version control but if the machine specific <em>licenseFilePath</em> it is present it will be hard to get it to work well.</p>
<h3>New configuration</h3>
<p>There are new sections in <em>web.config</em> and for <em>episerver.shell</em> and <em>episerver.datastore</em>. </p>
<h4>episerver.shell</h4>
<p>You need to add you modules here if you want to add your own things to the new menu system or add gadgets to the new Dashboard.</p>
<h4>episerver.datastore</h4>
<p>Even if you do not use the datastore yourself EPiServer does for XForms and other features that was previously handled by the now deprecated <em>objectstore</em>. You need to make sure that you change the <em>connectionStringName</em>-attribute to match the one your site is using.</p>
<p>Since it is possible to have different values on connectionStringName-attribute on <em>configuration/episerver/sites/site/siteSettings</em>-tag in an Enterprise setup this can be problematic.</p>
<h3>Change of configuration does not restart application</h3>
<p>Both <em>episerver</em> and <em>episerver.framework</em> configuration section has restartOnExternalChanges attrubute set to false.</p>
<p>This is annoying because you have to remember to manually do a <em>iisreset</em> or change <em>web.config</em> to trigger a restart so your changes take effect.</p>
<h3>New Site/License Information feature in Admin Mode</h3>
<p>There is a new feature that enables you to upload, activate or request a demo license in admin mode. <strong>This feature should <u>not be used by developers</u> since it adds machine specific information episerver.config. </strong>If you do and check in the changes your co-developers will get a file that does not work on their computer.</p>
<p>My suggestion is to continue using the manual approach and add the <em>Licence.config</em>-file to the application root folder your self. Remeber that if you want to put your license files under version control it is possible to do that very easily because EPiServer will look for “<em>License.config</em>” first and then “<em><strong>MACHINENAME</strong>License.config</em>” so just rename your <em>license.config</em>-file and check it in.</p>
<h3>Location of EPiServer User Interface is changed during upgrade</h3>
<p>Notice that all location and VPP paths for EPiServers User Interface are changed during upgrade. If you path to edit mode was <em>/secret/edit</em> before it will now be <em>/secret/<strong>CMS</strong>/edit</em>. There is no redirect so bookmarks or hard coded links in your application to edit mode may break.</p>
<h3>Language files</h3>
<p>Notice that you no longer can translate the whole EPiServer User Interface yourself (or override some translations) by changing xml-files in the lang folder. The new Dashboard feature (aka. Shell, Online Center) is using binary resource assemblies.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2010/03/10/configuration-management-and-episerver-cms-6/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>EPiServer &#8211; Security and Access Control (1/2)</title>
		<link>http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 07:15:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/</guid>
		<description><![CDATA[EPiServer CMS is using the standard methods in ASP.NET to handle authentication and authorization. On top of this they have added a few providers to handle authentication and access control to EPiServer assets like pages and files uploaded by editors.
Make sure that you read up on how the authentication, location and authorization-tags works in web.config [...]]]></description>
			<content:encoded><![CDATA[<p>EPiServer CMS is using the standard methods in ASP.NET to handle authentication and authorization. On top of this they have added a few providers to handle authentication and access control to EPiServer assets like pages and files uploaded by editors.</p>
<p><strong>Make sure that you read up on how the authentication, location and authorization-tags works in <em>web.config</em> before you try to understand security in EPiServer CMS.</strong></p>
<h3>Check list for ASP.NET security</h3>
<ul>
<li><strong>MachineKey</strong> – Always add a machinekey-tag to your <em>web.config</em>-file. Use this <a href="http://www.orcsweb.com/articles/aspnetmachinekey.aspx" target="_blank">online tool to generate the MachineKey</a>. </li>
<li><strong>Authentication</strong> – I almost always use ASP.NET Forms authentication because it gives you the most flexibility. This is all you need and I always set timeout high to get the “Remember Me”-checkbox to work as expected. Sometimes I also use the <em>defaultUrl</em>-attribute to control what happens after login.
<pre><code>&lt;authentication mode=&quot;Forms&quot;&gt;
  &lt;forms loginUrl=&quot;Util/login.aspx&quot; defaultUrl=&quot;/&quot;
    timeout=&quot;<strong>129600</strong>&quot; /&gt;
&lt;/authentication&gt;</code></pre>
</li>
<li><strong>Membership</strong> and <strong>RoleProvider</strong> – Configures how a username and password is validated and how to retrieve what groups a user is a member of. </li>
<li><strong>Authorization</strong> – EPiServer uses authorization tags together with location tags to control access to physical folders like the EPiServer user interface. </li>
</ul>
<h3>Select Security PROVIDERS</h3>
<p>Select the right providers for your site:</p>
<ul>
<li><strong>SqlMembershipProvider</strong> and <strong>SqlRoleProvider</strong> from Microsoft stores username, password and group membership in a SQL database. EPiServer is preconfigured with the needed tables so you can just start using them by changing <em>defaultProvider</em>-attribute.</li>
<li><strong>WindowsMembershipProvider</strong> and <strong>WindowsRoleProvider</strong> from EPiServer enabled forms login but with windows credentials. This is the default provider for a new installation. A big limitation if an editor needs to work with Access Control is that Window Users and Groups are only synchronized when a user log on. So it is not possible to add rights to a user before it has logged in at least one time and the security admin tool shows cached data for who is a member of a group.</li>
<li><strong>ActiveDirectoryMembershipProvider</strong> from Microsoft and <strong>ActiveDirectoryRoleProvider</strong> from EPiServer. Tries to workaround the problem with cached Users and Groups by talking directly to the Active Directory. I have personally have had a lot of issues with exceptions from the Active Directory providers and trouble to get it to work in a DMZ. They are also sensitive to interruptions if the LDAP server is not available. I recommend to use WindowsMembershipProvider if possible since it also uses the local machine as a cache.</li>
<li><strong>MultiplexingMembershipProvider</strong> and <strong>MultiplexingRoleProvider</strong> from EPiServer forwards the requests to a list of providers and this enables you to combine both SQL and Windows accounts.</li>
</ul>
<h3>TIPS – IF you Can not login with your Windows Account</h3>
<p>EPiServer <strong>WindowsMembershipProvider</strong> does not work if you try to login with a domain account but do your machine does not have a working connection to your Domain Controler. </p>
<p>Workaround by creating a local account that is a member of the local administrators group.</p>
<h3>Tips – Use a local group to optimize and handle Groups in groups </h3>
<p>EPiServer <strong>WindowsRoleProvider</strong> uses queries that only retrieve a list of groups you are a member of directly. It does not discover if you indirectly are a member of group through another group.</p>
<p>This is quite annoying and and AD-admin get something sad in their eyes if you suggest that you should not use groups in groups.</p>
<p>Workaround this by creating a local group on the web server and add the AD group that is using groups in groups. <strong>WindowsRoleProvider</strong> will see that you are a direct member of the local group. </p>
<p>This technique can also be useful if a lot of different AD-groups should have the same access in EPiServer. The reason is that EPiServer stores one row in a table for each access control entry for each EPiServer page and directory in VPP. </p>
<p>It could simplify your web.config if you do not have to maintain a long list group names for edit and admin mode access. (EPiServer 6 has a new feature that takes care of this.)</p>
<h3>Break in to an EPiServer site </h3>
<p>Forgot the password? Only got ftp-access? Do not worry, as long as you have the right to change web.config you can always break in!</p>
<p>You need to comment out all “&lt;deny users=&quot;*&quot; /&gt;” in web.config and then it is possible to access edit and admin mode without authentication.</p>
<p>I suggest that you reset your password or create a new account in admin mode and turn on security as fast as possible!</p>
<p>Notice that you must login to be able to edit pages.</p>
<h3>Access Rights for pages and uploaded files</h3>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image_thumb.png" width="244" height="145" /></a> EPiServer has the following Access Rights that can be set per page. You can also set access right for files in the File Manager. </p>
<ul>
<li><strong>Read</strong> – Let’s you see the page or download the file.</li>
<li><strong>Create</strong> – Allows you to create child pages that will inherit the same ACL as the parent, upload new files or create directories.</li>
<li><strong>Change</strong> – Allows you to save a new version of a page and mark it ready to publish. You can also check in a new version of an existing files.</li>
<li><strong>Delete</strong> – Allows you to move a page to the wastebasket or delete it permanently. You can delete files and directories.</li>
<li><strong>Publish</strong> – Allows you to change and publish pages. Not applicable on files.</li>
<li><strong>Administer</strong> – Allows you to change the ACL for this page or directory as an editor and change dynamic properties on this page (and indirectly all children)</li>
</ul>
<p>Users with access to admin mode can always change access control lists and do not need Administer right.</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image1.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image_thumb1.png" width="240" height="190" /></a>Notice that you can only set Access Rights per directory and not on individual files.</p>
<p>Page Files are special. Each page can have its own page folder and files uploaded to this directory have the same availability as the page. So if the page is not publish – no one can access the files in the page folder except editors. Very convenient since scheduled publishing also affects the files! </p>
</p>
<p>The same happens when the page is moved to the waste basket. No one can access the files in the page folder than editors. This is a common cause for broken images and links to document when editors copy and paste pages. If you delete the original page, no one can access the images its page folder!</p>
<h3>Tips for Access Right configuration</h3>
<p>If you follow these guidelines it will be much easier to administer access.</p>
<ul>
<li>Avoid giving users access rights directly. Always add roles (groups) and make users members of these instead.</li>
<li>Never give WebEditors group any access rights (except on small sites where you are not going to use Access Rights at all). This roles is intended as a master switch if you have access to edit mode or not.</li>
<li>Give the virtual role “Creator” the right to change and delete pages if you setup a site with writers and an editors-in-chief that publish pages. It will save a lot of maintenance work when writers makes mistakes. </li>
<li>Using role names with both location and role will simplify when you administer who is a member of what, i.e. pressrelease_writer, pressrelease_publisher, startpage_editor, article_writer, blog_admin</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using jQuery to add thousands separator to textbox</title>
		<link>http://blog.fredrikhaglund.se/blog/2010/03/05/using-jquery-to-add-thousands-separator-to-textbox/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2010/03/05/using-jquery-to-add-thousands-separator-to-textbox/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 06:03:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Thousands Separator]]></category>
		<category><![CDATA[tusentalsavgränsare]]></category>
		<category><![CDATA[tusentalsseparator]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=223</guid>
		<description><![CDATA[
// < ![CDATA[
$(function() {
    var numberInputs = $("input.number");
    var convertToCurrencyDisplayFormat = function(str) {
        var regex = /(-?[0-9]+)([0-9]{3})/;
        str += '';
        while (regex.test(str)) {
      [...]]]></description>
			<content:encoded><![CDATA[<p><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script><script type="text/javascript">
// < ![CDATA[
$(function() {
    var numberInputs = $("input.number");
    var convertToCurrencyDisplayFormat = function(str) {
        var regex = /(-?[0-9]+)([0-9]{3})/;
        str += '';
        while (regex.test(str)) {
            str = str.replace(regex, '$1 $2');
        }
        str += ' kr';
        return str;
    };
    var stripNonNumeric = function(str) {
        str += ''; 
        str = str.replace(/[^0-9]/g, '');
        return str;
    };
    numberInputs.each(function() {
        this.value = convertToCurrencyDisplayFormat( this.value );
    });
    numberInputs.blur(function() {
        this.value = convertToCurrencyDisplayFormat( this.value );
    });
    numberInputs.focus(function() {
        this.value = stripNonNumeric( this.value );
    });
    $("form").submit(function() {
        numberInputs.each(function() {
            this.value = stripNonNumeric( this.value );
        });
    });
});
// ]]&gt;</script>
<p><strong>UPDATED: Code improved after feedback from Henrik Tengelin.</strong></p>
<p>It is much easier to read large numbers with with <b>thousands separator</b> but how to get them to work with page validation in a good way?</p>
<p>The solution in this case was to sprinkle some jQuery on the page!</p>
<h3>Test how it works here</h3>
<p>
<input class="number" value="1234" />
<input class="number" value="12" />
<input class="number" value="12345678" /></p>
<h3>JavaScript code for adding thousands separator as watermark</h3>
<pre class="code">$(<span style="color: blue">function</span>() {
    <span style="color: blue">var </span>numberInputs = $(<span style="color: #a31515">&quot;input.number&quot;</span>);
    <span style="color: blue">var </span>convertToCurrencyDisplayFormat = <span style="color: blue">function</span>(str) {
        <span style="color: blue">var </span>regex = /(-?[0-9]+)([0-9]{3})/;
        str += <span style="color: #a31515">''</span>;
        <span style="color: blue">while </span>(regex.test(str)) {
            str = str.replace(regex, <span style="color: #a31515">'$1 $2'</span>);
        }
        str += <span style="color: #a31515">' kr'</span>;
        <span style="color: blue">return </span>str;
    };
    <span style="color: blue">var </span>stripNonNumeric = <span style="color: blue">function</span>(str) {
        str += <span style="color: #a31515">''</span>;
        str = str.replace(/[^0-9]/g, <span style="color: #a31515">''</span>);
        <span style="color: blue">return </span>str;
    };
    numberInputs.each(<span style="color: blue">function</span>() {
        <span style="color: blue">this</span>.value = convertToCurrencyDisplayFormat(<span style="color: blue">this</span>.value);
    });
    numberInputs.blur(<span style="color: blue">function</span>() {
        <span style="color: blue">this</span>.value = convertToCurrencyDisplayFormat(<span style="color: blue">this</span>.value);
    });
    numberInputs.focus(<span style="color: blue">function</span>() {
        <span style="color: blue">this</span>.value = stripNonNumeric(<span style="color: blue">this</span>.value);
    });
    $(<span style="color: #a31515">&quot;form&quot;</span>).submit(<span style="color: blue">function</span>() {
        numberInputs.each(<span style="color: blue">function</span>() {
            <span style="color: blue">this</span>.value = stripNonNumeric(<span style="color: blue">this</span>.value);
        });
    });
});</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2010/03/05/using-jquery-to-add-thousands-separator-to-textbox/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reset Trial Counter for Protexis Licensing V2</title>
		<link>http://blog.fredrikhaglund.se/blog/2010/03/04/reset-trial-counter-for-protexis-licensing-v2/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2010/03/04/reset-trial-counter-for-protexis-licensing-v2/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 17:13:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[KGyGaAvL.sys]]></category>
		<category><![CDATA[Protexis]]></category>
		<category><![CDATA[Sage Act!]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2010/03/04/reset-trial-counter-for-protexis-licensing-v2/</guid>
		<description><![CDATA[It is annoying when a trial expires before you had time testing the software. Sometimes it is just enough to reinstall to get a new trial period but usually they hide the information so it is persistent.
I used Sysinternal’s Process Monitor to find out what resources the license manager (PsiService_2.exe) used and cleared them away [...]]]></description>
			<content:encoded><![CDATA[<p>It is annoying when a trial expires before you had time testing the software. Sometimes it is just enough to reinstall to get a new trial period but usually they hide the information so it is persistent.</p>
<p>I used Sysinternal’s Process Monitor to find out what resources the license manager (PsiService_2.exe) used and cleared them away to get a new fresh trial period.</p>
<p>If you have licensed products using this service you should be careful and keep backups of all values/files.</p>
<p>These instructions are valid for Windows 7 64-bit but just remove “Wow6432Node” for 32 bit systems:</p>
<ul>
<li>Stop “Protexis Licensing V2”-service and the application you are evaluating. </li>
<li>Clear registry:
<ul>
<li>HKEY_USERS\.DEFAULT\Software\Protexis\Licenses </li>
<li>HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Protexis\Licenses </li>
</ul>
</li>
<li>Delete files:
<ul>
<li>C:\ProgramData\KGyGaAvL.sys </li>
<li>C:\ProgramData\88AD984CE6.sys (filename varies) </li>
</ul>
</li>
<li>Start service </li>
<li>Start the application </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2010/03/04/reset-trial-counter-for-protexis-licensing-v2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Tool to re-index all EPiServer pages</title>
		<link>http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 18:19:55 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[LazyIndexer]]></category>
		<category><![CDATA[SoftLink]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/</guid>
		<description><![CDATA[You get a warning when you try to delete a file or EPiServer page if it is referenced form another page.
EPiServer uses EPiServer.DataAbstraction.SoftLink for this feature and all links to files, other EPiServer pages and external urls are stored here every time you publish a page.
It is also worth to notice that EPiServer built-in keyword [...]]]></description>
			<content:encoded><![CDATA[<p>You get a warning when you try to delete a file or EPiServer page if it is referenced form another page.</p>
<p>EPiServer uses <em>EPiServer.DataAbstraction.SoftLink</em> for this feature and all links to files, other EPiServer pages and external urls are stored here every time you publish a page.</p>
<p>It is also worth to notice that EPiServer built-in keyword table that is used for text searching pages also is updated during publish.</p>
<h3>Corrupt data = Broken Links</h3>
<p>The index can be corrupt or out of sync and then it is <strong>possible to delete a file or a page without getting a warning that it has incoming links</strong>. Text search can also fail or return wrong data.</p>
<p>I have seen this very often after a migration from EPiServer CMS 4. EPiServer CMS 4 databases tends to have really poor data for soft links.</p>
<p>The index is updated when you publish a page with a delay controled by <em>indexingDelayAfterPublish</em> setting. If the delay it is very large and the application restarts before the page is indexed, neither soft links or keywords will be updated.</p>
<h3>How to repair EPiServer CMS soft link and keyword index</h3>
<p>I have created an admin tool that we always run after migration from EPiServer 4 and also if we want to repair the index if the settings has been strange.</p>
<p>You sould set <em>indexingDelayAfterPublish</em> to a very large delay during the time you run the tool because if you try to use <em>LaxyIndexer.IndexPage()</em> in more than one thread at the same time you are guaranteed to get deadlocks or get other strange SQL exceptions sooner or later.</p>
<blockquote><p>System.Data.SqlClient.SqlException:Violation of PRIMARY KEY constraint &#8216;PK_tblPageKeyword&#8217;. Cannot insert duplicate key in object &#8216;dbo.tblPageKeyword&#8217;.</p>
</blockquote>
<h3>Example code</h3>
<pre class="code">[GuiPlugIn(DisplayName = <span style="color: #a31515">&quot;Reindex pages&quot;</span>, Description = <span style="color: #a31515">&quot;Tool to index keywords and soft links&quot;</span>, Area = PlugInArea.AdminMenu, Url = <span style="color: #a31515">&quot;~/Common/FixIndexing.aspx&quot;</span>)]
<span style="color: blue">public partial class </span><span style="color: #2b91af">FixIndexing </span>: System.Web.UI.Page
{
    <span style="color: blue">private static readonly </span>ILog log;
    <span style="color: blue">private static long </span>QueueLength;
    <span style="color: blue">private static long </span>IndexedPages;
    <span style="color: blue">private static </span><span style="color: #2b91af">DateTime </span>Started = <span style="color: #2b91af">DateTime</span>.MinValue;
    <span style="color: blue">private static readonly </span>Queue&lt;PageData&gt; Queue = <span style="color: blue">new </span>Queue&lt;PageData&gt;();
    <span style="color: blue">private static object </span>LockRoot = <span style="color: blue">new object</span>();

    <span style="color: blue">static </span>FixIndexing()
    {
        log = LogManager.GetLogger(<span style="color: blue">typeof</span>(FixIndexing));
    }

    <span style="color: blue">protected override void </span>OnLoad(<span style="color: #2b91af">EventArgs </span>e)
    {
        <span style="color: blue">base</span>.OnLoad(e);
        UpdateStatus();
    }

    <span style="color: blue">private void </span>UpdateStatus()
    {
        <span style="color: blue">long </span>q = <span style="color: #2b91af">Interlocked</span>.Read(<span style="color: blue">ref </span>QueueLength);
        <span style="color: blue">long </span>n = <span style="color: #2b91af">Interlocked</span>.Read(<span style="color: blue">ref </span>IndexedPages);
        <span style="color: blue">if </span>(Started != <span style="color: #2b91af">DateTime</span>.MinValue)
        {
            StatusLabel.Text = <span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Started: {0}  Indexed pages: {1}  Queue: {2}&quot;</span>, Started, n, q);
        }
        FixPageSoftLinkButton.Enabled = q &lt;= 0;
    }

    <span style="color: blue">protected void </span>FixPageSoftLinkButton_Click(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
    {
        log.Info(<span style="color: #a31515">&quot;Start LazyIndex of all pages!&quot;</span>);
        Started = <span style="color: #2b91af">DateTime</span>.Now;
        <span style="color: #2b91af">ThreadPool</span>.QueueUserWorkItem(ThreadProc);
        UpdateStatus();
    }

    <span style="color: green">// This thread procedure performs the task.
    </span><span style="color: blue">static void </span>ThreadProc(<span style="color: #2b91af">Object </span>stateInfo)
    {
        <span style="color: blue">if </span>(!<span style="color: #2b91af">Monitor</span>.TryEnter(LockRoot)) <span style="color: blue">return</span>; <span style="color: green">//Job was already running
        </span><span style="color: blue">try
        </span>{
            IndexedPages = 0;
            PageData page;
            Queue.Enqueue(DataFactory.Instance.GetPage(PageReference.RootPage, LanguageSelector.MasterLanguage()));
            <span style="color: #2b91af">Interlocked</span>.Increment(<span style="color: blue">ref </span>QueueLength);
            <span style="color: blue">while </span>((page = Queue.Dequeue()) != <span style="color: blue">null</span>)
            {
                <span style="color: #2b91af">Interlocked</span>.Decrement(<span style="color: blue">ref </span>QueueLength);
                <span style="color: blue">try
                </span>{
                    log.Debug(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Indexing page {0}:{1}...&quot;</span>, page.PageLink.ID, page.PageName));
                    LazyIndexer.IndexPage(page.PageLink.ID);
                    <span style="color: #2b91af">Interlocked</span>.Increment(<span style="color: blue">ref </span>IndexedPages);
                }
                <span style="color: blue">catch </span>(<span style="color: #2b91af">Exception </span>ex)
                {
                    <span style="color: blue">int </span>id = (stateInfo <span style="color: blue">as </span>PageData) != <span style="color: blue">null </span>? ((PageData)stateInfo).PageLink.ID : -1;
                    log.Error(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Error while indexing {0}&quot;</span>, id), ex);
                }
                <span style="color: blue">try
                </span>{
                    PageDataCollection pages = DataFactory.Instance.GetChildren(page.PageLink, LanguageSelector.MasterLanguage());
                    log.Debug(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Done indexing page {0}. Adding {1} children to Queue...&quot;</span>, page.PageLink.ID, pages.Count));
                    <span style="color: blue">foreach </span>(PageData data <span style="color: blue">in </span>pages)
                    {
                        Queue.Enqueue(data);
                        <span style="color: #2b91af">Interlocked</span>.Increment(<span style="color: blue">ref </span>QueueLength);
                    }
                }
                <span style="color: blue">catch </span>(<span style="color: #2b91af">Exception </span>ex)
                {
                    <span style="color: blue">int </span>id = (stateInfo <span style="color: blue">as </span>PageData) != <span style="color: blue">null </span>? ((PageData)stateInfo).PageLink.ID : -1;
                    log.Error(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Error while adding children for {0}&quot;</span>, id), ex);
                }

            }
        }
        <span style="color: blue">finally
        </span>{
            <span style="color: #2b91af">Monitor</span>.Exit(LockRoot);
        }

    }

}</pre>
<h3>Index as Scheduled task</h3>
<p>Another way to use the code above is to just add an <em>Execute()</em> method that calls <em>ThreadProc</em> and register it as a Scheduled Job plug-in. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to get started developing with EPiServer CMS</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/12/23/how-to-get-started-developing-with-episerver-cms/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/12/23/how-to-get-started-developing-with-episerver-cms/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 09:00:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Beginner]]></category>
		<category><![CDATA[EPiServer CMS]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/12/23/how-to-get-started-developing-with-episerver-cms/</guid>
		<description><![CDATA[I got a question in the mail today how to get started with EPiServer CMS as a developer. Here are my tips:

Register at world.episerver.com with your work email address.
Start by downloading and installing &#34;EPiServer CMS 5 R2 SP2&#34; plus SDK on a machine with Visual Studio 2008 and IIS installed.
See the installation instructions that are [...]]]></description>
			<content:encoded><![CDATA[<p>I got a question in the mail today how to get started with EPiServer CMS as a developer. Here are my tips:</p>
<ul>
<li>Register at <a href="http://world.episerver.com/ " target="_blank">world.episerver.com</a> with your work email address.</li>
<li>Start by <a href="http://world.episerver.com/Download/Categories/Products/EPiServer-CMS/" target="_blank">downloading and installing &quot;EPiServer CMS 5 R2 SP2&quot; plus SDK</a> on a machine with Visual Studio 2008 and IIS installed.
<p>See the installation instructions that are linked on the download page.</li>
<li>You generate demo licenses here: <a href="http://license.episerver.com/" target="_blank">license.episerver.com</a></li>
<li>Learn more in the <a href="http://world.episerver.com/Get-Started/Developing-with-EPiServer-CMS/" target="_blank">Getting-Started</a> section by watching video presentations and reading articles and tutorials.</li>
<li>Take the <a href="http://www.episerver.com/en/Education/Course-Schedule---Developers/" target="_blank">basic developer training for EPiServer CMS (E2550)</a>.</li>
<li>Get certified as EPiServer Developer after you have participated in 2-3 EPiServer projects. Read my <a href="http://blog.fredrikhaglund.se/blog/2008/11/30/how-to-become-a-episerver-ceritified-developer/" target="_blank">certification tips</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/12/23/how-to-get-started-developing-with-episerver-cms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debugging &#8220;Exception has been thrown by the target of an invocation&#8221;</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/12/22/debugging-exception-has-been-thrown-by-the-target-of-an-invocation/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/12/22/debugging-exception-has-been-thrown-by-the-target-of-an-invocation/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 05:00:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Debug]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/12/22/debugging-exception-has-been-thrown-by-the-target-of-an-invocation/</guid>
		<description><![CDATA[I got a question how to find what was wrong when you only got an error “Exception has been thrown by the target of an invocation. [The server committed a protocol violation The server response was: …]” from a junior developer and I want to share my answer with all of you since it can [...]]]></description>
			<content:encoded><![CDATA[<p>I got a question how to find what was wrong when you only got an error “Exception has been thrown by the target of an invocation. [The server committed a protocol violation The server response was: …]” from a junior developer and I want to share my answer with all of you since it can be a little tricky.</p>
<p>The Exception “thrown by the target of invocation” indicated that an error has occurred in code called by using invoke through dot net reflection. This technique is common when you have plug-ins (like scheduled jobs in EPiServer) and other late binding in run-time.</p>
<p>The text in square brackets are the original exception (caught by the <em>Invoke()</em> method) and gives a clue what goes wrong but it is usually not enough to find the error.</p>
<h3>How to find more clues when debugging</h3>
<p>As always when searching for the cause of a problem or error condition the first rule is to get more clues.&#160; Usually this process consist of finding a reproducible test scenario that triggers the condition and hook up the debugger to see what is happening inside the application.</p>
<p>We must make sure it halts on thrown exceptions even if it outside our code to get a call stack that can help us. Open your options dialog and uncheck”Enable Just My Code”.</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/clip_image002.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="clip_image002" border="0" alt="clip_image002" align="right" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/clip_image002_thumb.jpg" width="244" height="143" /></a></p>
<p>With default settings the debugger will only break on uncaught exceptions. We need the debugger to break when an exceptions are thrown regardless of they are handled by a try-catch statement.</p>
<p>This can be changed in your Exceptions dialog (Ctrl+Shift+E). You can either set it to catch all managed exceptions as I have in the screen shot below or if you know what exception you are looking for you can halt on that one alone to minimize noise since it will probably halt on exceptions a lot of places that are normal before reaching your area of intrest.</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/clip_image004.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="clip_image004" border="0" alt="clip_image004" align="left" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/clip_image004_thumb.jpg" width="240" height="125" /></a></p>
<p>With this setup we are now ready to run the test case again to trigger the error. If everything is correctly configured it will break on the exception and show you a call stack.</p>
<p>Use the debugger windows in Visual Studio to examine the Call Stack. Inspect parameters and Local Variables at each step in the call stack. This should give enough clues so to find what is causing the error.</p>
<h3>How to find more clues when you do not have the source code</h3>
<p>If the exception is raised in code that is not our own we can use several strategies to find out more. One of the best is to use Lutz Roeder’s .NET Reflector and click File&gt;Open to load all assemblies in your web applications bin-folder. Search for the class or method and Disassemble the methods outside your code and get more clues. (Another way, if the exception is inside Microsoft code, is to configure VS to use Microsoft source server to download source code.)</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/clip_image006.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="clip_image006" border="0" alt="clip_image006" align="right" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/clip_image006_thumb.jpg" width="244" height="176" /></a></p>
<p>Here is an example of when I caught a “Exception has been thrown by the target of an invocation.&#160; [NullReferenceException: Object reference not set to an instance of an object.]“ and found <i>TransformCategoryForExport</i> in the call stack.</p>
<p>By analyzing the call stack we can usually also find the point in our own code that is starting the chain of calls causing the exception. I would recommend setting a break point there and rerunning the test case to see if the parameters to the call are invalid.</p>
<h3>Need more help?</h3>
<p>God luck with you bug hunting! If you are stuck you are welcome to contact me at INEXOR and buy my services.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/12/22/debugging-exception-has-been-thrown-by-the-target-of-an-invocation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>EPiServer with developers on both x32 and x64</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/12/19/episerver-with-developers-on-both-x32-and-x64/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/12/19/episerver-with-developers-on-both-x32-and-x64/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 12:07:31 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/12/19/episerver-with-developers-on-both-x32-and-x64/</guid>
		<description><![CDATA[Today&#8217;s tip is for all of you who want to share the same web.config among all developers in a project so you can check-in and handle changes in your Source Code Control Repository.
EPiServer installation directory and web.config
You might have noticed that the default installation path is different on 32-bit and 64-bit windows. Either you install [...]]]></description>
			<content:encoded><![CDATA[<p>Today&#8217;s tip is for all of you who want to share the same web.config among all developers in a project so you can check-in and handle changes in your Source Code Control Repository.</p>
<h3>EPiServer installation directory and web.config</h3>
<p>You might have noticed that the default installation path is different on 32-bit and 64-bit windows. Either you install EPiServer at “C:\Program Files\EPiServer” or “C:\Program Files (x86)\EPiServer”.</p>
<p>This is an issue if you have developers working on a project with both 32 and 64-bit windows since you have references to EPiServer installation directory in Program Files in your <em>web.config</em>. </p>
<p>But it can be easily solved by using a NTFS junction for developers running x64.</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/image.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="image" border="0" alt="image" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/12/image_thumb.png" width="500" height="253" /></a></p>
<p>Run CMD Shell as an administrator and run:</p>
<p> <code>
<pre>cd &quot;C:\Program Files&quot;
mklink /j EPiServer &quot;C:\Program Files (x86)\EPiServer&quot;</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/12/19/episerver-with-developers-on-both-x32-and-x64/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>I do not like the trend for EPiServer web.config!</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/10/21/i-do-not-like-the-trend-for-episerver-webconfig/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/10/21/i-do-not-like-the-trend-for-episerver-webconfig/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 15:15:24 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/10/21/i-do-not-like-the-trend-for-episerver-webconfig/</guid>
		<description><![CDATA[Everyone is talking about CoC (Convention over Configuration) and DRY (Don&#8217;t Repeat Yourself) today. The idea is to reduce the amount of repetitive, needless configuration and just keep what&#8217;s important.
Here is a graph with the number of lines in web.config for a clean installation of EPiServer CMS from version 4 to 6 (CTP2). Adding Community, [...]]]></description>
			<content:encoded><![CDATA[<p>Everyone is talking about CoC (Convention over Configuration) and DRY (Don&#8217;t Repeat Yourself) today. The idea is to reduce the amount of repetitive, needless configuration and just keep what&#8217;s important.</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/10/image.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="image" border="0" alt="image" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/10/image-thumb.png" width="500" height="301" /></a>Here is a graph with the number of lines in <em>web.config</em> for a clean installation of EPiServer CMS from version 4 to 6 (CTP2). Adding Community, Mail or other product will not make it better. </p>
<h3>Complexity is making EPiServer CMS expensive to own</h3>
<p>Handling <em>web.config</em> takes time and effort when you have to merge changes between different environments during deployment and each version is adding more and more configuration to your <em>web.config</em>-file.</p>
<p>And it increases the risk or mistakes because important settings disappears in all noise from comments and default settings.</p>
<h3>What can be done?</h3>
<p>Here are my suggestions and I urge EPiServer to implement the before they release EPiServer CMS 6:</p>
<ul>
<li>Comments: -246 lines. Just moving all comments and example settings to a separate file that is overwritten with the latest version during upgrade.</li>
<li>Oracle: -60 lines. Why not a separate sample file for oracle?</li>
<li>EPiServer UI-settings. –78&#160; lines. Why not mount user interface folders using IIS virtual folders? Then you could move a lot in location tags to other web.config files!</li>
<li>Workflow: –42 lines. Not used by many. Why not put it in the sample file for people to include if they want it or start it with default values.</li>
<li>RemoteEvents: –32 lines. WCF Service configuration – Why not have a programmatic or shared database config</li>
<li>siteSettings: A line over 1500 characters long. Why not remove the default values and make it shorter?</li>
<li>Providers: –8 lines. Skip adding providers that are not used. Just keep the other in the sample file.     </li>
</ul>
<p>Enough whining for today <img src='http://blog.fredrikhaglund.se/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/10/21/i-do-not-like-the-trend-for-episerver-webconfig/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>EPiServer CMS: How to configure Remote Events with many servers and Firewalls between them</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/09/22/episerver-cms-how-to-configure-remote-events-with-many-servers-and-firewalls-between-them/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/09/22/episerver-cms-how-to-configure-remote-events-with-many-servers-and-firewalls-between-them/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 20:40:22 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[enableRemoteEvents]]></category>
		<category><![CDATA[EPiServer 5]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[RemoteEventsBinding]]></category>
		<category><![CDATA[WCF]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/09/22/episerver-cms-how-to-configure-remote-events-with-many-servers-and-firewalls-between-them/</guid>
		<description><![CDATA[The Event Management System in EPiServer CMS 5 is used to propagate information that a page has changed to other web servers connected to the same database. 
This is very important to setup if you have more than one web server or an enterprise site with several start pages because if it does not invalidate [...]]]></description>
			<content:encoded><![CDATA[<p>The Event Management System in EPiServer CMS 5 is used to propagate information that a page has changed to other web servers connected to the same database. </p>
<p>This is very important to setup if you have more than one web server or an enterprise site with several start pages because if it does not invalidate cache, the other web sites can potentially return old versions of a page!</p>
<h3>Pitfall – Default configuration is using Multicast UDP!</h3>
<p>If you read <a href="http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-5/EPiServer-CMS-5-R2-SP2/Configuring-EPiServer-CMS-5-R2-SP2-Enterprise/">Configuring EPiServer CMS 5 R2 SP2 Enterprise</a> you will learn that all you have to do is to set <code>enableRemoteEvents=&quot;true&quot;</code> in <em>web.config</em>. </p>
<p>It is only mentioned briefly that it is using UDP and you may have to change your firewall settings. Too be more specific the default configuration is using multicast UDP broadcast! Tell this to your network guys and watch their reaction&#8230;</p>
<p>If you look around you will also find a tech note about the <a href="http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-5/EPiServer-CMS-5-R2-SP2/Event-Management-System-Specification/">Event Management System Specification</a> and a FAQ about <a href="http://world.episerver.com/FAQ/Items/Multicast-UDP-not-working/">setting up a server to use TCP protocol</a> but not all clues needed are found there – you have to dig with the reflector to find out the rest.</p>
<h3>Scenario: 4 start pages, 8 Front-end servers IN DMZ and 2 in LAN</h3>
<p>You can change how the Event Management System communicates by changing WCF settings in <em>web.config</em>. It is possible to use TCP instead of UDP and also specify ports to use.</p>
<p>First, the current release (5 R2 SP2) does not support WCF Port Sharing so we need one port opened in the firewall for each start page (that is when you have several <em>siteSettings</em>-tags in web.config).</p>
<p>In our case we need to get four ports (for example port 13000-13003) opened in the firewall for TCP traffic between servers in DMZ and LAN.</p>
<p>Use the sample configuration below as a template to get it to work. In production I suggest using <em>configSource</em>-attribute in <em>web.config</em> to keep the WCF-settings in separate files.</p>
<h4>Web.Config</h4>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">services </span><span style="color: red">configSource</span><span style="color: blue">=</span>&quot;<span style="color: blue">system.serviceModel.services.config</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">client </span><span style="color: red">configSource</span><span style="color: blue">=</span>&quot;<span style="color: blue">system.serviceModel.client.config</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">serviceBehaviors</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">behavior </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">DebugServiceBehaviour</span>&quot;<span style="color: blue">&gt;
        &lt;!--</span><span style="color: green">TODO: the option should be only in test environment true in the production should be false</span><span style="color: blue">--&gt;
        &lt;</span><span style="color: #a31515">serviceDebug </span><span style="color: red">includeExceptionDetailInFaults</span><span style="color: blue">=</span>&quot;<span style="color: blue">true</span>&quot; <span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">behavior</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">serviceBehaviors</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">netTcpBinding</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">binding </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot;<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">security </span><span style="color: red">mode</span><span style="color: blue">=</span>&quot;<span style="color: blue">None</span>&quot; <span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">binding</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">netTcpBinding</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>system.serviceModel.services.config</h4>
<p>Use this to configure WCF Services (listens to incoming messages). Setup one service for each EPiServer site-tag.</p>
<ul>
<li>Name should be unique. </li>
<li>Name must be the value of episerver/sites[siteid] plus &quot;/EPiServer.Events.Remote.EventReplication&quot;, i.e. if siteId is “sss.se” then name should be “sss.se/EPiServer.Events.Remote.EventReplication”. </li>
<li>Each site must use a diffrent port in services/service/endpoint[address]. </li>
<li>Use &quot;localhost&quot; in the address attribute to bind to all NIC on the machine. </li>
</ul>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">services</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.se/EPiServer.Events.Remote.EventReplication</span>&quot; <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">DebugServiceBehaviour</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventServiceEndPoint</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://localhost:13000/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.no/EPiServer.Events.Remote.EventReplication</span>&quot; <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">DebugServiceBehaviour</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventServiceEndPoint</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://localhost:13001/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.dk/EPiServer.Events.Remote.EventReplication</span>&quot; <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">DebugServiceBehaviour</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventServiceEndPoint</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://localhost:13002/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.com/EPiServer.Events.Remote.EventReplication</span>&quot; <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">DebugServiceBehaviour</span>&quot;<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventServiceEndPoint</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://localhost:13003/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">services</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h4>system.serviceModel.client.config</h4>
<p>And each server that changes the content must also be aware of where to send notifications so we must list all servers and websites. </p>
<ul>
<li>Name should be unique. </li>
<li>It is better if address contains IP-addresses than hostnames. </li>
<li>There should be one endpoint for each website on a server where port number matches the ports used in the services/service/endpoint[address]. </li>
</ul>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">client</span><span style="color: blue">&gt;
  &lt;!-- </span><span style="color: green">SERVER1 </span><span style="color: blue">--&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.se-SERVER1</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER1:13000/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.no-SERVER1</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER1:13001/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.dk-SERVER1</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER1:13002/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.com-SERVER1</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER1:13003/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;!-- </span><span style="color: green">SERVER2 </span><span style="color: blue">--&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.se-SERVER2</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER2:13000/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.no-SERVER2</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER2:13001/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.dk-SERVER2</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER2:13002/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">name</span><span style="color: blue">=</span>&quot;<span style="color: blue">sss.com-SERVER2</span>&quot; <span style="color: red">contract</span><span style="color: blue">=</span>&quot;<span style="color: blue">EPiServer.Events.ServiceModel.IEventReplication</span>&quot; <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>&quot;<span style="color: blue">RemoteEventsBinding</span>&quot; <span style="color: red">address</span><span style="color: blue">=</span>&quot;<span style="color: blue">net.tcp://SERVER2:13003/RemoteEventService</span>&quot; <span style="color: red">binding</span><span style="color: blue">=</span>&quot;<span style="color: blue">netTcpBinding</span>&quot; <span style="color: blue">/&gt;
  &lt;!-- </span><span style="color: green">Repeat pattern above for all other servers and sites </span><span style="color: blue">--&gt;
&lt;/</span><span style="color: #a31515">client</span><span style="color: blue">&gt;</span></pre>
<p>Good luck! And let me know if this helps you or if you get stuck&#8230;</p>
<p><em>Credits to Petter Klang at EPiServer Support and Shahram Shahinzadeh on the backend dev team that has been helping us out.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/09/22/episerver-cms-how-to-configure-remote-events-with-many-servers-and-firewalls-between-them/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>EPiServer LicenseException: x.x.x.x is not a valid ip-address</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/09/11/episerver-licenseexception-xxxx-is-not-a-valid-ip-address/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/09/11/episerver-licenseexception-xxxx-is-not-a-valid-ip-address/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 13:20:58 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[Hosting]]></category>
		<category><![CDATA[LicenseException]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=242</guid>
		<description><![CDATA[I got a support question on this Exception today. First thought is that the ip-address was misstyped or the wrong license.config file was used but ipconfig /all and the IPRestiriction tag in license.config matched!
How does EPiServer validate the ip-address?
The code to check is quite simple. It is using the DNS service to lookup the name [...]]]></description>
			<content:encoded><![CDATA[<p>I got a support question on this Exception today. First thought is that the ip-address was misstyped or the wrong license.config file was used but ipconfig /all and the IPRestiriction tag in license.config matched!</p>
<h3>How does EPiServer validate the ip-address?</h3>
<p>The code to check is quite simple. It is using the DNS service to lookup the name of the computer and then lookup all ip-addresses for that computer name.</p>
<pre><code>foreach (IPAddress address in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
    if (!IPAddress.IsLoopback(address) &amp;&amp; this._ip.Equals(address))
    {
        this._isValid = true;
    }
}
</code></pre>
<h3>Troubleshooting License Exception  </h3>
<p>A quick test is to add a small debug.aspx file to find out what values are returned.</p>
<pre><code>&lt;%@ Page Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot;  %&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</a>
 &quot;&gt;
&lt;script runat=&quot;server&quot;&gt;

    protected void Button1_Click(object sender, EventArgs e)
    {
        foreach (System.Net.IPAddress address in System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList)
        {
            ListBox1.Items.Add(address.ToString()+ &quot;-&quot; + System.Net.IPAddress.IsLoopback(address).ToString());
        }
    }
&lt;/script&gt;
&lt;html xmlns=&quot;<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>
 &quot; &gt;
&lt;head runat=&quot;server&quot;&gt;&lt;title&gt;&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;h1&gt;Check IP-addresses&lt;/h1&gt;
    &lt;p&gt;Current host name: &lt;%= System.Net.Dns.GetHostName() %&gt;&lt;/p&gt;
    &lt;div&gt;
        &lt;asp:ListBox ID=&quot;ListBox1&quot; runat=&quot;server&quot;&gt;&lt;/asp:ListBox&gt;
        &lt;asp:Button ID=&quot;Button1&quot; runat=&quot;server&quot; onclick=&quot;Button1_Click&quot; Text=&quot;Test&quot; /&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3>Resolution to LicenseException in this case</h3>
<p>Running the test aboved showed us that the IP-address returned was the loopback address 127.0.0.1 instead of the computers ip-address.</p>
<p>Since this setup is an enterprise site with a lot of diffrent host names pointing to diffrent start pages the local hosts-file (at C:\Windows\System32\drivers\etc\hosts) was edited and all known host names was added pointing to 127.0.0.1 to make it possible to test. One entry was accidentally added with the machine name and when we removed that line everything started to work!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/09/11/episerver-licenseexception-xxxx-is-not-a-valid-ip-address/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Raise your quality with easy http-protocol analysis</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/06/15/raise-your-quality-with-easy-http-protocol-analysis/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/06/15/raise-your-quality-with-easy-http-protocol-analysis/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 06:30:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/06/15/raise-your-quality-with-easy-http-protocol-analysis/</guid>
		<description><![CDATA[
Both Fiddler (shown below) and Firebug can monitor Network traffic from your browser to web servers. I use it as a debugging tool all the time and could not live without it.
Discover broken links to images, java scripts, etc in your pages
Just browsing around can help you find errors. Look at the image below to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/06/image-thumb8.png"></a>
<p>Both <a href="http://www.fiddler2.com/fiddler2/" target="_blank">Fiddler</a> (shown below) and <a href="http://getfirebug.com/" target="_blank">Firebug</a> can monitor Network traffic from your browser to web servers. I use it as a debugging tool all the time and could not live without it.</p>
<h3>Discover broken links to images, java scripts, etc in your pages</h3>
<p>Just browsing around can help you find errors. Look at the image below to see how broken links to images referred from your HTML or CSS lights up in red.</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/06/image-thumb9.png" target="_blank"><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" border="0" alt="image_thumb[9]" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/06/image-thumb9-thumb.png" width="500" height="284" /></a></p>
<h3>Strange Java Script errors &#8211; Browser does not always refresh</h3>
<p>Have you noticed that EPiServer and other products emit a License Exception as text on your page? At least in earlier releases of EPiServer CMS it could inject it&#8217;s error message in the beginning of any file. A java script file starting with &quot;License Exception…&quot; does not work. Neither do a PNG or JPG file with some extra data in the beginning.</p>
<p>So use Fiddler when EPiServer Edit Mode does not work as expected!</p>
<ul>
<li>You can find that it fails to get files. This can be caused by miss configuration, like no ASP.NET wild card mapping or incorrect setup of VPP&#8217;s or <em>siteSettings</em> in you <em>web.config</em>. </li>
<li>You can also see how cache directives affects your browser. The default settings in a fresh EPiServer CMS installation will tell your browser to cache the following files in 12 hours: <em>.png .jpg .jpeg .css .js .gif</em>. </li>
</ul>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/06/image-thumb10.png" target="_blank"><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" border="0" alt="image_thumb[10]" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/06/image-thumb10-thumb.png" width="500" height="284" /></a></p>
</p>
</p>
<p>So, to get rid of error messages injected in the beginning of java scripts and images hitting F5 will not help. As you see above the server returns 304 – file is not changed &#8211; and your local (broken) file is used.&#160; You need to clear your browser cache to get rid of it!</p>
<p>Also <a href="http://labs.episerver.com/en/Blogs/Per/Tags/Caching/" target="_blank">read more about how to configure caching in EPiServer in Per Bjurström&#8217;s blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/06/15/raise-your-quality-with-easy-http-protocol-analysis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Move built-in property to another tab when editing</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/06/08/move-built-in-property-to-another-tab-when-editing/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/06/08/move-built-in-property-to-another-tab-when-editing/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 06:30:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[OwnerTab]]></category>
		<category><![CDATA[TabDefinition]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/06/08/move-built-in-property-to-another-tab-when-editing/</guid>
		<description><![CDATA[ One of our customers required that we limited access to the Advanced Information tab in edit mode for normal editors. A reasonable requirement but how do you enable normal editors to adjust the sort order? 
The answer is to move these built-in properties to a new tab.
Where to I hook my Event in EPiServer?
In [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2009/06/image.png"><img style="border-right-width: 0px; margin: 0px 0px 10px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="right" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/06/image-thumb.png" width="240" height="145" /></a> One of our customers required that we limited access to the Advanced Information tab in edit mode for normal editors. A reasonable requirement but how do you enable normal editors to adjust the sort order? </p>
<p>The answer is to move these built-in properties to a new tab.</p>
<h3>Where to I hook my Event in EPiServer?</h3>
<p>In latest releases of EPiServer CMS you are not allowed to access come parts of EPiServer to early. That is why I hook <em>FirstBeginRequest</em> event on EPiServer <em>InitializationModule</em> during <em>Application_Start</em> in <em>Global.asax</em>. You could also do this in <em>Init()</em> of an <em>HttpModule</em>.</p>
<p>All initialization is then done in that Event handler. We start by loading the target <em>TabDefinition</em> to get the <em>ID</em> then we hook <em>EditPanel.LoadedPage</em>. </p>
<p>EditPanel is the user class implementing EPiServers editor interface and LoadedPage is a static event that is fired every time the editor is shown. A perfect hook to tweak the editor! </p>
<h3>Source Code in Global.asax.cs to change tab for properties </h3>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> Application_Start(Object sender, EventArgs e)
{
    InitializationModule.FirstBeginRequest += InitializationModule_FirstBeginRequest;
}

<span class="kwrd">void</span> InitializationModule_FirstBeginRequest(<span class="kwrd">object</span> sender, EventArgs e)
{
    CreateEventToMovePageOrderPropertyToCustomTab();
}

<span class="kwrd">private</span> <span class="kwrd">int</span> pageOrderTabID;

<span class="kwrd">private</span> <span class="kwrd">void</span> CreateEventToMovePageOrderPropertyToCustomTab()
{
    <span class="kwrd">string</span> pageOrderTabName = WebConfigurationManager.AppSettings[<span class="str">&quot;PageOrderTab&quot;</span>];
    var pageOrderTab = TabDefinition.Load(pageOrderTabName);
    <span class="kwrd">if</span> (pageOrderTab!=<span class="kwrd">null</span>)
    {
        pageOrderTabID = pageOrderTab.ID;
        EditPanel.LoadedPage += EditPanel_LoadedPage;
    }
}

<span class="kwrd">void</span> EditPanel_LoadedPage(EditPanel sender, LoadedPageEventArgs e)
{
    e.Page.Property[<span class="str">&quot;PageChildOrderRule&quot;</span>].OwnerTab = pageOrderTabID;
    e.Page.Property[<span class="str">&quot;PagePeerOrder&quot;</span>].OwnerTab = pageOrderTabID;
}</pre>
<h3>Settings in web.config</h3>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">configuration</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">appSettings</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">key</span><span class="kwrd">=&quot;PageOrderTab&quot;</span>
         <span class="attr">value</span><span class="kwrd">=&quot;Sidadministration&quot;</span><span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">appSettings</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">configuration</span><span class="kwrd">&gt;</span></pre>
<p>As usual, drop a comment if you think this is usefull! It is good for my blogging morale. <img src='http://blog.fredrikhaglund.se/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/06/08/move-built-in-property-to-another-tab-when-editing/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Are you safe? Dangers of XSS&#8230;</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/06/03/cross-site-scripting-xss/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/06/03/cross-site-scripting-xss/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 07:55:34 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=210</guid>
		<description><![CDATA[If you allow the visitors of your site to contribute, for example with a simple comment this textbox, you take the risk that a malicious user inject evil code in a comment.
This evil code is then executed in the browser by your sites&#8217; ordinary visitors. Scripts can steals passwords (maybe your own admin account), trick the user [...]]]></description>
			<content:encoded><![CDATA[<p>If you allow the visitors of your site to contribute, for example with a simple comment this textbox, you take the risk that a malicious user inject evil code in a comment.</p>
<p>This evil code is then executed in the browser by your sites&#8217; ordinary visitors. Scripts can steals passwords (maybe your own admin account), trick the user to give up other senestive data or download malvare because they trust your site.</p>
<p>This kind of security vulnerability is reffered to as <a title="Wikipedia" href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS or Cross Site Scripting</a>. </p>
<h3>Always have input validation and filter you input</h3>
<p>A common aproach is to sanitize the data with a whitelisted or blacklisted characters to eliminate dangerous characters before storing or using the data. Another, is to always html encode data when it is rendered.  But it is harder than you think to get it right!</p>
<h3>70 ways to write the same character</h3>
<p>So you think you are smart and have a string replace or regular expression that removes &#8220;&lt;&#8221; from the user&#8217;s input on your website to be safe? I guess you need to test again&#8230; I had too!</p>
<p>Did you know that there is 70 diffrent ways to write the &#8220;&lt;&#8221; character in html? <a href="http://ha.ckers.org/xss.html" target="_blank">Read Robert Hansen&#8217;s good cheat sheet that lists known XSS attacks to get scared and take the problem serionsly</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/06/03/cross-site-scripting-xss/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sending an Email with an Edit Page-link</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/06/01/sending-an-email-with-an-edit-page-link/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/06/01/sending-an-email-with-an-edit-page-link/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 13:27:10 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/06/01/sending-an-email-with-an-edit-page-link/</guid>
		<description><![CDATA[Back from 2 healthy weeks of vacation on Iceland. Time to start blogging again!
This time I want to share a simple but useful snippet of code that sends an email to an EPiServer editor with a link that opens the page for editing in EPiServer Edit Mode.
How to create a go to Edit Mode link [...]]]></description>
			<content:encoded><![CDATA[<p>Back from 2 healthy weeks of vacation on Iceland. Time to start blogging again!</p>
<p><em>This time I want to share a simple but useful snippet of code that sends an email to an EPiServer editor with a link that opens the page for editing in EPiServer Edit Mode.</em></p>
<h3>How to create a go to Edit Mode link and mail it</h3>
<pre class="csharpcode"><span class="kwrd">string</span> baselink = UriSupport.AbsoluteUrlFromUIBySettings(<span class="str">&quot;edit/&quot;</span>);
<span class="kwrd">string</span> editlink = baselink + <span class="str">&quot;SwitchLanguage.aspx?language=&quot;</span> + page.LanguageBranch +
  <span class="str">&quot;&amp;epUrl=&quot;</span> + Server.UrlEncode(baselink + <span class="str">&quot;default.aspx?id=&quot;</span> + page.PageLink.ToString());
<span class="kwrd">string</span> pageurl = <span class="kwrd">string</span>.Format(<span class="str">&quot;&lt;a href=\&quot;{0}\&quot;&gt;Edit '{1}'&lt;/a&gt;&quot;</span>,
  editlink, page.PageName);

Utility.SendEmail(<span class="str">&quot;test@inexor.se&quot;</span>,

  EPiServerProfile.Current.EmailWithMembershipFallback,
  <span class="kwrd">string</span>.Format(<span class="str">&quot;[Moderate] {0}&quot;</span>, message),
  <span class="kwrd">string</span>.Format(
  <span class="str">@&quot;&lt;html&gt;&lt;body&gt;&lt;h1&gt;{0}&lt;/h1&gt;&lt;p&gt;The page&lt;b&gt;'{1}'&lt;/b&gt; must be review and published.&lt;/p&gt;&quot;</span> +
  <span class="str">@&quot;&lt;p&gt;Log in to EPiServer Edit Mode and use the following ID in the bottom left search box:&lt;br/&gt;&quot;</span> +
  <span class="str">@&quot;ID: &lt;b&gt;{2}&lt;/b&gt;&lt;/p&gt;&quot;</span> +
  <span class="str">@&quot;&lt;p&gt;Or click on the following link to login and review the page:&lt;br/&gt;{3}&lt;/p&gt;&quot;</span>,
  <span class="kwrd">new</span> <span class="kwrd">object</span>[] {message, page.PageName, page.PageLink.ID, pageurl}));</pre>
<h3>Works with unpublished versions of pages</h3>
<p>The code above expects a <em>PageData</em> object in the <em>page </em>variable. It handles WorkPageID if you send in a page that is just saved or retrieved through <em>PageVersion</em> class. </p>
<p>Read more about How to <a href="http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/">work with Unpublished PageData from code</a> in a previous blog post!</p>
<p>As usual, please leave a comment if you find it useful or have something to add. It is good for my blogging morale. <img src='http://blog.fredrikhaglund.se/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/06/01/sending-an-email-with-an-edit-page-link/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>12 Maj: EPiServer-utvecklare i Stockholm träffas</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/04/24/12-maj-episerver-utvecklare-i-stockholm-trffas/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/04/24/12-maj-episerver-utvecklare-i-stockholm-trffas/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 16:02:02 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Användarförening]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[SIG]]></category>
		<category><![CDATA[User Group]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/04/24/12-maj-episerver-utvecklare-i-stockholm-trffas/</guid>
		<description><![CDATA[Jag och René Voigt vill hälsa alla intresserade välkomna till vårt första möte för EPiServerutvecklare i Stockholm. Vi har många intressanta saker att dela med oss med kring webbutveckling och EPiServer.
Boka den 12 maj efter jobbet i din kalender.
Inbjudan kommer med mejl på måndag med tid, plats och program till de som är medlemmar i [...]]]></description>
			<content:encoded><![CDATA[<p>Jag och René Voigt vill hälsa alla intresserade välkomna till vårt första möte för EPiServerutvecklare i Stockholm. Vi har många intressanta saker att dela med oss med kring webbutveckling och EPiServer.</p>
<p>Boka den <strong>12 maj efter jobbet</strong> i din kalender.</p>
<p>Inbjudan kommer med mejl på måndag med tid, plats och program till de som är medlemmar i <a href="http://www.meetup.com/EPiServer-Stockholm/" target="_blank">nätverket för EPiServer-utvecklare i Stockholm</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/04/24/12-maj-episerver-utvecklare-i-stockholm-trffas/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Användarförening för EPiServer utvecklare?</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/03/06/anvndarfrening-fr-episerver-utvecklare/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/03/06/anvndarfrening-fr-episerver-utvecklare/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 10:44:57 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Användarförening]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[SIG]]></category>
		<category><![CDATA[User Group]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/03/06/anvndarfrening-fr-episerver-utvecklare/</guid>
		<description><![CDATA[EPiServer växer så det knakar och vi som utvecklar med produkten blir fler och fler. Jag tror tiden är mogen att dra igång ett fristående nätverk för EPiServer utvecklare!
Oavsett om man jobbar på ett litet eller stort företag finns det ett behov att dela erfarenheter och diskutera idéer kring webutveckling.
Med ett fristående forum kan vi [...]]]></description>
			<content:encoded><![CDATA[<p>EPiServer växer så det knakar och vi som utvecklar med produkten blir fler och fler. Jag tror tiden är mogen att dra igång ett fristående nätverk för EPiServer utvecklare!</p>
<p>Oavsett om man jobbar på ett litet eller stort företag finns det ett behov att dela erfarenheter och diskutera idéer kring webutveckling.</p>
<p>Med ett fristående forum kan vi som deltar själva sätta agendan. Är vi flera kan vi också påverka EPiServer.</p>
<h3>Komma igång</h3>
<p>Låt oss starta enkelt med att bara träffas efter jobbet. <a href="http://www.meetup.com/EPiServer-Stockholm/" target="_blank">Anmäl ditt intresse att vara med på Meetup.</a> När vi blivit några stycken bestämmer vi en tid och plats att träffas!</p>
<p>Skriv en kommentar nedan eller på <a href="http://www.meetup.com/EPiServer-Stockholm/" target="_blank">Meetup-sajten</a>  om du har förslag på ämnen att diskutera!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/03/06/anvndarfrening-fr-episerver-utvecklare/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Work with Unpublished PageData from code</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 18:01:20 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[AccessLevel]]></category>
		<category><![CDATA[DataFactory]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[GetChildren]]></category>
		<category><![CDATA[ILanguageSelector]]></category>
		<category><![CDATA[IsMasterLanguageBranch]]></category>
		<category><![CDATA[LanguageSelector]]></category>
		<category><![CDATA[PageVersion]]></category>
		<category><![CDATA[SaveAction]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[VersionStatus]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/</guid>
		<description><![CDATA[Mari Jørgensen wrote about Breaking change in GetChildren() and I would like to share some of my findings when working with PageData from code when you want to use the built-in flow for publishing.
As you might know a Page Version can have VersionStatus Not Ready (CheckedOut), Ready To Publish (CheckedOut), Published and Previously Published. Since [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://labs.episerver.com/en/Blogs/Mari-Jorgensen/">Mari Jørgensen</a> wrote about <a href="http://labs.episerver.com/en/Blogs/Mari-Jorgensen/Dates/2009/2/Breaking-change-in-GetChildren/">Breaking change in GetChildren()</a> and I would like to share some of my findings when working with <em>PageData</em> from code when you want to use the built-in flow for publishing.</p>
<p>As you might know a Page Version can have <em>VersionStatus</em> <strong>Not Ready </strong>(<em>CheckedOut</em>), <strong>Ready To Publish</strong> (<em>CheckedOut</em>), <strong>Published</strong> and <strong>Previously Published</strong>. Since you in almost all cases are only interested in the published version most methods in <em>DataFactory</em> class only returns <em>PageData</em> objects with the published version.</p>
<h3>Get unpublished pages and pages not in current language branch</h3>
<p><em>GetPage()</em> and <em>GetChildren()</em> returns page(s) published in the current language. You always have to use in a <em>ILanguageSelector</em> if you want to get <em>PageData</em> for another Language Branch than the current language branch.</p>
<pre class="csharpcode">PageDataCollection pages =
  DataFactory.Instance.GetChildren(
    CurrentPage.PageLink,  LanguageSelector.AutoDetect(<span class="kwrd">true</span>));</pre>
<p>This will retrieve all children the same way as the Page Tree in the Structure Tab in Edit Mode. If there is no published version in the <strong>Current Content Language</strong> it will return <em>PageData</em> for the Master Langauge Branch, regardless of Publish Status.</p>
<h3>Saving a page without publishing it</h3>
<p>It is easy to create a new page and not publish it. This can be used for moderation where an Editor uses the publish button in Edit mode to approve.</p>
<pre class="csharpcode">PageData page = DataFactory.Instance.GetDefaultPageData(
                  rootpage.PageLink, <span class="str">"My Page Type"</span>);
page.PageName = <span class="str">"New Page"</span>;
DataFactory.Instance.Save(page, SaveAction.CheckIn,
                          AccessLevel.NoAccess);</pre>
<p><em>SaveAction.CheckIn</em> will make you page Ready to Publish.</p>
<h3>Access Rights</h3>
<p>Even if the current your is not an Editor you may give them Edit access rights to their pages.  It is very easy to add access rights for the current user <span style="text-decoration: underline;">after</span> the page is saved. Note that all existing access right on the parent page will be inherited as usual.</p>
<pre class="csharpcode">PageAccessControlList acl = <span class="kwrd">new</span> PageAccessControlList(page.PageLink);
acl.Add(<span class="kwrd">new</span> AccessControlEntry(
          Membership.GetUser().UserName,
          AccessLevel.Read | AccessLevel.Edit | AccessLevel.Create | AccessLevel.Delete,
          SecurityEntityType.User));
acl.Save();</pre>
<p>It is also easy to filter a collection and remove pages you should not be able to change.</p>
<pre class="csharpcode"><span class="kwrd">new</span> FilterAccess(AccessLevel.Edit).Filter(pages);</pre>
<p>Another approach is to show the page but maybe disable the edit button.</p>
<pre class="csharpcode"><span class="kwrd">bool</span> canChange = page.QueryDistinctAccess(AccessLevel.Edit);</pre>
<h3>Page Versions and Unpublished Pages</h3>
<p>Property Values for the Published Version of a Page is stored in different tables in the database than all other versions of the page. You need something called <strong>WorkID</strong> in your <em>PageReference</em> to load other versions of a page than the published version.</p>
<p><strong>WARNING! Last time I checked <em>GetPage()</em> and <em>GetPages()</em> returned skeleton <em>PageData</em> objects, where all user defined properties are null, for unpublished pages if you did not have a <em>WorkID</em>.</strong></p>
<p>This is an example of how you have to use <em>PageVersion</em> class to retrieve a list of all versions of a page. Each <em>PageVersion</em> has a <em>PageReference</em> with both <em>PageID</em> and <em>WorkID</em>. </p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> PageData GetLastVersion(PageReference pageRef)
{
    PageVersionCollection pageVersions = PageVersion.List(pageRef);
    PageReference lastVersion = pageVersions[0].ID;
    <span class="kwrd">foreach</span> (PageVersion pageVersion <span class="kwrd">in</span> pageVersions)
    {
        <span class="kwrd">if</span> (pageVersion.IsMasterLanguageBranch)
        {
            lastVersion = pageVersion.ID;
        }
    }
    <span class="kwrd">return</span> DataFactory.Instance.GetPage(lastVersion,
             LanguageSelector.AutoDetect(<span class="kwrd">true</span>));
}</pre>
<p>When you have a <em>PageReference</em> with <em>WorkID</em> you can use it with <em>GetPage()</em> to retrieve other versions of a Page. Using and a <em>LanguageSelector</em> with fallback to Master Language is required to get around the filter.</p>
<h3>Update a page without creating a new version</h3>
<p>Sometimes you want to change a PageData object without creating a new version. In the example below UpdatePageFromForm copies values from text boxes to the page. If a value has changed it will be saved.</p>
<pre class="csharpcode">page = GetLastVersion(pageRef).CreateWritableClone();
UpdatePageFromForm(page);
<span class="kwrd">if</span> (page.IsModified)
{
    SaveAction saveAction = SaveAction.CheckIn;
    <span class="kwrd">if</span> (page.Status != VersionStatus.Published)
    {
        <span class="rem">// Update existing version if it is not published</span>
        saveAction = saveAction | SaveAction.ForceCurrentVersion;
    }
    DataFactory.Instance.Save(page, saveAction);
}</pre>
<p>That&#8217;s all for now folks!</p>
<p>Please, leave a comment if you learned something. It is good for my blogging morale to know that someone got helped&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>EPiServer SEO: Reduce Duplicate Content Links</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/02/15/episerver-seo-reduce-duplicate-content/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/02/15/episerver-seo-reduce-duplicate-content/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 19:12:35 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[ConvertedToExternal]]></category>
		<category><![CDATA[epslanguage]]></category>
		<category><![CDATA[FriendlyUrlRewriteProvider]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[UrlRewriteModule]]></category>
		<category><![CDATA[UrlRewriteProvider]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/02/15/episerver-seo-reduce-duplicate-content/</guid>
		<description><![CDATA[Google and other search engines does not like duplicate content. The reason is that the page&#8217;s reputation (or page rank) is calculated from incoming internal and external links. If you have more links leading to the same page the reputation will be split between the URLs.
One an EPiServer site with English as default language in [...]]]></description>
			<content:encoded><![CDATA[<p>Google and other search engines does not like duplicate content. The reason is that the page&#8217;s reputation (or page rank) is calculated from incoming internal and external links. If you have more links leading to the same page the reputation will be split between the URLs.</p>
<p>One an EPiServer site with English as default language in siteHosts-tag the start page can usually be reached by the following two URLs. (<a href="http://world.episerver.com/en/Documentation/Items/Tech-Notes/EPiServer-CMS-5/EPiServer-CMS-5-R2-SP1/Globalization/#Scenario%202%20-%20Local%20Domains%20Mapped%20to%20Languages" target="_blank">Read more about siteHosts, Globalization and how to set the default language for a domain</a>.)</p>
<ol>
<li><a href="http://www.mydomain.com/">www.mydomain.com/</a></li>
<li><a href="http://www.mydomain.com/en/">www.mydomain.com/<strong>en</strong>/</a></li>
</ol>
<p>EPiServer&#8217;s Friendly URL Rewriter adds &#8220;/en&#8221; to the beginning to select Language Branch if the internal URL contains the query parameter <em>epslanguage</em>.  So you can have a lot of both URLs on your site, both leading to the same page.</p>
<p>One recommended strategy to handle multiple URLs to the same page is to use 301 Redirection but that is a topic for another blog post (Ted Nyberg had a good post about this some time ago). In this post I want to show you how easy it is to tweak EPiServer&#8217;s Friendly URL Rewriting to eliminate duplicate URLs caused by language.</p>
<h3>Example of how to tweak EPiServer&#8217;s Friendly Url Rewriter</h3>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">class</span> Global : EPiServer.Global
{
    <span class="kwrd">protected</span> <span class="kwrd">void</span> Application_Start(Object sender, EventArgs e)
    {
        EPiServer.Web.UrlRewriteModule.HttpRewriteInit += UrlRewriteModule_HttpRewriteInit;
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// This adds the hooks to the UrlRewriter instance</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">private</span> <span class="kwrd">void</span> UrlRewriteModule_HttpRewriteInit(<span class="kwrd">object</span> sender, UrlRewriteEventArgs e)
    {
        UrlRewriteModuleBase module = sender <span class="kwrd">as</span> UrlRewriteModuleBase;
        <span class="kwrd">if</span> (module != <span class="kwrd">null</span>)
        {
            module.HtmlAddingRewriteToExternalFilter += module_HtmlAddingRewriteToExternalFilter;
            UrlRewriteProvider.ConvertedToExternal += UrlRewriteProvider_ConvertedToExternal;
        }
    }

<span class="rem">    /// &lt;summary&gt;</span> 

    <span class="rem">/// Remove language from path if it is the default for the hostname.</span>

    <span class="rem">/// &lt;/summary&gt;</span> 

    <span class="kwrd">private</span> <span class="kwrd">void</span> UrlRewriteProvider_ConvertedToExternal(<span class="kwrd">object</span> sender, UrlRewriteEventArgs e)
    {
        <span class="kwrd">if</span> (e.IsModified)
        {
            <span class="kwrd">string</span> lang = LanguageSelection.GetLanguageFromHost();
            <span class="kwrd">if</span> (e.Url.Path.StartsWith( <span class="str">'/'</span> + lang + <span class="str">'/'</span>))
            {
                e.Url.Path = e.Url.Path.Substring(lang.Length + 1);
            }
        }
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Prevent Rewrite To External for Trace.axd and </span>

<span class="rem">    /// other locations I do not want EPiServer to interfere with.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">private</span> <span class="kwrd">void</span> module_HtmlAddingRewriteToExternalFilter(<span class="kwrd">object</span> sender, UrlRewriteEventArgs e)
    {
        <span class="kwrd">string</span> path = e.Url.Path.ToLowerInvariant();
        e.Cancel = e.Cancel || path.EndsWith(<span class="str">"trace.axd"</span>) || path.StartsWith(<span class="str">"/MyWebApp"</span>)

<span class="rem"> </span>   }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/02/15/episerver-seo-reduce-duplicate-content/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>EPiServer Page Type usage report</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/02/09/episerver-page-type-usage-report/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/02/09/episerver-page-type-usage-report/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 05:15:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/02/09/episerver-page-type-usage-report/</guid>
		<description><![CDATA[Do you have a lot of page types in an EPiServer project and a gut feeling some of the are not used? 
Quite common if you migrate a project from EPiServer CMS 4 that are based on the EPiServerSample project or if you inherit a project based on one of the new Public or Demo [...]]]></description>
			<content:encoded><![CDATA[<p>Do you have a lot of page types in an EPiServer project and a gut feeling some of the are not used? </p>
<p>Quite common if you migrate a project from EPiServer CMS 4 that are based on the <em>EPiServerSample</em> project or if you inherit a project based on one of the new Public or Demo templates.</p>
<h3>SQL Query for Page Type usage</h3>
<pre class="csharpcode"><span class="kwrd">SELECT</span>
  pt.Name,
  pt.Filename,
  <span class="kwrd">COUNT</span>(p.pkID) <span class="kwrd">AS</span> Antal
<span class="kwrd">FROM</span>
  tblPage <span class="kwrd">AS</span> p <span class="kwrd">RIGHT</span> <span class="kwrd">OUTER</span> <span class="kwrd">JOIN</span>
  tblPageType <span class="kwrd">AS</span> pt <span class="kwrd">ON</span> p.fkPageTypeID = pt.pkID
<span class="kwrd">GROUP</span> <span class="kwrd">BY</span>
  pt.Name, pt.Filename, pt.SortOrder
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span>
  pt.SortOrder</pre>
<p>Before you run this query, remember to empty your recycle bin and also check that your <em>pageRootId</em> in <em>web.config</em>. If it is not equal to one there can be a lot of hidden pages in your database.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/02/09/episerver-page-type-usage-report/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to patch/fix/hack someone else&#8217;s assembly</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/02/06/how-to-patchfixhack-someone-elses-assembly/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/02/06/how-to-patchfixhack-someone-elses-assembly/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 08:00:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[AssemblyDelaySign]]></category>
		<category><![CDATA[AssemblyKeyFile]]></category>
		<category><![CDATA[sn.exe]]></category>
		<category><![CDATA[Strong Name Tool]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/02/06/how-to-patchfixhack-someone-elses-assembly/</guid>
		<description><![CDATA[Here is my recipe when I can see no workaround to a defect or other problem and want to get around it. This is not for the faint hearted and I do not recommend it for production!
1. Extract source code and patch code
You need to use Roaders&#8217; Reflector to export the assembly. Right-click on top [...]]]></description>
			<content:encoded><![CDATA[<p>Here is my recipe when I can see no workaround to a defect or other problem and want to get around it. This is not for the faint hearted and I do not recommend it for production!</p>
<h3>1. Extract source code and patch code</h3>
<p>You need to use <a href="http://www.red-gate.com/products/reflector/" target="_blank">Roaders&#8217; Reflector</a> to export the assembly. Right-click on top node and select Export&#8230;</p>
<p>Then comment out offending lines, add your logging, or patch defects.</p>
<h3>2. Recompile strong-named assembly with only the public-key</h3>
<p>Extract the public key from the existing assembly with the <a href="http://msdn.microsoft.com/en-us/library/k5b5tt23.aspx" target="_blank">Strong Name Tool</a>:</p>
<pre>sn -e C:xxxbinStarCommunity.Core.dll C:tempNetstar.snk</pre>
<p>Since we do not have the private key we must compile with delayed signing. Change the exported <em>AssemblyInfo.cs</em>:</p>
<pre class="csharpcode">[assembly: System.Reflection.AssemblyDelaySign(<span class="kwrd">true</span>)]
[assembly: System.Reflection.AssemblyKeyFile(<span class="str">@&quot;Netstar.snk&quot;</span>)]</pre>
<p>Build project and replace the assembly in the web applications bin-folder.</p>
<h3>3. Get the assembly to load without signing </h3>
<p>Disable Strong Name verification so the dot net framework accepts the patched assembly without signing. Use the Strong Name tool and tell it to skip verification on all assemblies with the public key you exported above. </p>
<pre>sn -Vr *,0bd7a6276e8c109e</pre>
<p>NOTE: The hex code above is from the public-key used by NetStar but you must change it to match the public key in your assembly. The change is global on the machine.</p>
</p>
<h3>4. Restart and test</h3>
<p>Policy changes requires a restarts so do a <em>IISReset</em> to get the patched assembly to load.</p>
<p>Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/02/06/how-to-patchfixhack-someone-elses-assembly/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>EPiServer log: More configuration tips</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/02/03/episerver-log-more-configuration-tips/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/02/03/episerver-log-more-configuration-tips/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 16:53:48 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[log4net]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/02/03/episerver-log-more-configuration-tips/</guid>
		<description><![CDATA[Nicklas Israelsson shared in his blog how you can exclude some name spaces from the EPiServer log to reduce the noise while debugging. A very useful tip! I would like to share how I use logging to collect exceptions (and debug info) in production.
How to setup production logging of Exceptions in EPiServer 
Paste the example [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://world.episerver.com/en/Blogs/Nicklas-Israelsson/">Nicklas Israelsson</a> shared in his blog <a href="http://world.episerver.com/en/Blogs/Nicklas-Israelsson/Dates/2009/2/EPiServer-log-Excluding-rows-from-selected-namespaces/">how you can exclude some name spaces from the EPiServer log to reduce the noise while debugging.</a> A very useful tip! I would like to share how I use logging to collect exceptions (and debug info) in production.</p>
<h3>How to setup production logging of Exceptions in EPiServer </h3>
<p>Paste the example below into the <em>EPiServerLog.config</em> file in the root of your EPiServer application. </p>
<pre class="csharpcode"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">=&quot;1.0&quot;</span> <span class="attr">encoding</span><span class="kwrd">=&quot;utf-8&quot;</span>?<span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">log4net</span><span class="kwrd">&gt;</span>

  <span class="rem">&lt;!-- Appender with one new log file per day --&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">appender</span> <span class="attr">name</span><span class="kwrd">=&quot;fileLogAppender&quot;</span>
            <span class="attr">type</span><span class="kwrd">=&quot;log4net.Appender.RollingFileAppender&quot;</span> <span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">file</span> <span class="attr">value</span><span class="kwrd">=&quot;E:\EPiServerLog\www.example.com&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">encoding</span> <span class="attr">value</span><span class="kwrd">=&quot;utf-8&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">lockingModel</span> <span class="attr">type</span><span class="kwrd">=&quot;log4net.Appender.FileAppender+MinimalLock&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">appendToFile</span> <span class="attr">value</span><span class="kwrd">=&quot;true&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">rollingStyle</span> <span class="attr">value</span><span class="kwrd">=&quot;Date&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">staticLogFileName</span> <span class="attr">value</span><span class="kwrd">=&quot;false&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">datePattern</span> <span class="attr">value</span><span class="kwrd">=&quot;.yyyyMMdd.'log'&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">layout</span> <span class="attr">type</span><span class="kwrd">=&quot;log4net.Layout.PatternLayout&quot;</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">conversionPattern</span> <span class="attr">value</span><span class="kwrd">=&quot;%date %level [%thread] %type.%method - %message%n&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">layout</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">appender</span><span class="kwrd">&gt;</span>

  <span class="rem">&lt;!-- Log page publish to find editor related errors. --&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">logger</span> <span class="attr">name</span><span class="kwrd">=&quot;EPiServer.DataAccess.PageSaveDB&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">level</span> <span class="attr">value</span><span class="kwrd">=&quot;DEBUG&quot;</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">logger</span><span class="kwrd">&gt;</span>

  <span class="rem">&lt;!-- Removing all rows coming from OptimisticCache --&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">logger</span> <span class="attr">name</span><span class="kwrd">=&quot;EPiServer.Core.OptimisticCache&quot;</span> <span class="attr">additivity</span><span class="kwrd">=&quot;false&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">level</span> <span class="attr">value</span><span class="kwrd">=&quot;Off&quot;</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">appender-ref</span> <span class="attr">ref</span><span class="kwrd">=&quot;fileLogAppender&quot;</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">logger</span><span class="kwrd">&gt;</span>  

  <span class="rem">&lt;!-- Send all errors to file. Level: Off, Fatal, Error, Warn, Info, Debug, All --&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">root</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">level</span> <span class="attr">value</span><span class="kwrd">=&quot;Error&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">appender-ref</span> <span class="attr">ref</span><span class="kwrd">=&quot;fileLogAppender&quot;</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">root</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">log4net</span><span class="kwrd">&gt;</span></pre>
<p>TODO: You need to adjust the file-tag (<em>&quot;E:\EPiServerLog\&quot;</em>) to an existing folder where the account used by your asp.net application are allowed to write. Also notice that backslash must be escaped.</p>
<h4>lockingModel</h4>
<p>Notice that this differs from what is shipped in the default <em>EPiServerLog.config</em> file (that does not work <a href="http://en.wikipedia.org/wiki/AFAIK" target="_blank">AFAIK</a>).</p>
<h4>file, rollingStyle, staticLogFileName, datePattern</h4>
<p>These tags configures one file per day in the folder specified by the file-tag. I prefer to set <em>staticLogFileName</em> to false even if true might get some better performance.</p>
<h4>level</h4>
<p>Change level from <em>Error</em> to <em>Debug</em> or <em>All</em> if you need more data when you debug. Do remember to change it back to Error when you are done because your files grow fast and using reflection to find type and method steals some CPU-time, too.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/02/03/episerver-log-more-configuration-tips/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>EPiServer Error Handling (broken in R2 &amp; IIS7)</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/01/20/episerver-error-handling-broken-in-r2/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/01/20/episerver-error-handling-broken-in-r2/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 06:03:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/01/20/episerver-error-handling-broken-in-r2/</guid>
		<description><![CDATA[As you might have noticed EPiServer has its own Error Handling that has the following features.

It shows a localized error message. 
It can hide the Exception details and stack trace – if you do not have the permission needed 
It can send an email with a message from the user and also include the exception [...]]]></description>
			<content:encoded><![CDATA[<p>As you might have noticed EPiServer has its own Error Handling that has the following features.</p>
<ul>
<li>It shows a localized error message. </li>
<li>It can hide the Exception details and stack trace – if you do not have the permission needed </li>
<li>It can send an email with a message from the user and also include the exception details and call stack in the mail </li>
</ul>
<h3>GlobalErrorHandling setting works like customErrors mode</h3>
<p>You control EPiServer Error Handling with three settings in web.config.</p>
<table cellspacing="0" cellpadding="2" width="495" border="1">
<tbody>
<tr>
<td valign="top" colspan="2"><em>GlobalErrorHandling</em></td>
</tr>
<tr>
<td valign="top" width="129"><em>Off</em> </td>
<td valign="top" width="364">Let ASP.NET handle the error as specified by &lt;customErrors mode=&quot;&quot;&gt;</td>
</tr>
<tr>
<td valign="top" width="129"><em>RemoteOnly</em> </td>
<td valign="top" width="364">Show EPiServer Error handler for remote access but use ASP.NET default behavior for local calls. Combine this setting with &lt;customErrors mode=&quot;RemoteOnly&quot;&gt;</td>
</tr>
<tr>
<td valign="top" width="129"><em>On</em> </td>
<td valign="top" width="364">Always show</td>
</tr>
</tbody>
</table>
<p>Make sure <em>&lt;system.net&gt;&lt;mailSettings&gt;</em> is setup for sending mail and then just set <em>globalErrorMail </em>to an email address and EPiServer will start sending nice error reports to you. </p>
<p>Optionally set <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://EPiServer.Configuration:5.2.375.7:8fe83dea738b45b7/EPiServer.Configuration.Settings/property:ErrorMailHandler:String"><em>ErrorMailHandler</em></a> if you want to replace the default sending of the mail in <em>&quot;~/Util/SendErrorReport.aspx&quot;.</em> This can be useful if you want to add extra processing to prevent noise (many message for same error) or log to a database instead.</p>
<h3>NOTE: GlobalErrorHandling in EPiServer CMS 5 R2 (No SP)</h3>
<p>The behavior of <em>GlobalErrorHandling</em> setting is broken in EPiServer CMS 5 R2 because some refactoring to optimize the code accidently inverted it. </p>
<p><strong>Workaround:</strong> Set it to <em>Off</em> in R2! (Will be fixed in R2 SP1)</p>
<h3>IIS7 and Error Handling – new property TrySkipIisCustomErrors</h3>
<p>As you might have noticed custom error handling works differently in IIS7. There is a new tag <a href="http://msdn.microsoft.com/en-us/library/ms690497.aspx" target="_blank">system.webserver/httpErrors</a><em></em> in your applicationHost.config or web.config.</p>
<p>ASP.NET hands over control to IIS if the status code is over 400 and both the standard APS.NET yellow screen of death or a custom error page you generated in code can be replaced later in the pipeline with IIS7 custom errors.</p>
<p>The new property <em><a href="http://msdn.microsoft.com/en-us/library/system.web.httpresponse.tryskipiiscustomerrors.aspx" target="_blank">Response.TrySkipIisCustomErrors</a></em> must be set to true if you want your content to be shown after you change <em><a href="http://msdn.microsoft.com/en-us/library/system.web.httpresponse.statuscode.aspx" target="_blank">Response.StatusCode</a></em>. ASP.NET does this for its yellow screen of death in compatibility mode. You also need the <em><a href="http://msdn.microsoft.com/en-us/library/ms690497.aspx" target="_blank">existingResponse</a></em>-attribute to be set to <em>auto</em>.</p>
<p><strong>Workaround:</strong> Set <em><a href="http://msdn.microsoft.com/en-us/library/ms690497.aspx" target="_blank">existingResponse</a></em>-attribute to <em>PassThrough</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/01/20/episerver-error-handling-broken-in-r2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Search in EPiServer can generate invalid html</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/01/16/search-in-episerver-can-generate-invalid-html/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/01/16/search-in-episerver-can-generate-invalid-html/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 17:05:10 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/01/16/search-in-episerver-can-generate-invalid-html/</guid>
		<description><![CDATA[I found two defects in the public templates for searching that makes it possible that the search result contains invalid html. Since a lot of people copied this code to their own sites I think is worth mentioning.
EPiServer.Core.Html.TextIndexer.StripHtml()
This method returns text with html tags removed. An optimization defect was introduced in R2. 
If maxTextLengthToReturn parameter [...]]]></description>
			<content:encoded><![CDATA[<p>I found two defects in the public templates for searching that makes it possible that the search result contains invalid html. Since a lot of people copied this code to their own sites I think is worth mentioning.</p>
<h3>EPiServer.Core.Html.TextIndexer.StripHtml()</h3>
<p>This method returns text with html tags removed. An optimization defect was introduced in R2. </p>
<p>If <em>maxTextLengthToReturn</em> parameter is greater than zero you risk that it cuts the raw text in the middle of a html-tag and then the regular expression that removes html-tags will fail. </p>
<p>You can end up with half a tag in the end of the string. </p>
<p>Exampel: &quot;ipsum dolor <strong>&lt;p al</strong>&quot; </p>
<h3>Search.aspx &#8211; HtmlEncode missing</h3>
<p>In <em>Search.aspx </em>from the public templates a call is made to a local method to view a short snippet of text for each page in the search result. </p>
<p>Since this preview text can contain reserved characters like &quot;&lt;&quot; or &quot;&amp;&quot; (even if the defect above is fixed) you should always call HtmlEncoded like this: </p>
<pre class="csharpcode"><span class="asp">&lt;%</span># HttpUtility.HtmlEncode(GetPreviewText(Container.DataItem)) <span class="asp">%&gt;</span></pre>
<p>Read more about <a href="http://blog.fredrikhaglund.se/blog/2008/12/08/epipattern-how-to-render-valid-xhtml-part-12/" target="_blank">pitfalls that can cause invalid html in EPiServer</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/01/16/search-in-episerver-can-generate-invalid-html/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharing My Updated Toolbox with you</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/01/13/sharing-my-updated-toolbox-with-you/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/01/13/sharing-my-updated-toolbox-with-you/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 14:47:38 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Add new tag]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=189</guid>
		<description><![CDATA[I have updated My Toolbox page with some more usefull productivity enhacning tools. A few highlights from the list:
Pixel Perfect
A Firebug extension that allows you to easily overlay a web composition (an image) on top of the developed HTML to see if you CSS is correct &#8211; Thanks for the top René!
Asterisk Key
Forgot a password? But [...]]]></description>
			<content:encoded><![CDATA[<p>I have updated <a href="http://blog.fredrikhaglund.se/toolbox/">My Toolbox page with some more usefull productivity enhacning tools</a>. A few highlights from the list:</p>
<h3><a onclick="pageTracker._trackPageview('/outbound/article/https://addons.mozilla.org/firefox/addon/7943');" href="https://addons.mozilla.org/firefox/addon/7943" target="_blank">Pixel Perfect</a></h3>
<p>A Firebug extension that allows you to easily overlay a web composition (an image) on top of the developed HTML to see if you CSS is correct &#8211; Thanks for the top René!</p>
<h3><a onclick="pageTracker._trackPageview('/outbound/article/http://www.lostpassword.com/free.htm');" href="http://www.lostpassword.com/free.htm" target="_blank">Asterisk Key</a></h3>
<p><img class="size-full wp-image-190 alignleft" title="Woodwork" src="http://blog.fredrikhaglund.se/wp-content/uploads/2009/01/snickrar_200x190.png" alt="" width="200" height="190" />Forgot a password? But it is there &#8211; hidden under asterisk in the password box. This tool extract the secrets for you!</p>
<p>Using the right tools makes you productive but there is so much tools and utilities out there so I like to spy on other people to see what tools they use so I also can try them.</p>
<p>Please share, if you have a tool that makes your life easier!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/01/13/sharing-my-updated-toolbox-with-you/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EPiPattern: How to render valid xhtml (part 1/2)</title>
		<link>http://blog.fredrikhaglund.se/blog/2008/12/08/epipattern-how-to-render-valid-xhtml-part-12/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2008/12/08/epipattern-how-to-render-valid-xhtml-part-12/#comments</comments>
		<pubDate>Mon, 08 Dec 2008 12:39:50 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[EPiPattern]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[HtmlEncode]]></category>
		<category><![CDATA[script injection]]></category>
		<category><![CDATA[ToWebString]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=182</guid>
		<description><![CDATA[How do you inject dynamic content into your web page? Following is a list of the most common methods I find when doing quality and code reviews with some comments and dangerous pitfalls.
#1: Inline Expressions with Code Render Blocks
Using inline expressions is a shortcut for calling the Write method.
Example &#8211; DONT:
&#60;h2&#62;&#60;%= CurrentPage.PageName %&#62;&#60;/h2&#62;
&#60;img src="&#60;%= CurrentPage["ImageUrl"] [...]]]></description>
			<content:encoded><![CDATA[<p>How do you inject dynamic content into your web page? Following is a list of the most common methods I find when doing quality and code reviews with some comments and dangerous pitfalls.</p>
<h3>#1: Inline Expressions with Code Render Blocks</h3>
<p>Using <a href="http://msdn.microsoft.com/en-us/library/k6xeyd4z.aspx" target="_blank">inline expressions</a> is a shortcut for calling the <a href="http://msdn.microsoft.com/en-us/library/system.web.httpresponse.write.aspx">Write</a> method.</p>
<h4>Example &#8211; DONT:</h4>
<pre class="csharpcode">&lt;h2&gt;&lt;%= CurrentPage.PageName %&gt;&lt;/h2&gt;
&lt;img src=<span class="str">"&lt;%= CurrentPage["</span>ImageUrl<span class="str">"] %&gt;"</span> alt=<span class="str">"&lt;%= CurrentPage["</span>MainIntro<span class="str">"] %&gt;"</span> /&gt;
&lt;div <span class="kwrd">class</span>=<span class="str">"mainarea"</span>&gt;

     &lt;%= CurrentPage[<span class="str">"MainBody"</span>] %&gt;
&lt;/div&gt;</pre>
<p>Since xhtml is just text, writing some more in-between existing static blocks is fast and simple. Probably the easiest way to inject dynamic content but it is also dangerous!</p>
<h4>Example – DO always use HtmlEncode:</h4>
<pre class="csharpcode">&lt;h2&gt;&lt;%= HttpUtility.HtmlEncode(CurrentPage.PageName) %&gt;&lt;/h2&gt;</pre>
<p>What happens if our PageName property contains a &#8220;&lt;&#8221; or &#8220;&amp;&#8221; character in the example above? Your page will not validate and you risk that it breaks down. It can also be exposed to <a title="How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings" href="http://msdn.microsoft.com/en-us/library/a2a4yykt.aspx" target="_blank">script injection</a> if the content is user generated.</p>
<p>To be on the safe side you should always call <em><a href="http://msdn.microsoft.com/en-us/library/73z22y6h.aspx" target="_blank">HttpUtility.HtmlEncode</a></em> on all strings that you inject with inline expressions.</p>
<h4>Example – DO always use a fallback for src-attributes</h4>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">img</span> <span class="attr">src</span><span class="kwrd">="&lt;%= CurrentPage["</span><span class="attr">ImageUrl</span><span class="kwrd">"] ?? "</span>/<span class="attr">Missing</span>.<span class="attr">png</span><span class="kwrd">" %&gt;"</span> <span class="kwrd">/&gt;</span></pre>
<p>If your ImageUrl property is empty you would get a img-tag with an empty src-attribute. This can lead to the page being rendered twice. <a title="How Firefox Handles Empty SRC tags" href="http://geekswithblogs.net/bcaraway/archive/2007/08/24/114945.aspx" target="_blank">FireFox interpret a null src-attribute a relative url and evaluate it using the page url as base returning the same url</a>.</p>
<h3>#2: With EPiServer:Property web control</h3>
<p>Using the EPiServer Property Web Controls instead of inline expressions has several benefits. It could be used for rendering the PageName and MainBody in the example above.</p>
<h4>Example – DO use EPiServer:Property web control</h4>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">h2</span><span class="kwrd">&gt;&lt;</span><span class="html">EPiServer:Property</span> <span class="attr">PropertyName</span><span class="kwrd">="PageName"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">/&gt;&lt;/</span><span class="html">h2</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">EPiServer:Property</span> <span class="attr">CssClass</span><span class="kwrd">="mainarea"</span> <span class="attr">PropertyName</span><span class="kwrd">="MainBody"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">/&gt;</span></pre>
<p>1) When rendering EPiServer&#8217;s <em>ToWebString()</em> is used. This does almost the same job as always calling <em>HtmlEncode</em> yourself.</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> CreateDefaultControls()
{
    Label target = <span class="kwrd">new</span> Label();
    target.Text = PropertyData.ToWebString();
    CopyWebAttributes(target);
    Controls.Add(target);
}</pre>
<p>2) It enables the Simple Edit feature for the editors without any extra work. (If you do not know what &#8220;Simple Edit&#8221; is, you should read the <a title="EPiServer Documentation" href="http://world.episerver.com/en/Documentation/Categories/Documentation-Type/Manuals/" target="_blank">Editors Manual for EPiServer</a> before doing any more development.)</p>
<p>3) Different types have get different rendering automatically. Commonly used for <em>PageReferences</em> and Url&#8217;s that are rendered as a Hyperlink.</p>
<h4>Example – DO use EPiServer:Property for rendering links if possible</h4>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">EPiServer:PageList</span> <span class="attr">PageLinkProperty</span><span class="kwrd">="NewsArchivePage"</span> <span class="attr">MaxCount</span><span class="kwrd">="5"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">HeaderTemplate</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">h3</span><span class="kwrd">&gt;&lt;</span><span class="html">EPiServer:Property</span> <span class="attr">PropertyName</span><span class="kwrd">="PageLink"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">/&gt;&lt;/</span><span class="html">h3</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">ul</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">HeaderTemplate</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">ItemTemplate</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">li</span><span class="kwrd">&gt;&lt;</span><span class="html">EPiServer:Property</span> <span class="attr">PropertyName</span><span class="kwrd">="PageLink"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">/&gt;&lt;/</span><span class="html">li</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">ItemTemplate</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">FooterTemplate</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">ul</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">FooterTemplate</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">EPiServer:PageList</span><span class="kwrd">&gt;</span></pre>
<p>4) Use <em>PageLinkProperty</em> to follow a Page-property to another page and render a value. Takes care of all hassle and calls <em>GetPage()</em> and check for nulls for you.</p>
<h4>Example – DO use EPiServer:Property to render values from another page</h4>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">h3</span><span class="kwrd">&gt;&lt;</span><span class="html">EPiServer:Property</span> <span class="attr">PageLinkProperty</span><span class="kwrd">="FeatureArticlePage"</span> <span class="attr">PropertyName</span><span class="kwrd">="PageLink"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">/&gt;&lt;/</span><span class="html">h3</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">div</span><span class="kwrd">&gt;&lt;</span><span class="html">EPiServer:Property</span> <span class="attr">PageLinkProperty</span><span class="kwrd">="FeatureArticlePage"</span> <span class="attr">PropertyName</span><span class="kwrd">="MainIntro"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="kwrd">/&gt;&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2008/12/08/epipattern-how-to-render-valid-xhtml-part-12/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>How to become a EPiServer Ceritified Developer</title>
		<link>http://blog.fredrikhaglund.se/blog/2008/11/30/how-to-become-a-episerver-ceritified-developer/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2008/11/30/how-to-become-a-episerver-ceritified-developer/#comments</comments>
		<pubDate>Sun, 30 Nov 2008 11:30:19 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Certification]]></category>
		<category><![CDATA[EPiServer CMS]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=178</guid>
		<description><![CDATA[I would like to congratulate Mikael Lundin to becoming a Certified EPiServer Developer. He writes about this experience in his blog with some tips about what you should study. I would like to complement what he has written with some of the tips I give to my students who are going to take the certification.
About [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" src="/wp-content/uploads/2008/12/certificate.gif" alt="" width="48" height="48" />I would like to congratulate <a title="Mikael Lundin about EPiServer Certification" href="http://mint.litemedia.se/2008/11/29/episerver-cms-5-certified-developer/" target="_blank">Mikael Lundin to becoming a Certified EPiServer Developer</a>. He writes about this experience in his blog with some tips about what you should study. I would like to complement what he has written with some of the tips I give to my students who are going to take the certification.</p>
<h3>About the EPiServer Certification</h3>
<p>You have two hours to complete around 70 multiple choice questions. You can skip a question during exam and go back to it later but you can not change answered questions.  To pass, you need answer correct on 60% of the questions.</p>
<h3>My tips for passing the test</h3>
<p>Preparing yourself is a must because the the goal of the test is to separate those who have worked with EPiServer from those who have not. But working with EPiServer is not enough, you must also have a good understanding of all features availible in EPiServer, even those you have not used&#8230;</p>
<ul>
<li>Do develop with EPiServer for a while before you take the test. I do not think many have passed the certification directly after <a title="Read more about EPiServer Training" href="http://www.episerver.com/en/Start_page/Education/" target="_blank">competing the basic developer training</a>.</li>
<li>Do check <a title="More about EPiServer Certification" href="http://www.episerver.com/en/Start_page/Education/EPiServer-Certified--Developer/" target="_blank">EPiServer&#8217;s list of Knowledge Areas</a> you are going to be tested on.</li>
<li>Do read the <a title="EPiServer Documentation" href="http://world.episerver.com/en/Documentation/" target="_blank">Editors and Administrators manual</a>. As a developer you are supposed to know how to use the product from an end users perspective.</li>
<li>EPiServer Developers knows to little about Deployment in general. Make sure that you undrestand how to configure EPiServer. Do you know how Mirroring works or Enterprise features like multi-homed sites and load balancing is configured?</li>
<li>Do read all the <a title="EPiServer Tech Notes" href="http://world.episerver.com/en/Documentation/Categories/Documentation-Type/Tech-notes/" target="_blank">Tech Notes for the latest EPiServer CMS</a> release. You need to have a basic understanding about all features in EPiServer.</li>
<li>Do read through the pages in the <em>Developers Guide</em> part of <a title="EPiServer CMS Online SDK" href="http://sdk.episerver.com/library/cms5/" target="_blank">EPiServer SDK</a>, too. Personally I do not understand why they put some pages in the SDK and some as Tech Notes. It is high and low in both places and you must at least browse through it all&#8230;</li>
<li>Do not try to read through the whole Framework Reference. You could look on a few key classes like: PageBase, UserControlBase, TemplatePage, IPageSource, PageData, PageReference, DataFactory, PropertyData and PropertyDataControl. And also make sure you know your EPiServer Web Controls.</li>
</ul>
<p>Many questions is on a very detailed level and I must say that I have heard a lot of complints that the test is too hard. You have to make qualified guesses. I had to do a lot of qualified guessing myself , and I&#8217;m an EPiServer teacher and have turned EPiServer inside out with Roeders Reflector!</p>
<p>Remeber, you do not have to get 100% to pass and if you follow the tips above I&#8217;m sure you too will be a Certified EPiServer Developer&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2008/11/30/how-to-become-a-episerver-ceritified-developer/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>EPiServer Developers Wanted!</title>
		<link>http://blog.fredrikhaglund.se/blog/2008/11/28/episerver-developers-wanted/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2008/11/28/episerver-developers-wanted/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 17:26:30 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[R2]]></category>
		<category><![CDATA[WebParts]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=177</guid>
		<description><![CDATA[We need more help. There has been a lot of things to do lately so I have not been able to blog as much as I want to but after release I have a lot of things to share with you all.
Problems with WebParts in EPiServer CMS R2?
Disappearing WebParts after upgrading a project to R2 is one [...]]]></description>
			<content:encoded><![CDATA[<p>We need more help. There has been a lot of things to do lately so I have not been able to blog as much as I want to but after release I have a lot of things to share with you all.</p>
<h3>Problems with WebParts in EPiServer CMS R2?</h3>
<p>Disappearing WebParts after upgrading a project to R2 is one of the fun things I have solved. It is related to serialization and reducing the number of assemblies by moving classes. I have a workaround if you need &#8211; just drop me a line&#8230;</p>
<h3>EPiServer Developer position open at INEXOR AB</h3>
<p><a title="DN Jobb - Drivna och erfarna EPiServer utvecklare sökes!" href="http://www.dn.se/DNet/jsp/polopoly.jsp?d=3127&amp;sa_id=329175988" target="_blank">My employer is looking for more EPiServer Developers to hire</a>. Even if the job ad is in Swedish, the working language is English so let us know if you are looking for a new job.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2008/11/28/episerver-developers-wanted/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>#2: Hidden Gems of EPiServer CMS R2</title>
		<link>http://blog.fredrikhaglund.se/blog/2008/09/26/2-hidden-gems-of-episerver-cms-r2/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2008/09/26/2-hidden-gems-of-episerver-cms-r2/#comments</comments>
		<pubDate>Fri, 26 Sep 2008 04:58:13 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/?p=176</guid>
		<description><![CDATA[Friendly URL Rewrite works with AJAX UpdatePanel
Finally! The new UpdatePanelPostBackRewritePipe class will take care of rewrite of all URL&#8217;s in an UpdatePanel. No need for manual conversion of links or dirty workarounds when using AJAX.
New &#8211; PropertyLinkCollection

Built in support for link collections that makes it possible to build lists without using pages or a custom [...]]]></description>
			<content:encoded><![CDATA[<h3>Friendly URL Rewrite works with AJAX UpdatePanel</h3>
<p>Finally! The new <em>UpdatePanelPostBackRewritePipe</em> class will take care of rewrite of all <a href="http://blog.fredrikhaglund.se/wp-admin/s">URL&#8217;s</a> in an UpdatePanel. No need for manual conversion of links or dirty workarounds when using AJAX.</p>
<h3>New &#8211; PropertyLinkCollection</h3>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2008/09/image3.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://blog.fredrikhaglund.se/wp-content/uploads/2008/09/image-thumb1.png" border="0" alt="image" width="244" height="107" align="right" /></a></p>
<p>Built in support for link collections that makes it possible to build lists without using pages or a custom component.</p>
<p>The data is stored as a xhtml string where each link is an a-tag. You you display it with EPiServer Property Control it is rendered as a ul/li-list.</p>
<h3>PageData</h3>
<p>It is now possible to call <strong><em>GetPageLanguage()</em></strong> on a page to get other language version. Only a shortcut to the data factory but very convenient. You can also get a list of <strong><em>PageLanguages.</em></strong></p>
<p>The <strong>PageGuid</strong> is exposed as a new property on a the page.</p>
<p><strong><em>SearchDataSource</em></strong> will always call <strong><em>CreateWriteableClone()</em></strong> on a page because it adds properties like <em>PageRank</em>. Since you can not <a href="http://blog.fredrikhaglund.se/blog/2008/05/28/access-dynamic-property/">access Dynamic Properties on a cloned page without workaround</a> there is a new method <strong><em>PopulateDynamicProperties()</em></strong> on the page that adds them locally.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2008/09/26/2-hidden-gems-of-episerver-cms-r2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>#1: Hidden Gems of EPiServer CMS R2</title>
		<link>http://blog.fredrikhaglund.se/blog/2008/09/25/1-hidden-gems-of-episerver-cms-r2/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2008/09/25/1-hidden-gems-of-episerver-cms-r2/#comments</comments>
		<pubDate>Thu, 25 Sep 2008 08:12:43 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2008/09/25/1-hidden-gems-of-episerver-cms-r2/</guid>
		<description><![CDATA[The next release of EPiServer called R2 is not far away. Roger Wirz have written more about the major features in the R2 release at EPiServer World.
I would like to share some of the smaller improvements I have found during my work with the upcoming release. Everything looks very promising!
EPiServer GUI deleted 
In previous release [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 0px 0px 10px 10px; border-right-width: 0px" height="148" alt="Gemstones" src="http://blog.fredrikhaglund.se/wp-content/uploads/2008/09/image1.png" width="145" align="right" border="0" />The next release of EPiServer called R2 is not far away. <a href="http://world.episerver.com/en/Articles/Items/EPiServer-CMS-R2---Features/">Roger Wirz have written more about the major features in the R2 release at EPiServer World</a>.</p>
<p>I would like to share some of the smaller improvements I have found during my work with the upcoming release. Everything looks very promising!</p>
<h3>EPiServer GUI deleted </h3>
<p>In previous release EPiServer filled the web folder with files needed for EPiServer&#8217;s own user interface. We had hundreds of files in UI, Util, App_Themes/Default and WebServices that we needed to take care. </p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="476" alt="image" src="http://blog.fredrikhaglund.se/wp-content/uploads/2008/09/image2.png" width="431" border="0" /> </p>
<p>EPiServer CMS R2 uses the Virtual Path Provider to mount a a virtual file system for these folders instead. This simplifies version control and deployment!</p>
<p> <code>&lt;virtualPath&gt;    <br />&#160; &lt;providers&gt;     <br />&#160;&#160;&#160; &lt;add name=&quot;Util&quot;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; virtualPath=&quot;~/Util&quot;     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; physicalPath=&quot;C:\Program\EPiCMS\5.2.80...\Util&quot;    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; type=&quot;...VirtualPathNonUnifiedProvider...&quot; /&gt;    </p>
<p> </code>
<p>This new way to map a folder into your web application is provided by the new class <em>VirtualPathNonUnifiedProvider</em><strong>.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2008/09/25/1-hidden-gems-of-episerver-cms-r2/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
