<?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>RuslanY Blog &#187; ASPNET</title>
	<atom:link href="http://ruslany.net/tag/aspnet/feed/" rel="self" type="application/rss+xml" />
	<link>http://ruslany.net</link>
	<description>IIS, FastCGI, PHP and other interesting stuff</description>
	<lastBuildDate>Fri, 30 Jul 2010 23:07:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>10 URL Rewriting Tips and Tricks</title>
		<link>http://ruslany.net/2009/04/10-url-rewriting-tips-and-tricks/</link>
		<comments>http://ruslany.net/2009/04/10-url-rewriting-tips-and-tricks/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 22:34:21 +0000</pubDate>
		<dc:creator>ruslany</dc:creator>
				<category><![CDATA[URLRewrite]]></category>
		<category><![CDATA[ASPNET]]></category>

		<guid isPermaLink="false">http://ruslany.net/?p=307</guid>
		<description><![CDATA[This post describes some of the tips and tricks that one may find useful when solving URL-based problems for their web server or web site. Each tip/trick has a description of a problem and then an example of how it can be solved with IIS 7 URL Rewrite Module. 1. Add or Remove Trailing Slash [...]]]></description>
			<content:encoded><![CDATA[<p>This post describes some of the tips and tricks that one may find useful when solving URL-based problems for their web server or web site. Each tip/trick has a description of a problem and then an example of how it can be solved with <a title="URL Rewrite Module for IIS 7.0" href="http://www.iis.net/extensions/URLRewrite" target="_blank">IIS 7 URL Rewrite Module</a>.</p>
<h3>1. Add or Remove Trailing Slash</h3>
<p>Many web applications use “virtual URLs” &#8211; that is the URLs that do not directly map to the file and directory layout on web server’s file system. An example of such application may be an ASP.NET MVC application with URL format similar to this: <a href="http://stackoverflow.com/questions/60857/modrewrite-equivalent-for-iis-7-0">http://stackoverflow.com/questions/60857/modrewrite-equivalent-for-iis-7-0</a> or a PHP application with URL format that looks like this: <a href="http://ruslany.net/2008/11/url-rewrite-module-release-to-web/">http://ruslany.net/2008/11/url-rewrite-module-release-to-web/</a>. If you try to request these URLs with or without trailing slash you will still get the same page. That is OK for human visitors, but may be a problem for search engine crawlers as well as for web analytics services. Different URLs for the same page may cause crawlers to treat the same page as different pages, thus affecting the page ranking. They will also cause Web Analytics statistics for this page to be split up.<span id="more-307"></span></p>
<p>This problem is very easy to fix with a rewrite rule. Having or not having a trailing slash in the URL is a matter of taste, but once you’ve made a choice you can enforce the canonical URL format by using one of these rewrite rules:</p>
<p>To always remove trailing slash from the URL:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Remove trailing slash&quot; stopProcessing=&quot;true&quot;&gt;
  &lt;match url=&quot;(.*)/$&quot; /&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsFile&quot; negate=&quot;true&quot; /&gt;
    &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsDirectory&quot; negate=&quot;true&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;Redirect&quot; redirectType=&quot;Permanent&quot; url=&quot;{R:1}&quot; /&gt;
&lt;/rule&gt;
</pre>
<p>To always add trailing slash to the URL:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Add trailing slash&quot; stopProcessing=&quot;true&quot;&gt;
  &lt;match url=&quot;(.*[^/])$&quot; /&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsFile&quot; negate=&quot;true&quot; /&gt;
    &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsDirectory&quot; negate=&quot;true&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;Redirect&quot; redirectType=&quot;Permanent&quot; url=&quot;{R:1}/&quot; /&gt;
&lt;/rule&gt;
</pre>
<h3>2. Enforce Lower Case URLs</h3>
<p>A problem similar to the trailing slash problem may happen when somebody links to your web page by using different casing, e.g. <a href="http://ruslany.net/2008/07/iisnet-uses-url-rewrite-module/">http://ruslany.net/2008/07/IISNET-Uses-Url-Rewrite-Module/</a> vs. <a href="http://ruslany.net/2008/07/iisnet-uses-url-rewrite-module/">http://ruslany.net/2008/07/iisnet-uses-url-rewrite-module/</a>. In this case again the search crawlers will treat the same page as two different pages and two different statistics sets will show up in Web Analytics reports.</p>
<p>What you want to do is to ensure that if somebody comes to your web site by using a non-canonical link, then you redirect them to the canonical URL that uses only lowercase characters:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Convert to lower case&quot; stopProcessing=&quot;true&quot;&gt;
  &lt;match url=&quot;.*[A-Z].*&quot; ignoreCase=&quot;false&quot; /&gt;
  &lt;action type=&quot;Redirect&quot; url=&quot;{ToLower:{R:0}}&quot; redirectType=&quot;Permanent&quot; /&gt;
&lt;/rule&gt;
</pre>
<h3>3. Canonical Hostnames</h3>
<p>Very often you may have one IIS web site that uses several different host names. The most common example is when a site can be accessed via <strong>http://www.yoursitename.com</strong> and via <strong>http://yoursitename.com</strong>. Or, perhaps, you have recently changed you domain name from <strong>oldsitename.com</strong> to <strong>newsitename.com</strong> and you want your visitors to use new domain name when bookmarking links to your site. A very simple redirect rule will take care of that:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Canonical Host Name&quot; stopProcessing=&quot;true&quot;&gt;
  &lt;match url=&quot;(.*)&quot; /&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{HTTP_HOST}&quot; negate=&quot;true&quot; pattern=&quot;^ruslany\.net$&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;Redirect&quot; url=&quot;http://ruslany.net/{R:1}&quot; redirectType=&quot;Permanent&quot; /&gt;
&lt;/rule&gt;
</pre>
<p>To see an example of how that works try browsing to <a href="http://www.ruslany.net/2008/10/aspnet-postbacks-and-url-rewriting/">http://www.ruslany.net/2008/10/aspnet-postbacks-and-url-rewriting/</a>. You will see in the browser’s address bar that “www” is removed from the domain name.</p>
<h3>4. Redirect to HTTPS</h3>
<p>When a site that requires SSL is accessed via non-secure HTTP connection, IIS responds with HTTP 403 (Unauthorized) status code. This may be fine if you always expect that your site visitors will be typing “https://…” in the browser’s address bar. But if you want your site to be easily discoverable and more user friendly, you probably would not want to return 403 response to visitors who came over unsecure HTTP connection. Instead you would want to redirect them to the secure equivalent of the URL they have requested. A typical example is this URL: <a href="http://www.paypal.com"><strong>http</strong>://www.paypal.com</a>. If you follow it you will see that browser gets redirected to <a href="https://www.paypal.com"><strong>https</strong>://www.paypal.com</a>.</p>
<p>With URL Rewrite Module you can perform this kind of redirection by using the following rule:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Redirect to HTTPS&quot; stopProcessing=&quot;true&quot;&gt;
  &lt;match url=&quot;(.*)&quot; /&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{HTTPS}&quot; pattern=&quot;^OFF$&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;Redirect&quot; url=&quot;https://{HTTP_HOST}/{R:1}&quot; redirectType=&quot;SeeOther&quot; /&gt;
&lt;/rule&gt;
</pre>
<p>Note that for this rule to work within the same web site you will need to disable “Require SSL” checkbox for the web site. If you do not want to do that, then you can create two web sites in IIS – one with http binding and another with https binding – and then add this rule to the web.config file of the site with http binding.</p>
<h3>5. Return HTTP 503 Status Code in Response</h3>
<p>HTTP status code 503 means that the server is currently unable to handle the request due to maintenance. This status code implies that the outage is temporary, so when search engine crawler gets HTTP 503 response from your site, it will know not to index this response, but instead to come back later.</p>
<p>When you stop the IIS application pool for your web site, IIS will return HTTP 503 for all requests to that site. But what if you are doing maintenance to a certain location of the web site and you do not want to shut down the entire site because of that? With URL Rewrite Module you can return 503 response only when HTTP requests are made to a specific URL path:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Return 503&quot; stopProcessing=&quot;true&quot;&gt;
  &lt;match url=&quot;^products/sale/.*&quot; /&gt;
  &lt;action type=&quot;CustomResponse&quot; statusCode=&quot;503&quot;
               subStatusCode=&quot;0&quot;
               statusReason=&quot;Site is unavailable&quot;
               statusDescription=&quot;Site is down for maintenance&quot; /&gt;
&lt;/rule&gt;
</pre>
<h3>6. Prevent Image Hotlinking</h3>
<p><a title="Image Hotlinking" href="http://en.wikipedia.org/wiki/Inline_linking" target="_blank">Image Hotlinking</a> is the use of an image from one site into a web page belonging to a second site. Unauthorized image hotlinking from your site increases bandwidth use, even though the site is not being viewed as intended. There are other concerns with image hotlinking, for example copyrights or usage of images in an inappropriate context.</p>
<p>With URL Rewrite Module, it is very easy to prevent image hotlinking. For example the following rewrite rule prevents hotlinking to all images on a web site <a href="http://ruslany.net">http://ruslany.net</a>:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Prevent image hotlinking&quot;&gt;
  &lt;match url=&quot;.*\.(gif|jpg|png)$&quot;/&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{HTTP_REFERER}&quot; pattern=&quot;^$&quot; negate=&quot;true&quot; /&gt;
    &lt;add input=&quot;{HTTP_REFERER}&quot; pattern=&quot;^http://ruslany\.net/.*$&quot; negate=&quot;true&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;Rewrite&quot; url=&quot;/images/say_no_to_hotlinking.jpg&quot; /&gt;
&lt;/rule&gt;
</pre>
<p>This rule will rewrite a request for any image file to <strong>/images/say_no_to_hotlinking.jpg</strong> only if the HTTP Referer header on the request is not empty and is not equal to the site’s domain.</p>
<h3>7. Reverse Proxy To Another Site/Server</h3>
<p>By using URL Rewrite Module together with <a title="Application Request Routing" href="http://www.iis.net/extensions/ApplicationRequestRouting" target="_blank">Application Request Routing module</a> you can have IIS 7 act as a reverse proxy. For example, you have an intranet web server and you want to expose its content over internet. To enable that you will need to perform the following configuration steps on the server that will act as a proxy:</p>
<p><strong>Step1</strong>: Check the “Enable proxy” checkbox located in Application Request Routing feature view is IIS Manager.</p>
<p><strong>Step2</strong>: Add the following rule to the web site that will be used to proxy HTTP requests:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Proxy&quot;&gt;
  &lt;match url=&quot;(.*)&quot; /&gt;
  &lt;action type=&quot;Rewrite&quot; url=&quot;http://internalserver/{R:1}&quot; /&gt;
&lt;/rule&gt;
</pre>
<p>Note the <strong><em>http://</em></strong> prefix in the rewrite rule action. That is what indicates that this request must be proxy’ed, instead of being rewritten. When rule has “Rewrite” action with the URL that contains the protocol prefix, then URL Rewrite Module will not perform its standard URL rewriting logic. Instead it will pass the request to Application Request Routing module, which will proxy that request to the URL specified in the rule.</p>
<h3>8. Preserve Protocol Prefix in Reverse Proxy</h3>
<p>The rule in previous tip always uses non-secure connection to the internal content server. Even if the request came to the proxy server over HTTPS, the proxy server will pass that request to the content server over HTTP. In many cases this may be exactly what you want to do. But sometimes it may be necessary to preserve the secure connection all the way to the content server. In other words, if client connects to the server over HTTPS, then the proxy should use “https://” prefix when making requests to content server. Similarly, if client connected over HTTP, then proxy should use “http://” connection to content server.</p>
<p>This logic can be easily expressed by this rewrite rule:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Proxy&quot;&gt;
  &lt;match url=&quot;(.*)&quot; /&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{CACHE_URL}&quot; pattern=&quot;^(https?)://&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;Rewrite&quot; url=&quot;{C:1}://internalserver/{R:1}&quot; /&gt;
&lt;/rule&gt;
</pre>
<h3>9. Rewrite/Redirect Based on Query String Parameters</h3>
<p>When rewriting/redirection decisions are being made by using values extracted from the query string, very often one cannot rely on having the query string parameters always listed in exact same order. So the rewrite rule must be written in such a way so that it can extract the query string parameters independently of their relative order in the query string.</p>
<p>The following rule shows an example of how two different query string parameters are extracted from the query string and then used in the rewritten URL:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;Query String Rewrite&quot;&gt;
  &lt;match url=&quot;page\.asp$&quot; /&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{QUERY_STRING}&quot; pattern=&quot;p1=(\d+)&quot; /&gt;
    &lt;add input=&quot;##{C:1}##_{QUERY_STRING}&quot; pattern=&quot;##([^#]+)##_.*p2=(\d+)&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;rewrite&quot; url=&quot;newpage.aspx?param1={C:1}&amp;amp;amp;param2={C:2}&quot; appendQueryString=&quot;false&quot;/&gt;
&lt;/rule&gt;
</pre>
<p>With this rule, when request is made to page.asp?p2=321&amp;p1=123, it will be rewritten to newpage.aspx?param1=123&amp;param2=321. Parameters p1 and p2 can be in any order in the original query string.</p>
<h3>10. Avoid Rewriting of Requests for ASP.NET Web Resources</h3>
<p>ASP.NET-based web applications very often make requests to WebResources.axd file to retrieve assembly resources and serve them to the Web browser. There is no such file exists on the server because ASP.NET generates the content dynamically when WebResources.axd is requested. So if you have a URL rewrite rule that does rewriting or redirection only if requested URL does not correspond to a file or a folder on a web server’s file system, that rule may accidentally rewrite requests made to WebResources.axd and thus break your application.</p>
<p>This problem can be easily prevented if you add one extra condition to the rewrite rule:</p>
<pre name="code" class="xml">
&lt;rule name=&quot;RewriteUserFriendlyURL1&quot; stopProcessing=&quot;true&quot;&gt;
  &lt;match url=&quot;^([^/]+)/?$&quot; /&gt;
  &lt;conditions&gt;
    &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsFile&quot; negate=&quot;true&quot; /&gt;
    &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsDirectory&quot; negate=&quot;true&quot; /&gt;
    &lt;!--  The following condition prevents rule from rewriting requests to .axd files --&gt;
    &lt;add input=&quot;{URL}&quot; negate=&quot;true&quot; pattern=&quot;\.axd$&quot; /&gt;
  &lt;/conditions&gt;
  &lt;action type=&quot;Rewrite&quot; url=&quot;article.aspx?p={R:1}&quot; /&gt;
&lt;/rule&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://ruslany.net/2009/04/10-url-rewriting-tips-and-tricks/feed/</wfw:commentRss>
		<slash:comments>55</slash:comments>
		</item>
		<item>
		<title>Setup IIS on Server Core – Windows Server 2008 R2</title>
		<link>http://ruslany.net/2009/02/setup-iis-on-server-core-windows-server-2008-r2/</link>
		<comments>http://ruslany.net/2009/02/setup-iis-on-server-core-windows-server-2008-r2/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 01:20:24 +0000</pubDate>
		<dc:creator>ruslany</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[ASPNET]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ruslany.net/?p=260</guid>
		<description><![CDATA[This post has been updated from its original version to correct the installation instructions, which have changed since the time the post was written in Feb 2009. With the addition of .NET Framework to Server Core in Windows Server 2008 R2 the Server Core installation option became even more appealing for those who want to use [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>This post has been updated from its original version to correct the installation instructions, which have changed since the time the post was written in Feb 2009.</p></blockquote>
<p>With the addition of .NET Framework to Server Core in Windows Server 2008 R2 the Server Core installation option became even more appealing for those who want to use a very low footprint server for hosting their applications. Availability of .NET framework provides the following great benefits:</p>
<ol>
<li><strong>ASP.NET support</strong> – you can now use Server Core to host your ASP.NET applications.</li>
<li><strong>IIS Remote Management</strong> – Server Core does not provide any user interface other than command line. But if you prefer to use IIS Manager UI to administer IIS, you can now use IIS Remote Manager to connect to IIS on Server Core and perform all the management tasks from within familiar UI of IIS Manager.</li>
<li><strong>PowerShell</strong> – Windows Server 2008 R2 includes IIS PowerShell snapin, which is also available on Server Core.</li>
</ol>
<p>This post describes how to setup and configure IIS on Server Core in Windows Server 2008 R2. Specifically the following tasks are described:</p>
<ul>
<li>Using oclist and ocsetup commands</li>
<li>Basic Installation of IIS</li>
<li>Installing ASP.NET</li>
<li>Installing PowerShell and IIS snap-in</li>
<li>Enabling IIS Remote Management</li>
</ul>
<p><span id="more-260"></span></p>
<h3>Using oclist and ocsetup commands</h3>
<p><strong>oclist</strong> command can be used to list the available and installed roles and services on the server. The output of the command looks similar to below:</p>
<p><a href="http://ruslany.net/wp-content/uploads/2009/02/oclist.png"><img class="alignnone size-medium wp-image-261" style="border: 0px;" title="oclist" src="http://ruslany.net/wp-content/uploads/2009/02/oclist-500x245.png" alt="oclist command output" width="500" height="245" /></a></p>
<p>It is important to understand how <strong>oclist</strong> renders component dependencies. For example, in the above screenshot the oclist output shows that IIS-FTPExtensibility is dependent on IIS-FTPSvc, so in order to install IIS-FTPExtensibility it is first necessary to install IIS-FTPSvc.</p>
<p><strong>ocsetup</strong> command can be used to install and uninstall individual roles and services.</p>
<h3>Basic Installation of IIS</h3>
<p>To perform basic and default installation of IIS on Server Core run the following command:</p>
<pre name="code" class="dos">
start /w ocsetup IIS-WebServerRole
</pre>
<p>After the command has run you can run <strong>oclist | more</strong> and check which IIS components have been installed.</p>
<h3>Installing .NET Framework</h3>
<p>If you plan to use ASP.NET or IIS Remote Management then it is necessary to install .NET Framework first. To install it use the following commands:</p>
<pre name="code" class="dos">
start /w ocsetup NetFx2-ServerCore
start /w ocsetup NetFx2-ServerCore-WOW64
</pre>
<h3>Installing ASP.NET</h3>
<p>To install ASP.NET on Server Core run the following commands in exact same order as listed below:</p>
<pre name="code" class="dos">
start /w ocsetup WAS-NetFxEnvironment
start /w ocsetup IIS-ISAPIExtensions
start /w ocsetup IIS-ISAPIFilter
start /w ocsetup IIS-NetFxExtensibility
start /w ocsetup IIS-ASPNET
</pre>
<h3>Installing PowerShell and IIS snap-in</h3>
<p>First, install the PowerShell by running the command as below:</p>
<pre name="code" class="dos">
start /w ocsetup MicrosoftWindowsPowerShell
</pre>
<p>Next, launch the PowerShell by running this command:</p>
<pre name="code" class="dos">
\windows\system32\WindowsPowerShell\v1.0\powershell.exe
</pre>
<p>After running this command you should see a PowerShell prompt.</p>
<p>In order to enable the IIS snapin it is necessary to change the script execution policy by running this command:</p>
<pre name="code" class="dos">
Set-ExecutionPolicy RemoteSigned
</pre>
<p><strong>Restart PowerShell</strong> for the policy changes to take effect. After re-entering the PowerShell import the IIS snapin:</p>
<pre name="code" class="dos">
import-module WebAdministration
</pre>
<p>After that you can get the list of available IIS cmdlets by typing</p>
<pre name="code" class="dos">
get-command –module WebAdministration
</pre>
<p>Refer to the article <a title="Managing IIS with IIS 7.0 PowerShell Snap-in" href="http://learn.iis.net/page.aspx/447/managing-iis-with-the-iis-70-powershell-snap-in/">Managing IIS with IIS 7.0 PowerShell Snap-in</a> for more information.</p>
<h3>Enabling IIS Remote Management</h3>
<p>In order to install IIS remote management service it is necessary to install .NET Framework first. Refer to the <strong>Installing .NET Framework</strong> section above for more details.</p>
<p>Install the IIS management service by executing this command:</p>
<pre name="code" class="dos">
start /w ocsetup IIS-ManagementService
</pre>
<p>Then enable remote management by running this command:</p>
<pre name="code" class="dos">
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WebManagement\Server ^
/v EnableRemoteManagement /t REG_DWORD /d 1
</pre>
<p>And finally start the management service:</p>
<pre name="code" class="dos">
net start wmsvc
</pre>
<p>Now you can connect to the IIS on the Server Core from a remote machine by using <a title="IIS Remote Manager" href="http://www.iis.net/downloads/default.aspx?tabid=34&amp;g=6&amp;i=1626" target="_blank">IIS Remote Manager</a>.</p>
<p><em><strong>Acknowledgement</strong>: thanks to Saad Ladki and <a title="Thomas Deml blog" href="http://blogs.iis.net/thomad/">Thomas Deml </a>from IIS team for explaining to me all these steps.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://ruslany.net/2009/02/setup-iis-on-server-core-windows-server-2008-r2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ASP.NET postbacks and URL rewriting</title>
		<link>http://ruslany.net/2008/10/aspnet-postbacks-and-url-rewriting/</link>
		<comments>http://ruslany.net/2008/10/aspnet-postbacks-and-url-rewriting/#comments</comments>
		<pubDate>Thu, 23 Oct 2008 05:04:11 +0000</pubDate>
		<dc:creator>ruslany</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[ASPNET]]></category>

		<guid isPermaLink="false">http://ruslany.net/2008/10/aspnet-postbacks-and-url-rewriting/</guid>
		<description><![CDATA[ASP.NET Web Forms extensively use postback mechanism in order to maintain the state of the server-side controls on the web page. This makes it somewhat tricky to perform URL rewriting for ASP.NET pages. When a server side form control is added to the web page, ASP.NET will render the response with HTML &#60;form&#62; tag that [...]]]></description>
			<content:encoded><![CDATA[<p>ASP.NET Web Forms extensively use postback mechanism in order to maintain the state of the server-side controls on the web page. This makes it somewhat tricky to perform URL rewriting for ASP.NET pages. When a server side form control is added to the web page, ASP.NET will render the response with HTML &lt;form&gt; tag that contains an action attribute pointing back to the page where the form control is. This means that if URL rewriting was used for that page, the action attribute will point back to the rewritten URL, not to the URL that was requested from the browser. This will cause the browser to show rewritten URL any time a postback occurs.</p>
<p><span id="more-105"></span>Let me demonstrate this on an example. Assume you have a very simple web form in a file called <strong>default.aspx. </strong>When you request <strong>http://localhost/default.aspx</strong> in a browser and then view the HTML source for the response, you will see that the response contains the &lt;form&gt; element, which looks similar to this:</p>
<pre name="code" class="html">
&lt;form name=&quot;form1&quot; method=&quot;post&quot; action=&quot;Default.aspx&quot; id=&quot;form1&quot;&gt;
</pre>
<p>The <strong>action</strong> attribute contains the URL where the form data will be posted to when you click on the button in the web page.</p>
<p>Now, let&#8217;s create a very simple rewrite rule that rewrites URL from <strong>http://localhost/homepage</strong> to <strong>http://localhost/default.aspx</strong>.</p>
<pre name="code" class="xml">
&lt;rewrite&gt;
  &lt;rules&gt;
    &lt;rule name=&quot;MyRule&quot; patternSyntax=&quot;Wildcard&quot;&gt;
      &lt;match url=&quot;homepage&quot; /&gt;
      &lt;action type=&quot;Rewrite&quot; url=&quot;default.aspx&quot; /&gt;
    &lt;/rule&gt;
  &lt;/rules&gt;
&lt;/rewrite&gt;
</pre>
<p>When you request <strong>http://localhost/homepage</strong> in a browser, the URL will be rewritten in accordance to the above rule and the page will be shown correctly in the browser:</p>
<p><a href="http://ruslany.net/wp-content/uploads/2008/10/postback1.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://ruslany.net/wp-content/uploads/2008/10/postback1-thumb.png" border="0" alt="Postback1" width="504" height="276" /></a></p>
<p>However, when you click on the <strong>Submit</strong> button, the browser&#8217;s address bar will display <strong>http://localhost/default.aspx</strong>, thus exposing the internal URL, that you wanted to hide by using URL rewriting:</p>
<p><a href="http://ruslany.net/wp-content/uploads/2008/10/postback2.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://ruslany.net/wp-content/uploads/2008/10/postback2-thumb.png" border="0" alt="Postback2" width="504" height="266" /></a></p>
<p>A few workarounds to fix this behavior existed in previous versions of ASP.NET. For example, you could sub-class the form control, or use Control Adapter as explained <a title="ScottGu blog" href="http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx" target="_blank">here</a>.  However, these workarounds were not very easy to implement. Luckily, the ASP.NET in .NET Framework 3.5 SP1 provides a very simple way to fix that. Now you can use the property of the <strong>HtmlForm</strong> class called <strong>Action</strong> to set the postback URL to the one that was requested by browser before any rewriting happened. In ASP.NET you can obtain that URL by using <strong>HttpRequest.RawUrl</strong> property. So, to fix the postback URL for your web form when you use URL Rewrite Module, you would need to add the following code to the page:</p>
<pre name="code" class="csharp">
protected void Page_Load(object sender, EventArgs e)
{
    form1.Action = Request.RawUrl;
}
</pre>
<p>After this change, if you reload the web page at <strong>http://localhost/homepage</strong> and then click on submit button you will see that the browser&#8217;s address bar still displays the correct URL:</p>
<p><a href="http://ruslany.net/wp-content/uploads/2008/10/postback3.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://ruslany.net/wp-content/uploads/2008/10/postback3-thumb.png" border="0" alt="Postback3" width="504" height="266" /></a></p>
<p>If you view the HTML for the response you will see that the &lt;form&gt; tag now contains the correct action URL:</p>
<pre name="code" class="html">
&lt;form name=&quot;form1&quot; method=&quot;post&quot; action=&quot;/homepage&quot; id=&quot;form1&quot;&gt;
</pre>
<p>When you use ASP.NET master pages you could add the Page_Load method to the master page and that would take care of postback action URL for all the pages in your web application. Note thought that in order to be able to use the HtmlForm.Action property you have to upgrade to .NET Framework 3.5 SP1.</p>
]]></content:encoded>
			<wfw:commentRss>http://ruslany.net/2008/10/aspnet-postbacks-and-url-rewriting/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Wildcard script mapping and IIS 7 integrated pipeline</title>
		<link>http://ruslany.net/2008/09/wildcard-script-mapping-and-iis-7-integrated-pipeline/</link>
		<comments>http://ruslany.net/2008/09/wildcard-script-mapping-and-iis-7-integrated-pipeline/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 03:30:18 +0000</pubDate>
		<dc:creator>ruslany</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[ASPNET]]></category>

		<guid isPermaLink="false">http://ruslany.net/2008/09/wildcard-script-mapping-and-iis-7-integrated-pipeline/</guid>
		<description><![CDATA[The big benefit of IIS 7 integrated request processing pipeline is the fact that all the nice and useful ASP.NET features can be used for any type of content on your web site; not just for ASP.NET-specific content. For example, ASP.NET SQL-based membership can be used to protect static files and folders. Also, ASP.NET extensibility [...]]]></description>
			<content:encoded><![CDATA[<p>The big benefit of IIS 7 integrated request processing pipeline is the fact that all the nice and useful ASP.NET features can be used for any type of content on your web site; not just for ASP.NET-specific content. For example, ASP.NET SQL-based membership can be used to protect static files and folders. Also, ASP.NET extensibility API&#8217;s, such as <strong>IHttpHandler</strong> and <strong>IHttpModule</strong> can be used to add custom modules and handlers that would be executed even for non-ASP.NET content.</p>
<p>IIS 6 did not have this level of integration. ASP.NET was plugged into IIS 6 as an ISAPI extension and by default was configured to handle ONLY requests mapped to that extension &#8211; for example any request that ended with &#8220;.aspx&#8221; would be be processed by ASP.NET extension. This obviously was a big limitation for customers who wanted to be able to use ASP.NET features for all other contend on web site. The most common way to workaround that was to use &#8220;Wildcard script mapping&#8221;. This post explains how an application that used wildcard script mapping in IIS 6 can be migrated over to IIS 7.</p>
<p><span id="more-95"></span> Assume you had configured ASP.NET in IIS 6 to handle all requests by using wildcard script mapping. For example you had an ASP.NET module for URL rewriting and you wanted this module to handle extension-less URLs.</p>
<p>This wildcard script map configuration is typically done within IIS 6 manager by opening the properties dialog for either web server or web site and selecting <strong>Home Directory</strong> tab, then clicking on <strong>Configuration</strong> button and then clicking on the <strong>Insert</strong> button for &#8220;Wildcard application maps&#8221;:</p>
<p><a href="http://ruslany.net/wp-content/uploads/2008/09/wildcardiis6.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://ruslany.net/wp-content/uploads/2008/09/wildcardiis6-thumb.png" border="0" alt="WildcardIIS6" width="390" height="379" /></a></p>
<p>Now, as you move your application to IIS 7, you want to configure it to achieve the same behavior of ASP.NET. There are two options on how this can be done: using <strong>Classic</strong> pipeline mode or using <strong>Integrated</strong> pipeline mode.</p>
<h3>Wildcard script mapping in IIS 7 classic pipeline mode</h3>
<p>With classic pipeline mode the ASP.NET is plugged into the IIS request processing pipeline as an ISAPI extension &#8211; exactly the same way as it was in IIS 6. In fact, if you open %WINDIR%\system32\inetsrv\config\applicationHost.config file and locate the &lt;handlers&gt; section inside of it you can see how IIS is configured to map ASP.NET specific requests to the <strong>aspnet_isapi.dll</strong>:</p>
<pre name="code" class="xml">
&lt;handlers accessPolicy=&quot;Read, Script&quot;&gt;
  ...
  &lt;add name=&quot;PageHandlerFactory-ISAPI-2.0&quot;
       path=&quot;*.aspx&quot; verb=&quot;GET,HEAD,POST,DEBUG&quot;
       modules=&quot;IsapiModule&quot;
       scriptProcessor=&quot;%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll&quot;
       preCondition=&quot;classicMode,runtimeVersionv2.0,bitness32&quot; responseBufferLimit=&quot;0&quot; /&gt;
  ...
&lt;/handlers&gt;
</pre>
<p>Notice the <strong>preCondition</strong> attribute for the handler mapping. Among other things this attribute is set to <strong>classicMode</strong>, which ensures that this handler mapping only takes effect when the application pool is configured to run in classic mode.</p>
<p>Now if you want to configure wildcard mapping for the ASP.NET running in classic mode, you can add one more handler mapping to the &lt;handlers&gt; section just before the handler mapping for static files:</p>
<pre name="code" class="xml">
&lt;handlers accessPolicy=&quot;Read, Script&quot;&gt;
  ...
  &lt;add name=&quot;ASP.NET-ISAPI-2.0-Wildcard&quot;
     path=&quot;*&quot; verb=&quot;GET,HEAD,POST,DEBUG&quot;
     modules=&quot;IsapiModule&quot;
     scriptProcessor=&quot;%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll&quot;
     preCondition=&quot;classicMode,runtimeVersionv2.0,bitness32&quot; responseBufferLimit=&quot;0&quot; /&gt;
  &lt;add name=&quot;StaticFile&quot;
     path=&quot;*&quot; verb=&quot;*&quot;
     modules=&quot;StaticFileModule,DefaultDocumentModule,DirectoryListingModule&quot;
     resourceType=&quot;Either&quot; requireAccess=&quot;Read&quot; /&gt;
&lt;/handlers&gt;
</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>The relative order of the wildcard handler mapping is important: if you define this handler mapping after the &#8220;StaticFile&#8221; handler mapping then &#8220;StaticFile&#8221; will handle all the requests and no requests will ever come to ASP.NET wildcard handler.</p>
<p>As you may already know the ASP.NET wildcard handler mapping in IIS 7 is subject to the same performance limitations as existed in IIS 6. The problem with this kind of handler mapping is that ALL requests are processed by it, including requests for static files. The ASP.NET static file handler is not as powerful as native IIS static file handler. Plus static files served by ASP.NET will not be cached by IIS in kernel mode. Because of these performance limitations it is recommended that you use IIS 7 integrated pipeline to achieve the same functionality as with wildcard mappings in IIS 6.</p>
<h3>IIS 7 integrated pipeline instead of wildcard script mapping</h3>
<p>With integrated pipeline, the ASP.NET functionality is fully integrated into the main request processing in IIS, which means that all ASP.NET features are now available for any type of requests. This effectively eliminates the need for the wildcard handler mapping. Now you can use your existing ASP.NET modules and have them applied to all requests.</p>
<p>For example let&#8217;s say you had a URL rewriting module written in ASP.NET. On IIS 6 this module was registered inside of the &lt;system.web&gt; section in web.config file as below:</p>
<pre name="code" class="xml">
&lt;system.Web&gt;
  &lt;httpModules&gt;
    ...
    &lt;add name=&quot;MyUrlRewrite&quot;
         type=&quot;SomeNamespace.MyModules.UrlRewrite, SomeNamespace.MyModules&quot; /&gt;
    ...
  &lt;/httpModules&gt;
&lt;/system.Web&gt;
</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<p><a href="http://11011.net/software/vspaste"></a>Since on IIS 6 this module was only executed for requests to managed content, it only worked for URLs that had .aspx extension, such <em>as http://example.com/archive/2008/08/26/post-title.<strong>aspx</strong></em>. If you wanted it to handle extension-less URLs you had to configure wildcard script mapping for ASP.NET. With IIS 7 integrated pipeline you do not have to do that anymore. In order to make this module apply to extension-less URLs you need to register it within the &lt;system.webServer&gt; section inside of web.config file as below:</p>
<pre name="code" class="xml">
&lt;system.webServer&gt;
  &lt;modules &gt;
    ...
    &lt;add name=&quot;MyUrlRewrite&quot;
         type=&quot;SomeNamespace.MyModules.UrlRewrite, SomeNamespace.MyModules&quot;
         preCondition=&quot;&quot; /&gt;
    ...
  &lt;/modules&gt;
&lt;system.webServer&gt;
</pre>
<p>Make sure that you leave the preCondition attribute empty here as it would enforce that the module will be executed for all requests, not just for requests for ASP.NET specific content.</p>
<p>Registering your managed modules this way does not have such dramatic performance impact as when using wildcard script mappings. Even though the module is invoked for all requests to web application, all the existing handler mappings are still in effect, which means that the static files are still served by the native IIS static file handler. Another benefit of registering your module this way is that now it can be applied to requests for PHP, ASP or any other dynamic pages. You would not be able to do that if you used wildcard script mappings.</p>
<p>One last thing to mention here is that you can also use the attribute on the &lt;modules&gt; section called <strong>runAllManagedModulesForAllRequests</strong>.</p>
<pre name="code" class="xml">
&lt;system.webServer&gt;
  &lt;modules runAllManagedModulesForAllRequests=&quot;True&quot; &gt;
    ...
    &lt;add name=&quot;MyUrlRewrite&quot;
         type=&quot;SomeNamespace.MyModules.UrlRewrite, SomeNamespace.MyModules&quot;
         preCondition=&quot;ManagedHandler&quot; /&gt;
    ...
  &lt;/modules&gt;
&lt;system.webServer&gt;
</pre>
<p>This attributes forces IIS to ignore the preCondition=&#8221;managedHandler&#8221; attribute, hence all managed modules will be invoked for all requests to web application.</p>
]]></content:encoded>
			<wfw:commentRss>http://ruslany.net/2008/09/wildcard-script-mapping-and-iis-7-integrated-pipeline/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
