ASP.NET / IIS7 Url Rewrite maps not working - asp.net

I've followed the instructions Learn IIS's webpage for adding static redirects with a rewrite map for my asp.net application.
The following is the config:
<rule name="Redirect rule1 for Information" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{Information:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}" appendQueryString="true" />
</rule>
And
<rewriteMaps>
<rewriteMap name="Information">
<add key="/Information/CorporateSales.aspx"
value="/KB/Information/CorporateSales" />
<add key="/Information/ComputerRepair.aspx"
value="/KB/Information/ComputerRepair" />
</rewriteMap>
</rewriteMaps>
This was even originally created by the wizard in IIS's manager for using rewrite maps.
So the idea is that /Information/CorporateSales.aspx --> /KB/Information/CorporateSales with a 301 redirect (MOVED PERMANENTLY).
However I'm just getting the original aspx page (Which we're removing later) loading. I've even deleted the file incase it was defaulting to an existing resource, and with that i just get a plain 404 without the redirect.
Anyone have an idea?
Let me clarify something:
Rewrite module works, it's installed and running. My standard regex rules work nicely. But my rewrite map does not.

This article http://www.iis.net/learn/extensions/url-rewrite-module/using-rewrite-maps-in-url-rewrite-module and code below worked for me.
<rewrite>
<rules>
<rule name="Redirect rule1 for RedirectURLs">
<match url=".*" />
<conditions>
<add input="{RedirectURLs:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="RedirectURLs">
<add key="/privacy.php" value="/privacy" />
</rewriteMap>
</rewriteMaps>
</rewrite>

I was having a similar problem and found this question. It took me a little while, but I was able to figure out what the problem was.
My rewriteMap contained the urls "/Default2.aspx" and "/Dashboard.aspx".
When I would go to Default2.aspx, I would get a 404 rather than get redirected to Dashboard.aspx as expected.
The issue I found was that on my machine, the application was running in a subdirectory. The rewriteMap paths would only work if I used the full path (including the application folder), e.g., "/TestSite/Default2.aspx".
So I could have added duplicate entries in my rewriteMap to account for application directories on developer machines, but that seemed messy. I looked at the other rewrite rules in the application that did not have this issue and I noticed that they were using the {REQUEST_FILENAME} variable, rather than {REQUEST_URI}. So I switched the rule to use {REQUEST_FILENAME} and remove the first slash from the urls in my rewriteMap.

Do you have Url rewriting installed as part of IIS7/7.5? This is not installed by default. Also, make sure your app pool is set to integrated pipline mode, no classic.
Edit
From this:
http://learn.iis.net/page.aspx/469/using-rewrite-maps-in-url-rewrite-module/
This only thing I see that you're doing is adding the 'stopProcessing' attribute. Have you tried removing that?

Previously I had same problem as you described.
Could you update your code to
<match url="(.*)" />
and I hope you aware,
<add input="{Information:{REQUEST_URI}}" pattern="(.+)" />
this condition will capture full URL except the domain.
example on this url:
www.example.com/Information/CorporateSales.aspx
it will check matching condition of
Information/CorporateSales.aspx on rewriteMap
and for sure it wont be match with this url
www.example.com/old/Information/CorporateSales.aspx

Did you reset the app pool and the iis site ?
In some cases it can take up to 72 hours (iirc) to propagate throughout the world.

Related

How to share cookie between domain and subdomain, but not other subdomains

