简体   繁体   中英

How to url redirect/rewrite .asp into .aspx

I'm running in the Cassini developer server inside Visual Studio 2012, and I need to redirect clients from the legacy .asp pages to .aspx pages.

Note: Ideally I would redirect clients from .asp to a friendly url, and then internally do a rewrite to .aspx

POST /ResetClock.asp

HTTP/1.1 307 Temporary Redirect
Location: //stackoverflow.us/ResetClock

And then internally:

POST /ResetClock

rewrites into /ResetClock.ashx (Yes, I changed it to .ashx ; that's the virtue of url rewriting).

Like what Hanselman did

This is a lot like what Scott Hanselman did :

  • Request for /foo.html
  • gives the client a redirect to /foo
  • client request for /foo
  • is re-written into /foo.html

The attempted hack

I tried the hack solution; alter the .asp page to force a redirect to the .ashx (and live to fight with the url re-write syntax another day):

ResetClock.asp

<% 
   Response.Redirect("ResetClock.aspx")
   Response.End 
%>

Except that Cassini does not serve .asp pages at all:

This type of page is not served.

Description: The type of page you have requested is not served because it has been explicitly forbidden. The extension '.asp' may be incorrect. Please review the URL below and make sure that it is spelled correctly.

Requested URL: /WebSite/FetchTimes.asp

Which points to a related issue. The solution I end up using cannot require anything that isn't already available on the IIS7.5. And it cannot require anything that needs access to the IIS Admin tools; and must exist entirely within the web-site (eg the web.config ).

The question

How do I re-write .asp into something more ASP.net-ish?

Edit : Changed GET to a POST to thwart nitpickers who wonder why the 307 Temporary Redirect and not 302 Found or 303 See Other .

The solution is to create an IHttpModule . HttpModules let you intercept every request, and react as you desire.

The first step is to create the plumbing of an IHttpModule :

class UrlRewriting : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += new EventHandler(this.Application_BeginRequest);
        application.EndRequest += new EventHandler(this.Application_EndRequest);
    }

    public void Dispose()
    {
        //Nothing to do here
    }

    private void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;
    }

    private void Application_EndRequest(object sender, EventArgs e)
    {
    }
}

And then register our HttpHandler in the web.config file:

web.config :

<configuration>
   <system.web>
      <httpModules>
         <add name="UrlRewriting" type="UrlRewriting"/>
      </httpModules>
   </system.web>
</configuration>

Now we have a method ( Application_BeginRequest ) that will run every time a request is made.

Issue client redirect if they ask for ASP page

The first order of business is redirect the client to a "clean" form. For example, a request for /File.asp is redirected to /File :

private void Application_BeginRequest(object sender, EventArgs e)
{
   HttpApplication application = (HttpApplication)sender;
   HttpContext context = application.Context;

   //Redirct any requests to /File.asp into a /File
   if (context.Request.Url.LocalPath == VirtualPathUtility.ToAbsolute("~/File.asp"))
   {
      //Be sure to issue a 307 Temporary Redirect in case the client issued a POST (i.e. a non-GET)
      //If we issued 302 Found, a buggy client (e.g. Chrome, IE, Firefox) might convert the POST to a GET.
      //If we issued 303 See Other, the client is required to convert a POST to a GET.
      //If we issued 307 Temporary Redirect, the client is required to keep the POST method
      context.Response.StatusCode = (int)HttpStatusCode.TemporaryRedirect;
      context.Response.RedirectLocation = VirtualPathUtility.ToAbsolute("~/File");
      context.Response.End();
   }
}

And then the internal rewrite

Now that the client will be asking for /File , we have to re-write that internally to an .aspx , or in my case, an .ashx file:

private void Application_BeginRequest(object sender, EventArgs e)
{
   HttpApplication application = (HttpApplication)sender;
   HttpContext context = application.Context;

   //Redirct any requests to /ResetClock.asp into a /File
   if (context.Request.Url.LocalPath == VirtualPathUtility.ToAbsolute("~/ResetClock.asp"))
   {
      //Be sure to issue a 307 Temporary Redirect in case the client issued a POST (i.e. a non-GET)
      //If we issued 302 Found, the buggy client might convert the POST to a GET.
      //If we issued 303 See Other, the client is required to convert a POST to a GET.
      //If we issued 307 Temporary Redirect, the client is required to keep the POST method
      context.Response.StatusCode = (int)HttpStatusCode.TemporaryRedirect;
      context.Response.RedirectLocation = VirtualPathUtility.ToAbsolute("~/ResetClock");
      context.Response.End();
   }

   //Rewrite clean url into actual handler
   if (context.Request.Url.LocalPath == VirtualPathUtility.ToAbsolute("~/ResetClock"))
   {
      String path = "~/ResetClock.ashx"; //no need to map the path
      context.Server.Execute(path, true);

      //The other page has been executed
      //Do not continue or we will hit the 404 of /ResetClock not being found
      context.Response.End();
   }
}

IIS contains some basic url redirection

Starting with some unknown version of IIS, they added a (now mocked) form of URL Rewriting. It doesn't issuing a client redirect, only an internal re-write. But at least it could be used to solve my problem (responding to an ASP page with ASP.net content):

web.config

<configuration>
   <system.web>
      <urlMappings>
         <add url="~/ResetClock.asp" mappedUrl="~/ResetClock.ashx"/>
      </urlMappings>
   </system.web>
</configuration>

The client will still appear to have found a resource at /ResetClock.asp , but the guts of the response will have come from /ResetClock.ashx .

Note : Any code is released into the public domain. No attribution required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM