<?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>Tobin Titus &#187; configuration</title>
	<atom:link href="http://tobint.com/blog/tag/configuration/feed/" rel="self" type="application/rss+xml" />
	<link>http://tobint.com</link>
	<description>You Are What You Don&#039;t Automate</description>
	<lastBuildDate>Fri, 03 Feb 2012 23:05:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>IIS Security – Past and Present</title>
		<link>http://tobint.com/blog/iis-security-past-and-present/</link>
		<comments>http://tobint.com/blog/iis-security-past-and-present/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 07:31:00 +0000</pubDate>
		<dc:creator>tobint</dc:creator>
				<category><![CDATA[technical]]></category>
		<category><![CDATA[ApplicationPools]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[IIS51]]></category>
		<category><![CDATA[IIS6]]></category>
		<category><![CDATA[IIS7]]></category>
		<category><![CDATA[Installation]]></category>
		<category><![CDATA[Logging]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[url rewriter]]></category>

		<guid isPermaLink="false">http://tobint.com/Blog/IIS-Security--Past-and-Present</guid>
		<description><![CDATA[This topic has been covered many times both by Microsoft and non-Microsoft employees. However, I’ve recently been asked what the main features of IIS 7 are and have seen a great deal of misinformation about IIS security on twitter, blog posts and forums. I think, therefore, the issue deserves yet another look. In this post, [...]
Related posts:<ol>
<li><a href='http://tobint.com/blog/where-can-i-find-feature-x-in-iis-7-0/' rel='bookmark' title='Where can I find &lt;feature x&gt; in IIS 7.0 ?'>Where can I find &lt;feature x&gt; in IIS 7.0 ?</a></li>
<li><a href='http://tobint.com/blog/net-security-no-no/' rel='bookmark' title='.NET Security No No'>.NET Security No No</a></li>
<li><a href='http://tobint.com/blog/asp-net-1-1-iis-6-0-and-64-bit-windows/' rel='bookmark' title='ASP.NET 1.1, IIS 6.0 and 64-bit Windows'>ASP.NET 1.1, IIS 6.0 and 64-bit Windows</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftobint.com%2Fblog%2Fiis-security-past-and-present%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftobint.com%2Fblog%2Fiis-security-past-and-present%2F&amp;source=tobint&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>This topic has been covered many times both by Microsoft and non-Microsoft employees. However, I’ve recently been asked what the main features of IIS 7 are and have seen a great deal of misinformation about IIS security on twitter, blog posts and forums. </p>
<p>I think, therefore, the issue deserves yet another look. In this post, I’m going to go over security in the past for IIS and then move on to talk about security features in IIS 7. These are not in any particular order. This post is not meant to diminish the many thoughtful works already created by others – both complimentary and critical. This is just meant to bring the subject back up for discussion again in hopes that you can be properly equipped with the decision making information you may need.</p>
<h2>Ghosts of IIS Security Past</h2>
<p>The reason for so much misinformation about the current state of security in IIS is likely due to the earned reputation the product had in versions previous to IIS 6.0. A quick search on the web for <a href="http://search.live.com/results.aspx?q=IIS+5+security+vulnerability&#038;src=IE-SearchBox&#038;Form=IE8SRC" target="_blank">IIS 5 security vulnerabilities</a> may be like a walk down memory lane for some of the more veteran administrators and IT staff across the globe. The search results are littered with critical vulnerabilities related to buffer overflows, ISAPI extensions, exploits on rarely-used features, or features that were available by a default installation. We are haunted by names like “<a href="http://en.wikipedia.org/wiki/Code_Red_(computer_worm)" target="_blank">Code Red</a>” and “<a href="http://en.wikipedia.org/wiki/Nimda" target="_blank">Nimda</a>”. I don’t know about you, but those very names send shivers down my spine. I was consulting as a developer and web administrator for a very large property management company when these hit. We were lucky enough to avoid these as we had patched our services. That said, many whom I did business with on a regular basis were not very happy. So, to be clear, I feel the misinformation that is spread today is built on an element of experience with previous versions. Secunia reports <a href="http://secunia.com/advisories/product/39/" target="_blank">16 advisories and 6 vulnerabilities</a> with IIS 5.  And so started the reputation , perhaps deservedly so, that IIS was not secure unless you really knew what you were doing with security.</p>
<p>Bill Gates was apparently visited by the ghosts of security past, present and future when he laid his head on his pillow January 14th, 2002. I say that because on January 15th, 2002 Mr. Gates sent out the <a href="http://www.wired.com/techbiz/media/news/2002/01/49826" target="_blank">now-famous trustworthy computing memo</a> to every employee at Microsoft.  This set off a major revamp of products from the ground up. Standards were set for test planning and testing. Writing Secure Code was mandatory reading for every Microsoft developer and tester. The results have been staggering.</p>
<p>Security drastically improved in Microsoft products over the years, and IIS was definitely no exception to this. IIS 6 saw <a href="http://secunia.com/advisories/product/1438/" target="_blank">5 security advisories and 4 vulnerabilities</a> reported since 2003. Not to get ahead of myself, but IIS 7 has <a href="http://secunia.com/advisories/product/17543/" target="_blank">exactly 1 advisor and 1 vulnerability</a> from Secunia. Compare this against Apache 2.0.x which has had <a href="http://secunia.com/advisories/product/73/" target="_blank">39 advisories and 23 vulnerabilities</a> (4 of which are still unpatched as of this writing) and Apache 2.2.x which has had <a href="http://secunia.com/advisories/product/9633/" target="_blank">10 advisories and 16 vulnerabilities</a> (2 of which are still unpatched as of this writing) in the same period.  Now I have seen attempts (<a href="http://googleonlinesecurity.blogspot.com/2007/06/web-server-software-and-malware.html" target="_blank">[1]</a>, <a href="http://blog.washingtonpost.com/securityfix/2007/05/cyber_crooks_hijack_activities_1.html" target="_blank">[2]</a>) to quantify or otherwise explain these numbers further. You can read those articles for yourself and determine how much weight you want to give them. However you skew it, the facts should speak for themselves – IIS has dramatically improved and taken a leadership roll in security in IIS 6 and 7. Our ghost of IIS past still haunts the product’s reputation today, despite obvious strides taken. Even if you feel you like Apache better I think it is only fair to give credit where it is due. </p>
<h2>Improvements in IIS 6</h2>
<p>The IIS team took the four tenants of Microsoft’s Trustworthy Computing initiative to heart: Secure by Design, Secure by Default, Secure in Deployment and Secure Communication. Since we are already on the next version, I won’t spend a great deal of time talking about the security improvements in the last version other than a brief overview so you know how they relate to changes in our current version, IIS 7. </p>
<p>IIS 6 took vast strides to improve security. During upgrade installations, IIS 6 was disabled by default if the previous server had not been secured by the <a href="http://blog.washingtonpost.com/securityfix/2007/05/cyber_crooks_hijack_activities_1.html" target="_blank">IIS lockdown tool</a>. The architecture was completely revamped to separate kernel-mode HTTP listening from user-mode application execution. Changes were made to application pools, authentication, access control, encryption and certificate handling, auditing, logging and patch management that made the product far superior to its predecessors. You can find a detailed list of these features on <a href="http://technet.microsoft.com/en-us/library/cc736369.aspx" target="_blank">TechNet</a>.  SecurityFocus did a comparison of these features in <a href="http://www.securityfocus.com/infocus/1765" target="_blank">March of 2004</a>.Server Watch wrote an article in <a href="http://www.serverwatch.com/tutorials/article.php/3294371" target="_blank">December of 2003</a>. By most accounts, everything accomplished in IIS 6 was a huge step in the right direction.</p>
<p>Despite the massive steps already taken in IIS6, IIS 7 took these all a bit further. Let’s go ahead and investigate these now.</p>
<h2>Improvements in IIS 7.x</h2>
<h3>Customizable Installation</h3>
<p>Continuing with the tenant of being secure in deployment, IIS 7 has made installation a wonder to behold. In IIS 6, you could reduce your attack surface by disabling features native to web server. However, these features were still loaded into the process. This carried not only a security factor, but also a performance and memory footprint issue.  IIS 7 has a completely modular architecture. That means that features which you do not want are not only NOT loaded into the process, you can leave the bits for those features off of your disk completely. </p>
<h3>Limitable Attack Surface</h3>
<p>This is a bit dubious and is essentially part of the customizable installation. By reducing the modules that are available on disk or loaded into a process, you significantly reduce the attack surface for your specialized web servers. If all you intend to do is serve static content with caching and no default documents, you can simply install the static file handler and caching module and leave the rest of the IIS modules off of your server. Additional controls and limitations will also reduce your attack surface and I’ll cover those below.</p>
<h3>IUSR account</h3>
<p>Anyone who has tried to migrate an IIS installation from one machine to another or attempted to recover your installation on a new machine, previous to IIS 7, has likely run into an issue with the local “IUSR_<machine_name>” account.  IIS 7 now uses a built-in IUSR account that allows you to easily copy your security settings from one machine to the next. This is great news for those using distributed configuration in web farms, recovery, restoration, or replication.</p>
<h3>IIS_IUSRS group</h3>
<p>IIS 6 introduced the IIS_WPG group. Application pool security identities had to be assigned to this group in order to host the w3wp.exe process. Like the IUSR account, IIS 7 now creates a built-in security group (IIS_IUSRS) and assigns application pool identities to the group automatically. You can find more information about the built-in user and built-in group for IIS 7 on IIS.NET (<a href="http://learn.iis.net/page.aspx/140/understanding-the-built-in-user-and-group-accounts-in-iis-7/." target="_blank">Understanding the Built-In User and Group Accounts in IIS 7.0</a>). </p>
<h3>ASP.NET / IIS Unified Security Architecture</h3>
<p>Previous versions of IIS did not provide a unified approach to security with ASP.NET. The IIS 7 unified request pipeline that supports both Windows and non-Windows principals and provides one place to do all authentication and authorization. Apart from simplification and performance improvements, this also reduces the attack surface and allows for greater flexibility in authentication / authorization scenarios with custom modules.</p>
<h3>Request Filtering / URL Rewriting</h3>
<p>IIS 7.0 includes a request filtering module that is based on the URLScan ISAPI Filter for IIS 6.0. The module helps you tighten security of your Web servers. </p>
<p>The IIS team has also released an add-on URL rewrite module for IIS 7.0, which provides functionality for rule-based URL manipulation. Even though the primary purpose of the URL rewrite module is to rewrite URL paths for requests, the rewrite module can also be used as a security enforcement tool that helps prevent access to Web site content.</p>
<h3>Application Pool Identities</h3>
<p>On top of Application Pool Isolation, IIS introduces a new security feature in Service Pack 2 of Windows Server 2008 and Windows Vista. It&#8217;s called Application Pool Identities. Application Pool Identities allows you to run Application Pools under an unique account without having to create and manage domain or local accounts. The name of the Application Pool account corresponds to the name of the Application Pool. </p>
<h3>Kernel mode SSL</h3>
<p>The implementation of SSL has changed from IIS 6.0 to IIS 7.0.  On Windows Server 2003, all SSL configuration was stored in the IIS metabase and encryption/decryption happened in user mode (required a lot of kernel/user mode transitions).  On Windows Vista and Windows Server® 2008, HTTP.sys handles SSL encryption/decryption in kernel mode, resulting in up to 20% better performance for secure connections.  </p>
<h3>Configuration Improvements</h3>
<p>IIS 7.0 allows locking and unlocking configuration settings in various levels and scopes. Locking down configuration means that it cannot be overridden (or set at all) at lower levels in the hierarchy. Unlocking configuration can only be done at the level where it was locked. This is useful, for example, when creating different configuration for different sites or paths, and only some of sites and paths are allowed to override it. Locking can be done at the section level or for specific elements, attributes, collection elements and collection directives within sections.</p>
<h3>Dynamic IP Restriction</h3>
<p>IIS 7 provides a new module that allows dynamic, temporary IP address restriction. This module prevents brute force attacks and HTTP clients that make unusually high number of concurrent requests or a large number of requests over a short period of time.</p>
<h2>Summary</h2>
<p>A verbose list of security features in IIS 6 and IIS 7 might be nearly impossible. Apart from the obvious features, there were numerous improvements to code made over these two versions that make the product far more secure than IIS 5 and earlier. That said, this should give you a summary start on information. I’ve listed some reference documents that may help you understand these features better.  In general, I would encourage you to ask questions of the product team and or other users on the <a href="http://forums.iis.net/" target="_blank">IIS.NET forums</a> if you hear something that sounds negative regarding IIS. If the feedback is true, the product team has the benefit of improving the next release. If the feedback is unfounded, the product team has the benefit of helping you find the information you need to make an informed decision. </p>
<h2>See Also</h2>
<ul>
<li><a href="http://channel9.msdn.com/posts/scobleizer/Brent-Hill-and-Roger-Grimes-Chatting-about-IIS-7s-security/"><strong>Brent Hill and Roger Grimes &#8211; Chatting about IIS 7&#8242;s security</strong></a> (From Sept. 2005) </li>
<li><a href="http://channel9.msdn.com/shows/TechNet+Radio/TechNet-radio-Learn-about-the-IIS7-Security-features-and-benefits/" target="_blank"><strong>TechNet radio: Learn about the IIS7 Security features and benefits</strong></a>  </li>
<li><a href="http://www.gartner.com/DisplayDocument?doc_cd=125453" target="_blank"><strong>Management Update: IIS Is No Longer the Problem in Web Server Security</strong></a> (Gartner) </li>
<li><a href="http://www.microsoft.com/emea/spotlight/sessionh.aspx?videoid=568&#038;PUID=00034001826C5CC7" target="_blank"><strong>IIS 7 Security: Less Exposure, Greater Control</strong></a> </li>
<li><a href="http://technet.microsoft.com/en-us/library/cc731278.aspx" target="_blank"><strong>TechNet: Configure Web Server Security</strong></a> </li>
<li><a href="http://learn.iis.net/page.aspx/88/configuring-security/" target="_blank"><strong>IIS.NET : Configuring Security</strong></a> </li>
<li><a href="http://learn.iis.net/page.aspx/139/iis7-security-improvements/" target="_blank"><strong>IIS.NET : IIS Security Improvements</strong></a> </li>
<li><a href="http://learn.iis.net/page.aspx/548/using-dynamic-ip-restrictions/" target="_blank"><strong>Using Dynamic IP Restrictions</strong></a> </li>
<li><a href="http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering" target="_blank"><strong>IIS.NET Configuration Reference: Request Filtering</strong></a> </li>
</ul>
<p>Related posts:<ol>
<li><a href='http://tobint.com/blog/where-can-i-find-feature-x-in-iis-7-0/' rel='bookmark' title='Where can I find &lt;feature x&gt; in IIS 7.0 ?'>Where can I find &lt;feature x&gt; in IIS 7.0 ?</a></li>
<li><a href='http://tobint.com/blog/net-security-no-no/' rel='bookmark' title='.NET Security No No'>.NET Security No No</a></li>
<li><a href='http://tobint.com/blog/asp-net-1-1-iis-6-0-and-64-bit-windows/' rel='bookmark' title='ASP.NET 1.1, IIS 6.0 and 64-bit Windows'>ASP.NET 1.1, IIS 6.0 and 64-bit Windows</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://tobint.com/blog/iis-security-past-and-present/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IIS cannot start after upgrade to Vista SP1</title>
		<link>http://tobint.com/blog/iis-cannot-start-after-upgrade-to-vista-sp1/</link>
		<comments>http://tobint.com/blog/iis-cannot-start-after-upgrade-to-vista-sp1/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 00:31:40 +0000</pubDate>
		<dc:creator>tobint</dc:creator>
				<category><![CDATA[technical]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[IIS7]]></category>
		<category><![CDATA[sp1]]></category>
		<category><![CDATA[troubleshooting]]></category>
		<category><![CDATA[vista]]></category>

		<guid isPermaLink="false">http://tobint.com/Blog/IIS-cannot-start-after-upgrade-to-Vista-SP1</guid>
		<description><![CDATA[Some time ago, I tried to start up the IIS Management Console on my Vista machine and I received an exception. After trying a few quick fixes, I gave up. I had several VPC images that I worked from and I didn&#8217;t particularly need this machine to work when I had so many others.  However, [...]
Related posts:<ol>
<li><a href='http://tobint.com/blog/enabling-vsnet-2008-to-work-with-iis-70/' rel='bookmark' title='Enabling VS.NET 2008 to work with IIS 7.0'>Enabling VS.NET 2008 to work with IIS 7.0</a></li>
<li><a href='http://tobint.com/blog/iis-7-0-error-support/' rel='bookmark' title='IIS 7.0 Error Support'>IIS 7.0 Error Support</a></li>
<li><a href='http://tobint.com/blog/asp-net-1-1-iis-6-0-and-64-bit-windows/' rel='bookmark' title='ASP.NET 1.1, IIS 6.0 and 64-bit Windows'>ASP.NET 1.1, IIS 6.0 and 64-bit Windows</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftobint.com%2Fblog%2Fiis-cannot-start-after-upgrade-to-vista-sp1%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftobint.com%2Fblog%2Fiis-cannot-start-after-upgrade-to-vista-sp1%2F&amp;source=tobint&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Some time ago, I tried to start up the IIS Management Console on my Vista machine and I received an exception. After trying a few quick fixes, I gave up. I had several VPC images that I worked from and I didn&#8217;t particularly need this machine to work when I had so many others.  However, I&#8217;ve been doing a great deal of development on this machine now, and having IIS working is obviously rather handy. So, I tracked down the exception and solved my problem. I thought I&#8217;d go ahead and chronical my adventures for anyone else who is having this issue and needs help.</p>
<p>So first of all, the error that was displayed when I started inetmgr was as follows:</p>
<pre>---------------------------
Failed to connect
---------------------------
There was an error when trying to connect. Do you want to retype your credentials and try again?
Details:
Creating an instance of the COM component with CLSID {2B72133B-3F5B-4602-8952-803546CE3344}
from the IClassFactory failed due to the following error: 8007000d.
---------------------------
Yes   No
---------------------------</pre>
<p>So I thought that this might be a configuration error. I tried to roll back to a known good configuration but appcmd failed with the following exception:</p>
<blockquote><p>ERROR ( hresult:80070426, message:Command execution failed.<br />
The service has not been started. )</p></blockquote>
<p>I tried to start the service with a good old fashion iisreset command and the following exception occurred:</p>
<blockquote><p>Attempting stop&#8230;<br />
Internet services successfully stopped<br />
Attempting start&#8230;<br />
Restart attempt failed.<br />
The IIS Admin Service or the World Wide Web Publishing Service, or a service dep<br />
endent on them failed to start.  The service, or dependent services, may had an<br />
error during its startup or may be disabled.</p></blockquote>
<p>Once again, I thought I&#8217;d go into the services console and try to start IIS manually. After trying to start it manually, it failed, stating that a dependent service failed. So I looked at Windows Process Activation Services (WAS) and noticed it was stopped. I tried to start it manually and found the following:</p>
<blockquote><p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Services<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Windows could not start the Windows Process Activation Service service on Local Computer.<br />
Error 13:<br />
The data is invalid.<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
OK �<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p></blockquote>
<p>So I checked out the event log and found the following four entries:</p>
<p><strong>First Event</strong> :</p>
<blockquote><p>Log Name:      System<br />
Source:        Service Control Manager<br />
Date:          9/21/2008 11:52:00 PM<br />
Event ID:      7001<br />
Task Category: None<br />
Level:         Error<br />
Keywords:      Classic<br />
User:          N/A<br />
Description:<br />
The World Wide Web Publishing Service service depends on the Windows Process Activation Service service which failed to start because of the following error:<br />
The data is invalid.</p></blockquote>
<p><strong>Second Event:</strong></p>
<blockquote><p>Log Name:      System<br />
Source:        Service Control Manager<br />
Date:          9/21/2008 11:52:00 PM<br />
Event ID:      7023<br />
Task Category: None<br />
Level:         Error<br />
Keywords:      Classic<br />
User:          N/A<br />
Description:<br />
The Windows Process Activation Service service terminated with the following error:<br />
The data is invalid.</p></blockquote>
<p><strong>Third Event:</strong></p>
<blockquote><p>Log Name:      System<br />
Source:        Microsoft-Windows-WAS<br />
Date:          9/21/2008 11:51:59 PM<br />
Event ID:      5005<br />
Task Category: None<br />
Level:         Error<br />
Keywords:      Classic<br />
User:          N/A<br />
Description:<br />
Windows Process Activation Service (WAS) is stopping because it encountered an error. The data field contains the error number.</p></blockquote>
<p><strong>Fourt Event:</strong></p>
<blockquote><p>Log Name:      System<br />
Source:        Microsoft-Windows-WAS<br />
Date:          9/21/2008 11:51:59 PM<br />
Event ID:      5036<br />
Task Category: None<br />
Level:         Error<br />
Keywords:      Classic<br />
User:          N/A<br />
Description:<br />
The configuration manager for Windows Process Activation Service (WAS) did not initialize. The data field contains the error number.</p></blockquote>
<p>I checked through my event logs and realized that this started happening after I had upgraded to SP1. I hadn&#8217;t recognized this as the issue because, as I said, don&#8217;t typically use IIS on this machine on a regular basis. I decided to go back to my initial assessment that this had to be configuration related. I started doing comparisons between configuration of a pure Vista installation vs a Vista machine with SP1. I found that the schema had changed during the install, but something had been left out.  The schema file was updated to add the configurationHistory configuration section, but a corresponding section definition was not added to the applicationHost.config file.  </p>
<p>Whether this was what was causing the problem or not, I knew this was going to cause a problem. I added the following configuration entry to the applicationHost.config file under the section group for &#8220;system.applicationHost&#8221;. </p>
<pre>&lt;section name="configHistory" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /&gt;</pre>
<p>After this I started the WAS service, the World Wide Publishing Service and the IIS Admin Service. I opened up the IIS Management Console and everything was working just fine.</p>
<p>I&#8217;m not sure what exactly happened during the SP1 upgrade that caused this file to not be updated, but I&#8217;m pleased to report that all things are up and running again.</p>
<p>Related posts:<ol>
<li><a href='http://tobint.com/blog/enabling-vsnet-2008-to-work-with-iis-70/' rel='bookmark' title='Enabling VS.NET 2008 to work with IIS 7.0'>Enabling VS.NET 2008 to work with IIS 7.0</a></li>
<li><a href='http://tobint.com/blog/iis-7-0-error-support/' rel='bookmark' title='IIS 7.0 Error Support'>IIS 7.0 Error Support</a></li>
<li><a href='http://tobint.com/blog/asp-net-1-1-iis-6-0-and-64-bit-windows/' rel='bookmark' title='ASP.NET 1.1, IIS 6.0 and 64-bit Windows'>ASP.NET 1.1, IIS 6.0 and 64-bit Windows</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://tobint.com/blog/iis-cannot-start-after-upgrade-to-vista-sp1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Accessing Custom IIS 7 Configuration at Runtime</title>
		<link>http://tobint.com/blog/accessing-custom-configuration-at-runtime-with-microsoft-web-administration/</link>
		<comments>http://tobint.com/blog/accessing-custom-configuration-at-runtime-with-microsoft-web-administration/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 23:07:45 +0000</pubDate>
		<dc:creator>tobint</dc:creator>
				<category><![CDATA[technical]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[IIS7]]></category>

		<guid isPermaLink="false">http://tobint.com/?p=734</guid>
		<description><![CDATA[I&#8217;ve been working on a series of posts and Webcasts in my &#8220;spare time&#8221; directed at some of the areas in which I am most frequently asked questions. I am currently working on developing topics dealing with IIS configuration. It seems logical that this would bring me a great deal of questions considering that IIS [...]
Related posts:<ol>
<li><a href='http://tobint.com/blog/iis-cannot-start-after-upgrade-to-vista-sp1/' rel='bookmark' title='IIS cannot start after upgrade to Vista SP1'>IIS cannot start after upgrade to Vista SP1</a></li>
<li><a href='http://tobint.com/blog/accessing-microsoft-web-administration-through-powershell-part-i/' rel='bookmark' title='Accessing IIS 7 APIs through PowerShell (Part I)'>Accessing IIS 7 APIs through PowerShell (Part I)</a></li>
<li><a href='http://tobint.com/blog/sdk-sample-programmatically-change-the-runtime-version-of-an-application-pool-in-iis-7/' rel='bookmark' title='Change the runtime of an IIS 7 application pool'>Change the runtime of an IIS 7 application pool</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Ftobint.com%2Fblog%2Faccessing-custom-configuration-at-runtime-with-microsoft-web-administration%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Ftobint.com%2Fblog%2Faccessing-custom-configuration-at-runtime-with-microsoft-web-administration%2F&amp;source=tobint&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I&#8217;ve been working on a series of posts and Webcasts in my &#8220;spare time&#8221; directed at some of the areas in which I am most frequently asked questions. I am currently working on developing topics dealing with IIS configuration. It seems logical that this would bring me a great deal of questions considering that IIS 7.0 is using a completely different configuration system than it did in previous versions. That said, I wanted to follow up to my Webcast (&#8220;<a href="http://learn.iis.net/page.aspx/471/extending-iis-configuration">Extending IIS Configuration</a>&#8220;) with an article, and another webcast dealing with accessing custom configuration data at runtime.</p>
<p>In the webcast, I described how to extend an existing IIS configuration system object. I want to talk a little more about that. In this blog post I will take on four topics:</p>
<ol>
<li>
<div>Give you some warnings that were not provided in the Webcast regarding extending native IIS configuration</div>
</li>
<li>
<div>Show you how to access your <strong>extended configuration data </strong>at runtime in a managed-code HTTP module</div>
</li>
<li>
<div>Describe how to improve the example used in the Webcast in a custom configuration section.</div>
</li>
<li>
<div>Show you how to access your <strong>custom configuration section</strong> at runtime in a managed-code HTTP module</div>
</li>
</ol>
<h3>Extending Native Configuration Elements</h3>
<h4>Introduction</h4>
<p>I talked with Carlos today to discuss the validity of extending native configuration elements for our own purposes. While there are certainly valid reasons to do this, it doesn&#8217;t come without a risk to your application. Any time that you modify a piece of data that was created by another party &#8212; Microsoft or otherwise &#8212; you run the risk of having your data overwritten or corrupting the data that the other party needs to use. That said, lets revisit the sample that is frequently given in many articles and was reused in my webcast.</p>
<h4>Warnings</h4>
<p>In our Webcast, we discussed the idea that you could extend a native configuration element simply by creating a new configuration element schema and placing it in our <span style="font-family: courier;">%windir%sytem32inetsrvconfigschema</span> directory. For our example, we created a file named <em>SiteOwner_schema.xml</em> and put the following code into it:</p>
<p><!--</p>
<p>.code {<br />
word-wrap:break-word;<br />
margin:10px;<br />
padding:10px;<br />
border:2px ridge white;<br />
background-color:#f5f5f5;<br />
font-family:courier new;<br />
font-size:10pt;<br />
}<br />
--></p>
<div class="code"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">configSchema</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
    </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">sectionSchema</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;system.applicationHost/sites&#8221;&gt;</span><span style="color: #000000;"><br />
        </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerName&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;<br />
        &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerEmail&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;<br />
        &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerPhone&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;   <br />
    &lt;/</span><span style="color: #800000;">sectionSchema</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">configSchema</span><span style="color: #0000ff;">&gt;</span></div>
<p>All we have done is matched the same section schema path as the existing &#8220;system.applicationHost/sites&#8221; sectionSchema element in our <em>IIS_schema.xml</em> file. We then added schema information for our three new attributes.</p>
<p>This simple step allows us to immediately start adding attributes to our site configuration, and to access that data programmatically, through PowerShell, and through the AppCmd utility. However, you should be aware of a few dangers before you do something of this nature.</p>
<p>The first problem is that many of our native configuration elements have associated &#8220;default&#8221; configuration elements. For instance, the &lt;site/&gt; element has an associated &lt;siteDefaults/&gt; element. When modifying the configuration schema for &lt;site/&gt; , you should also modify the &lt;siteDefaults/&gt; configuration schema to match. That said, you might consider changing the above sample configuration schema as follows:</p>
<div class="code"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">configSchema</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
    </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">sectionSchema</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;system.applicationHost/sites&#8221;&gt;</span><span style="color: #000000;"><br />
        </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerName&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;<br />
        &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerEmail&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;<br />
        &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerPhone&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;<br />
</span><span style="color: #0000ff;">    &lt;/</span><span style="color: #800000;">sectionSchema</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">   <br />
</span><strong>    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">element</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;siteDefaults&#8221;&gt;</span><span style="color: #000000;">      <br />
        </span></strong><strong><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerName&#8221;</span><span style="color: #ff0000;"> defaultValue</span><span style="color: #0000ff;">=&#8221;undefined&#8221;</span><span style="color: #ff0000;"> type</span></strong><strong><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;<br />
        &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerEmail&#8221;</span><span style="color: #ff0000;"> defaultValue</span><span style="color: #0000ff;">=&#8221;undefined&#8221;</span><span style="color: #ff0000;">  type</span></strong><strong><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;<br />
        &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerPhone&#8221;</span><span style="color: #ff0000;"> defaultValue</span><span style="color: #0000ff;">=&#8221;undefined&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;/&gt;   <br />
</span></strong><strong><span style="color: #0000ff;">     &lt;/</span><span style="color: #800000;">element</span><span style="color: #0000ff;">&gt;</span></strong><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">configSchema</span><span style="color: #0000ff;">&gt;</span></div>
<p>As you can see, in the <strong>bolded</strong> section above we have now modified the &lt;siteDefaults/&gt; configuration element to match our changes to the &lt;site/&gt; element.  This isn&#8217;t the end of the story, however. While changing this might have seemed simple, modifying other elements become much more complex. Consider the fact that when you modify the schema for &lt;application/&gt; elements, there are several places where &lt;applicationDefaults/&gt; are kept. You will find &lt;applicationDefaults/&gt; under both the sites collection definition, as well as under the associated a site element definition. If you modify the application schema definition, you must be sure to edit the schema for both of the applicationDefaults definitions. This gets even more complex if you try to modify the &lt;virtualDirectoryDefaults/&gt; definition. You&#8217;ll find that defined three times in the native configuration: under the <strong>sites</strong> <strong>collection</strong> definition, under the <strong>application element </strong>definition, and under the <strong>site element</strong> definition itself.</p>
<p>You can see how you can quickly start adding complexity to your changes. Making sure that you make changes everywhere you need to becomes all the more risky.</p>
<p>The second problem you may have is that you may not be able to rely on your third-party to keep their schema definition in line with your own expectations. From one minor revision to the next, a configuration schema you may be depending on can change before your very eyes. This becomes a huge issue. Your future installation may need to make many dependency and version checks to decide what schema document to install, and your module may even need to make checks in case the user upgrades the third-party component without installing the upgraded schema. This can get very tricky, to say the least.</p>
<p>The third problem we can run into when we take a dependency on existing configuration is that external code may not behave the way we want it to. For instance, there is no guarantee that utilities and code written to handle those elements will know what to do if it encounters data that it doesn&#8217;t expect. Sure, we can cause IIS to validate our changes through schema, but there is no guarantee that the components which handle those elements can take on the challenge of handling the existing data. There is even a good chance that you could cause an Access Violation (read: crash) if the data is not handled properly. There is also a good chance that the components which normally handle those elements may overwrite your custom data.</p>
<p>So before we go on to show you how to access this extended configuration element data, please <span style="color: red; font-weight: bold;">be warned</span> that it may not be the best solution to your problem. Later in this article, I will describe how to modify our example to give us the same functionality without altering the schema definition of the existing elements.</p>
<h3>Accessing Extended Native Configuration Elements at Runtime</h3>
<h4>Introduction</h4>
<p>With the warnings having been fairly posted, I&#8217;ll show you quickly how to access your custom configuration data at runtime from an HTTP module. Once you have saved your schema file to the appropriate directory, its time to write the HTTP module. That module is going to be very simple. We need to create a module that uses the PreSendRequestHeaders event. In this event we will get our &#8220;system.applicationHost/sites&#8221; configuration section, loop through the configured sites looking for the site on which the current HTTP request is executing, and then write HTTP headers out to the client. Just to make sure that our sample is working, we&#8217;ll wrap it up by adding JavaScript to an HTML page that will request the headers from the Web site and display them in a message box.</p>
<h4>Getting Started</h4>
<p>For this sample, I used Visual Studio 2008, but you can use plain old notepad and command-line compilation if your are feeling particularly froggy.</p>
<p><strong>Visual Studio 2008 Walk-through</strong></p>
<p>The following walk-through will create an HTTP module that can display the site owner details of the configuration system</p>
<ol>
<li>Click on the <strong>File</strong> | <strong>New</strong> | <strong>Project</strong> &#8230;  menu item.</li>
<li>In the &#8220;<strong>Project types</strong>&#8221; tree on the left, drill down to the <strong>C#</strong> | <strong>Windows</strong> tree element</li>
<li>In the &#8220;<strong>Templates</strong>&#8221; selector on the right, select the &#8220;Class Library&#8221; template</li>
<li>Change the <strong>Name </strong>of the project to &#8220;<em>SiteOwner</em>&#8220;</li>
<li>Change the Location to &#8220;c:samples&#8221;</li>
<li>Verify that the &#8220;Create directory for solution&#8221; checkbox is checked</li>
<li>Click <strong>OK</strong></li>
<li>Click on the <strong>Project</strong> | <strong>Add Reference &#8230; </strong>menu item.</li>
<li>Under the <strong>.NET</strong> tab, select the component with the <strong>Component Name</strong> of &#8220;<em>System.Web</em>&#8220;</li>
<li>Click <strong>OK</strong></li>
<li>Rename the &#8220;Class1.cs&#8221; file in the <strong>Solution Explorer</strong> to &#8220;<em>SiteOwnerHeaderModule.cs</em>&#8220;</li>
<li>Paste the following code in &#8220;<em>SiteOwnerHeaderModule.cs&#8221;</em> file:
<div class="code"><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System.Web</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System.Web.Hosting</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">Microsoft.Web.Administration</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System.Collections.Specialized</span><span style="color: #0000ff;">;</span><span style="color: #808080;"></p>
<p></span><span style="color: #0000ff;">namespace</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner</span><span style="color: #808080;"><br />
</span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
    </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">class</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwnerHeaderModule</span><span style="color: #808080;"> </span><span style="color: #000000;">:</span><span style="color: #808080;"> </span><span style="color: #2b91af;">IHttpModule</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">void</span><span style="color: #808080;"> </span><span style="color: #000000;">Dispose()</span><span style="color: #808080;"> </span><span style="color: #000000;">{}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">void</span><span style="color: #808080;"> </span><span style="color: #000000;">Init(</span><span style="color: #2b91af;">HttpApplication</span><span style="color: #808080;"> </span><span style="color: #000000;">context)</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
            </span><span style="color: #000000;">context.PreSendRequestHeaders</span><span style="color: #808080;"> </span><span style="color: #000000;">+</span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #0000ff;">new</span><span style="color: #808080;"> </span><span style="color: #2b91af;">EventHandler</span><span style="color: #000000;">(OnPreSendRequestHeaders)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
        </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">void</span><span style="color: #808080;"> </span><span style="color: #000000;">OnPreSendRequestHeaders(</span><span style="color: #0000ff;">object</span><span style="color: #808080;"> </span><span style="color: #000000;">sender,</span><span style="color: #808080;"> </span><span style="color: #2b91af;">EventArgs</span><span style="color: #808080;"> </span><span style="color: #000000;">e){<br />
<span style="color: #006400;">            // Get the site collection</span></span><span style="color: #808080;"><br />
            </span><span style="color: #2b91af;">ConfigurationSection</span><span style="color: #808080;"> </span><span style="color: #000000;">section</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"><br />
                </span><span style="color: #000000;">WebConfigurationManager.GetSection(</span><span style="color: #808080;">&#8220;system.applicationHost/sites&#8221;</span><span style="color: #000000;">)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
            </span><span style="color: #2b91af;">ConfigurationElementCollection</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSites</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">section.GetCollection()</span><span style="color: #0000ff;">;</span><br />
<span style="color: #000000;"><span style="color: #808080;">            </span><span style="color: #2b91af;">HttpApplication</span> app = (<span style="color: #2b91af;">HttpApplication</span>)sender<span style="color: #0000ff;">;</span><br />
</span><span style="color: #808080;">            </span><span style="color: #2b91af;">HttpContext</span> context <span style="color: #0000ff;">=</span> app.Context<span style="color: #0000ff;">;</span><br />
 <span style="color: #808080;">           </span><span style="color: #006400;">// Loop through the sites to find the site of<br />
</span><span style="color: #808080;">            </span><span style="color: #006400;">// the currently executing request</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">foreach</span><span style="color: #808080;"> </span><span style="color: #000000;">(</span><span style="color: #2b91af;">ConfigurationElement</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSite</span><span style="color: #808080;"> </span><span style="color: #0000ff;">in</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSites)</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
                </span><span style="color: #0000ff;">if</span><span style="color: #808080;"> </span><span style="color: #000000;">(HostingEnvironment.SiteName</span><span style="color: #808080;"> </span><span style="color: #0000ff;">==</span><span style="color: #808080;"> </span><span style="color: #000000;">(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">)cfgSite.GetAttributeValue(</span><span style="color: #808080;">&#8220;name&#8221;</span><span style="color: #000000;">))</span><span style="color: #808080;"> </span><span style="color: #000000;">{<br />
</span><span style="color: #808080;">                    </span><span style="color: #006400;">// This is the correct site, get the site owner attributes</span><span style="color: #808080;"><br />
                    </span><span style="color: #000000;">SiteOwner</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #0000ff;">new</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner(cfgSite)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                    </span><span style="color: #000000;">NameValueCollection</span><span style="color: #808080;"> </span><span style="color: #000000;">headers</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #2b91af;">context</span><span style="color: #000000;">.Response.Headers</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                    </span><span style="color: #000000;">headers.Add(</span><span style="color: #808080;">&#8220;Site-Owner-Name&#8221;</span><span style="color: #000000;">,</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner.Name)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                    </span><span style="color: #000000;">headers.Add(</span><span style="color: #808080;">&#8220;Site-Owner-Email&#8221;</span><span style="color: #000000;">,</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner.Email)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                    </span><span style="color: #000000;">headers.Add(</span><span style="color: #808080;">&#8220;Site-Owner-Phone&#8221;</span><span style="color: #000000;">,</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner.Phone)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                    </span><span style="color: #0000ff;">break;</span><span style="color: #808080;"><br />
                </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
            </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
    </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
    </span><span style="color: #0000ff;">class</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #000000;">Name</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"> </span><span style="color: #0000ff;">get;</span><span style="color: #808080;"> </span><span style="color: #0000ff;">set;</span><span style="color: #808080;"> </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #000000;">Email</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"> </span><span style="color: #0000ff;">get;</span><span style="color: #808080;"> </span><span style="color: #0000ff;">set;</span><span style="color: #808080;"> </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #000000;">Phone</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"> </span><span style="color: #0000ff;">get;</span><span style="color: #808080;"> </span><span style="color: #0000ff;">set;</span><span style="color: #808080;"> </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner(</span><span style="color: #2b91af;">ConfigurationElement</span><span style="color: #808080;"> </span><span style="color: #000000;">site)</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Name</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">site.GetAttributeValue(</span><span style="color: #808080;">&#8220;ownerName&#8221;</span><span style="color: #000000;">)</span><span style="color: #808080;"> </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Email</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">site.GetAttributeValue(</span><span style="color: #808080;">&#8220;ownerEmail&#8221;</span><span style="color: #000000;">)</span><span style="color: #808080;"> </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Phone</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">site.GetAttributeValue(</span><span style="color: #808080;">&#8220;ownerPhone&#8221;</span><span style="color: #000000;">)</span><span style="color: #808080;"> </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string;</span><span style="color: #808080;"><br />
        </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
    </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
</span><span style="color: #000000;">}</span><span style="color: #808080;"> </span></div>
</li>
<li>Click the <strong>File</strong> | <strong>Save</strong> menu item.</li>
<li>Right-click the SiteOwner project in the <strong>Solution Explorer </strong>window and select <strong>Properties</strong> from the menu</li>
<li>Click the <strong>Signing</strong> tab</li>
<li>Check the <strong>Sign the assembly</strong> checkbox</li>
<li>Select &#8220;&lt;new&gt;&#8221; from the <strong>Choose a strong name key file</strong> dropdown box</li>
<li>Type &#8220;KeyFile&#8221; in the <strong>Key file name</strong> box</li>
<li>Uncheck the checkbox labeled <strong>Protect my key file with a password</strong></li>
<li>Click <strong>OK</strong></li>
<li>Click the <strong>File</strong> | <strong>Save SiteOwner</strong> menu item</li>
<li>Click the <strong>Build</strong> | <strong>Build SiteOwner</strong> menu item.</li>
</ol>
<p><strong>Notepad.exe and Command-line Walk-through</strong></p>
<p>The following walk-through will create an HTTP module that can display the site owner details of the configuration system. This walk-through assumes that you have the Microosft .NET Framework SDK or Windows SDK installed. These include the C# compilers needed to build. For more help on building with csc.exe, see &#8220;<a href="http://msdn.microsoft.com/en-us/library/78f4aasd.aspx" target="_blank">Command-line building With csc.exe</a>&#8221;</p>
<ol>
<li>Paste the code from step 10 of the Visual Studio .NET 2008 walk-through into a new notepad instance</li>
<li>Click <strong>File</strong> | <strong>Save As</strong> &#8230;</li>
<li>Browse to the &#8220;<em>C:samples</em>&#8221; folder if it exists; create the folder if it does not</li>
<li>Type &#8220;<em>SiteOwnerHeaderModule.cs</em>&#8221; in the <strong>File name </strong>box</li>
<li>Click the <strong>Save</strong> button</li>
<li>Open a new <strong>SDK Command Prompt</strong> (Windows SDK) or <strong>Visual Studio Command Prompt</strong> (Visual Studio 2008).</li>
<li>At the command prompt type:<br />
csc.exe /target:module /out:SiteOwner.netmodule /debug /r:System.Web.dll /r:%windir%system32inetsrvMicrosoft.Web.Administration.dll SiteOwnerHeaderModule.cs</li>
<li>Press ENTER then type:<br />
sn.exe -k keyfile.snk</li>
<li>Press ENTER then type:<br />
al.exe /out:SiteOwner.dll SiteOwner.netmodule /keyfile:keyfile.snk</li>
</ol>
<h4>Deploying Your HTTP Module</h4>
<p>Once you have built your assembly using either Visual Studio 2008 or csc.exe, its time to deploy it to your system. This sample assumes that you don&#8217;t want all of your customers to have to install this same component to each Web site, so we&#8217;ll install it as a default module on the system.</p>
<p><strong>Registering the Assembly in the GAC</strong></p>
<p>To do this we first need to copy the assembly file(s) to the target system, and register them in the Global Assembly Cache. Using your preferred method to copy the files, copy the SiteOwner.dll (<strong>and</strong> SiteOwner.netmodule if you used command-line compilation) to the %windir%system32inetsrv directory on the target installation machine. Next open up a command prompt and type:</p>
<p>gacutil -i %windir%system32InetSrvSiteOwner.dll</p>
<p>Now you&#8217;ll need to get a copy of the &#8220;Public Key Token&#8221; for the assembly so that you can install this &#8220;strong-named assembly&#8221; module in IIS. To do this open up your <em>%windir%assembly</em> directory in <strong>Windows Explorer</strong>. Scroll down to the SiteOwner &#8220;file&#8221; in that window and copy the &#8220;Public Key Token&#8221;. You can do this easily by right-clicking the &#8220;file&#8221; and selecting <strong>Properties</strong> from the menu. Double click on the <strong>Public Key Token</strong> to select the entire contents, then right click the highlighted text and select <strong>Copy</strong> from the menu.</p>
<p><a href="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_4.png"><img style="border-width: 0px;" src="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_thumb_1.png" border="0" alt="image" width="230" height="260" /></a></p>
<p><strong>Installing the Module as a Default Module in IIS 7.0</strong></p>
<p>Now that you have your assembly registered and your Public Key Token copied, its time to add this module to all the Web sites on your IIS 7.0 server. To accomplish this, open up your <em>%windir%system32inetsrvconfigapplicationHost.config</em> file in notepad. Scroll down near the bottom of the file to the default location path that looks something like this:</p>
<p>&lt;location path=&#8221;" overrideMode=&#8221;Allow&#8221;&gt;</p>
<p>Inside of that element scroll down to the &lt;modules&gt; element under the &lt;system.webServer&gt; section. You should find a number of modules already listed. To add yours, simply scroll to the bottom of the list and <strong>type</strong> the following:</p>
<p>&lt;add name=&#8221;SiteOwner&#8221; type=&#8221;SiteOwner.SiteOwnerHeaderModule, SiteOwner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=&#8221; /&gt;</p>
<p>Once you have typed this line in, you can paste your Public Key Token in right after &#8220;PublicKeyToken=&#8221; in the line you just typed. Save the applicationHost.config file.</p>
<p><strong>Testing the Module</strong></p>
<p>Choose a Web site on your server to test your application. If you want to run this module for files other than ASP.NET files, you&#8217;ll need to choose a Web site running in Integrated Pipeline. For our sample, we are going to make an HTML file to test our code. Our HTML file will contain some JavaScript that will get the headers from the server and display them in a message box. We could use a number of diagnostic tools to do this same work, but this will serve our purposes.</p>
<p>Open up Notepad and paste the following markup into it:</p>
<div class="code"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script</span><span style="color: #ff0000;"> language</span><span style="color: #0000ff;">=&#8221;JavaScript&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;text/javascript&#8221;&gt;</span><span style="color: #808080;"><br />
</span><span style="color: #000000;">&lt;!&#8211;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">var</span><span style="color: #808080;"> </span><span style="color: #000000;">req</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #0000ff;">new</span><span style="color: #808080;"> </span><span style="color: #0000ff;">ActiveXObject</span><span style="color: #000000;">(</span><span style="color: #808080;">&#8216;Microsoft.XMLHTTP&#8217;</span><span style="color: #000000;">)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #000000;">req.open(</span><span style="color: #808080;">&#8216;HEAD&#8217;</span><span style="color: #000000;">,</span><span style="color: #808080;"> </span><span style="color: #000000;">location.href,</span><span style="color: #808080;"> </span><span style="color: #0000ff;">false</span><span style="color: #000000;">)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #000000;">req.send()</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">alert</span><span style="color: #000000;">(req.getAllResponseHeaders())</span><span style="color: #808080;"><br />
</span><span style="color: #006400;">//&#8211;&gt;<br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span></div>
<p>Save the file to the physical root of the Web site you wish to test. Type in the corresponding URL to your test file in your web browser. Your result should be a JavaScript alert that looks something like the following:</p>
<p><a href="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_2.png"><img style="border-width: 0px;" src="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_thumb.png" border="0" alt="image" width="260" height="220" /></a> </p>
<p>You&#8217;ll notice in my results, I have already set the Site&#8217;s ownerName attribute. (see the Webcast titled &#8220;<a href="http://learn.iis.net/page.aspx/471/extending-iis-configuration">Extending IIS Configuration</a>&#8221; to see how).</p>
<h3>Improving our Sample</h3>
<h4>Introduction</h4>
<p>As I stated earlier in this post, this demonstrates something that is definitely possible, but somewhat risky to do. We now want to improve our sample to limit our dependencies on native and/or third-party configuration schema definitions, and prevent us from encroaching on another module&#8217;s configuration territory. In concept, what we will do is move our configuration data to its own configuration section and use the site&#8217;s ID to allow us to map the data from the site collection to our configuration section.</p>
<h4>Modifying the Schema</h4>
<p>First, you&#8217;ll want to remove the custom site owner configuration data from the site nodes. Otherwise, once we modify the schema, the configuration will not validate. Once you&#8217;ve removed that data open the <em>SiteOwner_schema.xml</em> file in notepad and change it to the following:</p>
<div class="code"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">configSchema</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
    </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">sectionSchema</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;system.applicationHost/siteOwner&#8221;&gt;</span><span style="color: #000000;"><br />
        </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">collection</span><span style="color: #ff0000;"> addElement</span><span style="color: #0000ff;">=&#8221;site&#8221;&gt;</span><span style="color: #000000;"><br />
        </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;id&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;uint&#8221;</span><span style="color: #ff0000;"> required</span><span style="color: #0000ff;">=&#8221;true&#8221;</span><span style="color: #ff0000;"> isUniqueKey</span><span style="color: #0000ff;">=&#8221;true&#8221;</span><span style="color: #ff0000;"> </span><span style="color: #0000ff;">/&gt;<br />
            &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerName&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;</span><span style="color: #ff0000;"> </span><span style="color: #0000ff;">/&gt;<br />
            &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerEmail&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;</span><span style="color: #ff0000;"> </span><span style="color: #0000ff;">/&gt;<br />
            &lt;</span><span style="color: #800000;">attribute</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;ownerPhone&#8221;</span><span style="color: #ff0000;"> type</span><span style="color: #0000ff;">=&#8221;string&#8221;</span><span style="color: #ff0000;"> </span><span style="color: #0000ff;">/&gt;<br />
        &lt;/</span><span style="color: #800000;">collection</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
    </span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">sectionSchema</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">configSchema</span><span style="color: #0000ff;">&gt;</span></div>
<p>Save the file in the same location as you did previously. Now we need to tell the <em>applicationHost.config</em> file about our new section schema. To do this, we add a new <strong>section</strong> declaration underneath of the <strong>system.applicationHost</strong> sectionGroup in the <em>applicationHost.config</em> file.</p>
<div class="code"><em><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">sectionGroup</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;system.applicationHost&#8221;&gt;</span></em><span style="color: #000000;"><br />
</span><span style="color: #0000ff;"><strong>    &#8230;<br />
</strong></span><span style="color: #0000ff;"><strong>    &lt;</strong></span><strong><span style="color: #800000;">section</span><span style="color: #ff0000;"> name</span><span style="color: #0000ff;">=&#8221;siteOwner&#8221;</span><span style="color: #ff0000;"> allowDefinition</span><span style="color: #0000ff;">=&#8221;AppHostOnly&#8221;</span><span style="color: #ff0000;"> overrideModeDefault</span><span style="color: #0000ff;">=&#8221;Deny&#8221;</span><span style="color: #ff0000;"> </span></strong><span style="color: #0000ff;"><strong>/&gt;<br />
</strong></span><span style="color: #0000ff;"><strong>    &#8230;</strong><br />
<em>&lt;/</em></span><em><span style="color: #800000;">sectionGroup</span><span style="color: #0000ff;">&gt;</span> </em></div>
<p>Next we need to modify our HTTP module to read from the new configuration section:</p>
<div class="code"><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System.Web</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System.Web.Hosting</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">Microsoft.Web.Administration</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">using</span><span style="color: #808080;"> </span><span style="color: #000000;">System.Collections.Specialized</span><span style="color: #0000ff;">;</span><span style="color: #808080;"></p>
<p></span><span style="color: #0000ff;">namespace</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner{</span><span style="color: #808080;"><br />
    </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">class</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwnerHeaderModule</span><span style="color: #808080;"> </span><span style="color: #000000;">:</span><span style="color: #808080;"> </span><span style="color: #2b91af;">IHttpModule</span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">void</span><span style="color: #808080;"> </span><span style="color: #000000;">Dispose()</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"> </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">void</span><span style="color: #808080;"> </span><span style="color: #000000;">Init(</span><span style="color: #2b91af;">HttpApplication</span><span style="color: #808080;"> </span><span style="color: #000000;">context){</span><span style="color: #808080;"><br />
            </span><span style="color: #000000;">context.PreSendRequestHeaders</span><span style="color: #808080;"><br />
                </span><span style="color: #000000;">+</span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #0000ff;">new</span><span style="color: #808080;"> </span><span style="color: #2b91af;">EventHandler</span><span style="color: #000000;">(OnPreSendRequestHeaders)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
        </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">void</span><span style="color: #808080;"> </span><span style="color: #000000;">OnPreSendRequestHeaders(</span><span style="color: #0000ff;">object</span><span style="color: #808080;"> </span><span style="color: #000000;">sender,</span><span style="color: #808080;"> </span><span style="color: #2b91af;">EventArgs</span><span style="color: #808080;"> </span><span style="color: #000000;">e){</span><span style="color: #808080;"><br />
            </span><span style="color: #006400;">// Get the site collection<br />
</span><span style="color: #808080;">            </span><span style="color: #2b91af;">ConfigurationSection</span><span style="color: #808080;"> </span><span style="color: #000000;">section</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"><br />
</span>                <span style="color: #000000;">WebConfigurationManager.GetSection(</span><span style="color: #808080;">&#8220;system.applicationHost/sites&#8221;</span><span style="color: #000000;">)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
            </span><span style="color: #2b91af;">ConfigurationElementCollection</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSites</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">section.GetCollection()</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
            <span style="color: #2b91af;">HttpApplication</span><span style="color: #000000;"> app = (</span><span style="color: #2b91af;">HttpApplication</span><span style="color: #000000;">)sender</span><span style="color: #0000ff;">;</span><br />
<span style="color: #808080;">            </span><span style="color: #2b91af;">HttpContext</span><span style="color: #000000;"> context </span><span style="color: #0000ff;">=</span><span style="color: #000000;"> app.Context</span><span style="color: #0000ff;">;</span></span><span style="color: #808080;"><br />
            </span><span style="color: #006400;">// Loop through the sites to find the site of<br />
</span><span style="color: #808080;">            </span><span style="color: #006400;">// the currently executing request<br />
</span><span style="color: #808080;">            </span><span style="color: #0000ff;">foreach</span><span style="color: #808080;"> </span><span style="color: #000000;">(</span><span style="color: #2b91af;">ConfigurationElement</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSite</span><span style="color: #808080;"> </span><span style="color: #0000ff;">in</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSites){</span><span style="color: #808080;"><br />
</span><span style="color: #808080;">                </span><span style="color: #0000ff;">if</span><span style="color: #808080;"> </span><span style="color: #000000;">(HostingEnvironment.SiteName</span><span style="color: #808080;"> </span><span style="color: #0000ff;">==</span><span style="color: #808080;"> </span><span style="color: #000000;"><span style="color: #000000;">(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">)cfgSite.GetAttributeValue(</span><span style="color: #808080;">&#8220;name&#8221;</span><span style="color: #000000;">)</span>){</span><span style="color: #808080;"><br />
                    </span><span style="color: #006400;">// This is the correct site, find the associated<br />
</span><span style="color: #808080;">                    </span><span style="color: #006400;">// Site Owner record in our custom config section<br />
</span><span style="color: #808080;">                    </span><span style="color: #000000;">SiteOwner</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner.Find(<span style="color: #000000;">(</span><span style="color: #0000ff;">long</span><span style="color: #000000;">)cfgSite.GetAttributeValue(</span><span style="color: #808080;">&#8220;id&#8221;</span><span style="color: #000000;">)</span>)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                    </span><span style="color: #0000ff;">if</span><span style="color: #808080;"> </span><span style="color: #000000;">(siteOwner</span><span style="color: #808080;"> </span><span style="color: #000000;">!</span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #0000ff;">null</span><span style="color: #000000;">) {</span><span style="color: #808080;"><br />
                        </span><span style="color: #006400;">// Add the headers if we found a matching<br />
</span><span style="color: #808080;">                        </span><span style="color: #006400;">// site owner record configured<br />
</span><span style="color: #808080;">                        </span><span style="color: #000000;">NameValueCollection</span><span style="color: #808080;"> </span><span style="color: #000000;">headers</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #2b91af;">context</span><span style="color: #000000;">.Response.Headers</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                        </span><span style="color: #000000;">headers.Add(</span><span style="color: #808080;">&#8220;Site-Owner-Name&#8221;</span><span style="color: #000000;">,</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner.Name)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                        </span><span style="color: #000000;">headers.Add(</span><span style="color: #808080;">&#8220;Site-Owner-Email&#8221;</span><span style="color: #000000;">,</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner.Email)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                        </span><span style="color: #000000;">headers.Add(</span><span style="color: #808080;">&#8220;Site-Owner-Phone&#8221;</span><span style="color: #000000;">,</span><span style="color: #808080;"> </span><span style="color: #000000;">siteOwner.Phone)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                    </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
                    </span><span style="color: #0000ff;">break;</span><span style="color: #808080;"><br />
                </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
            </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
    </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
    </span><span style="color: #0000ff;">class</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner{</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #000000;">Name</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"> </span><span style="color: #0000ff;">get;</span><span style="color: #808080;"> </span><span style="color: #0000ff;">set;</span><span style="color: #808080;"> </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #000000;">Email</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"> </span><span style="color: #0000ff;">get;</span><span style="color: #808080;"> </span><span style="color: #0000ff;">set;</span><span style="color: #808080;"> </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string</span><span style="color: #808080;"> </span><span style="color: #000000;">Phone</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"> </span><span style="color: #0000ff;">get;</span><span style="color: #808080;"> </span><span style="color: #0000ff;">set;</span><span style="color: #808080;"> </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner(</span><span style="color: #2b91af;">ConfigurationElement</span><span style="color: #808080;"> </span><span style="color: #000000;">owner){</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Name</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">owner.GetAttributeValue(</span><span style="color: #808080;">&#8220;ownerName&#8221;</span><span style="color: #000000;">)</span><span style="color: #808080;"> </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string;</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Email</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">owner.GetAttributeValue(</span><span style="color: #808080;">&#8220;ownerEmail&#8221;</span><span style="color: #000000;">)</span><span style="color: #808080;"> </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string;</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Phone</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"> </span><span style="color: #000000;">owner.GetAttributeValue(</span><span style="color: #808080;">&#8220;ownerPhone&#8221;</span><span style="color: #000000;">)</span><span style="color: #808080;"> </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #0000ff;">string;</span><span style="color: #808080;"><br />
        </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
        </span><span style="color: #0000ff;">public</span><span style="color: #808080;"> </span><span style="color: #0000ff;">static</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner</span><span style="color: #808080;"> </span><span style="color: #000000;">Find(</span><span style="color: #0000ff;">long</span><span style="color: #808080;"> </span><span style="color: #000000;">siteId){<br />
</span>             <span style="color: #006400;">// Find the matching siteOwner record for this siteId</span>          <span style="color: #808080;"><br />
            </span><span style="color: #2b91af;">ConfigurationSection</span><span style="color: #808080;"> </span><span style="color: #000000;">section</span><span style="color: #808080;"> </span><span style="color: #0000ff;">=</span><span style="color: #808080;"><br />
</span>                        <span style="color: #000000;">WebConfigurationManager.GetSection(</span><span style="color: #808080;">&#8220;system.applicationHost/siteOwner&#8221;</span><span style="color: #000000;">)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
            </span><span style="color: #2b91af;">ConfigurationElementCollection</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSiteOwners</span><span style="color: #808080;"> </span><span style="color: #0000ff;">= </span><span style="color: #000000;">section.GetCollection()</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">foreach</span><span style="color: #808080;"> </span><span style="color: #000000;">(</span><span style="color: #2b91af;">ConfigurationElement</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgOwner</span><span style="color: #808080;"> </span><span style="color: #0000ff;">in</span><span style="color: #808080;"> </span><span style="color: #000000;">cfgSiteOwners)</span><span style="color: #808080;"> </span><span style="color: #000000;">{</span><span style="color: #808080;"><br />
                </span><span style="color: #0000ff;">if</span><span style="color: #808080;"> </span><span style="color: #000000;">(siteId</span><span style="color: #808080;"> </span><span style="color: #0000ff;">==</span><span style="color: #808080;"> </span><span style="color: #000000;">(</span><span style="color: #0000ff;">long</span><span style="color: #000000;">)cfgOwner.GetAttributeValue(</span><span style="color: #808080;">&#8220;id&#8221;</span><span style="color: #000000;">)){</span><span style="color: #808080;"><br />
                    </span><span style="color: #0000ff;">return</span><span style="color: #808080;"> </span><span style="color: #0000ff;">new</span><span style="color: #808080;"> </span><span style="color: #000000;">SiteOwner(cfgOwner)</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
                </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
            </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
            </span><span style="color: #0000ff;">return</span><span style="color: #808080;"> </span><span style="color: #0000ff;">null;</span><span style="color: #808080;"><br />
        </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
    </span><span style="color: #000000;">}</span><span style="color: #808080;"><br />
</span><span style="color: #000000;">}</span></div>
<p> </p>
<p>There isn&#8217;t much changed in this compared to the last. The difference, apart from a few code comments, is that I&#8217;ve modified the <strong>OnPreRequestHeaders</strong> function to get the current site ID, and pass that into the static <strong>SiteOwner.Find</strong> function. Then I modified the <strong>SiteOwner.Find</strong> function to read from our new configuration section. <span style="text-decoration: underline;">Please note</span> that production code would likely set SiteOwner to extend from <strong>ConfigurationElement</strong>, and a special <strong>ConfigurationSection </strong>would be developed. Go ahead and compile and deploy this assembly the same way you did with the previous version. Make sure that you run gacutil on the new assembly once it is copied. Also, since we are running against a static HTML file, you might need to run <strong>iisreset.exe</strong> from a command-line in order to clear the cache from the server.</p>
<p>Once you have deployed your assembly and the schema file, its time to test the application. If we refresh our Web page, we will get a JavaScript alert without any site owner headers listed:</p>
<p><a href="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_6.png"><img style="border-width: 0px;" src="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_thumb_2.png" border="0" alt="image" width="260" height="191" /></a></p>
<p>This is because we haven&#8217;t created any site owner configuration entries yet. So lets add a record directly to our config. I added the following configuration directly after the &lt;sites&gt; node in the <strong>applicationHost.config</strong> file:</p>
<div class="code"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">siteOwner</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
    </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">site</span><span style="color: #ff0000;"> id</span><span style="color: #0000ff;">=&#8221;1&#8243;</span><span style="color: #ff0000;"> ownerName</span><span style="color: #0000ff;">=&#8221;Tobin Titus&#8221;</span><span style="color: #ff0000;"> ownerEmail</span><span style="color: #0000ff;">=&#8221;tobint@microsoft.com&#8221;</span><span style="color: #ff0000;"> ownerPhone</span><span style="color: #0000ff;">=&#8221;555-121-2121&#8243;</span><span style="color: #ff0000;"> </span><span style="color: #0000ff;">/&gt;<br />
&lt;/</span><span style="color: #800000;">siteOwner</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">        </span></div>
<p>Save your file and refresh your Web browser. You should now see your site owner configuration data.</p>
<p><a href="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_8.png"><img style="border-width: 0px;" src="http://blogs.iis.net/blogs/tobintitus/WindowsLiveWriter/AccessingCustomConfigurat.Administration_135EF/image_thumb_3.png" border="0" alt="image" width="260" height="220" /></a></p>
<h3>Conclusions</h3>
<p>In this blog post, we&#8217;ve walked through extending existing IIS configuration objects, and accessing the custom data at runtime through an HTTP module. We&#8217;ve also talked about the risks of this approach and have demonstrated a better approach. This approach gives us the same ability to customize our IIS 7.0 configuration system, but gives us a much smaller dependency on the native configuration schema. We have little worry about schema changes, we don&#8217;t have to worry about other modules or utilities stomping on our custom data, and most importantly, we are far less likely to cause any Access Violations with the later approach. </p>
<p>Many thanks go to Carlos once again for his help in putting this post together as well as for his <a href="http://www.carlosag.net/Tools/WindowsLiveWriter/Default.aspx" target="_blank">CodeColorizer</a> plug-in for Live Writer. High-fives and cookies in his office!</p>
<p>Related posts:<ol>
<li><a href='http://tobint.com/blog/iis-cannot-start-after-upgrade-to-vista-sp1/' rel='bookmark' title='IIS cannot start after upgrade to Vista SP1'>IIS cannot start after upgrade to Vista SP1</a></li>
<li><a href='http://tobint.com/blog/accessing-microsoft-web-administration-through-powershell-part-i/' rel='bookmark' title='Accessing IIS 7 APIs through PowerShell (Part I)'>Accessing IIS 7 APIs through PowerShell (Part I)</a></li>
<li><a href='http://tobint.com/blog/sdk-sample-programmatically-change-the-runtime-version-of-an-application-pool-in-iis-7/' rel='bookmark' title='Change the runtime of an IIS 7 application pool'>Change the runtime of an IIS 7 application pool</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://tobint.com/blog/accessing-custom-configuration-at-runtime-with-microsoft-web-administration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