Our ASP.NET MVC web application has a few different subdomains we use for testing and legacy code. The subdomains are:
www.sitename.com (production site)
test.sitename.com (testing)
original.sitename.com (legacy code)
staging.sitename.com (occasionally used to testing right before a deployment)
We purposefully have the forms authentication not using domain level cookies because we want the cookies to be unique across these different subdomains. The problem is, when people get a link to the root domain (sitename.com), it requires them to log in again to get a cookie, even though they're already logged in to www.sitename.com.
Is there a way to share the cookie between only www.sitename.com and sitename.com without the other subdomains being affected?
You can avoid this problem by redirecting your non www domain to www with UrlRewrite module in >IIS7
rewrite rule to put into web.config
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to WWW" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^example.com$" />
</conditions>
<action type="Redirect" url="http://www.example.com/{R:0}"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
I'd recommend forcing the use of the www. version of the site, for this reason amongst others, this site has excellent reasons why...
http://www.yes-www.org/why-use-www/
To do this in .net you can add the following to your web.config
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to www" stopProcessing="true">
<match url="(.*)" />
<conditions trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="^sitename.com$" />
</conditions>
<action type="Redirect" url="{MapProtocol:{HTTPS}}://www.{HTTP_HOST}{HTTP_URL}" redirectType="Permanent"/>
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="MapProtocol">
<add key="on" value="https" />
<add key="off" value="http" />
</rewriteMap>
</rewriteMaps>
</rewrite>
</system.webServer>
This will auto-redirect permanently (see the addition of redirectType="Permanent") for non-www URLs to the www equivalent and retain the HTTP(s) protocol.
The trackAllCaptures part is related to the regex pattern matching - in our case we do not need to capture anything; we only need to match for the rule, so we can leave as false.
The regex pattern ^sitename.com$ will match when the hostname matches exactly to "sitename.com" - the ^ means the start position and the $ means the end position
The rewrite map is from an idea from Jeff Graves I believe, http://jeffgraves.me/2012/11/06/maintain-protocol-in-url-rewrite-rules/
The way I have shown shows just one way to do this, like with most things - there are multiple ways on achieving this.
Scott Forsyth has an article on a different way of achieving this too (also references Jeff Graves)
http://weblogs.asp.net/owscott/url-rewrite-protocol-http-https-in-the-action
You can use some thing like
sessionCookie.Domain = ".yourdomain.com" ;
then you will be able to request same cookies from any subdomain and edit it if you want.

How to preserve query parameters using IIS HTTP wildcard redirects?

I'm trying to configure redirects to prepare the switch from an ASP to an MVC website. The IIS wildcard redirects are working fine, but I cannot figure out how to preserve the query parameters.
Example:
<system.webServer>
<httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Permanent">
<add wildcard="/EmailAddress-Verify.aspx" destination="https://foo.com/account/email-verify$Q" />
</httpRedirect>
</system.webServer>
I read that $Q will preserve the query params but it's not working. Google could not find anything on that issue.. is there anything I'm missing here?
Thanks!
So this configuration was working perfectly! I just had to clear my browser cache since the redirection is Permanent and the browser 'remembered' my previous configuration while I was playing with the config file. My bad!
Y̶o̶u̶ ̶h̶a̶v̶e̶ ̶e̶x̶a̶c̶t̶D̶e̶s̶t̶i̶n̶a̶t̶i̶o̶n̶=̶"̶t̶r̶u̶e̶"̶.̶ However, more importantly, when you want to have more granular control with redirects, you're much better off using the URL Rewrite module. Your bit would be something like the following (not tested and quickly written up):
<rewrite>
<rules>
<rule name="Email Address Verify Redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{REQUEST_URI}" pattern="^EmailAddress-Verify.aspx(.*)$" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="https://foo.com/account/email-verify{R:1}" />
</rule>
...
</rewrites>
Oh, now that I think about it, you could probably just do a straight up pattern without the following wildcard and just appendQueryString="True" in the action.

IIS URL Rewriting and MVC

