ASP.NET HttpContext.RemapHandler to remap to ASP Classic - asp.net

We are upgrading an ASP Classic website (actually, a virtual directory under a larger website) to ASP.NET 3.5. There will be some legacy directories that remain ASP Classic. Other than that, every .asp file will be replaced by an .aspx file in the same location in the directory hierarchy. We would like not to break old links coming into the site from elsewhere. The website is hosted on IIS 6 (and we have no control over this).
My idea was, in IIS, to replace the usual handler for .asp files, asp.dll, with aspnet_isapi.dll. First question: If I do that, will requests for .asp files then be routed through any custom HTTP modules I create and register in web.config?
Then I would create an HTTP module hooked into BeginRequest that would test whether a request's path (before any querystring) ends in .asp. If so, it would check whether the physical file exists. If not, then I'll use HttpContext.RewritePath to append the "x" to the ".asp". Otherwise, if the .asp file DOES exist, I'll use HttpContext.RemapHandler to switch the handler back to asp.dll so that the file will be processed as the ASP Classic file that it is.
Second question: Will this work? Third question: What do I use as the argument to the RemapHandler method? How do I acquire a reference to an instance of the ASP Classic handler? (If I knew the answer to the third question, I'd have just tried all this on my own!)
UPDATE: OK, I did try it out myself, except that I renamed the remaining .asp files so that their extension is .aspc (ASP Classic), and in IIS I assigned the old asp.dll as their handler. Then, instead of checking whether the .asp file requested exists and remapping to the ASP Classic handler if so, I checked instead whether a file in the corresponding physical location except with the extension .aspc exists. If so, I rewrite the URL to append the "c". This worked! Therefore, the answer to my first question, above, is "yes", and the answer to my second question is "yes, pretty much, except that the part about remapping the handler is unknown". But it would be preferable not to have to change the extensions on all my legacy .asp files, so I am left with one question: Will the original RemapHandler approach work and, if so, what is its argument?

Did you know, that you could handle this quite easily using the web.config file and redirect rules in IIS?
You need to activate the URL Rewrite2 module described here.
This is a really nice feature of IIS, to solve routing problems, see here also for some examples.
Looking at your case, I would do something along the lines of this:
<rule name="execute classic asp if file exists" stopProcessing="true">
<match url="(\w+\.asp)$" />
<conditions>
<add input="C:\Path\To\Your\WebApp\{R:1}.asp" matchType="IsFile" />
</conditions>
<action type="Rewrite" url="{R:1}c" appendQueryString="true" />
</rule>
<rule name="execute dotnet otherwise" stopProcessing="true">
<match url="(\w+\.asp)$" />
<action type="Rewrite" url="{R:1}x" appendQueryString="true" />
</rule>
I'm not sure if all RegExes here would work for you, but its meant as a start to experiment. The reason to explicitely write C:\Path\To\Your\WebApp\ is, that I didn't find a way to get the base path of the web app as a parameter.

Related

how to avoid 301 errors when serving static content using iis url rewrite

I am trying my website to get images(static contents) from other server (or site) using IIS url rewrites. Below is the sameple rule written where it checks for any image request and serves it from another website on same server
<rule name="image" stopProcessing="true">
<match url="^Images/(.+)$" />
<action type="Redirect" url="http://localhost/PGFeedReadAPI/Images/{R:1}" appendQueryString="false" />
</rule>
This works fine and I am getting results however with 301 error i.e. request goes to server it response with 301 (moved permanently) to browser and then browser makes fresh request to new url. Can we avoid this round tripping? I would prefer to achieve this without any code changes (i.e. with only configuration changes). Please pardon if I am missing some basic concepts.
Check out the answer from this post:
Put images on CDN, using MVC3 on IIS7
Use a response filter to change the urls before they make it to the client. This will avoid 301s.
I took this a step further and added caching so that I query the CDN on app start, hold a dictionary of the static file names to CDN urls and quickly swap in. It also auto-uploads missing files from local to CDN and adds them to the dictionary for future reference (asynchronously).

app_offline.htm not working for rewritten URLs

I have a Rewrite rule for a specific page, to make it more SEO friendly.
<rewrite>
<rules>
<rule name="Friendly Threads">
<match url="Topic/([^/]*)/([^/]*)/[^[#\?]*\??(.*)" />
<action type="Rewrite" url="thread_messages.asp?ThreadID={R:1}&PageNumber={R:2}&{R:3}" />
</rule>
</rules>
</rewrite>
But whenever I drop an app_offline.htm file in the root, the site will go to the app_offline.htm page for all URLs except for those matching the above match.
Is this expected, or have I possibly got something misconfigured somewhere?
If it makes any difference, this is a classic ASP site running under IIS 8 (Windows 2012).
(And yes, I know this is like putting a 90 year old behind the wheel of a Lamborghini.)
As far as I know app_offline.htm only works for ASP.NET. As the rewrite result is classic ASP, the page is handled by another IIS module, so it won't care about app_offline.htm existence.
In another saying, you have done nothing wrong, but classic ASP does not support app_offline.htm.

IIS 7 URL Rewrite for 404 and Sitefinity

We have a new Sitefinity site that is replacing our marketing site. The switchover happened last friday, and we uncovered a problem today: there is content (pdfs, jpgs) on the old site that can no longer be accessed, and did not make it into the content migration plan. On top of that, management has removed rollback as an option.
So, the solution I have come up with is to use IIS 7's url rewriting module to point to a new url that hosts the old site so that content can be accessed. This is the xml in my web.config that I have come up with:
<rewrite>
<rules>
<rule name="RedirectFileNotFound" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{URL}" negate="false" pattern="/\.*$" />
</conditions>
<action type="Redirect" url="http://www.oldsite.com{REQUEST_URI}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
It attempts to test if the URL resolves to a file or folder, and makes sure that we are requesting something with an extension. If the rules pass, it redirects to the same location on the old site. Ideally, this would mean that anything linking to the old site previously would be able to be left alone.
The problem is, nothing gets redirected.
By fiddling with the rules, I have verified that the module is operational, i.e. i can set it up to rewrite everything, and it works. but these rules do not work.
My theory is that since Sitefinity uses database storage, it somehow short circuits the "IsFile" match type. Complete guess, but I'm kind of at a loss at this point.
How to I use urlrewriting to redirect for 404's in this manner?
I am not sure how the rewriter is implemented, but those rules seem to be too general. Sitefinity uses the routing engine and registers a series of routes that it handles. By definition, those routes are interpreted sequentially, so if a more general rule exists before a more specific one, the latter will not work.
I suspect what may be happening is that the Sitefinity rules already handle the request before the rewriter gets a chance to redirect it. What I can advise is to either implement more specific rewrite/redirect rules, or just handle the whole issue using a different approach. What was the reason your old files were inaccessible after the migration? Can you give a specific URL that fails to return the file, so we can work with a scenario?
this is just a shot in the dark, but do you have "file system fallback" enabled in the sitefinity advanced settings for libraries? perhaps the module is intercepting the request and not letting it proceeed to the file-system...
Thank you guys for your help, but it turned out to be a problem with Dynamic Served Content in general.
Assume that all requests are actually handled by a Default.aspx page. This isn't the way that Sitefinity works, but it is the way that DotNetNuke works, and illustrates the problem nicely.
The url rewrite isfile and isdirectory flags check for physical existence of files. In this case, only Default.aspx actually physically exists. All the other dynamically served content is generated later in the request cycle, and has no physical existence whatsoever.
Because of that, the isfile flag will always fail, and the redirect rule will always execute.
The solution I went with was to allow IIS and .NET to handle the 404s themselves, which properly respects generated content. and route that to a custom error page, 404redirection.aspx. There is code on that page that redirects to my old site, where that content is likely to be host. That site then has additional 404 handling that routes back to the 404NotFound.aspx page, so requests for files that don't exist in either system make a round trip and look like they never went anywhere. This also has the nice side effect of pages that aren't found on the old server get to display our new, pretty, rebranded 404 on the new server.
Simply put, rather than attempting to pre-empt the content generation and error handing, I took a more "go with the flow" approach, and then diverted the flow at a more opportune time.

What is the correct way to be able to serve up an ASP.NET MVC page with URL /areas?

I am trying to get ASP.MVC to handle the URL /areas i.e. http://example.com/areas. By convention there is a folder called Areas, so /areas never gets to my controller.
I want to be able to tell MVC to ignore this folder in this one case.
Ordinarily I would not use a name that conflicts with an existing folder but I am migrating a web application from Django to ASP.NET MVC and have a section of pages under /areas. I would prefer not to have to change all the existing URL's just because of the framework.
For performance reasons I would prefer not to configure all requests to go through the MVC pipeline.
What other solutions are there?
It might be possible to use the IIS URL Rewrite module to redirect requests to specific folder and avoid the MVC pipeline completely.
The example below is from http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/ which shows how to rewrite paths to point at a static resource (Under the heading "Static content management.")
<rewrite>
<rules>
<rule name="Rewrite to new folder">
<match url="^Images/(.+)$" />
<action type="Rewrite" url="NewImages/{R:1}" />
</rule>
</rules>
</rewrite>
I'm curious if you could use an IgnoreRoute in your global.asax.cs file which would cause MVC to ignore that completely and not use the MVC processor for anything in that folder
routes.IgnoreRoute("areas/{*pathInfo}");

ASP .NET page name "alias"

I have a web of which I have two versions: one in spanish and one in english. They are located in different servers and different domains. So they actually behave as two different websites.
I only have one ASP .NET project, and depending on the domain, I show all texts in spanish or in english. That's working right.
I developed it first in spanish, so my page names are written in spanish, like "Buscar.aspx" ("Buscar" means "Search").
I would like to translate also the page's name, so that in browser's address bar, it would appear the english names. For instance, for my page "Buscar.aspx" I would like to appear "Search.aspx" in the address bar.
So my question is: is there any way to declare some kind of "alias" (or some other mechanism), so that I can process requests to "Buscar.aspx" and "Search.aspx" through one single ASP .NET page, but still appearing in the address bar as two different addresses?
URL Rewriting
You could rewrite Search.aspx to Buscar.aspx
<rewrite>
<rules>
<rule name="Search">
<match url="^Search.aspx" />
<action type="Rewrite" url="Buscar.aspx" />
</rule>
</rules>
</rewrite>
These rules could then be put in your English web.config file
Have a look at routing. You can find some documentation here: ASP.NET Routing
Routing means that you can specify a path that maps to a certain ASPX. If you switch the routing configuration based on your language setting you have what you need :)

Resources