IIS URL Rewriting and MVC - asp.net

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.

Related

Using IIS Rewrite URL for SEO to move all Cold Fusion CFM pages to ASP aspx pages

I am moving a large database driven website from coldfusion .cfm to .net aspx. I am pretty much finished now, but I need to do 301 redirects on all the coldfusion pages to the new aspx ones, so google and such like as we don't want to lose the search engine positioning. So I intended to use URL Rewrite for this, but I cannot get it working, most of the time I just get 404s back.
Basically, my new aspx pages are all the same filename, just .cfm is replaced with .aspx, some pages can have a long querystring after them and some not.
Examples:
http://www.example.com/test.cfm needs to be remapped to http://www.example.com/test.aspx
http://www.example.com/test2.cfm?a=1&b=2&c=3 needs to be remapped to http://www.example.com/test2.aspx?a=1&b=2&c=3
The site itself has hundreds of pages and some pages have over 8 variables in the querystring, so I just wanted to try and do a straight map over in URL rewrite. I cannot do a rule per page as that will take ages!
My current attempt is:
<rule name="redirect all requests" stopProcessing="true">
<match url="^(.*)$" ignoreCase="true" />
<conditions logicalGrouping="MatchAll">
<add input="{URL}" pattern="^http://www.example.com/(.*).cfm(.*)$" />
</conditions>
<action type="Redirect" url="http://www.example.com/{C:1}.aspx" appendQueryString="true" logRewrittenUrl="true" />
</rule>
This just does a 404 for me. Obviously the cfm pages do not exist and the aspx ones now do. I still have cold fusion installed on the server for now, and do not want to uninstall it until google has updated itself (it case of issues so I can always go back).
Any help would be much appreciated.
Thanks
David
It's like this...
<rule name="CFM301ASP" stopProcessing="true">
<match url="^(.*)$" />
<conditions>
<add input="{REQUEST_FILENAME}" pattern="^.*\.cfm$" negate="false" ignoreCase="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
</conditions>
<action type="Redirect" url="/yourfile.aspx" appendQueryString="true" redirectType="Permanent" />
</rule>
This only works on CFMs that do not exist (isFile=false). It will 301 redirect CFMs that would cause a 404, to your ASP file, and append the URL variables.
The documentation seems to cover all of this.
From the docs on HTTP Redirect:
<configuration>
<system.webServer>
<httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Found">
<add wildcard="*.php" destination="/default.htm" />
</httpRedirect>
</system.webServer>
</configuration>
This led me to believe that you should be able to map URLs from one file extenstion to another.
Creating Rewrite Rules for the URL Rewrite Module
<rewrite>
<rules>
<rule name="Rewrite to article.aspx">
<match url="^article/([0-9]+)/([_0-9a-z-]+)" />
<action type="Rewrite" url="article.aspx?id={R:1}&title={R:2}" />
</rule>
</rules>
</rewrite>
Try reading through these docs, you should be able to find the correct syntax that will allow you to just transfer from *.cfm to *.aspx, passing along the same query strings, or making translations as needed.

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.

MVC3 + WordPress IIS Url Rewriting Rules

I have a ASP.NET MVC3 website located at http://mydomain.com/mymvcapp/. However, the root of the webiste (mydomain.com) contains a WordPress site running PHP. Therefore, I put the following IIS URL Rewrite rule to allow WordPress to function correctly via its rewriting mechanisms:
<rewrite>
<rules>
<rule name="wordpress" patternSyntax="Wildcard">
<match url="*" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php"/>
</rule>
</rules>
</rewrite>
So with this rule in place my WordPress functions perfectly, however, my MVC rewriting does NOT work. How would I alter this rule to allow both WordPress and MVC (under the /mymvcapp/ folder) to coexist nicely?
Figured it out on my own. Regex is probably one of the most powerful YET complicated / confusing technologies there is. But in this case the patternSyntax flag was set to Wildcard, not Regex, which caused my confusion. Hope this helps someone else out there! =]
<rewrite>
<rules>
<rule name="wordpress" patternSyntax="Wildcard">
<match url="*" />
<conditions logicalGrouping="MatchAll">
<add input="{PATH_INFO}" pattern="/mymvcapp/*" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" />
</rule>
</rules>
</rewrite>
This is one of the very few posts anywhere that talks about making WordPress and ASP.NET coexist nicely in an IIS setup. So Kudos for that.
I was thinking to post this as comment to either your original question or the answer, but I chose to write an "answer" only because this is an honest question and I need some formatting capabilities.
I have multiple ASP.NET apps running on by site. In particular the root website is running an MVC4 app.
Since I cannot have WordPress installed at the root, my plan was to have it on its own app folder http://mydomain.com/wordpress/ and then have a URL-rewrite rule that to do the following (using peudo-code):
blog.mydomain.com/{path} --> mydomain.com/wordpress/{path}
I've only caused a mess with this approach and have not been successful using pretty permalinks, sometimes getting into redirect-loops and other times breaking links to .css files, admin pages, etc...
Have you ever given this a thought, i.e., having wordpress as a subapp instead and do sub-domain URL-rewriting?!?!
I had a similar situation but I had no need to edit my web.config file. Instead I followed instructions here at https://wordpress.org/support/article/giving-wordpress-its-own-directory/ where this is documented.
At point 7) within Moving WordPress process to a subfolder Method II (With URL change) you find options for a IIS installation.

Stopping hotlinking from a directory using web.config

I have a folder on my site for caching large flash movies and I want to stop other people from embedding them in their site; I would like to try and do this using the web.config file only. How could this be done?
My first attempt at a rule (which doesn't work):
The following rule was supposed to prevent public access (and embedding) to .swf files in the cache folder 'CurrentCache' - http://myurl.com/ContentCache/ and give a replacement movie 'NoEmbedFromCacheSWF.swf' instead.
<rule name="Prevent SWF hotlinking" enabled="true">
<match url="^(ContentCache)(.swf)$" ignoreCase="true" />
<conditions>
<add input="{HTTP_REFERER}" pattern="^http://(.*\.)?myurl\.com/.*$" negate="true" />
</conditions>
<action type="Rewrite" url="/Content/Flash/NoEmbedFromCacheSWF.swf" />
</rule>
Thanks in advance!
Note: I think I have got the regex wrong in the <match url="A swf inside /ContentCache/" ignoreCase="true" /> line, any ideas what it should?
You can build an HttpModule for this. There is a blog posting describing exactly what you want to do I think:
HttpModule to block external referrers in ASP.NET
Edit: Of course I'm bending the rules here about web.config only. You have to use an external module, but then you can use it referencing from web.config only without modifying any of your code.
Edit2: If you want to do it using a rewrite rule, you have to change your pattern, like this:
<rule name="Prevent SWF hotlinking" enabled="true">
<match url="/ContentCache/.*\.swf$" ignoreCase="true" />
<conditions>
<add input="{HTTP_REFERER}" pattern="^http://(.*\.)?myurl\.com/.*$" negate="true" />
</conditions>
<action type="Rewrite" url="/Content/Flash/NoEmbedFromCacheSWF.swf" />
</rule>
The pattern used is a regular expression, you can read up on them here and you can test them for example on this webpage.

ASP.NET / IIS7 Url Rewrite maps not working

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.

Resources