My hosting plan has a limited number of web applications for use, but unlimited subdomains. I plan to take advantage of these subdomains by using IIS rewriting, like the following:
<rule name="Home Rewrite" enabled="true">
<match url="^(.*)$" />
<conditions>
<add input="{HTTP_HOST}" pattern="^home\.mydomain\.com$" />
</conditions>
<action type="Rewrite" url="home/{R:1}" />
</rule>
This works fine for the most part, I can go to http://home.mydomain.com and it'll take me to what is essentially http://www.mydomain.com/home as expected.
I am publishing using Web Deploy, and I believe the host is IIS7.
The problem is that I want to take advantage of #Html.ActionLink, but when viewing the source, this resolves out to include the virtual directory.
So what I end up with is a site that works when I go to the original address:
http://www.mydomain.com/home/application
And a site that loads, but doesn't function correctly, at the redirected address:
http://home.mydomain.com/application
With generated URLs in the page source pointing relative to the original address:
/home/application/Account/Login
This applies to links to other pages/routes, bundles, basically anywhere that ~/ or #Html.ActionLink is used.
How do I get around this? I'm hoping to keep the use of #Html.ActionLink at least, I think I can live without the tildes.
I finally found a solution!
https://support.gearhost.com/entries/23689272-URL-Rewrite-Subdomain
My web.config rewrite rule required an extra line:
<rule name="Home Rewrite" enabled="true">
<match url="^(.*)$" />
<conditions>
<add input="{HTTP_HOST}" pattern="^home\.mydomain\.com$" />
<add input="{PATH_INFO}" pattern="^/home/" negate="true" /> <!-- This one! -->
</conditions>
<action type="Rewrite" url="home/{R:1}" />
</rule>
Now everyone is happy :)
You could write a custom HtmlHelper so instead of using ActionLink you can use MyActionLink and it can generate the url you need.

IIS HTTP to HTTPS relative redirect

