<?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>hamang.net &#187; .NET</title>
	<atom:link href="http://hamang.net/category/net/feed/" rel="self" type="application/rss+xml" />
	<link>http://hamang.net</link>
	<description>- the everyday life</description>
	<lastBuildDate>Tue, 15 Feb 2011 10:05:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Configuration Handling Reloaded</title>
		<link>http://hamang.net/2011/02/15/configuration-handling-reloaded/</link>
		<comments>http://hamang.net/2011/02/15/configuration-handling-reloaded/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 07:54:19 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=241</guid>
		<description><![CDATA[Configuration handling of web projects is a well discussed topic. There are lots of examples on how to configure web.config for different environments; using configSections, naming conventions, T4 transformations, web deployment projects etc. Until now, this have been quite painful. Visual Studio 2010, however, has a new feature which opens up a lot of new [...]]]></description>
			<content:encoded><![CDATA[<p>Configuration handling of web projects is a well discussed topic. There are lots of examples on how to configure web.config for different environments; using configSections, naming conventions, T4 transformations, web deployment projects etc.</p>
<p>Until now, this have been quite painful. Visual Studio 2010, however, has a new feature which opens up a lot of new possibilities; Config Transformations. This is a very cool feature and triggers when you publish your web application within Visual Studio.</p>
<p>Here is an example on how to handle advanced configurations and make them available locally too for testing and debugging purposes.</p>
<p><strong>The challenge:</strong></p>
<ul>
<li>I want different config files for different environments.</li>
<li>I want to test different configurations locally and be able to debug them on my machine with a simple change. This means I must be able to compile my web.config file dynamically when building</li>
<li>I want my own settings which does not affect the configurations for my teammates. </li>
</ul>
<p><strong>XmlTransformation task to the rescue!<br />
 </strong></p>
<p>With the new XmlTransformation task for MSBuild, it is possible to manually trigger config transformations. This is great news because then we can control which files will be transformed and when they will be transformed. I can make more complex configurations and also have my own transformations which are personal and not checked into the version control system.</p>
<p>First, I would like to be able to test the different configurations. Lets say I have a web application which will behave different in different environments. This could be controlled in a database or it could be controlled in a config file.</p>
<p>As an example, I have created a simple solution with 2 themes, one <span style="color: #fd0101;">red</span> and one <span style="color: #0101fd;">blue</span> theme. Changing the configuration, should also change the theme on the web site. In order to achieve this I have created 2 themes in my solutions with a stylesheet for each theme that will set the background color of the header for the default ASP.NET site that comes with Visual Studio:</p>
<p><br class="spacer_" /></p>
<div id="attachment_244" class="wp-caption aligncenter" style="width: 510px"><a href="http://hamang.net/wp-content/uploads/2011/02/themes.png"><img class="size-full wp-image-244" title="themes" src="http://hamang.net/wp-content/uploads/2011/02/themes.png" alt="" width="500" height="309" /></a><p class="wp-caption-text">2 themes, one red and one blue</p></div>
<p><br class="spacer_" /></p>
<p>In order to be able to change this, I create some configurations in the Configuration manager in Visual Studio:</p>
<p><a href="http://hamang.net/wp-content/uploads/2011/02/configs.png"><img class="aligncenter size-full wp-image-245" title="configs" src="http://hamang.net/wp-content/uploads/2011/02/configs.png" alt="" width="500" height="231" /></a></p>
<p>With the configurations, I am able to create additional transformation files for web.config:</p>
<p><br class="spacer_" /></p>
<div id="attachment_246" class="wp-caption aligncenter" style="width: 510px"><a href="http://hamang.net/wp-content/uploads/2011/02/weconfigs.png"><img class="size-full wp-image-246" title="weconfigs" src="http://hamang.net/wp-content/uploads/2011/02/weconfigs.png" alt="" width="500" height="244" /></a><p class="wp-caption-text">Transformations files</p></div>
<p><br class="spacer_" /></p>
<p>Also notice that I have a <em>Web.master.config</em> file and a <em>Web.mysettings.config</em> file. The master file is the base file that will be used for all transformations. This should contain the settings which is most common for the different configurations. The mysettings file is my personal config file which I use for my personal configurations. For instance, I like to use Fiddler and this contains transformations for adding Fiddler proxy to the <em>web.config </em>file.</p>
<p>The content of the <em>Web.mysettings.config</em> file:</p>
<pre style="font-family: consolas;"><span style="color: blue;">&lt;?</span><span style="color: #a31515;">xml</span><span style="color: blue;"> </span><span style="color: red;">version</span><span style="color: blue;">=</span>"<span style="color: blue;">1.0</span>"<span style="color: blue;">?&gt;</span>
<span style="color: blue;">&lt;</span><span style="color: #a31515;">configuration</span><span style="color: blue;"> </span><span style="color: red;">xmlns:xdt</span><span style="color: blue;">=</span>"<span style="color: blue;">http://schemas.microsoft.com/XML-Document-Transform</span>"<span style="color: blue;">&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">system.net</span><span style="color: blue;">&gt;</span>
<span style="color: blue;">        &lt;</span><span style="color: #a31515;">defaultProxy</span><span style="color: blue;"> </span><span style="color: red;">xdt:Transform</span><span style="color: blue;">=</span>'<span style="color: blue;">Insert</span>'<span style="color: blue;">&gt;</span>
<span style="color: blue;">            &lt;</span><span style="color: #a31515;">proxy</span><span style="color: blue;"> </span><span style="color: red;">proxyaddress</span><span style="color: blue;">=</span>"<span style="color: blue;">http://127.0.0.1:8888</span>"<span style="color: blue;">/&gt;</span>
<span style="color: blue;">        &lt;/</span><span style="color: #a31515;">defaultProxy</span><span style="color: blue;">&gt;</span>
<span style="color: blue;">    &lt;/</span><span style="color: #a31515;">system.net</span><span style="color: blue;">&gt;</span>
<span style="color: blue;">&lt;/</span><span style="color: #a31515;">configuration</span><span style="color: blue;">&gt;</span></pre>
<p>Selecting the <em>debug &#8211; blue </em>configuration should result in the standard blue color for the default ASP.NET site when running/debugging the web application:</p>
<p><a href="http://hamang.net/wp-content/uploads/2011/02/blueweb.png"><img class="aligncenter size-full wp-image-247" title="blueweb" src="http://hamang.net/wp-content/uploads/2011/02/blueweb.png" alt="" width="500" height="249" /></a></p>
<p>Selecting the <em>debug &#8211; red</em> configuration should result in having a red header in the web site:</p>
<p><a href="http://hamang.net/wp-content/uploads/2011/02/redweb.png"><img class="aligncenter size-full wp-image-248" title="redweb" src="http://hamang.net/wp-content/uploads/2011/02/redweb.png" alt="" width="500" height="249" /></a></p>
<p>In real life, a lot of different appsettings could be different for the different configurations.  In this example, the <em>Web.debug &#8211; red.config </em>file only contains</p>
<pre><span style="font-family: Consolas; color: blue;" lang="EN-GB">&lt;?</span><span style="font-family: Consolas; color: #a31515;" lang="EN-GB">xml</span><span style="font-family: Consolas; color: blue;" lang="EN-GB"> </span><span style="font-family: Consolas; color: red;" lang="EN-GB">version</span><span style="font-family: Consolas; color: blue;" lang="EN-GB">=</span><span style="font-family: Consolas;" lang="EN-GB">"<span style="color: blue;">1.0</span>"<span style="color: blue;">?&gt;</span>
<span style="color: blue;">&lt;</span><span style="color: #a31515;">configuration</span><span style="color: blue;"> </span><span style="color: red;">xmlns:xdt</span><span style="color: blue;">=</span>"<span style="color: blue;">http://schemas.microsoft.com/XML-Document-Transform</span>"<span style="color: blue;">&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">system.web</span><span style="color: blue;">&gt;</span>
<span style="color: blue;">        &lt;</span><span style="color: #a31515;">pages</span><span style="color: blue;"> </span><span style="color: red;">xdt:Transform</span><span style="color: blue;">=</span>"<span style="color: blue;">SetAttributes</span>"<span style="color: blue;"> </span><span style="color: red;">theme</span><span style="color: blue;">=</span>"<span style="color: blue;">Red</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">    &lt;/</span><span style="color: #a31515;">system.web</span><span style="color: blue;">&gt;</span>
<span style="color: blue;">&lt;/</span><span style="color: #a31515;">configuration</span><span style="color: blue;">&gt;</span></span></pre>
<p>which will change the theme of the <em>pages </em>element.</p>
<p>Now, here comes the real magic. This is the code you have put into the project file of the web application to be able to modify the Web.config file. Edit the project file and paste this before the &lt;/Project&gt; closing element</p>
<pre style="font-family: consolas;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">UsingTask</span><span style="color: blue;"> </span><span style="color: red;">TaskName</span><span style="color: blue;">=</span>"<span style="color: blue;">TransformXml</span>"<span style="color: blue;"> </span><span style="color: red;">AssemblyFile</span><span style="color: blue;">=</span>"<span style="color: blue;">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">  &lt;!--</span><span style="color: green;"> This is a hack to perform the master =&gt; transform without mysettings of web.config when publishing the website. It will only trigger on </span><span style="color: blue;">--&gt;</span>
<span style="color: blue;">  &lt;!--</span><span style="color: green;"> publish within Visual Studio. It actually overrides the TransformWebConfig Target in the original Microsoft.Web.publishing.targets file, </span><span style="color: blue;">--&gt;</span>
<span style="color: blue;">  &lt;!--</span><span style="color: green;"> but since it is empty by default, it should work fine! </span><span style="color: blue;">--&gt;</span>
<span style="color: blue;">  &lt;</span><span style="color: #a31515;">Target</span><span style="color: blue;"> </span><span style="color: red;">Name</span><span style="color: blue;">=</span>"<span style="color: blue;">TransformWebConfig</span>"<span style="color: blue;">&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">Message</span><span style="color: blue;"> </span><span style="color: red;">Text</span><span style="color: blue;">=</span>"<span style="color: blue;">%09 ------------- Transforming web.config.master =</span><span style="color: red;">&amp;gt;</span><span style="color: blue;"> web.config with $(Configuration) transformations --------------</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">TransformXml</span><span style="color: blue;"> </span><span style="color: red;">Source</span><span style="color: blue;">=</span>"<span style="color: blue;">web.master.config</span>"<span style="color: blue;"> </span><span style="color: red;">Transform</span><span style="color: blue;">=</span>"<span style="color: blue;">web.$(Configuration).config</span>"<span style="color: blue;"> </span><span style="color: red;">Destination</span><span style="color: blue;">=</span>"<span style="color: blue;">web.config</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">  &lt;/</span><span style="color: #a31515;">Target</span><span style="color: blue;">&gt;</span>
<span style="color: blue;">  &lt;</span><span style="color: #a31515;">Target</span><span style="color: blue;"> </span><span style="color: red;">Name</span><span style="color: blue;">=</span>"<span style="color: blue;">BeforeBuild</span>"<span style="color: blue;">&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">Message</span><span style="color: blue;"> </span><span style="color: red;">Text</span><span style="color: blue;">=</span>"<span style="color: blue;">%09 ------------- Transforming web.config with $(Configuration) transformations --------------</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">TransformXml</span><span style="color: blue;"> </span><span style="color: red;">Condition</span><span style="color: blue;">=</span>"<span style="color: blue;">Exists('web.mysettings.config')</span>"<span style="color: blue;"> </span><span style="color: red;">Source</span><span style="color: blue;">=</span>"<span style="color: blue;">web.master.config</span>"<span style="color: blue;"> </span><span style="color: red;">Transform</span><span style="color: blue;">=</span>"<span style="color: blue;">web.$(Configuration).config</span>"<span style="color: blue;"> </span><span style="color: red;">Destination</span><span style="color: blue;">=</span>"<span style="color: blue;">web.transformed.config</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">TransformXml</span><span style="color: blue;"> </span><span style="color: red;">Condition</span><span style="color: blue;">=</span>"<span style="color: blue;">Exists('web.mysettings.config')</span>"<span style="color: blue;"> </span><span style="color: red;">Source</span><span style="color: blue;">=</span>"<span style="color: blue;">web.transformed.config</span>"<span style="color: blue;"> </span><span style="color: red;">Transform</span><span style="color: blue;">=</span>"<span style="color: blue;">web.mysettings.config</span>"<span style="color: blue;"> </span><span style="color: red;">Destination</span><span style="color: blue;">=</span>"<span style="color: blue;">web.config</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">    &lt;</span><span style="color: #a31515;">TransformXml</span><span style="color: blue;"> </span><span style="color: red;">Condition</span><span style="color: blue;">=</span>"<span style="color: blue;">!Exists('web.mysettings.config')</span>"<span style="color: blue;"> </span><span style="color: red;">Source</span><span style="color: blue;">=</span>"<span style="color: blue;">web.master.config</span>"<span style="color: blue;"> </span><span style="color: red;">Transform</span><span style="color: blue;">=</span>"<span style="color: blue;">web.$(Configuration).config</span>"<span style="color: blue;"> </span><span style="color: red;">Destination</span><span style="color: blue;">=</span>"<span style="color: blue;">web.config</span>"<span style="color: blue;"> /&gt;</span>
<span style="color: blue;">  &lt;/</span><span style="color: #a31515;">Target</span><span style="color: blue;">&gt;</span>
<span style="color: blue;">  &lt;</span><span style="color: #a31515;">Target</span><span style="color: blue;"> </span><span style="color: red;">Name</span><span style="color: blue;">=</span>"<span style="color: blue;">AfterBuild</span>"<span style="color: blue;">&gt;</span>
<span style="color: blue;">    &lt;!--</span><span style="color: green;">&lt;Delete Condition="Exists('web.mysettings.config')" FiThe BeforeBuoilles="web.transformed.config" /&gt;</span><span style="color: blue;">--&gt;</span>
<span style="color: blue;">  &lt;/</span><span style="color: #a31515;">Target</span><span style="color: blue;">&gt;</span></pre>
<p>Some comments on the code:</p>
<ul>
<li>The <em>TransformXml </em>task comes with Visual Studio 2010, so all you have to do is make a reference to it with the using statement. </li>
<li>In the <em>BeforeBuild </em>Target,  this is where the transformations take place. This makes it possible to dynamically create Web.config every time a build triggers. </li>
<li>Using Source and Destination, it is possible to do transformations to all kind of XML file types, not only Web.config.- You could have appSettings.config, connectionsTrings.config etc. It would also be possible to make more hierarchical transformations by doing more than one transformation. Lets say there are some common settings for the red configuration which should be transformed in all environments, it would be possible to have this in a separate config file that will be transformed into the final web.config file. </li>
<li> The <em>AfterBuild</em> target should clean up the temporary config files. However, there seems to be a bug with the TransformXml task locking the files, so lets hope Microsoft fixes this in a future version.</li>
<li>The <em>Web.mysettings.config</em> transformation only triggers if there is a mysettings file available. This means not all teammembers have to create this file if they don&#039;t need to. </li>
<li>The target TransformWebConfig is a minor hack. In order to prevent the mysettings transformation when doing a <em>Publish&#8230;</em> within Visual Studio, I had to find a target in the <em>Publish&#8230;</em> event which triggers only when publishing. This target actually does nothing in the default <em>Microsoft.Web.Publishing.targets</em> file, so that&#039;s the reason for overriding this particular target. I wish it would be possible to actually hook into the publish event in Visual Studio through MSBuild, but that seems impossible. And using a target in MSBuild also overrides the target without having the option to call the base target which is overridden, so anything you do in that target will not be continued in the <em>Microsoft.Web.Publishing.targets </em>file. Lets hope MS don&#039;t put anything into that target in the future. I also tried to use <em>DependsOnTargets</em>, but that seems to trigger the target depending on, not listening to wheter the target has been run. That&#039;s a big difference. </li>
</ul>
<p><strong>Conclusion</strong></p>
<p>Using the TransformXml task is a pretty simple solution to a complex problem. It comes with Visual Studio 2010 and makes environmental and application specific configurations much simpler to handle in real life. For Visual Studio 2008 and earlier, you still need to think different. Have a look at <a href="http://ilearnable.net/2010/08/02/t4-for-complex-configuration/" target="_blank">Andreas post on how to make complex transformations using T4 templates</a>.</p>
<p>You can download the sample solution here: <a href="http://hamang.net/wp-content/uploads/2011/02/ConfigExample.zip">ConfigExample.zip</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2011/02/15/configuration-handling-reloaded/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>True dynamic controls</title>
		<link>http://hamang.net/2011/02/03/true-dynamic-controls/</link>
		<comments>http://hamang.net/2011/02/03/true-dynamic-controls/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 13:18:42 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=224</guid>
		<description><![CDATA[This is something I have been struggeling with so many times, and there are a lot of examples on how to programatically add controls to a page. In this example I add dynamically created controls which remembers their state on postbacks. The problem: I want to add new controls to a page. Clicking a button [...]]]></description>
			<content:encoded><![CDATA[<p>This is something I have been struggeling with so many times, and there are a lot of examples on how to programatically add controls to a page. In this example I add dynamically created controls which remembers their state on postbacks.</p>
<p>The problem:</p>
<ul>
<li>I want to add new controls to a page. Clicking a button adds a new control to the page. </li>
<li>The new control should remember its state through ViewState and postback events should work as normal. </li>
</ul>
<p>The solution:</p>
<ul>
<li>I can add the controls to a Panel or Placeholder and I have to do it in an early stage in the page lifecycle.</li>
<li>Some experiments and thoughts
<ul>
<li>The dynamically added controls needs to be added to the page on every postback. It is not possible to add a new control and forget it. This means I need to have a loop where the controls are added to the page.</li>
<li>The ID of the control need to be the same on every postback in order for the control to remember its state through ViewState. </li>
<li>Doing some testing, I tried adding the controls in PreInit. This is where <a href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" target="_blank">Microsoft recommends </a>to add dynamically created controls. The only problem here is that the ViewState is not available at this stage. So I am not able to track how many controls that have been added to the page. I have a property <em>NumberOfDynamicControls </em>which holds how many dynamically controls that have been added. The same goes with Init, no luck. The ViewState is loaded between Init and Load.</li>
<li>You can add controls to the page in almost any event (PreInit, Init, Load, postback event etc.) and it will render fine. However, the ViewState will not be tracked and it is not possible to add and render more than one control. </li>
<li>The only solution I found was to override the LoadViewState event and add the controls there. This seems like a hack, and probably is, but everything seems to work fine regarding ViewState tracking and postback events. </li>
<li>I need to have the dynamic control available as an invisible &#034;ghost&#034; control before it is &#034;added&#034; to the page. This is to keep track of the state of the control. When clicking the &#034;Add&#034; button, the ghost control is set visible, although it&#039;s already there. </li>
</ul>
</li>
</ul>
<p>Here is the code:</p>
<p>This is the HTML markup. I&#039;m having a simple Panel and a button. Everytime I click the Add button, a new dynamically created button is added to the page.</p>
<pre class="brush: html">&lt;asp:Panel runat="server" ID="Panel1" &gt;
 &lt;asp:Button Text="Add" runat="server" OnClick="AddControlToPanel" /&gt;
 &lt;/asp:Panel&gt;   

   
</pre>
<p>I have to initialize a &#034;ghost&#034; control. The dynamically created button is actually added to the page before it is visible. This is to track ViewState. Clicking the Add button makes the ghost control visible:</p>
<pre class="brush: csharp"> protected void AddControlToPanel(object sender, EventArgs e)
        {
            Button newButton = Panel1.FindControl("ButtonDynamic" + (NumberOfDynamicControls - 1)) as Button;
            if (newButton != null)
            {
                newButton.Visible = true;
                newButton.Text = "New button";
                NumberOfDynamicControls++;
            }
        }
</pre>
<p>Here is the tracking of number of dynamically created controls added to the page. The value is stored in the ViewState.</p>
<pre class="brush: csharp"> protected int NumberOfDynamicControls
        {
            get { return ViewState["numberOfDynamicControls"] == null ? 1 : (int)ViewState["numberOfDynamicControls"]; }
            set { ViewState["numberOfDynamicControls"] = value; }
        }
</pre>
<p>Here comes the real magic. By overriding the LoadViewState and rebuilding the dynamically added controls, everything works as expected.</p>
<pre class="brush: csharp"> protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            if (IsPostBack)
            {
                InitializeDynamicButtons(NumberOfDynamicControls);
            }
        }

protected void InitializeDynamicButtons(int numberOfButtons)
        {
            for (int i = 0; i &lt; numberOfButtons; i++)
            {
                Button dynamicButton = new Button();
                Panel1.Controls.Add(dynamicButton);
                dynamicButton.ID = "ButtonDynamic" + i;
                dynamicButton.Click += DynamicButton_Click;
                dynamicButton.Visible = false;
            }
        }
</pre>
<p>The dynamically created button also has a click event:</p>
<pre class="brush: csharp"> void DynamicButton_Click(object sender, EventArgs e)
        {
            Button button = (Button) sender;
            button.Text = "Clicked!";
        }
</pre>
<p>Before:</p>
<p><br class="spacer_" /></p>
<p><br class="spacer_" /></p>
<div id="attachment_234" class="wp-caption aligncenter" style="width: 483px"><a href="http://hamang.net/wp-content/uploads/2011/02/dyn1.jpg"><img class="size-full wp-image-234" title="dyn1" src="http://hamang.net/wp-content/uploads/2011/02/dyn1.jpg" alt="" width="473" height="183" /></a><p class="wp-caption-text">The page before adding the dynamic buttons</p></div>
<p><br class="spacer_" /></p>
<p><br class="spacer_" /></p>
<p style="text-align: left;"> </p>
<p>After:<br class="spacer_" /></p>
<p><br class="spacer_" /></p>
<div id="attachment_235" class="wp-caption aligncenter" style="width: 483px"><a href="http://hamang.net/wp-content/uploads/2011/02/dyn2.jpg"><img class="size-full wp-image-235" title="dyn2" src="http://hamang.net/wp-content/uploads/2011/02/dyn2.jpg" alt="" width="473" height="182" /></a><p class="wp-caption-text">The added buttons. Notice I have clicked the middle button and the state is managed.</p></div>
<p><br class="spacer_" /></p>
<p><br class="spacer_" /></p>
<p style="text-align: left;">Here is the complete code:</p>
<p style="text-align: left;"><a href="http://hamang.net/wp-content/uploads/2011/02/DynamicControls.zip">DynamicControls</a></p>
<p style="text-align: left;">If you know some other good ways to achieve this, let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2011/02/03/true-dynamic-controls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating dynamic menus in EPiServer</title>
		<link>http://hamang.net/2010/02/10/creating-dynamic-menus-in-episerver/</link>
		<comments>http://hamang.net/2010/02/10/creating-dynamic-menus-in-episerver/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 09:32:42 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=201</guid>
		<description><![CDATA[My first post in almost a year! What is going on! &#034;Been busy, things are happening, blah blah blah&#034;&#8230;no excuse, really. I signed up for twitter almost a year ago, and I think I lost some focus in the blogging sphere. Anyway, this first post in 2010 is about EPiServer, the best CMS out there [...]]]></description>
			<content:encoded><![CDATA[<p><em>My first post in almost a year! What is going on! &#034;Been busy, things are happening, blah blah blah&#034;&#8230;no excuse, really.<a href="http://www.twitter.com/knut_hamang" target="_blank"> I signed up for twitter</a> almost a year ago, and I think I lost some focus in the blogging sphere. Anyway, this first post in 2010 is about EPiServer, the best CMS out there today!</em></p>
<h3>The challenge</h3>
<p>I want to create a more dynamic page tree than the standard EPiServer PageTree. More like an <a href="http://jqueryui.com/demos/accordion/#mouseover">Accordion panel </a>which has 2 or 3 levels (doesn&#039;t matter) and all available nodes are expanded by default. The real challenge is to get the whole page tree with all nodes expanded (not only the nodes which are selected) and setting correct class on the expanded items. Whether this is an accordion or another cool menu script is all the same.</p>
<h3>The Solution</h3>
<p>Start out with the default PageTree control in EPiServer controls.</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">EPiServer</span><span style="color: blue;">:</span><span style="color: #a31515;">PageTree</span> <span style="color: red;">ID</span><span style="color: blue;">=&#034;PageTreeLeftMenu&#034;</span> <span style="color: red;">runat</span><span style="color: blue;">=&#034;server&#034;</span> <span style="color: red;">ExpandAll</span><span style="color: blue;">=&#034;true&#034;</span> <span style="color: red;">NumberOfLevels</span><span style="color: blue;">=&#034;2&#034;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">HeaderTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">div</span> <span style="color: red;">class</span><span style="color: blue;">=&#034;leftmenu&#034;&gt;</span> <span style="color: green;">&lt;!&#8211; Header &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">HeaderTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">IndentTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span> <span style="color: green;">&lt;!&#8211; Indent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">IndentTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">ItemHeaderTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span> <span style="color: red;">&lt;%# GetExpandedClass(Container.DataItem) %&gt;</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">ItemHeaderTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">ExpandedTopTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">EPiServer</span><span style="color: blue;">:</span><span style="color: #a31515;">Property</span> <span style="color: red;">PropertyName</span><span style="color: blue;">=&#034;PageLink&#034;</span> <span style="color: red;">runat</span><span style="color: blue;">=&#034;server&#034;</span> <span style="color: blue;">/&gt;</span> <span style="color: green;">&lt;!&#8211; ExpandedTop &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">ExpandedTopTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">SelectedExpandedTopTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">EPiServer</span><span style="color: blue;">:</span><span style="color: #a31515;">Property</span> <span style="color: red;">PropertyName</span><span style="color: blue;">=&#034;PageLink&#034;</span> <span style="color: red;">runat</span><span style="color: blue;">=&#034;server&#034;</span> <span style="color: red;">CssClass</span><span style="color: blue;">=&#034;selected&#034;</span> <span style="color: blue;">/&gt;</span> <span style="color: green;">&lt;!&#8211; SelectedExpandedTop &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">SelectedExpandedTopTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">ExpandedItemTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">EPiServer</span><span style="color: blue;">:</span><span style="color: #a31515;">Property</span> <span style="color: red;">PropertyName</span><span style="color: blue;">=&#034;PageLink&#034;</span> <span style="color: red;">runat</span><span style="color: blue;">=&#034;server&#034;</span> <span style="color: blue;">/&gt;</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">ExpandedItemTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">SelectedExpandedItemTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">EPiServer</span><span style="color: blue;">:</span><span style="color: #a31515;">Property</span> <span style="color: red;">PropertyName</span><span style="color: blue;">=&#034;PageLink&#034;</span> <span style="color: red;">runat</span><span style="color: blue;">=&#034;server&#034;</span> <span style="color: red;">CssClass</span><span style="color: blue;">=&#034;selected&#034;</span> <span style="color: blue;">/&gt;</span> <span style="color: green;">&lt;!&#8211; SelectedExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">SelectedExpandedItemTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">ItemFooterTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">ItemFooterTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">UnindentTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span> <span style="color: green;">&lt;!&#8211; UnIndent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">UnindentTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">FooterTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">div</span><span style="color: blue;">&gt;</span> <span style="color: green;">&lt;!&#8211; Footer &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">FooterTemplate</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">EPiServer</span><span style="color: blue;">:</span><span style="color: #a31515;">PageTree</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: blue;"><br />
 </span></p>
</div>
<p>Things to notice:</p>
<ul>
<li>&#034;<strong>ExpandAll</strong>&#034; is set to true. This will dump the whole tree, not just the nodes which are selected by the user.</li>
<li>Only the <strong>*Expanded* templates</strong> are in use for Top and Item (ie.ExpandedTopTemplate).  When using &#034;ExpandAll&#034; these are the templates used, not the regular Top Template and ItemTemplate.</li>
<li>&lt;%# <strong>GetExpandedClass</strong>(Container.DataItem) %&gt; &#8211; This is the magic for setting the correct style on the expanded items. In addition there is a &#034;selected&#034; class on the selected menu item</li>
</ul>
<p>The Codebehind looks like this:</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: blue;">protected</span> <span style="color: blue;">void</span> Page_Load(<span style="color: blue;">object</span> sender, <span style="color: #2b91af;">EventArgs</span> e)</p>
<p style="margin: 0px;">{</p>
<p style="margin: 0px;">PageTreeLeftMenu.PageLink = LeftMenuPageLink;</p>
<p style="margin: 0px;">PageTreeLeftMenu.DataBind();</p>
<p style="margin: 0px;">}</p>
<p style="margin: 0px;"> </p>
<p style="margin: 0px;"><span style="color: blue;">protected</span> <span style="color: #2b91af;">PageReference</span> LeftMenuPageLink</p>
<p style="margin: 0px;">{</p>
<p style="margin: 0px;"><span style="color: blue;">get</span></p>
<p style="margin: 0px;">{</p>
<p style="margin: 0px;"><span style="color: #2b91af;">PageReference</span> leftMenuPageLink = CurrentPage[<span style="color: #a31515;">"LeftMenuRoot"</span>] <span style="color: blue;">as</span> <span style="color: #2b91af;">PageReference</span>;</p>
<p style="margin: 0px;"><span style="color: blue;">return</span> leftMenuPageLink;</p>
<p style="margin: 0px;">}</p>
<p style="margin: 0px;">}</p>
<p style="margin: 0px;"> </p>
<p style="margin: 0px;"><span style="color: blue;">protected</span> <span style="color: blue;">string</span> GetExpandedClass(<span style="color: blue;">object</span> dataItem)</p>
<p style="margin: 0px;">{</p>
<p style="margin: 0px;"><span style="color: #2b91af;">PageData</span> page = dataItem <span style="color: blue;">as</span> <span style="color: #2b91af;">PageData</span>;</p>
<p style="margin: 0px;"><span style="color: blue;">if</span> (page != <span style="color: blue;">null</span> &amp;&amp; PageTreeLeftMenu.OpenPages.Contains(page.PageLink))</p>
<p style="margin: 0px;"><span style="color: blue;">return</span> <span style="color: #a31515;">&#034;class=\&#034;expanded\&#034;"</span>;</p>
<p style="margin: 0px;"><span style="color: blue;">return</span> <span style="color: blue;">string</span>.Empty;</p>
<p style="margin: 0px;"> </p>
<p style="margin: 0px;">}</p>
</div>
<p>Things to notice:</p>
<ul>
<li>LeftmenuPageLink is just an example on how to set the start point for the left menu.</li>
<li><strong>GetExpandedClass </strong>is the method that sets the correct class on the &lt;li&gt;. This is done by checking if the page in the tree is available in PageTree.OpenPages. This is what makes it possible to make the dynamic menu. If the OpenPages method was not available, it would not be possible to highlight the expanded nodes without traversing each node or doing some javascripting.</li>
</ul>
<p>The output should look something like this</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 43</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">div</span> <span style="color: red;">class</span><span style="color: blue;">=&#034;leftcolumn&#034;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 44</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">div</span> <span style="color: red;">class</span><span style="color: blue;">=&#034;leftmenu&#034;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 45</span> <span style="color: green;">&lt;!&#8211; Header &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 46</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 47</span> <span style="color: green;">&lt;!&#8211; Indent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 48</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span> <span style="color: red;">class</span><span style="color: blue;">=&#034;expanded&#034;&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Consulting/&#034;&gt;</span>Consulting<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 49</span> <span style="color: green;">&lt;!&#8211; ExpandedTop &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 50</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 51</span> <span style="color: green;">&lt;!&#8211; Indent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 52</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span> <span style="color: red;">class</span><span style="color: blue;">=&#034;expanded&#034;&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">class</span><span style="color: blue;">=&#034;selected&#034;</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Consulting/Business-Consulting-/&#034;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 53</span> Business Consulting <span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 54</span> <span style="color: green;">&lt;!&#8211; SelectedExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 55</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 56</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Consulting/Project-and-Test-Management/&#034;&gt;</span>Project and Test</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 57</span> Management<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 58</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 59</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 60</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Consulting/IT-Consulting/&#034;&gt;</span>IT Consulting<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 61</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 62</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 63</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Consulting/Application-Development/&#034;&gt;</span>Application Development<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 64</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 65</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 66</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 67</span> <span style="color: green;">&lt;!&#8211; UnIndent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 68</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 69</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/&#034;&gt;</span>Solutions<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 70</span> <span style="color: green;">&lt;!&#8211; ExpandedTop &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 71</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 72</span> <span style="color: green;">&lt;!&#8211; Indent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 73</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/ERP/&#034;&gt;</span>ERP<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 74</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 75</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 76</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/Content-Management/&#034;&gt;</span>Content Management<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 77</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 78</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 79</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/Oil-and-Gas/&#034;&gt;</span>Oil and Gas<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 80</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 81</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 82</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/Industry/&#034;&gt;</span>Industry<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 83</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 84</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 85</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/E-Business/&#034;&gt;</span>E-Business<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 86</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 87</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 88</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/Banking&#8211;Finance-Suite/&#034;&gt;</span>Banking <span style="color: red;">&amp;amp;</span> Finance</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 89</span> Suite<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 90</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 91</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 92</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Solutions/Public-Sector-Suite/&#034;&gt;</span>Public Sector Suite<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 93</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 94</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 95</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 96</span> <span style="color: green;">&lt;!&#8211; UnIndent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 97</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 98</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Outsourcing/&#034;&gt;</span>Outsourcing<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 99</span> <span style="color: green;">&lt;!&#8211; ExpandedTop &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 100</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 101</span> <span style="color: green;">&lt;!&#8211; Indent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 102</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Outsourcing/ITO/&#034;&gt;</span>ITO<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 103</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 104</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 105</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/Outsourcing/Applications-Management/&#034;&gt;</span>Applications Management<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 106</span> <span style="color: green;">&lt;!&#8211; ExpandedItem &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 107</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 108</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 109</span> <span style="color: green;">&lt;!&#8211; UnIndent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 110</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 111</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/TestTest/&#034;&gt;</span>TestTest<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 112</span> <span style="color: green;">&lt;!&#8211; ExpandedTop &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 113</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 114</span> <span style="color: blue;">&lt;</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;&lt;</span><span style="color: #a31515;">a</span> <span style="color: red;">href</span><span style="color: blue;">=&#034;/en/TestTestTest/&#034;&gt;</span>TestTestTest<span style="color: blue;">&lt;/</span><span style="color: #a31515;">a</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 115</span> <span style="color: green;">&lt;!&#8211; ExpandedTop &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 116</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">li</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 117</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">ul</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 118</span> <span style="color: green;">&lt;!&#8211; UnIndent &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 119</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">div</span><span style="color: blue;">&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 120</span> <span style="color: green;">&lt;!&#8211; Footer &#8211;&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 121</span> <span style="color: blue;">&lt;/</span><span style="color: #a31515;">div</span><span style="color: blue;">&gt;</span></p>
</div>
<p>The result will look something like this:</p>
<p style="text-align: center;"><a href="http://hamang.net/wp-content/uploads/2010/02/leftmenu1.jpg"><img class="size-full wp-image-202 aligncenter" title="leftmenu1" src="http://hamang.net/wp-content/uploads/2010/02/leftmenu1.jpg" alt="" width="194" height="469" /></a></p>
<p>After adding the Accordion script, the Top items should collapse and only the expanded section should be visible. When moving the mouse over another section it should expand, but not highlight. The final result will look something like this.<br />
 <a href="http://hamang.net/wp-content/uploads/2010/02/leftmenu2.jpg"><img class="aligncenter size-full wp-image-203" title="leftmenu2" src="http://hamang.net/wp-content/uploads/2010/02/leftmenu2.jpg" alt="" width="194" height="250" /></a></p>
<h3>Conclusion</h3>
<p>Using dynamic menus could give the visitor a better experience. Whether its an Accordion panel or some other fancy scripted menu doesn&#039;t matter. Anyway you will have to dump the whole tree to a certain level (2 levels in this example) and set the correct classes on the elements to get the styling correct. The magic is the &#034;PageTree.OpenPages&#034; method which helps a lot in this scenario.</p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2010/02/10/creating-dynamic-menus-in-episerver/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Use regular expressions in Visual Studio to clean up code</title>
		<link>http://hamang.net/2009/02/20/use-regular-expressions-in-visual-studio-to-clean-up-code/</link>
		<comments>http://hamang.net/2009/02/20/use-regular-expressions-in-visual-studio-to-clean-up-code/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 12:30:41 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=191</guid>
		<description><![CDATA[This is a reminder to myself. Knut, remember that Regular Expressions are very handy to clean up a lot of messy code. Here is an example: The following function call results in a code analysis warning: DBHelper.SetPropertyFromDB(m_City, dr(&#034;CITY&#034;)) It&#039;s a helper function that returns the typed value from a DBValue. Not really useful these days [...]]]></description>
			<content:encoded><![CDATA[<p><em>This is a reminder to myself. </em></p>
<p><strong>Knut, remember that Regular Expressions are very handy to clean up a lot of messy code. </strong></p>
<p>Here is an example:<br />
The following function call results in a code analysis warning:</p>
<p style="font-family: Courier New,Courier,mono;">DBHelper.SetPropertyFromDB(m_City, dr(&#034;CITY&#034;))</p>
<p>It&#039;s a helper function that returns the typed value from a DBValue. Not really useful these days with NHibernate or Typed Datasets, but it&#039;s code from an old application. Here is the signature of the code:</p>
<p style="font-family: Courier New,Courier,mono;">Shared Sub SetPropertyFromDB(ByRef pProperty As Object, ByVal value As Object)</p>
<p>The warning reported is:</p>
<p><em>&#034;Warning: Implicit conversion from &#039;Object&#039; to &#039;String&#039; in copying the value of &#039;ByRef&#039; parameter &#039;pProperty&#039; back to the matching argument.&#034;</em></p>
<p>To fix this, I created a new method that returns the correct typed value instead of returning the referenced parameter and marked the old method &#034;Obsolete&#034;:</p>
<p style="font-family: Courier New,Courier,mono;">Public Shared Function GetDBValue(ByVal pProperty As Object, ByVal dbValue As Object) As Object</p>
<p>Now, I had to rewrite all the calls to the function (several hundred calls). This included returning the typed value into the same variable as the first parameter in the function call, like this:</p>
<p style="font-family: Courier New,Courier,mono;">m_City = DBHelper.GetDBValue(m_City, dr(&#034;CITY&#034;))</p>
<p>This is easily achieved by using Regular Expressions in the &#034;Find and Replace&#034; dialog in Visual Studio:</p>
<p>Find What:</p>
<p style="font-family: Courier New,Courier,mono;">DBHelper.SetPropertyFromDB\({.*},</p>
<p>(note: the \ escapes the ( and the expression group is marked by a {})</p>
<p>Replace with:</p>
<p style="font-family: Courier New,Courier,mono;">\1 = DBHelper.GetDBValue(\1,</p>
<p>(note: the \1 will represent the expression group)</p>
<p>Pretty simple, and very powerful  <img src='http://hamang.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2009/02/20/use-regular-expressions-in-visual-studio-to-clean-up-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extend the GridView</title>
		<link>http://hamang.net/2009/02/19/extend-the-gridview/</link>
		<comments>http://hamang.net/2009/02/19/extend-the-gridview/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 10:29:56 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://hamang.net/2009/02/19/extend-the-gridview/</guid>
		<description><![CDATA[The default GridView class has by default a lot of great features. However, some important features are missing. One of the most important is the ability to display the grid even if it is empty. Here is a great class extending the GridView with some additional features. http://forums.asp.net/p/1012442/2951765.aspx#2951765]]></description>
			<content:encoded><![CDATA[<p>The default GridView class has by default a lot of great features. However, some important features are missing. One of the most important is the ability to display the grid even if it is empty.<br />
Here is a great class extending the GridView with some additional features.</p>
<p><a href="http://forums.asp.net/p/1012442/2951765.aspx#2951765" target="_blank">http://forums.asp.net/p/1012442/2951765.aspx#2951765</a></p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2009/02/19/extend-the-gridview/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Web application absolute path</title>
		<link>http://hamang.net/2008/12/17/web-application-absolute-path/</link>
		<comments>http://hamang.net/2008/12/17/web-application-absolute-path/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 13:56:37 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=176</guid>
		<description><![CDATA[Just a reminder on how to get the absolute path for the webapplication in ASP.NET HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) +        VirtualPathUtility.ToAbsolute(HttpContext.Current.Request.ApplicationPath) This will return http://subdomain.domain.com/applicationname You can drop those AppSettings with ApplicationPath]]></description>
			<content:encoded><![CDATA[<p>Just a reminder on how to get the absolute path for the webapplication in ASP.NET</p>
<p>HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) +        VirtualPathUtility.ToAbsolute(HttpContext.Current.Request.ApplicationPath)</p>
<p>This will return http://subdomain.domain.com/applicationname</p>
<p>You can drop those AppSettings with ApplicationPath <img src='http://hamang.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2008/12/17/web-application-absolute-path/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using log4net in Web Applications &#8211; a real-life example</title>
		<link>http://hamang.net/2008/12/12/using-log4net-in-web-applications-a-reallife-example/</link>
		<comments>http://hamang.net/2008/12/12/using-log4net-in-web-applications-a-reallife-example/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 08:30:08 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=164</guid>
		<description><![CDATA[I have seen many different configurations for Log4Net. Log4Net is a very simple, but flexible framework and there are lot of ways to configure it. Here is a real-life example on how we are using in the applications I am working on. First off, I won&#039;t say that this is the one and only way [...]]]></description>
			<content:encoded><![CDATA[<p>I have seen many different configurations for Log4Net. Log4Net is a very simple, but flexible framework and there are lot of ways to configure it. Here is a real-life example on how we are using in the applications I am working on.</p>
<p>First off, I won&#039;t say that this is the one and only way you should use Log4Net, but it handles most of the scenarios I can think of.  Some people think that one should not write wrappers for the loggers and use the logging framework directly in the class, but to be honest I like the wrapper because it makes it very simple to use the logging framework without too much knowledge on how it works. I would say that 95% of what is being logged, is typically errors and debug/useful information. I can&#039;t see any problem using a wrapper as I get the information I need from the loggers.</p>
<h3>Goals with this log configuration</h3>
<ul>
<li>Most important is of course logging errors. All errors should be logged.</li>
<li>Errors should be logged in a global file on the server that will role once a day.</li>
<li>Errors should be sent by email.</li>
<li>It should be possible to notify important information by email</li>
<li>It should be easy for the developers to use the logging framework</li>
<li>It should be possible to change log-level without restarting the application</li>
</ul>
<h3>Configuration and setup</h3>
<p>Log4Net consists of only one DLL. Get the latest version and put it in your bin folder. Make a reference to it in the Web Application Project.</p>
<h3>Log4net.config</h3>
<p>Create a new config file in the root of your Web Application. Name it Log4Net.config and paste the following code:</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;\red0\green128\blue0;}??\fs20 \cf1 &lt;?\cf3 xml\cf1  \cf4 version\cf1 =\cf0 "\cf1 1.0\cf0 "\cf1  \cf4 encoding\cf1 =\cf0 "\cf1 utf-8\cf0 "\cf1  ?&gt;\par ??&lt;\cf3 configuration\cf1 &gt;\par ??    &lt;\cf3 configSections\cf1 &gt;\par ??        &lt;\cf3 section\cf1  \cf4 name\cf1 =\cf0 "\cf1 log4net\cf0 "\cf1  \cf4 type\cf1 =\cf0 "\cf1 log4net.Config.Log4NetConfigurationSectionHandler, log4net\cf0 "\cf1  /&gt;\par ??    &lt;/\cf3 configSections\cf1 &gt;\par ??    &lt;\cf3 log4net\cf1 &gt;\par ??        &lt;\cf3 appender\cf1  \cf4 name\cf1 =\cf0 "\cf1 RollingLogFileAppender\cf0 "\cf1  \cf4 type\cf1 =\cf0 "\cf1 log4net.Appender.RollingFileAppender\cf0 "\cf1 &gt;\par ??            &lt;\cf3 threshold\cf1  \cf4 value\cf1 =\cf0 "\cf1 INFO\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 file\cf1  \cf4 value\cf1 =\cf0 "\cf1 Log\\[applicationname].log\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 appendToFile\cf1  \cf4 value\cf1 =\cf0 "\cf1 true\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 rollingStyle\cf1  \cf4 value\cf1 =\cf0 "\cf1 Date\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 datePattern\cf1  \cf4 value\cf1 =\cf0 "\cf1 '.'yyyyMMdd'.log'\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 layout\cf1  \cf4 type\cf1 =\cf0 "\cf1 log4net.Layout.PatternLayout\cf0 "\cf1 &gt;\par ??                &lt;\cf3 conversionPattern\cf1  \cf4 value\cf1 =\cf0 "\cf1 %date [%thread] %-5level %logger %X\{user\} %X\{url\} - %message%newline\cf0 "\cf1  /&gt;\par ??            &lt;/\cf3 layout\cf1 &gt;\par ??        &lt;/\cf3 appender\cf1 &gt;\par ??        &lt;\cf3 appender\cf1  \cf4 name\cf1 =\cf0 "\cf1 SmtpAppenderError\cf0 "\cf1  \cf4 type\cf1 =\cf0 "\cf1 log4net.Appender.SmtpAppender\cf0 "\cf1 &gt;\par ??            &lt;! \cf6 Set threshold for this appender\cf1  &gt;\par ??            &lt;\cf3 threshold\cf1  \cf4 value\cf1 =\cf0 "\cf1 WARN\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 to\cf1  \cf4 value\cf1 =\cf0 "\cf1 [someone]@[somewhere.com]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 from\cf1  \cf4 value\cf1 =\cf0 "\cf1 [someone]@[somewhere.com]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 subject\cf1  \cf4 value\cf1 =\cf0 "\cf1 Error from [applicationname]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 smtpHost\cf1  \cf4 value\cf1 =\cf0 "\cf1 [100.100.100.100]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 bufferSize\cf1  \cf4 value\cf1 =\cf0 "\cf1 1\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 lossy\cf1  \cf4 value\cf1 =\cf0 "\cf1 false\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 layout\cf1  \cf4 type\cf1 =\cf0 "\cf1 log4net.Layout.PatternLayout\cf0 "\cf1 &gt;\par ??                &lt;\cf3 conversionPattern\cf1  \cf4 value\cf1 =\cf0 "\cf1 %date %-5level %logger %X\{user\} %X\{url\} - %message%newline\cf0 "\cf1  /&gt;\par ??            &lt;/\cf3 layout\cf1 &gt;\par ??        &lt;/\cf3 appender\cf1 &gt;\par ??        &lt;\cf3 appender\cf1  \cf4 name\cf1 =\cf0 "\cf1 SmtpAppenderNotify\cf0 "\cf1  \cf4 type\cf1 =\cf0 "\cf1 log4net.Appender.SmtpAppender\cf0 "\cf1 &gt;\par ??            &lt;! \cf6 Set threshold for this appender\cf1  &gt;\par ??            &lt;\cf3 threshold\cf1  \cf4 value\cf1 =\cf0 "\cf1 INFO\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 to\cf1  \cf4 value\cf1 =\cf0 "\cf1 [someone]@[somewhere.com]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 from\cf1  \cf4 value\cf1 =\cf0 "\cf1 [someone]@[somewhere.com]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 subject\cf1  \cf4 value\cf1 =\cf0 "\cf1 Error from [applicationname]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 smtpHost\cf1  \cf4 value\cf1 =\cf0 "\cf1 [100.100.100.100]\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 bufferSize\cf1  \cf4 value\cf1 =\cf0 "\cf1 1\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 lossy\cf1  \cf4 value\cf1 =\cf0 "\cf1 false\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 layout\cf1  \cf4 type\cf1 =\cf0 "\cf1 log4net.Layout.PatternLayout\cf0 "\cf1 &gt;\par ??                &lt;\cf3 conversionPattern\cf1  \cf4 value\cf1 =\cf0 "\cf1 %date - %message%newline\cf0 "\cf1  /&gt;\par ??            &lt;/\cf3 layout\cf1 &gt;\par ??        &lt;/\cf3 appender\cf1 &gt;\par ??        &lt;\cf3 root\cf1 &gt;\par ??            &lt;\cf3 level\cf1  \cf4 value\cf1 =\cf0 "\cf1 Error\cf0 "\cf1  /&gt;        \par ??        &lt;/\cf3 root\cf1 &gt;\par ??        &lt;\cf3 logger\cf1  \cf4 name\cf1 =\cf0 "\cf1 Application\cf0 "\cf1 &gt;\par ??            &lt;! \cf6 Set level for this logger\cf1  &gt;\par ??            &lt;\cf3 level\cf1  \cf4 value\cf1 =\cf0 "\cf1 INFO\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 appender-ref\cf1  \cf4 ref\cf1 =\cf0 "\cf1 RollingLogFileAppender\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 appender-ref\cf1  \cf4 ref\cf1 =\cf0 "\cf1 SmtpAppenderError\cf0 "\cf1  /&gt;\par ??        &lt;/\cf3 logger\cf1 &gt;\par ??        &lt;\cf3 logger\cf1  \cf4 name\cf1 =\cf0 "\cf1 Notify\cf0 "\cf1 &gt;\par ??            &lt;! \cf6 Set level for this logger\cf1  &gt;\par ??            &lt;\cf3 level\cf1  \cf4 value\cf1 =\cf0 "\cf1 INFO\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 appender-ref\cf1  \cf4 ref\cf1 =\cf0 "\cf1 RollingLogFileAppender\cf0 "\cf1  /&gt;\par ??            &lt;\cf3 appender-ref\cf1  \cf4 ref\cf1 =\cf0 "\cf1 SmtpAppenderNotify\cf0 "\cf1  /&gt;\par ??        &lt;/\cf3 logger\cf1 &gt;\par ??    &lt;/\cf3 log4net\cf1 &gt;\par ??&lt;/\cf3 configuration\cf1 &gt;} --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">&lt;?</span><span style="color: #a31515;">xml</span><span style="color: blue;"> </span><span style="color: red;">version</span><span style="color: blue;">=</span>"<span style="color: blue;">1.0</span>"<span style="color: blue;"> </span><span style="color: red;">encoding</span><span style="color: blue;">=</span>"<span style="color: blue;">utf-8</span>"<span style="color: blue;"> ?&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: #a31515;">configuration</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">    &lt;</span><span style="color: #a31515;">configSections</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: #a31515;">section</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net</span>"<span style="color: blue;"> </span><span style="color: red;">
        type</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net.Config.Log4NetConfigurationSectionHandler, log4net</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">    &lt;/</span><span style="color: #a31515;">configSections</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">    &lt;</span><span style="color: #a31515;">log4net</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: #a31515;">appender</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">RollingLogFileAppender</span>"<span style="color: blue;">
            </span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net.Appender.RollingFileAppender</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">threshold</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">INFO</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">file</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">Log\[applicationname].log</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">appendToFile</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">true</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">rollingStyle</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">Date</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">datePattern</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">'.'yyyyMMdd'.log'</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">layout</span><span style="color: blue;"> </span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net.Layout.PatternLayout</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">                &lt;</span><span style="color: #a31515;">conversionPattern</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">%date [%thread] %-5level
                  %logger %X{user} %X{url} - %message%newline</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;/</span><span style="color: #a31515;">layout</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;/</span><span style="color: #a31515;">appender</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: #a31515;">appender</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">SmtpAppenderError</span>"<span style="color: blue;"> </span><span style="color: red;">
                  type</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net.Appender.SmtpAppender</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;!--</span><span style="color: green;">Set threshold for this appender</span><span style="color: blue;">--&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">threshold</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">ERROR</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">to</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">[someone]@[somewhere.com]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">from</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">[someone]@[somewhere.com]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">subject</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">Error from [applicationname]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">smtpHost</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">[100.100.100.100]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">bufferSize</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">1</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">lossy</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">false</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">layout</span><span style="color: blue;"> </span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net.Layout.PatternLayout</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">                &lt;</span><span style="color: #a31515;">conversionPattern</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">%date %-5level
                %logger %X{user} %X{url} - %message%newline</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;/</span><span style="color: #a31515;">layout</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;/</span><span style="color: #a31515;">appender</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: #a31515;">appender</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">SmtpAppenderNotify</span>"<span style="color: blue;">
                  </span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net.Appender.SmtpAppender</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;!--</span><span style="color: green;">Set threshold for this appender</span><span style="color: blue;">--&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">threshold</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">INFO</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">to</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">[someone]@[somewhere.com]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">from</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">[someone]@[somewhere.com]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">subject</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">Error from [applicationname]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">smtpHost</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">[100.100.100.100]</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">bufferSize</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">1</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">lossy</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">false</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">layout</span><span style="color: blue;"> </span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">log4net.Layout.PatternLayout</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">                &lt;</span><span style="color: #a31515;">conversionPattern</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">%date - %message%newline</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;/</span><span style="color: #a31515;">layout</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;/</span><span style="color: #a31515;">appender</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: #a31515;">root</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">level</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">Error</span>"<span style="color: blue;"> /&gt;        </span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;/</span><span style="color: #a31515;">root</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: #a31515;">logger</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">Application</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;!--</span><span style="color: green;">Set level for this logger</span><span style="color: blue;">--&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">level</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">INFO</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">appender-ref</span><span style="color: blue;"> </span><span style="color: red;">ref</span><span style="color: blue;">=</span>"<span style="color: blue;">RollingLogFileAppender</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">appender-ref</span><span style="color: blue;"> </span><span style="color: red;">ref</span><span style="color: blue;">=</span>"<span style="color: blue;">SmtpAppenderError</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;/</span><span style="color: #a31515;">logger</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;</span><span style="color: #a31515;">logger</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">Notify</span>"<span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;!--</span><span style="color: green;">Set level for this logger</span><span style="color: blue;">--&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">level</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>"<span style="color: blue;">INFO</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">appender-ref</span><span style="color: blue;"> </span><span style="color: red;">ref</span><span style="color: blue;">=</span>"<span style="color: blue;">RollingLogFileAppender</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">            &lt;</span><span style="color: #a31515;">appender-ref</span><span style="color: blue;"> </span><span style="color: red;">ref</span><span style="color: blue;">=</span>"<span style="color: blue;">SmtpAppenderNotify</span>"<span style="color: blue;"> /&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">        &lt;/</span><span style="color: #a31515;">logger</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">    &lt;/</span><span style="color: #a31515;">log4net</span><span style="color: blue;">&gt;</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">configuration</span><span style="color: blue;">&gt;
</span></pre>
</div>
<p>Some comments on the Log4net.config file:</p>
<ul>
<li>The RollingFileAppender is great for rolling the logfile once a day.
<ul>
<li>It has a threshold of INFO, meaning it will log anything from the application except debug information</li>
<li>The logfiles are created in a subdirectory of web root. This should be changed on the production server to not expose information about the application.</li>
<li>The datePattern is specifying how the rolling files are named. The current day will be named &#034;applicationname.log&#034; and yesterdays file will be named &#034;applicationname.log.20081211.log&#034;. The rolling file extension (.log)  makes it easy to open the file in the same editor as the current log. All files will be sorted correctly when using the ISO style date in the filename.</li>
<li>In the conversionPattern you will see two speacial entries with the following format: %X{name}. These are custom formats which can be used for special purposes. This configuration adds the authenticated username and the url which fails if there is an error. This is useful information.</li>
</ul>
</li>
<li>The SmtpAppenders are used for sending emails. It&#039;s really not my favourite configuration, spamming the developers or some other people with emails when some errors occur, but some like it.
<ul>
<li>The threshold is different for the two SmtpAppenders, as is the subject of the email.</li>
<li>The buffersize is set to 1 in the example, meaning that the email is sent right away when an error occur. Increasing the buffer will hold the email until the buffer is reached. This can be useful on the production server, especially for the Notify appender as it is probably not that important to notify right away.</li>
<li>Lossy is set to false, also to send the email right away. It is possible to hold the email until an evaluator is triggered, for instance when a error occurs. Setting lossy to true requires an evaluator.</li>
<li>It is possible to add filters to the appenders to determine which emails should be sent and which to drop.</li>
</ul>
</li>
<li>There are two specific loggers that the application will use. The root logger can be used to log 3.party libraries also using Log4Net. I like to use specific loggers in the application and enabling the root logger if I am tracing an error where I need more information from 3.party libraries, ie. NHibernate or other frameworks using Log4net. Remember to set the level for the logger. If not set, the default level is WARN, which means INFO messages will not be logged.</li>
</ul>
<p>To be able to use the Log4Net.config file instead of putting everything into web.config, you will need to add the following line to AssemblyInfo.vb:</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red163\green21\blue21;\red0\green0\blue255;}??\fs20 &lt;Assembly: log4net.Config.XmlConfigurator(ConfigFile:=\cf3 "Log4Net.config"\cf0 , Watch:=\cf4 True\cf0 )&gt; } --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;">&lt;Assembly: log4net.Config.XmlConfigurator(ConfigFile:=<span style="color: #a31515;">"Log4Net.config"</span>, Watch:=<span style="color: blue;">True</span>)&gt;</pre>
</div>
<p>The advantage of separating the Log4Net configuration is that it is possible to change the configuration of the logging without restarting the application by changing web.config.  It also gives an better overview of the configuration, not having to browse through web.config to find the logging configuration.</p>
<h3>Logging unhandled errors</h3>
<p>All unhandled errors should be logged, which is pretty easy to achieve in web applications. Here is the Global.asax file:</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red0\green128\blue0;\red163\green21\blue21;}??\fs20 \cf1 Imports\cf0  System.Web\par ??\cf1 Imports\cf0  log4net\par ??\cf1 Imports\cf0  MainLib\par ??\par ??\cf1 Public\cf0  \cf1 Class\cf0  [Global]\par ??    \cf1 Inherits\cf0  System.Web.HttpApplication\par ??\par ??    \cf1 Sub\cf0  Application_Start(\cf1 ByVal\cf0  sender \cf1 As\cf0  \cf1 Object\cf0 , \cf1 ByVal\cf0  e \cf1 As\cf0  EventArgs)\par ??        \cf4 ' Fires when the application is started\par ??\cf0         \cf4 ' Initialize the logger in this context.\par ??\cf0         LogManager.GetLogger(\cf1 Me\cf0 .GetType)\par ??        LogHandler.LogInfo(\cf5 "============================"\cf0 , LogHandler.LogType.General)\par ??        LogHandler.LogInfo(\cf5 "    Starting application"\cf0 , LogHandler.LogType.General)\par ??        LogHandler.LogInfo(\cf5 "============================"\cf0 , LogHandler.LogType.General)\par ??    \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Sub\cf0  Session_Start(\cf1 ByVal\cf0  sender \cf1 As\cf0  \cf1 Object\cf0 , \cf1 ByVal\cf0  e \cf1 As\cf0  EventArgs)\par ??        \cf4 ' Fires when the session is started\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Sub\cf0  Application_BeginRequest(\cf1 ByVal\cf0  sender \cf1 As\cf0  \cf1 Object\cf0 , \cf1 ByVal\cf0  e \cf1 As\cf0  EventArgs)\par ??        \cf4 ' Fires at the beginning of each request\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Sub\cf0  Application_AuthenticateRequest(\cf1 ByVal\cf0  sender \cf1 As\cf0  \cf1 Object\cf0 , \cf1 ByVal\cf0  e \cf1 As\cf0  EventArgs)\par ??        \cf4 ' Fires upon attempting to authenticate the use\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Sub\cf0  Application_Error(\cf1 ByVal\cf0  sender \cf1 As\cf0  \cf1 Object\cf0 , \cf1 ByVal\cf0  e \cf1 As\cf0  EventArgs)\par ??        \cf4 ' Fires when an error occurs\par ??\cf0         LogHandler.LogError(\cf5 "Unhandled exception occured!"\cf0 , HttpContext.Current.User, HttpContext.Current.User, HttpContext.Current.Server.GetLastError())\par ??    \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Sub\cf0  Session_End(\cf1 ByVal\cf0  sender \cf1 As\cf0  \cf1 Object\cf0 , \cf1 ByVal\cf0  e \cf1 As\cf0  EventArgs)\par ??        \cf4 ' Fires when the session ends\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Sub\cf0  Application_End(\cf1 ByVal\cf0  sender \cf1 As\cf0  \cf1 Object\cf0 , \cf1 ByVal\cf0  e \cf1 As\cf0  EventArgs)\par ??        \cf4 ' Fires when the application ends\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??End\cf0  \cf1 Class\par ??} --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">Imports</span> System.Web</pre>
<pre style="margin: 0px;"><span style="color: blue;">Imports</span> log4net</pre>
<pre style="margin: 0px;"><span style="color: blue;">Imports</span> MainLib</pre>
<pre style="margin: 0px;"><span style="color: blue;">Public</span> <span style="color: blue;">Class</span> [Global]</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Inherits</span> System.Web.HttpApplication</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Sub</span> Application_Start(<span style="color: blue;">ByVal</span> sender <span style="color: blue;">As</span> <span style="color: blue;">Object</span>, <span style="color: blue;">ByVal</span> e <span style="color: blue;">As</span> EventArgs)</pre>
<pre style="margin: 0px;">        <span style="color: green;">' Fires when the application is started</span></pre>
<pre style="margin: 0px;">        <span style="color: green;">' Initialize the logger in this context.</span></pre>
<pre style="margin: 0px;">        LogManager.GetLogger(<span style="color: blue;">Me</span>.GetType)</pre>
<pre style="margin: 0px;">        LogHandler.LogInfo(<span style="color: #a31515;">"============================"</span>, LogHandler.LogType.General)</pre>
<pre style="margin: 0px;">        LogHandler.LogInfo(<span style="color: #a31515;">"    Starting application"</span>, LogHandler.LogType.General)</pre>
<pre style="margin: 0px;">        LogHandler.LogInfo(<span style="color: #a31515;">"============================"</span>, LogHandler.LogType.General)</pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Sub</span> Session_Start(<span style="color: blue;">ByVal</span> sender <span style="color: blue;">As</span> <span style="color: blue;">Object</span>, <span style="color: blue;">ByVal</span> e <span style="color: blue;">As</span> EventArgs)</pre>
<pre style="margin: 0px;">        <span style="color: green;">' Fires when the session is started</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Sub</span> Application_BeginRequest(<span style="color: blue;">ByVal</span> sender <span style="color: blue;">As</span> <span style="color: blue;">Object</span>, <span style="color: blue;">ByVal</span> e <span style="color: blue;">As</span> EventArgs)</pre>
<pre style="margin: 0px;">        <span style="color: green;">' Fires at the beginning of each request</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Sub</span> Application_AuthenticateRequest(<span style="color: blue;">ByVal</span> sender <span style="color: blue;">As</span> <span style="color: blue;">Object</span>, <span style="color: blue;">ByVal</span> e <span style="color: blue;">As</span> EventArgs)</pre>
<pre style="margin: 0px;">        <span style="color: green;">' Fires upon attempting to authenticate the use</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Sub</span> Application_Error(<span style="color: blue;">ByVal</span> sender <span style="color: blue;">As</span> <span style="color: blue;">Object</span>, <span style="color: blue;">ByVal</span> e <span style="color: blue;">As</span> EventArgs)</pre>
<pre style="margin: 0px;">        <span style="color: green;">' Fires when an error occurs</span></pre>
<pre style="margin: 0px;">        LogHandler.LogError(<span style="color: #a31515;">"Unhandled exception occured!"</span>,
        HttpContext.Current.User, HttpContext.Current.Request.Url,
        HttpContext.Current.Server.GetLastError())</pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Sub</span> Session_End(<span style="color: blue;">ByVal</span> sender <span style="color: blue;">As</span> <span style="color: blue;">Object</span>, <span style="color: blue;">ByVal</span> e <span style="color: blue;">As</span> EventArgs)</pre>
<pre style="margin: 0px;">        <span style="color: green;">' Fires when the session ends</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Sub</span> Application_End(<span style="color: blue;">ByVal</span> sender <span style="color: blue;">As</span> <span style="color: blue;">Object</span>, <span style="color: blue;">ByVal</span> e <span style="color: blue;">As</span> EventArgs)</pre>
<pre style="margin: 0px;">        <span style="color: green;">' Fires when the application ends</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">End</span> <span style="color: blue;">Class</span></pre>
</div>
<p>Comments on Global.asax</p>
<ul>
<li>I have added some information logging in the Application_Start event. This will trigger every time the applications starts or recycles. If this occurs often you probably have some problems with resources on the server, ie. too little memory available for the application.</li>
<li>Application_Error occurs every time an unhandled error occurs. Use this to log all errors not logged elsewhere.</li>
<li>I have to initialize the logging framework in Application_Start by calling
<p style="margin: 0px;">LogManager.GetLogger(<span style="color: blue;">Me</span>.GetType).  I&#039;m not sure whether this is a bug or by design. It is not possible to let the LogHandler do the initialization. LogHandler is a wrapper class located in another assembly, maybe that is a problem, without really knowing why. LogManager is a class in Log4Net.</p>
</li>
</ul>
<h3>The LogHandler class</h3>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red163\green21\blue21;\red0\green128\blue0;}??\fs20 \cf1 Imports\cf0  System.Security.Principal\par ??\cf1 Imports\cf0  log4net\par ??\par ??\par ??\cf1 Public\cf0  \cf1 Class\cf0  LogHandler\par ??    \cf1 Const\cf0  _defaultApplicationLogger \cf1 As\cf0  \cf1 String\cf0  = \cf4 "Application"\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Enum\cf0  LogType\par ??        General\par ??        Notify\par ??    \cf1 End\cf0  \cf1 Enum\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  LogError(\cf1 ByVal\cf0  message \cf1 As\cf0  \cf1 String\cf0 , \cf1 ByVal\cf0  user \cf1 As\cf0  IPrincipal, \cf1 ByVal\cf0  url \cf1 As\cf0  Uri, \cf1 ByVal\cf0  [error] \cf1 As\cf0  Exception)\par ??        \cf1 Dim\cf0  logger \cf1 As\cf0  ILog = LogManager.GetLogger(_defaultApplicationLogger)\par ??        \cf1 If\cf0  \cf1 Not\cf0  [error].InnerException \cf1 Is\cf0  \cf1 Nothing\cf0  \cf1 Then\par ??\cf0             [error] = [error].InnerException\par ??        \cf1 End\cf0  \cf1 If\par ??\par ??\cf0         \cf5 'set user to log4net context, so we can use %X\{user\} in the appenders\par ??\cf0         \cf1 If\cf0  \cf1 Not\cf0  user \cf1 Is\cf0  \cf1 Nothing\cf0  \cf1 AndAlso\cf0  user.Identity.IsAuthenticated \cf1 Then\par ??\cf0             MDC.[Set](\cf4 "user"\cf0 , user.Identity.Name)\par ??        \cf1 End\cf0  \cf1 If\par ??\par ??\cf0         \cf5 'set url to log4net context, so we can use %X\{url\} in the appenders\par ??\cf0         MDC.[Set](\cf4 "url"\cf0 , url.ToString())\par ??\par ??        \cf1 If\cf0  logger.IsErrorEnabled \cf1 Then\par ??\cf0             logger.Error(message, [error])\par ??        \cf1 End\cf0  \cf1 If\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  LogInfo(\cf1 ByVal\cf0  message \cf1 As\cf0  \cf1 String\cf0 , \cf1 ByVal\cf0  type \cf1 As\cf0  LogType)\par ??        \cf1 Dim\cf0  logger \cf1 As\cf0  ILog = \cf1 Nothing\par ??\cf0         \cf1 If\cf0  type = LogType.Notify \cf1 Then\par ??\cf0             logger = LogManager.GetLogger(LogType.Notify.ToString)\par ??        \cf1 Else\par ??\cf0             logger = LogManager.GetLogger(_defaultApplicationLogger)\par ??        \cf1 End\cf0  \cf1 If\par ??\par ??\cf0         \cf1 If\cf0  logger.IsInfoEnabled \cf1 Then\par ??\cf0             logger.Info(message)\par ??        \cf1 End\cf0  \cf1 If\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??End\cf0  \cf1 Class\par ??} --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red163\green21\blue21;\red0\green128\blue0;}??\fs20 \cf1 Imports\cf0  System.Security.Principal\par ??\cf1 Imports\cf0  log4net\par ??\par ??\cf1 Public\cf0  \cf1 Class\cf0  LogHandler\par ??    \cf1 Const\cf0  _defaultApplicationLogger \cf1 As\cf0  \cf1 String\cf0  = \cf4 "Application"\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Enum\cf0  LogType\par ??        General\par ??        Notify\par ??    \cf1 End\cf0  \cf1 Enum\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  LogError(\cf1 ByVal\cf0  message \cf1 As\cf0  \cf1 String\cf0 , \cf1 ByVal\cf0  [error] \cf1 As\cf0  Exception)\par ??\par ??        \cf1 Dim\cf0  logger \cf1 As\cf0  ILog = LogManager.GetLogger(_defaultApplicationLogger)\par ??        \cf1 If\cf0  \cf1 Not\cf0  [error].InnerException \cf1 Is\cf0  \cf1 Nothing\cf0  \cf1 Then\par ??\cf0             [error] = [error].InnerException\par ??        \cf1 End\cf0  \cf1 If\par ??\par ??\cf0         \cf1 If\cf0  logger.IsErrorEnabled \cf1 Then\par ??\cf0             logger.Error(message, [error])\par ??        \cf1 End\cf0  \cf1 If\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  LogError(\cf1 ByVal\cf0  message \cf1 As\cf0  \cf1 String\cf0 , _\par ??                                \cf1 ByVal\cf0  user \cf1 As\cf0  IPrincipal, \cf1 ByVal\cf0  url \cf1 As\cf0  Uri, _\par ??                                \cf1 ByVal\cf0  [error] \cf1 As\cf0  Exception)\par ??        SetOptionalParametersOnLogger(user, url)\par ??        LogError(message, [error])\par ??    \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  LogInfo(\cf1 ByVal\cf0  message \cf1 As\cf0  \cf1 String\cf0 , \cf1 ByVal\cf0  type \cf1 As\cf0  LogType)\par ??        \cf1 Dim\cf0  logger \cf1 As\cf0  ILog = \cf1 Nothing\par ??\cf0         \cf1 If\cf0  type = LogType.Notify \cf1 Then\par ??\cf0             logger = LogManager.GetLogger(LogType.Notify.ToString)\par ??        \cf1 Else\par ??\cf0             logger = LogManager.GetLogger(_defaultApplicationLogger)\par ??        \cf1 End\cf0  \cf1 If\par ??\cf0         \cf1 If\cf0  logger.IsInfoEnabled \cf1 Then\par ??\cf0             logger.Info(message)\par ??        \cf1 End\cf0  \cf1 If\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  LogWarning(\cf1 ByVal\cf0  message \cf1 As\cf0  \cf1 String\cf0 , \cf1 ByVal\cf0  [error] \cf1 As\cf0  Exception)\par ??        \cf1 Dim\cf0  logger \cf1 As\cf0  ILog = LogManager.GetLogger(_defaultApplicationLogger)\par ??        \cf1 If\cf0  \cf1 Not\cf0  [error].InnerException \cf1 Is\cf0  \cf1 Nothing\cf0  \cf1 Then\par ??\cf0             [error] = [error].InnerException\par ??        \cf1 End\cf0  \cf1 If\par ??\cf0         \cf1 If\cf0  logger.IsWarnEnabled \cf1 Then\par ??\cf0             logger.Warn(message, [error])\par ??        \cf1 End\cf0  \cf1 If\par ??\cf0     \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Public\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  LogWarning(\cf1 ByVal\cf0  message \cf1 As\cf0  \cf1 String\cf0 , _\par ??                                 \cf1 ByVal\cf0  user \cf1 As\cf0  IPrincipal, \cf1 ByVal\cf0  url \cf1 As\cf0  Uri, _\par ??                                 \cf1 ByVal\cf0  [error] \cf1 As\cf0  Exception)\par ??        SetOptionalParametersOnLogger(user, url)\par ??        LogWarning(message, [error])\par ??    \cf1 End\cf0  \cf1 Sub\par ??\par ??\cf0     \cf1 Private\cf0  \cf1 Shared\cf0  \cf1 Sub\cf0  SetOptionalParametersOnLogger(\cf1 ByVal\cf0  user \cf1 As\cf0  IPrincipal, \cf1 ByVal\cf0  url \cf1 As\cf0  Uri)\par ??        \cf5 'set user to log4net context, so we can use %X\{user\} in the appenders\par ??\cf0         \cf1 If\cf0  \cf1 Not\cf0  user \cf1 Is\cf0  \cf1 Nothing\cf0  \cf1 AndAlso\cf0  user.Identity.IsAuthenticated \cf1 Then\par ??\cf0             MDC.[Set](\cf4 "user"\cf0 , user.Identity.Name)\par ??        \cf1 End\cf0  \cf1 If\par ??\par ??\cf0         \cf5 'set url to log4net context, so we can use %X\{url\} in the appenders\par ??\cf0         MDC.[Set](\cf4 "url"\cf0 , url.ToString())\par ??    \cf1 End\cf0  \cf1 Sub\par ??End\cf0  \cf1 Class\par ??\par ??} --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">Imports</span> System.Security.Principal</pre>
<pre style="margin: 0px;"><span style="color: blue;">Imports</span> log4net</pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;"><span style="color: blue;">Public</span> <span style="color: blue;">Class</span> LogHandler</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Const</span> _defaultApplicationLogger <span style="color: blue;">As</span> <span style="color: blue;">String</span> = <span style="color: #a31515;">"Application"</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Public</span> <span style="color: blue;">Enum</span> LogType</pre>
<pre style="margin: 0px;">        General</pre>
<pre style="margin: 0px;">        Notify</pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Enum</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Public</span> <span style="color: blue;">Shared</span> <span style="color: blue;">Sub</span> LogError(<span style="color: blue;">ByVal</span> message <span style="color: blue;">As</span> <span style="color: blue;">String</span>, <span style="color: blue;">ByVal</span> [error] <span style="color: blue;">As</span> Exception)</pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">        <span style="color: blue;">Dim</span> logger <span style="color: blue;">As</span> ILog = LogManager.GetLogger(_defaultApplicationLogger)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">If</span> <span style="color: blue;">Not</span> [error].InnerException <span style="color: blue;">Is</span> <span style="color: blue;">Nothing</span> <span style="color: blue;">Then</span></pre>
<pre style="margin: 0px;">            [error] = [error].InnerException</pre>
<pre style="margin: 0px;">        <span style="color: blue;">End</span> <span style="color: blue;">If</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">        <span style="color: blue;">If</span> logger.IsErrorEnabled <span style="color: blue;">Then</span></pre>
<pre style="margin: 0px;">            logger.Error(message, [error])</pre>
<pre style="margin: 0px;">        <span style="color: blue;">End</span> <span style="color: blue;">If</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Public</span> <span style="color: blue;">Shared</span> <span style="color: blue;">Sub</span> LogError(<span style="color: blue;">ByVal</span> message <span style="color: blue;">As</span> <span style="color: blue;">String</span>, _</pre>
<pre style="margin: 0px;">                                <span style="color: blue;">ByVal</span> user <span style="color: blue;">As</span> IPrincipal, <span style="color: blue;">ByVal</span> url <span style="color: blue;">As</span> Uri, _</pre>
<pre style="margin: 0px;">                                <span style="color: blue;">ByVal</span> [error] <span style="color: blue;">As</span> Exception)</pre>
<pre style="margin: 0px;">        SetOptionalParametersOnLogger(user, url)</pre>
<pre style="margin: 0px;">        LogError(message, [error])</pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Public</span> <span style="color: blue;">Shared</span> <span style="color: blue;">Sub</span> LogInfo(<span style="color: blue;">ByVal</span> message <span style="color: blue;">As</span> <span style="color: blue;">String</span>, <span style="color: blue;">ByVal</span> type <span style="color: blue;">As</span> LogType)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">Dim</span> logger <span style="color: blue;">As</span> ILog = <span style="color: blue;">Nothing</span></pre>
<pre style="margin: 0px;">        <span style="color: blue;">If</span> type = LogType.Notify <span style="color: blue;">Then</span></pre>
<pre style="margin: 0px;">            logger = LogManager.GetLogger(LogType.Notify.ToString)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">Else</span></pre>
<pre style="margin: 0px;">            logger = LogManager.GetLogger(_defaultApplicationLogger)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">End</span> <span style="color: blue;">If</span></pre>
<pre style="margin: 0px;">        <span style="color: blue;">If</span> logger.IsInfoEnabled <span style="color: blue;">Then</span></pre>
<pre style="margin: 0px;">            logger.Info(message)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">End</span> <span style="color: blue;">If</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Public</span> <span style="color: blue;">Shared</span> <span style="color: blue;">Sub</span> LogWarning(<span style="color: blue;">ByVal</span> message <span style="color: blue;">As</span> <span style="color: blue;">String</span>, <span style="color: blue;">ByVal</span> [error] <span style="color: blue;">As</span> Exception)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">Dim</span> logger <span style="color: blue;">As</span> ILog = LogManager.GetLogger(_defaultApplicationLogger)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">If</span> <span style="color: blue;">Not</span> [error].InnerException <span style="color: blue;">Is</span> <span style="color: blue;">Nothing</span> <span style="color: blue;">Then</span></pre>
<pre style="margin: 0px;">            [error] = [error].InnerException</pre>
<pre style="margin: 0px;">        <span style="color: blue;">End</span> <span style="color: blue;">If</span></pre>
<pre style="margin: 0px;">        <span style="color: blue;">If</span> logger.IsWarnEnabled <span style="color: blue;">Then</span></pre>
<pre style="margin: 0px;">            logger.Warn(message, [error])</pre>
<pre style="margin: 0px;">        <span style="color: blue;">End</span> <span style="color: blue;">If</span></pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Public</span> <span style="color: blue;">Shared</span> <span style="color: blue;">Sub</span> LogWarning(<span style="color: blue;">ByVal</span> message <span style="color: blue;">As</span> <span style="color: blue;">String</span>, _</pre>
<pre style="margin: 0px;">                                 <span style="color: blue;">ByVal</span> user <span style="color: blue;">As</span> IPrincipal, <span style="color: blue;">ByVal</span> url <span style="color: blue;">As</span> Uri, _</pre>
<pre style="margin: 0px;">                                 <span style="color: blue;">ByVal</span> [error] <span style="color: blue;">As</span> Exception)</pre>
<pre style="margin: 0px;">        SetOptionalParametersOnLogger(user, url)</pre>
<pre style="margin: 0px;">        LogWarning(message, [error])</pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">    <span style="color: blue;">Private</span> <span style="color: blue;">Shared</span> <span style="color: blue;">Sub</span> SetOptionalParametersOnLogger(<span style="color: blue;">ByVal</span> user <span style="color: blue;">As</span> IPrincipal, <span style="color: blue;">ByVal</span> url <span style="color: blue;">As</span> Uri)</pre>
<pre style="margin: 0px;">        <span style="color: green;">'set user to log4net context, so we can use %X{user} in the appenders</span></pre>
<pre style="margin: 0px;">        <span style="color: blue;">If</span> <span style="color: blue;">Not</span> user <span style="color: blue;">Is</span> <span style="color: blue;">Nothing</span> <span style="color: blue;">AndAlso</span> user.Identity.IsAuthenticated <span style="color: blue;">Then</span></pre>
<pre style="margin: 0px;">            MDC.[Set](<span style="color: #a31515;">"user"</span>, user.Identity.Name)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">End</span> <span style="color: blue;">If</span></pre>
<pre style="margin: 0px;"></pre>
<pre style="margin: 0px;">        <span style="color: green;">'set url to log4net context, so we can use %X{url} in the appenders</span></pre>
<pre style="margin: 0px;">        MDC.[Set](<span style="color: #a31515;">"url"</span>, url.ToString())</pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Sub</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">End</span> <span style="color: blue;">Class</span></pre>
<pre style="margin: 0px;"></pre>
</div>
</div>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"></div>
<p>Comments on LogHandler</p>
<ul>
<li>It&#039;s a pretty simple class which is easy to use. I could have added more wrapper methods with overload</li>
<li>The LogType enum defines whether the message should be notified (emailed) or not.</li>
<li>If I forget to set the level on the logger in the Log4Net.config, the logger.IsInfoEnabled will return false.</li>
<li>I am using the MDC class in the Log4Net framework to add the custom entries in the logged message for user and url (see Log4Net.config above)</li>
</ul>
<h3>Handling an error and notifying with success</h3>
<p>Sometimes when you know what could go wrong and you want to display a nice error message to the user, you could handle the error and display an errormessage to the user.</p>
<p>Example:</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red163\green21\blue21;}??\fs20     \cf3 Private\cf0  \cf3 Function\cf0  CreateUser() \cf3 As\cf0  User\par ??        \cf3 Dim\cf0  userName \cf3 As\cf0  \cf3 String\cf0  = TextBoxUserName.Text\par ??        \cf3 Dim\cf0  password \cf3 As\cf0  \cf3 String\cf0  = TextBoxPassword.Text\par ??        \cf3 Try\par ??\cf0             \cf3 Dim\cf0  user \cf3 As\cf0  \cf3 New\cf0  User(userName, password)\par ??            LogHandler.LogInfo(\cf4 "Yahoo! User with username "\cf0  &amp; userName &amp; \cf4 " created."\cf0 , LogHandler.LogType.Notify)\par ??            \cf3 Return\cf0  user\par ??        \cf3 Catch\cf0  iunex \cf3 As\cf0  InvalidUserNameException\par ??            Tools.AlertError(Page, iunex)\par ??            LogHandler.LogError(\cf4 "Error creating user with username "\cf0  &amp; userName, HttpContext.Current.User, HttpContext.Current.Request.Url, iunex)\par ??        \cf3 Catch\cf0  ipex \cf3 As\cf0  InvalidPasswordException\par ??            Tools.AlertError(Page, iunex)\par ??            LogHandler.LogError(\cf4 "Error creating user with password "\cf0  &amp; password, HttpContext.Current.User, HttpContext.Current.Request.Url, ipex)\par ??        \cf3 End\cf0  \cf3 Try\par ??\cf0     \cf3 End\cf0  \cf3 Function\par ??} --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">Private</span> <span style="color: blue;">Function</span> CreateUser() <span style="color: blue;">As</span> User</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Dim</span> userName <span style="color: blue;">As</span> <span style="color: blue;">String</span> = TextBoxUserName.Text</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Dim</span> password <span style="color: blue;">As</span> <span style="color: blue;">String</span> = TextBoxPassword.Text</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Try</span></pre>
<pre style="margin: 0px;">        <span style="color: blue;">Dim</span> user <span style="color: blue;">As</span> <span style="color: blue;">New</span> User(userName, password)</pre>
<pre style="margin: 0px;">        LogHandler.LogInfo(<span style="color: #a31515;">"Yahoo! User with username "</span> &amp; userName &amp; <span style="color: #a31515;">" created."</span>,
                           LogHandler.LogType.Notify)</pre>
<pre style="margin: 0px;">        <span style="color: blue;">Return</span> user</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Catch</span> iunex <span style="color: blue;">As</span> InvalidUserNameException</pre>
<pre style="margin: 0px;">        PageTools.DisplayError(Page, iunex)</pre>
<pre style="margin: 0px;">        LogHandler.LogWarning(<span style="color: #a31515;">"Error creating user with username "</span> &amp; userName, iunex)</pre>
<pre style="margin: 0px;">    <span style="color: blue;">Catch</span> ipex <span style="color: blue;">As</span> InvalidPasswordException</pre>
<pre style="margin: 0px;">        PageTools.DisplayError(Page, ipex)</pre>
<pre style="margin: 0px;">        LogHandler.LogWarning(<span style="color: #a31515;">"Error creating user with password "</span> &amp; password, ipex)</pre>
<pre style="margin: 0px;">    <span style="color: blue;">End</span> <span style="color: blue;">Try
    Return Nothing</span></pre>
<pre style="margin: 0px;"><span style="color: blue;">End</span> <span style="color: blue;">Function</span></pre>
</div>
<p>Comments on CreateUser:</p>
<ul>
<li>If successful, a notification is sent by email by using the LogInfo method and using LogHandler.Logtype.Notify</li>
<li>The User class will throw InvalidUserNameException or InvalidPasswordException in the credentials are invalid. I wish to display the errors to the user instead of displaying a general error page. In real life I would probably use some validation before calling the User constructor, but this is only an example.  <img src='http://hamang.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
<li>In addition to displaying the error to the user, the error is logged as a warning.This means it will be logged, but no email will be sent to the mailbox as this is not an error in the application.</li>
<li>All other exceptions raised when creating the user will be caught in Application_Error in Global.asax and logged there.</li>
</ul>
<h3>Loginformation</h3>
<p>Ok, now I have all the code I need to do decent logging. So what do I expect to see in the logfiles?</p>
<p>When building the application in DEBUG mode I will see the following in the logfile:</p>
<pre>2008-12-11 16:56:24,453 [14] INFO  Application (null) (null) - ============================
2008-12-11 16:56:24,468 [14] INFO  Application (null) (null) -     Starting application
2008-12-11 16:56:24,468 [14] INFO  Application (null) (null) - ============================
2008-12-11 16:56:25,937 [14] WARN Application 3DX5G3J\knuth http://localhost/fdb/default.aspx -
                                  Error creating user with username Knut Hamang
DAL.InvalidUserNameException: Username is already in use! Please select another username.
   at DAL.User..ctor(String username, String password) in C:\Knut\code\Repository\Internal_Systems\fdb\trunk\DAL\User.vb:line 97
   at fdb.default.CreateUser() in C:\Knut\code\Repository\Internal_Systems\fdb\trunk\Web\default.aspx.vb:line 69</pre>
<p>Building in RELEASE  mode I get the following information:</p>
<pre>2008-12-11 16:59:21,406 [14] INFO  Application (null) (null) - ============================
2008-12-11 16:59:21,421 [14] INFO  Application (null) (null) -     Starting application
2008-12-11 16:59:21,421 [14] INFO  Application (null) (null) - ============================
2008-12-11 16:59:22,812 [14] WARN Application 3DX5G3J\knuth http://localhost/fdb/default.aspx -
                             Error creating user with username Knut Hamang
DAL.InvalidUserNameException: Username is already in use! Please select another username.
   at DAL.User..ctor(String username, String password)
   at fdb.default.CreateUser()</pre>
<p>The difference is the stacktrace. I get the stacktrace in both cases, but I also get the line numbers in DEBUG mode. I can still read the trace and locate the method in the file that throws the error. The conclusion is that I get enough information to trace and fix the error, if there is one.</p>
<p>Please leave any comments on the configuration, and feel free to discuss different logging strategies for Web Applications.</p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2008/12/12/using-log4net-in-web-applications-a-reallife-example/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>bug: VS 2008 &#8211; Web Application Project opened as Web Site</title>
		<link>http://hamang.net/2008/11/03/bug-vs-2008-web-application-project-opened-as-web-site/</link>
		<comments>http://hamang.net/2008/11/03/bug-vs-2008-web-application-project-opened-as-web-site/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 12:44:28 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=153</guid>
		<description><![CDATA[I just bumped into a weird Visual Studio (aka. Vicious Studio)  bug. Not the first, but this is a pretty annoying one. I have taken an old .NET 1.1 Web application and converted it to .NET 3.5 using the VS Conversion Wizard. Everything seems ok, and I convert to Web Site to a Web Application [...]]]></description>
			<content:encoded><![CDATA[<p>I just bumped into a weird Visual Studio (aka. Vicious Studio)  bug. Not the first, but this is a pretty annoying one. I have taken an old .NET 1.1 Web application and converted it to .NET 3.5 using the VS Conversion Wizard. Everything seems ok, and I convert to Web Site to a Web Application Project. No problems so far. I fix some issues, close the solution, do some other stuff. Some days later I open the solution again. I then have about 200 errors and the Web Application Project is opened as a Web Site. Also the designer and resx files are not connected to the asp and codebehind files:</p>
<p><a href="http://hamang.net/wp-content/uploads/2008/11/proj_err.png"><img class="size-full wp-image-155 alignnone" title="disconnected files" src="http://hamang.net/wp-content/uploads/2008/11/proj_err.png" alt="" width="255" height="81" /></a></p>
<div style="clear:both;">It&#039;s not possible to change the project type in Visual Studio, as the project does not have a &#034;properties&#034; context menu item. The only option in the context menu is &#034;property pages&#034; as with regular web sites. Visual Studio actually thinks it&#039;s a Web Site and not a Web Application project anymore. The other missing context menu option is the &#034;Convert to Web Application&#034;. So Visual Studio thinks it&#039;s a Web Site that cannot be converted to a Web Application Project. Not surprisingly as I converted the Web Site to a Web Application Project right after the Conversion Wizard.</p>
<p>Ok, I have to start digging into the project and solution files. Comparing them to other solutions using Web Application project files, I can&#039;t seem to find anything suspicious. After some googling with no result, I decide to stare at the screen for a while and use WinMerge to determine what the difference might be. Suddenly I find one minor difference:</p>
<p>The solution file that works:</p>
<p><em>Project(&#034;{F184B08F-C81C-45F6-A57F-5ABD9991F28F}&#034;) = &#034;Clock&#034;, &#034;Clock.vbproj&#034;, &#034;{3B3D0F02-D310-4BFB-83AD-F62758BB8624}&#034;</em></p>
<p>The one that fails:</p>
<p><em>Project(&#034;{F184B08F-C81C-45F6-A57F-5ABD9991F28F}&#034;) = &#034;Calendar&#034;, &#034;Calendar\&#034;, &#034;{7B411329-B1CB-457F-A954-898DX16B85A6}&#034;</em></p>
<p>That&#039;s it. The Calendar project reference is missing the whole path to the project file. When i change it to:</p>
<p><em>Project(&#034;{F184B08F-C81C-45F6-A57F-5ABD9991F28F}&#034;) = &#034;Calendar&#034;, &#034;<strong>Calendar\Calendar.vbproj</strong>&#034;, &#034;{7B411329-B1CB-457F-A954-898DX16B85A6}&#034;</em></p>
<p>it opens as a Web Application Project, and now the resx and designer files are properly connected:</p></div>
<p><a href="http://hamang.net/wp-content/uploads/2008/11/proj_ok.png"><img class="alignnone size-full wp-image-156" title="files connected" src="http://hamang.net/wp-content/uploads/2008/11/proj_ok.png" alt="" width="248" height="96" /></a></p>
<div style="clear:both;">There might be other issues causing this behaviour, but at least this solved my problem. This is just the everyday life using Visual Studio. Actually I think it&#039;s a great IDE, but there are some strange behaviours now and then.</div>
<div style="clear:both;"></div>
<div style="clear:both;"><strong>Update </strong>- In some occasions you might wan&#039;t to remove the .webinfo file. This file can be causing this behaviour.  Just remove it and instead set the startup path for your application in properties for the Web Application project.</div>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2008/11/03/bug-vs-2008-web-application-project-opened-as-web-site/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>New version of the Silverlight Calendar</title>
		<link>http://hamang.net/2008/10/03/new-version-of-the-silverlight-calendar/</link>
		<comments>http://hamang.net/2008/10/03/new-version-of-the-silverlight-calendar/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 13:36:46 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Silverlight]]></category>

		<guid isPermaLink="false">http://hamang.net/?p=144</guid>
		<description><![CDATA[Some time ago, I wrote a birthday calendar in Silverlight 1.0. It was purely JavaScript and somewhat restricted because of that. Later I upgraded it to Silverlight 1.1, the first version of Silverlight that used managed code. Silverlight 1.1 is now Silverlight 2.0, but there has been a lot of changes between those version. So [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago, I wrote a <a href="/2008/01/29/silverligthcalendar/">birthday calendar</a> in Silverlight 1.0. It was purely JavaScript and somewhat restricted because of that. Later I upgraded it to Silverlight 1.1, the first version of Silverlight that used managed code. Silverlight 1.1 is now Silverlight 2.0, but there has been a lot of changes between those version.<br />
So here is the latest version compatible With Silverlight 2.0 Beta 2. I also added <a href="http://blogs.msdn.com/timrule/archive/2008/04/29/innerglow-effect-for-silverlight-2-beta-1.aspx" target="_blank">Tim Rule&#039;s excellent glowing and shadow effects</a>, which are just awesome!</p>
<p>Download it <a href="/files/SilverlightCalendar2.zip">here</a>.</p>
<p><a href="http://hamang.net/wp-content/uploads/2008/10/calendar2_2.jpg"><img class="alignnone size-medium wp-image-145" title="calendar Silverlight 2 Beta 2" src="http://hamang.net/wp-content/uploads/2008/10/calendar2_2-500x312.jpg" alt="" width="500" height="312" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2008/10/03/new-version-of-the-silverlight-calendar/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Html to Pdf in .NET</title>
		<link>http://hamang.net/2008/08/14/html-to-pdf-in-net/</link>
		<comments>http://hamang.net/2008/08/14/html-to-pdf-in-net/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 14:47:41 +0000</pubDate>
		<dc:creator>Knut Hamang</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Pdf]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I searched around for some OpenSource projects converting HTML to PDF, and stumbled upon a great library called iTextSharp . It&#039;s actually a Java library ported to .NET (typically isn&#039;t it?), and it has some really nice features. There are some good commercial products out there doing the same, but in my opinion this is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="/wp-content/uploads/2008/09/reader_icon_special.jpg"><img class="size-medium wp-image-31 alignleft" title="PDF" src="/wp-content/uploads/2008/09/reader_icon_special.jpg" alt="" width="125" height="104" /></a>I searched around for some OpenSource projects <strong>converting HTML to PDF</strong>, and stumbled upon a great library called <a href="http://sourceforge.net/projects/itextsharp/?abmode=1" target="_blank">iTextSharp</a> . It&#039;s actually a Java library ported to .NET (typically isn&#039;t it?), and it has some really nice features. There are some good commercial products out there doing the same, but in my opinion this is core functionality, so if one can get it for free and even get the source, nothing is better than that!</p>
<p>Regarding PDF creation, iTextSharps main function is <strong>generating PDF from scratch</strong>, not converting them from HTML. The library has a really understandable API for developers that are not familiar with the PDF specification, me beeing one of them.</p>
<p>Playing around with the API and reading some news lists and forum posts, I finally managed to get a working sample on how to export a GridView to PDF. This is a pretty simple sample, but you can play around with the API to add more formatting and do your stuff. Actually <strong>you can export anything in the XHTML</strong>, providing the markup is legal. However, <strong>not all html tags are supported</strong>. The intention of the author was not to make a HTML2PDF converter, but more like create PDF&#039;s from HTML if the markup supports the engine. So you will probably not be able to convert dynamic content you do not have control over, but it&#039;s excellent for creating reports etc. Supported tags are: &#034;ol ul li a pre font span br p div body table td th tr i b u sub sup em strong s strike h1 h2 h3 h4 h5 h6 img&#034;</p>
<p>So how does it work, then? Well, first you need to get the latest version of iTextSharp. Just place the dll to your bin folder in your Web Application Project (you&#039;re not using Web Projects, are you  <img src='http://hamang.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) and add a reference to it. Then create a new page, add a <strong>PlaceHolder</strong> to it, The placeholder will be the section of the HTML that you will export to PDF. You can add some more controls to the placeholder if you need. Inside the placeholder add a GridView and bind it to your datasource.</p>
<p>Add a ASP:Button to the page. This will trigger the export. The code when the button is clicked is doing all the exporting stuff:</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red0\green128\blue0;\red163\green21\blue21;}??\fs20 \cf1 protected\cf0  \cf1 void\cf0  ButtonCreatePdf_Click(\cf1 object\cf0  sender, \cf4 EventArgs\cf0  e)\par ??        \{\par ??            \cf5 //Set content type in response stream\par ??\cf0             Response.ContentType = \cf6 "application/pdf"\cf0 ;\par ??            Response.AddHeader(\cf6 "content-disposition"\cf0 , \cf6 "attachment;filename=FileName.pdf"\cf0 );\par ??            Response.Cache.SetCacheability(\cf4 HttpCacheability\cf0 .NoCache);\par ??\par ??            \cf5 //Render PlaceHolder to temporary stream \par ??\cf0             System.IO.\cf4 StringWriter\cf0  stringWrite = \cf1 new\cf0  \cf4 StringWriter\cf0 ();\par ??            System.Web.UI.\cf4 HtmlTextWriter\cf0  htmlWrite = \cf1 new\cf0  \cf4 HtmlTextWriter\cf0 (stringWrite);\par ??            PlaceholderPdf.RenderControl(htmlWrite);\par ??            \cf4 StringReader\cf0  reader = \cf1 new\cf0  \cf4 StringReader\cf0 (stringWrite.ToString());\par ??\par ??            \cf5 //Create PDF document \par ??\cf0             \cf4 Document\cf0  doc = \cf1 new\cf0  \cf4 Document\cf0 (\cf4 PageSize\cf0 .A4);\par ??            \cf4 HTMLWorker\cf0  parser = \cf1 new\cf0  \cf4 HTMLWorker\cf0 (doc);\par ??            \cf4 PdfWriter\cf0 .GetInstance(doc, Response.OutputStream);\par ??            doc.Open();\par ??            \par ??            \cf1 try\par ??\cf0             \{\par ??                \cf5 //Create a footer that will display page number\par ??\cf0                 \cf4 HeaderFooter\cf0  footer = \cf1 new\cf0  \cf4 HeaderFooter\cf0 (\cf1 new\cf0  \cf4 Phrase\cf0 (\cf6 "This is page: "\cf0 ), \cf1 true\cf0 ) \par ??                                           \{ Border = \cf4 Rectangle\cf0 .NO_BORDER \};\par ??                doc.Footer = footer;\par ??                \par ??                \cf5 //Parse Html\par ??\cf0                 parser.Parse(reader);\par ??            \}\par ??            \cf1 catch\cf0  (\cf4 Exception\cf0  ex)\par ??            \{\par ??                \cf5 //Display parser errors in PDF. \par ??\cf0                 \cf5 //Parser errors will also be wisible in Debug.Output window in VS\par ??\cf0                 \cf4 Paragraph\cf0  paragraph = \cf1 new\cf0  \cf4 Paragraph\cf0 (\cf6 "Error! "\cf0  + ex.Message);\par ??                paragraph.SetAlignment(\cf6 "center"\cf0 );\par ??                \cf4 Chunk\cf0  text = paragraph.Chunks[0] \cf1 as\cf0  \cf4 Chunk\cf0 ;\par ??                \cf1 if\cf0  (text != \cf1 null\cf0 )\par ??                \{\par ??                    text.Font.Color = \cf4 Color\cf0 .RED;\par ??                \}\par ??                doc.Add(paragraph);\par ??            \}\par ??            \cf1 finally\par ??\cf0             \{\par ??                doc.Close();\par ??            \}\par ??        \}} --></p>
<div style="font-size: 10pt; background: white; color: black; font-family: Courier New; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">
<p style="margin: 0px"><span style="color: #0000ff;"> protected</span> <span style="color: #0000ff;">void</span> ButtonCreatePdf_Click(<span style="color: #0000ff;">object</span> sender, <span style="color: #2b91af;">EventArgs</span> e)</p>
<p style="margin: 0px">{</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #008000;">//Set content type in response stream</span></p>
<p style="margin: 0px; padding-left: 30px;">Response.ContentType = <span style="color: #a31515;">&#034;application/pdf&#034;</span>;</p>
<p style="margin: 0px; padding-left: 30px;">Response.AddHeader(<span style="color: #a31515;">&#034;content-disposition&#034;</span>, <span style="color: #a31515;">&#034;attachment;filename=FileName.pdf&#034;</span>);</p>
<p style="margin: 0px; padding-left: 30px;">Response.Cache.SetCacheability(<span style="color: #2b91af;">HttpCacheability</span>.NoCache);</p>
<p style="margin: 0px; padding-left: 30px;">
<p style="margin: 0px; padding-left: 30px;"><span style="color: #008000;">//Render PlaceHolder to temporary stream </span></p>
<p style="margin: 0px; padding-left: 30px;">System.IO.<span style="color: #2b91af;">StringWriter</span> stringWrite = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">StringWriter</span>();</p>
<p style="margin: 0px; padding-left: 30px;">System.Web.UI.<span style="color: #2b91af;">HtmlTextWriter</span> htmlWrite = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">HtmlTextWriter</span>(stringWrite);</p>
<p style="margin: 0px; padding-left: 30px;">PlaceholderPdf.RenderControl(htmlWrite);</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #2b91af;">StringReader</span> reader = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">StringReader</span>(stringWrite.ToString());</p>
<p style="margin: 0px; padding-left: 30px;">
<p style="margin: 0px; padding-left: 30px;"><span style="color: #008000;">//Create PDF document </span></p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #2b91af;">Document</span> doc = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">Document</span>(<span style="color: #2b91af;">PageSize</span>.A4);</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #2b91af;">HTMLWorker</span> parser = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">HTMLWorker</span>(doc);</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #2b91af;">PdfWriter</span>.GetInstance(doc, Response.OutputStream);</p>
<p style="margin: 0px; padding-left: 30px;">doc.Open();</p>
<p style="margin: 0px; padding-left: 30px;">
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;">try</span></p>
<p style="margin: 0px; padding-left: 30px;">{</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #008000;">//Create a footer that will display page number</span></p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #2b91af;">HeaderFooter</span> footer = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">HeaderFooter</span>(<span style="color: #0000ff;">new</span> <span style="color: #2b91af;">Phrase</span>(<span style="color: #a31515;">&#034;This is page: &#034;</span>), <span style="color: #0000ff;">true</span>)</p>
<p style="margin: 0px; padding-left: 60px;">{ Border = <span style="color: #2b91af;">Rectangle</span>.NO_BORDER };</p>
<p style="margin: 0px; padding-left: 60px;">doc.Footer = footer;</p>
<p style="margin: 0px; padding-left: 60px;">
<p style="margin: 0px; padding-left: 60px;"><span style="color: #008000;">//Parse Html</span></p>
<p style="margin: 0px; padding-left: 60px;">parser.Parse(reader);</p>
<p style="margin: 0px; padding-left: 30px;">}</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;">catch</span> (<span style="color: #2b91af;">Exception</span> ex)</p>
<p style="margin: 0px; padding-left: 30px;">{</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #008000;">//Display parser errors in PDF. </span></p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #008000;">//Parser errors will also be wisible in Debug.Output window in VS</span></p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #2b91af;">Paragraph</span> paragraph = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">Paragraph</span>(<span style="color: #a31515;">&#034;Error! &#034;</span> + ex.Message);</p>
<p style="margin: 0px; padding-left: 60px;">paragraph.SetAlignment(<span style="color: #a31515;">&#034;center&#034;</span>);</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #2b91af;">Chunk</span> text = paragraph.Chunks[0] <span style="color: #0000ff;">as</span> <span style="color: #2b91af;">Chunk</span>;</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #0000ff;">if</span> (text != <span style="color: #0000ff;">null</span>)</p>
<p style="margin: 0px; padding-left: 60px;">{</p>
<p style="margin: 0px; padding-left: 90px;">text.Font.Color = <span style="color: #2b91af;">Color</span>.RED;</p>
<p style="margin: 0px; padding-left: 60px;">}</p>
<p style="margin: 0px; padding-left: 60px;">doc.Add(paragraph);</p>
<p style="margin: 0px; padding-left: 30px;">}</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;">finally</span></p>
<p style="margin: 0px; padding-left: 30px;">{</p>
<p style="margin: 0px; padding-left: 60px;">doc.Close();</p>
<p style="margin: 0px; padding-left: 30px;">}</p>
<p style="margin: 0px">}</p>
<p style="margin: 0px">
</div>
<p>Almost there. Clicking the button will result in an exception:</p>
<p class="error">Control &#039;GridView1&#039; of type &#039;GridView&#039; must be placed inside a form tag with runat=server.</p>
<p>This is because we are trying to render the PlaceHolder control in a stream and not in a WebForm. A neat .NET security feature to prevent Injection attacks. This exception is simply ignored by adding the following code to the page:</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">void</span> VerifyRenderingInServerForm(<span style="color: #2b91af;">Control</span> control)</p>
<p style="margin: 0px;">{</p>
<p style="margin: 0px;">
<p style="margin: 0px;">}</p>
</div>
<p>Now, clicking the button again results in another Exception:</p>
<p class="error">RegisterForEventValidation can only be called during Render();</p>
<p>Again, a security feature of .NET. Ignore this excpetion by setting EnableEventValidation=&#034;False&#034; in the Page header. <strong>If you are concerned about the security</strong> of the page, please check official documentation of the features that has been disabled for the page.</p>
<p>Now, clicking the button should result in a PDF document. If not, debug the application and check <strong>Debut Output</strong> window for exceptions. Probably the XHTML in the placeholder is not valid.</p>
<p>Note that I am using <strong>HTMLWorker </strong>class instead of the HtmlParser class in the iTextSharp library. According the the author, the HTMLParser is not supported. I tried both, and the HTMLWorker swallows a lot more HTML markup than the HtmlParser.</p>
<p>You probably also want to <strong>clean the HTML</strong> before parsing it with the HTMLWorker. Typically you want to remove javascript postbacks, anchors etc. from the GridView. This can be achieved with the following code:</p>
<p><!--<br />
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20             \cf3 string\cf0  html = stringWrite.ToString();\par ??            html = \cf4 Regex\cf0 .Replace(html, \cf5 "&lt;/?(a|A).*?&gt;"\cf0 , \cf5 ""\cf0 );\par ??            \cf4 StringReader\cf0  reader = \cf3 new\cf0  \cf4 StringReader\cf0 (html);}<br />
--></p>
<div style="font-size: 10pt; background: white; color: black; font-family: Courier New; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">
<p style="margin: 0px"><span style="color: #0000ff;">string</span> html = stringWrite.ToString();</p>
<p style="margin: 0px">html = <span style="color: #2b91af;">Regex</span>.Replace(html, <span style="color: #a31515;">&#034;&lt;/?(a|A).*?&gt;&#034;</span>, <span style="color: #a31515;">&#034;&#034;</span>);</p>
<p style="margin: 0px"><span style="color: #2b91af;">StringReader</span> reader = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">StringReader</span>(html);</p>
</div>
<p>You can also <strong>extend the HTMLWorker class </strong>making it more specialized for your purpose. For instance it would be great to be able to define pagebreaks in the final PDF document. Simply create a new class inherited from HTMLWorker.</p>
<p><!--<br />
{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf1 public\cf0  \cf1 class\cf0  \cf4 HTMLWorkerExtended\cf0  : \cf4 HTMLWorker\par ??\cf0     \{\par ??        \cf1 public\cf0  HTMLWorkerExtended(\cf4 IDocListener\cf0  document) : \cf1 base\cf0 (document)\par ??        \{\}\par ??\par ??        \cf1 public\cf0  \cf1 override\cf0  \cf1 void\cf0  StartElement(\cf4 String\cf0  tag, \cf4 Hashtable\cf0  h)\par ??        \{\par ??            \cf1 if\cf0  (tag.Equals(\cf5 "newpage"\cf0 ))\par ??                document.Add(\cf4 Chunk\cf0 .NEXTPAGE);\par ??            \cf1 else\par ??\cf0                 \cf1 base\cf0 .StartElement(tag, h);\par ??        \}\par ??    \}}<br />
--></p>
<div style="font-size: 10pt; background: white; color: black; font-family: Courier New; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">
<p style="margin: 0px"><span style="color: #0000ff;"> public</span> <span style="color: #0000ff;">class</span> <span style="color: #2b91af;">HTMLWorkerExtended</span> : <span style="color: #2b91af;">HTMLWorker</span></p>
<p style="margin: 0px">{</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;">public</span> HTMLWorkerExtended(<span style="color: #2b91af;">IDocListener</span> document) : <span style="color: #0000ff;">base</span>(document)</p>
<p style="margin: 0px; padding-left: 30px;">{}</p>
<p style="margin: 0px; padding-left: 30px;">
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">override</span> <span style="color: #0000ff;">void</span> StartElement(<span style="color: #2b91af;">String</span> tag, <span style="color: #2b91af;">Hashtable</span> h)</p>
<p style="margin: 0px; padding-left: 30px;">{</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #0000ff;">if</span> (tag.Equals(<span style="color: #a31515;">&#034;newpage&#034;</span>))</p>
<p style="margin: 0px; padding-left: 90px;">document.Add(<span style="color: #2b91af;">Chunk</span>.NEXTPAGE);</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #0000ff;">else</span></p>
<p style="margin: 0px; padding-left: 90px;"><span style="color: #0000ff;">base</span>.StartElement(tag, h);</p>
<p style="margin: 0px; padding-left: 30px;">}</p>
<p style="margin: 0px">}</p>
</div>
<p>Now, simply replace the HTMLWorker with the extended version and add a <strong>&lt;newpage /&gt;</strong> element to the HTML in the placeholder where you want a new page.</p>
<p><strong>There are some css styles not supported by default</strong>. For instance it is not possible to set the background-color style for an image or tablecell/-row. The only solution for adding more style support is changing the iTextSharp source. It&#039;s pretty simple, however. Open <strong>\text\html\simpleparser\FactoryProperties.cs</strong>. In the <strong>InsertStyle</strong> method add the following code to the foreach loop:</p>
<p><!--<br />
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red0\green0\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf1 else\cf0  \cf1 if\cf0  (key.Equals(\cf4 Markup\cf0 .CSS_KEY_BGCOLOR))\par ??                \{\par ??                    \cf4 Color\cf0  c = \cf4 Markup\cf0 .DecodeColor(prop[key]);\par ??                    \cf1 if\cf0  (c != \cf1 null\cf0 )\par ??                    \{\par ??                        \cf1 int\cf0  hh = c.ToArgb() &amp; 0xffffff;\par ??                        \cf4 String\cf0  hs = \cf5 "#"\cf0  + hh.ToString(\cf5 "X06"\cf0 , \cf4 NumberFormatInfo\cf0 .InvariantInfo);\par ??                        h[\cf5 "bgcolor"\cf0 ] = hs;\par ??                    \}\par ??                \}  }<br />
--></p>
<div style="font-size: 10pt; background: white; color: black; font-family: Courier New">
<p style="margin: 0px"><span style="color: #0000ff;"> else</span> <span style="color: #0000ff;">if</span> (key.Equals(<span style="color: #2b91af;">Markup</span>.CSS_KEY_BGCOLOR))</p>
<p style="margin: 0px"><span style="color: #0000ff;"> </span>{</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #2b91af;"><span style="color: #000000;"> </span><span style="color: #0000ff;"> </span>Color</span> c = <span style="color: #2b91af;">Markup</span>.DecodeColor(prop[key]);</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;"> if</span> (c != <span style="color: #0000ff;">null</span>)</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;"> </span>{</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #0000ff;"> int</span> hh = c.ToArgb() &amp; 0xffffff;</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #0000ff;"> </span><span style="color: #2b91af;">String</span> hs = <span style="color: #a31515;">&#034;#&#034;</span> + hh.ToString(<span style="color: #a31515;">&#034;X06&#034;</span>, <span style="color: #2b91af;">NumberFormatInfo</span>.InvariantInfo);</p>
<p style="margin: 0px; padding-left: 60px;"><span style="color: #0000ff;"> </span>h[<span style="color: #a31515;">"bgcolor"</span>] = hs;</p>
<p style="margin: 0px; padding-left: 30px;"><span style="color: #0000ff;"> </span>}</p>
<p style="margin: 0px"><span style="color: #0000ff;"> </span>}</p>
</div>
<p><strong>Update: </strong>Another example for adding border color to a table:</p>
<p>First, set the border style for the table, ie. style=&#034;border-color: #ff0000;&#034;</p>
<p>Then again, you need to apply the style to <strong>FactoryProperties.cs</strong> file as in the example above.</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20                 \cf3 else\cf0  \cf3 if\cf0  (key.Equals(\cf4 Markup\cf0 .CSS_KEY_BORDERCOLOR))\par ??                \{\par ??                    \cf4 Color\cf0  c = \cf4 Markup\cf0 .DecodeColor(prop[key]);\par ??                    \cf3 if\cf0  (c != \cf3 null\cf0 )\par ??                    \{\par ??                        \cf3 int\cf0  hh = c.ToArgb() &amp; 0xffffff;\par ??                        \cf4 String\cf0  hs = \cf5 "#"\cf0  + hh.ToString(\cf5 "X06"\cf0 , \cf4 NumberFormatInfo\cf0 .InvariantInfo);\par ??                        h[\cf5 "border-color"\cf0 ] = hs;\par ??                    \}\par ??                \}  } --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: blue;">else</span> <span style="color: blue;">if</span> (key.Equals(<span style="color: #2b91af;">Markup</span>.CSS_KEY_BORDERCOLOR))</pre>
<pre style="margin: 0px;">{</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">Color</span> c = <span style="color: #2b91af;">Markup</span>.DecodeColor(prop[key]);</pre>
<pre style="margin: 0px;">    <span style="color: blue;">if</span> (c != <span style="color: blue;">null</span>)</pre>
<pre style="margin: 0px;">    {</pre>
<pre style="margin: 0px;">        <span style="color: blue;">int</span> hh = c.ToArgb() &amp; 0xffffff;</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">String</span> hs = <span style="color: #a31515;">"#"</span> + hh.ToString(<span style="color: #a31515;">"X06"</span>, <span style="color: #2b91af;">NumberFormatInfo</span>.InvariantInfo);</pre>
<pre style="margin: 0px;">        h[<span style="color: #a31515;">"border-color"</span>] = hs;</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p>In addition you need to alter the output of the table as there is no default &#034;bordercolor&#034; style property in the IncTable class.</p>
<p>Open <strong>IncTable.cs</strong> and change the following code in the <strong>BuildTable </strong>method:<br />
Existing code:</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20             \cf3 for\cf0  (\cf3 int\cf0  row = 0; row &lt; rows.Count; ++row) \{\par ??                \cf4 ArrayList\cf0  col = (\cf4 ArrayList\cf0 )rows[row];\par ??                \cf3 for\cf0  (\cf3 int\cf0  k = 0; k &lt; col.Count; ++k) \{\par ??                    table.AddCell((\cf4 PdfPCell\cf0 )col[k]);\par ??                \}\par ??            \}} --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<pre style="margin: 0px;"><span style="color: blue;">for</span> (<span style="color: blue;">int</span> row = 0; row &lt; rows.Count; ++row) {</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">ArrayList</span> col = (<span style="color: #2b91af;">ArrayList</span>)rows[row];</pre>
<pre style="margin: 0px;">    <span style="color: blue;">for</span> (<span style="color: blue;">int</span> k = 0; k &lt; col.Count; ++k) {</pre>
<pre style="margin: 0px;">        table.AddCell((<span style="color: #2b91af;">PdfPCell</span>)col[k]);</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p>Replace with:</p>
<p><!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red163\green21\blue21;\red0\green0\blue255;}??\fs20             \cf3 String\cf0  bordercolor = (\cf3 String\cf0 )props[\cf4 "bordercolor"\cf0 ];\par ??            \cf5 for\cf0  (\cf5 int\cf0  row = 0; row &lt; rows.Count; ++row)\par ??            \{\par ??                \cf3 ArrayList\cf0  col = (\cf3 ArrayList\cf0 )rows[row];\par ??                \cf5 for\cf0  (\cf5 int\cf0  k = 0; k &lt; col.Count; ++k)\par ??                \{\par ??                    \cf3 PdfPCell\cf0  cell = (\cf3 PdfPCell\cf0 )col[k];\par ??                    cell.BorderColor = \cf3 Markup\cf0 .DecodeColor(bordercolor);\par ??                    table.AddCell(cell);\par ??                \}\par ??            \}\par ??} --></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black;">
<pre style="margin: 0px;"><span style="color: #2b91af;">String</span> bordercolor = (<span style="color: #2b91af;">String</span>)props[<span style="color: #a31515;">"border-color"</span>];</pre>
<pre style="margin: 0px;"><span style="color: blue;">for</span> (<span style="color: blue;">int</span> row = 0; row &lt; rows.Count; ++row)</pre>
<pre style="margin: 0px;">{</pre>
<pre style="margin: 0px;">    <span style="color: #2b91af;">ArrayList</span> col = (<span style="color: #2b91af;">ArrayList</span>)rows[row];</pre>
<pre style="margin: 0px;">    <span style="color: blue;">for</span> (<span style="color: blue;">int</span> k = 0; k &lt; col.Count; ++k)</pre>
<pre style="margin: 0px;">    {</pre>
<pre style="margin: 0px;">        <span style="color: #2b91af;">PdfPCell</span> cell = (<span style="color: #2b91af;">PdfPCell</span>)col[k];</pre>
<pre style="margin: 0px;">        cell.BorderColor = <span style="color: #2b91af;">Markup</span>.DecodeColor(bordercolor);</pre>
<pre style="margin: 0px;">        table.AddCell(cell);</pre>
<pre style="margin: 0px;">    }</pre>
<pre style="margin: 0px;">}</pre>
</div>
<p>This will change the border color on the cell in the table. Hint: It could be wise to check if the cell already has a border color before overwriting it with the table border color.</p>
<p>Recompile and add the new DLL to your project.</p>
<p>Happy Coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://hamang.net/2008/08/14/html-to-pdf-in-net/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
	</channel>
</rss>

