IIS 7 Rewrite - MultiViews Solution

I am migrating many sites from an aging IIS5 server to a new IIS7.5 server. Many of the sites utilize extensionless file names, and PORT80 “PageXchanger” was used to negotiate the file names. (for those not familiar, PageXchanger was an IIS solution for Apache’s “MultiViews”)

Well - PORT80 has discountinued that product, and the latest version is not compatible with IIS7, so I either re-write 100 websites, or create a solution!

I am looking at using the IIS7 Rewrite Module, and for the most part, I have made this work.


<rewrite>
     <rules>
         <rule name="PHP">
             <match url="^(.*)$" />
             <conditions>
                 <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                 <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
             </conditions>
             <action type="Rewrite" url="{R:0}.php" />
         </rule>
     </rules>
</rewrite>

In the end - if I type “www.site.com/test”, the page fetched is “test.php”. I have tested this and it works regardless of the depth of directories which is what I need.

This is great for hiding PHP extensions only, but I want the rewrite to look for a few extensions (ie: .html, .php, .htm). If .html doesn’t exists, look for .php. If that doesn’t exist, look for .htm. If that doesn’t exist - give up and throw a 404.

I know the answer is in this line “<action type=“Rewrite” url=”{R:0}.php" />" but I am not sure what to replace “.php” with to make it work.

Any ideas or suggestions?

Solved. Here is how it is done using “htm, html, php” as the three alternatives. The rewrite will look for them in order, and if one is found - it loads that file. Want PHP first? Just change the order of the rules.

The trick is with Conditions. Check to see if the file exists with that extension added. If the condition is not met, it will move to the next rule and try that.

(Note: I also check each rule to make sure the initial name is not a file, or a directory)

Here is my final set of rules to make this work on IIS7.


<rewrite>
    <rules>
        <rule name="HTM" stopProcessing="false">
            <match url="^(.*)$" />
            <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                <add input="{REQUEST_FILENAME}.htm" matchType="IsFile" />
            </conditions>
           <action type="Rewrite" url="{R:0}.htm" />
        </rule>
         <rule name="HTML">
           <match url="^(.*)$" />
           <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
               <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
               <add input="{REQUEST_FILENAME}.html" matchType="IsFile" />
            </conditions>
            <action type="Rewrite" url="{R:0}.html" />
        </rule>
        <rule name="PHP">
            <match url="^(.*)$" />
            <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                <add input="{REQUEST_FILENAME}.php" matchType="IsFile" />
            </conditions>
            <action type="Rewrite" url="{R:0}.php" />
        </rule>
    </rules>
</rewrite>

Still may need a little fine tuning - but overall this seems to do the job, and also retains any queries as well.