I recently got a SSL certificate for my website and want to redirect all traffic to HTTPS. I got everything to go to https://mydomain.com but if someone enters http://mydomain.com/anotherpage it drops the other page and just takes the user to the home page.
My rule in my web.config file looks like this:
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
I also tried https://{HTTP_HOST}{REQUEST_URI} without any success. Can anyone tell me what I need to do to make the website redirect to the proper HTTPS version of the page? I have a feeling it has something to do with the pattern, but I can't seem to figure out the syntax.
I found a way to do this, and you don't need the Rewrite module for it. The following worked for me on Windows 8 (IIS 8.5):
Remove the HTTP binding from your site (leave HTTPS in place)
Add another site
Make sure that the new site has HTTP binding
Configure HTTP Redirect as shown:
Now all HTTP request will redirect to your HTTPS site and will preserve the rest of the URL.
Change it to:
<rewrite>
<rules>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
I had the same problem where the R:1 was dropping my folders.
I fixed it like this.
<rule name="http to https" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"
appendQueryString="false" redirectType="SeeOther" />
</rule>
I can't comment yet or I'd leave this as a comment under AndyH's answer. The solution was correct, though I hit a single further snag (likely tied to the use of Adobe's Coldfusion server). I wanted to share some further research I had to do for any other unfortunate soul who may run into it.
Once set up, the redirect would always end at this url:
https://xxx.xxx.com/jakarta/isapi_redirect.dll
The fix for this was found in an Adobe thread (https://forums.adobe.com/thread/1034854): I had to change an application pool's settings as follows:
Real site (HTTPS binding only, actually contains code and virtual directories)
Application pool's Advanced Settings: Enable 32-Bit Applications : False
Http_Redirect site (HTTP binding only, is a blank shell of a folder with no directories)
Application pool's Advanced Settings: Enable 32-Bit Applications : True
EDIT: Another detail, tied to query string preservation:
Per suggestion in this post (http://www.developerfusion.com/code/4678/permanent-301-redirect-with-querystring-in-iis/)
Add $S$Q at the end of the domain and make sure the box for Redirect all requests to exact destination is checked. Then it will save the query string as well.
I believe AndyH's answer to be the easiest and best way. I have found using the URL rewrite can also conflict with code that may redirect the user to another page. IT commonly broke in our environment. But Andy's solution worked flawlessly. I also think Andy's solution will put less overhead on the server as it doesn't need to examine every url hitting it for possible re-write conditions.
I found a workaround:
Consider what in IIS is consired a website: simply a set of rules, the path in which get files and its bindings.
Furthermore, there's available a function called "HTTP Redirect" (included standardly in IIS), that redirect an host to another, keeping all subdirectory (it makes a relative path). The workaround is to leave just the binding for HTTPS (port 443) in your website, and create another with the binding on HTTP (port 80) and set for this an HTTP redirect to your URL with https://.
For example, consider a website called mytest and its urls http://www.mytest.com/ and https://www.mytest.com/.
Set for it instead only binding on https://www.mytest.com/, and delete the http binding. Then create a new website with the same local path, called mytest http with just a binding over port 80 (http://www.mytest.com/) and set for this one an HTTP Redirect to https://www.mytest.com/.
Simple and clean, and that should be as fast as directly the https url for the user, because it's just an internal redirect. I hope that can work for you!
You can add the URL Rewrite module to IIS (IIS 7 or higher) which allows you to add create the redirect in a visual way. The module can be downloaded here.
This step-by-step tutorial worked wonders for me and explains that when using this module, all it actually does is add some code to your web.config file as such:
<rewrite>
<rules>
<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther" />
</rule>
</rules>
</rewrite>
I have found that the
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
syntax will only work for the website's ROOT web.config file.
If the rewrite rule is applied to a virtual web.config file, then use..
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}{URL}" />
The {URL} syntax will include the initial forward slash, the virtual path, and any URL parameters.

IIS Rewrite not working (but redirection does)

I was trying to play with URL re-writing using the Rewrite Module 2.0 but I had no luck getting it to work. What I'm trying to do is re-write all calls to web app at port 80 to other applications hosted in IIS (or maybe on different servers on the network). Using the GUI provided by IIS I created the following rule:
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="site1/(.*)" />
<action type="Rewrite" url="http://localhost:7001/{R:1}" />
</rule>
</rules>
</rewrite>
Quiet simple, but unfortunately it does not work. On the other hand, when I change the action type to Redirect, it works fine.
What could be the problem?
I ran into this same issue yesterday, and it took me a long time to figure out.
The key here is that you've got an http:// prefix in your rewrite action; that makes this a special case that needs to be handled by Application Request Routing. The first step is to make sure that the Application Request Routing module is installed. You can find the module at https://www.iis.net/downloads/microsoft/application-request-routing. Once that is installed, go to your IIS web server (a level up from your web site), and open the Application Request Routing Cache feature. From the actions on the right, choose Server.Proxy.Settings, and make sure that the "Enable Proxy" checkbox is checked. This allows the URL rewrite task to be re-routed to Application Request Routing, and your reverse proxy should work for external requests.
The idea came from this excellent blog post from 2009: http://ruslany.net/2009/04/10-url-rewriting-tips-and-tricks/
Stumbled across this old post when I was trying to solve the same issue.
SOLVED!
Using Rewrite URL feature in IIS Services Manager I created a friendly URL rule.
This worked ok and when I looked at the rule in the web.config file (www root) it showed 1 rule to redirect and 1 rule to rewrite.
I edited this to suit 1 match. Then I just duplicated this code editing the product ID for each. Example below:
<rule name="RedirectUserFriendlyURL1" stopProcessing="true">
<match url="^product\.php$" />
<conditions>
<add input="{REQUEST_METHOD}" pattern="^POST$" negate="true" />
<add input="{QUERY_STRING}" pattern="^id_product=\b35\b" />
</conditions>
<action type="Redirect" url="990mm-bohemia-cast-iron-electric-radiator"
appendQueryString="false" />
</rule>
The first rule looks for the string "product.php" in the URL and "id_product=35", it then redirects to "990mm-bohemia-cast-iron-electric-radiator" which currently does not exist. Then (see below)
<rule name="RewriteUserFriendlyURL1" stopProcessing="true">
<match url="^\b990mm-bohemia-cast-iron-electric-radiator\b" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="product.php?id_product=35" />
</rule>
This rule rewrites the "product.php?id_product=35" bit to `990mm-bohemia-cast-iron-electric-radiator", creating the new location for the redirect.
Do make sure MVC routing doesn't steal your request. To prevent that from happening, ignore the route you're trying to rewrite:
RouteTable.Routes.Ignore("blog/{*pathInfo}");
Inspired by: https://sitecore.stackexchange.com/questions/3645/how-to-setup-a-reverse-proxy-with-sitecore
Change the Rewrite URL to AbsolutePath instead putting http://...
it should be
<action type="Rewrite" url="{R:1}" />
It worked for me, but in my case, I have been rewrite to a fixed webpage.

Resources