Replacing IIS rewrite rules in web.config transform

asp.netIisUrl RewritingWeb ConfigTransform

asp.net Problem Overview


I have some IIS rewrite rules that I want to vary by environment. The development rewrite rules are in the web.config file, then at the end of the web.test.config file I have:

    <appSettings>
         ...Some app settings tranforms here
    </appSettings>
    <system.webserver>
            <rewrite xdt:Transform="Replace">
              <rules>
                ... rules here
              </rules>
            </rewrite>
          </system.webserver>
        </configuration>

My app settings are getting transformed when I deploy to test, but by IIS rewrite rules are not. I was hoping the entire <rewrite> section would simply be replaced with the one in the transform file (as per http://msdn.microsoft.com/en-us/library/dd465326.aspx), but nothing is changing.

I have tried putting xdt:Transform="Replace" xdt:Locator="Match(name)"> on the individual rules too:

<rule name="Test rule" stopProcessing="true" xdt:Transform="Replace" xdt:Locator="Match(name)">

But again this makes no difference.

Is it even possible to replace rewrite rules in the web.config and if so, what am I missing?

asp.net Solutions


Solution 1 - asp.net

As I didn't have any rewrite rules in my main web.config, the Replace transform didn't work. I successfully used the Insert transform, as below:

  <system.webServer>
<rewrite xdt:Transform="Insert">
  <rules>
    <rule name="CanonicalHostNameRule1">
      <match url="(.*)" />
      <conditions>
        <add input="{HTTP_HOST}" pattern="^www\.mysite\.com$" negate="true" />
      </conditions>
      <action type="Redirect" url="http://www.mysite.com/{R:1}" />
    </rule>
  </rules>
</rewrite>
</system.webServer>

Solution 2 - asp.net

There is a lot of answers here with examples which is a good thing, but I think few details are missing. I have wrote about this in my website, the key point here is to add xdt:Transform="Insert" in the root tag hierarchy you want to be added for the respective environment.

By default you have your Web.config file, but you have also Web.Debug.config and Web.Release.config as seen in the image below:

enter image description here

Lets say you want to added a redirection from http to https in your release of the application. Then edit Web.Release.config and add following lines:

<?xml version="1.0"?>

.....
  <system.webServer>
    <rewrite xdt:Transform="Insert">
      <rules>
        ......
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

So next time you publish your project the tag with rewrite and its sub-content will be added to web.config file.

To see that before you publish, right click on Web.Release.config and click Preview Transform.

enter image description here

You will see the difference between initial version and release version.

enter image description here

Reference:

> Disclaimer: the link of this guideline refer to my personal web site.

Solution 3 - asp.net

The rewrite section worked weirdly to me at first when creating the release configs, errors and sections not showing at all. This is how i solved it.

> Microsoft (R) Build Engine version 12.0.31101.0

> Microsoft .NET Framework, version 4.0.30319.0

Edit After messing about with this i realized that having the rewrite tag on a server that does not have the rewrite plugin make the webserver return an error. I want different configurations on server and local development machine so the fix is:

The un-transformed web.config only needs a tag and in the web.config.release for a basic canonical host name rule

<configuration>
<system.webServer>
		<rewrite xdt:Transform="Insert">
   			<rules>
   			    <rule name="CanonicalHostNameRule" xdt:Transform="Insert">
					<match url="(.*)" />
					<conditions>
						<add input="{HTTP_HOST}" pattern="^www\.host\.com$" negate="true" />
					</conditions>
					<action type="Redirect" url="http://www.host.com/{R:1}" />
				</rule>
   			</rules>
   		</rewrite>
</system.webServer>
</configuration>

The action didn't need a name at all but the rewrite tag needs the xdt:Transform="Insert"

Obviously if you want it on your local machine as well, it would need an update instead.

Solution 4 - asp.net

It is possible to transform the rewrite section of system.webServer. I was initially having the same problem and realized that I had inadvertently placed the rewrite node incorrectly under system.web. While this does not look like your problem based on the limited snippet that you provided, I would still suspect that your issue is related to node placement in the transform file.

Here is what my Web.Debug.config looks like (and this version is writing the correct Web.config on a debug build):

<?xml version="1.0"?>

<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--
    In the example below, the "SetAttributes" transform will change the value of 
    "connectionString" to use "ReleaseSQLServer" only when the "Match" locator 
    finds an atrribute "name" that has a value of "MyDB".
    
    <connectionStrings>
      <add name="MyDB" 
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
  -->
  <system.web>
    <!--
      In the example below, the "Replace" transform will replace the entire 
      <customErrors> section of your web.config file.
      Note that because there is only one customErrors section under the 
      <system.web> node, there is no need to use the "xdt:Locator" attribute.
      
      <customErrors defaultRedirect="GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500" redirect="InternalError.htm"/>
      </customErrors>
    -->
  </system.web>
  <system.webServer>
    <rewrite xdt:Transform="Replace">
      <rules>
        <clear/>
        <rule name="Canonical Hostname">
          <!-- Note that I have stripped out the actual content of my rules for the purposes of posting here... -->
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Solution 5 - asp.net

A trick I use is give the action a name
then in my transform just add xdt:Transform="SetAttributes" xdt:Locator="Match(name)" like the following

<system.webServer>
<rewrite>
  <rules>

    <rule name="RedirecttoWWW" enabled="true"  >
      <match url="(.*)" />
      <conditions>
        <add input="{HTTP_HOST}" negate="true" pattern="^www\.([.a-zA-Z0-9]+)$" />
      </conditions>
      <action name="AddWWW" type="Redirect" url="http://www.{HTTP_HOST}/{R:0}" appendQueryString="true" redirectType="Permanent" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
    </rule>

  </rules>
</rewrite>

The above example is to add www to all requests

-------UPDATE-----

just an update adding name to the action will not work as wanted so I updated the code as the following

 <system.webServer>

      <rule name="RedirecttoWWW" enabled="true"  xdt:Transform="RemoveAll" xdt:Locator="Match(name)" >
      </rule>
      <rule name="RedirecttoWWW" enabled="true"  xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)" >
        <match url="(.*)" />
        <conditions>
          <add input="{HTTP_HOST}" negate="true" pattern="^www\.([.a-zA-Z0-9]+)$" />
        </conditions>
        <action  type="Redirect" url="http://{HTTP_HOST}/{R:0}" appendQueryString="true" redirectType="Permanent" />
      </rule>
    </rules>
  </rewrite>
  </system.webServer>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLDJView Question on Stackoverflow
Solution 1 - asp.netStuartQView Answer on Stackoverflow
Solution 2 - asp.netMaytham FahmiView Answer on Stackoverflow
Solution 3 - asp.netCrypthView Answer on Stackoverflow
Solution 4 - asp.netJ.R. ArmstrongView Answer on Stackoverflow
Solution 5 - asp.netMshtawythugView Answer on Stackoverflow