开发者

URL Rewrite in ASP.NET 3.5 and IIS 7 using HTTP Module

I am developing an application in ASP.NET 3.5 and IIS 7. I have written an HTTP Module to perform URL Rewrite, for instance, I want to rewrite a username to an Account ID "~/Profiles/profile.aspx?AccountID=" + account.AccountID.ToString();

See below:

using System; using System.Collections.Generic; using System.Data; using System.Configuration; using System.IO; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq;

public class UrlRewrite : IHttpModule
{
    private AccountRepository _accountRepository;
    private WebContext _webContext;

    public UrlRewrite()
    {
        _accountRepository = new AccountRepository();
        _webContext = new WebContext();
    }

    public void Init(HttpApplication application)
    {
        // Register event handler.
        application.PostResolveRequestCache +=
            (new EventHandler(this.Application_OnAfterProcess));
    }

    public void Dispose()
    {
    }

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

        string[] extensionsToExclude = { ".axd", ".jpg", ".gif", ".png", ".xml", ".config", ".开发者_运维知识库css", ".js", ".htm", ".html" };
        foreach (string s in extensionsToExclude)
        {
            if (application.Request.PhysicalPath.ToLower().Contains(s))
                return;
        }

        if (!System.IO.File.Exists(application.Request.PhysicalPath))
        {
            if (application.Request.PhysicalPath.ToLower().Contains("blogs"))
            {

            }
            else if (application.Request.PhysicalPath.ToLower().Contains("forums"))
            {

            }
            else
            {

                string username = application.Request.Path.Replace("/", "");

                Account account = _accountRepository.GetAccountByUsername(username);

                if (account != null)
                {
                    string UserURL = "~/Profiles/profile.aspx?AccountID=" + account.AccountID.ToString();
                    context.Response.Redirect(UserURL);
                }
                else
                {
                    context.Response.Redirect("~/PageNotFound.aspx");
                }
            }
        }
    }
}

I understand that I need to reference this Handler in web.config to get it to work but I don't know what I need to enter in the web.config file and where. Can some please help me here. Also, is there any other configuration needed to get this to work? Do I need to configure IIS?

Thanks in advance.

Regards

Walter


Depends on whether you are using IIS7 Classic or Integrated Pipeline Mode. The standard way to do this with Integrated Pipeline mode is as follows:

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="UrlRewrite" type="MyLibrary.UrlRewrite" />
  </modules>
</system.webServer>

But to be safe you probably want to support a combination of IIS7 Classic/Integrated with graceful degradation on IIS5/6 (in case your dev box uses a different OS), Rick Strahal recommends using the following code on the web config to support both and bypass the nasty error thrown by IIS if you make it backwards-compatible:

<system.web>
  <httpModules>
    <add name="UrlRewrite" type="MyLibrary.UrlRewrite" />
  </httpModules>
</system.web>
<system.webServer>
  <validation validateIntegratedModeConfiguration="false"/>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="UrlRewrite" type="MyLibrary.UrlRewrite" />
  </modules>
</system.webServer>

You will also notice an addition of runAllManagedModulesForAllRequest="true", this is relevant since otherwise the code in your HttpModule will only be executed when the browser calls for .aspx, .ashx, .asmx, etc files that are managed by the .NET framework.

Also, in order to actually rewrite the url (instead of redirect the user) you will need to use the context.RewritePath(string) method inside your event handler.

The way this works is that the application.Request.Path comes in with a 'friendly' string, which I imagine looks like this in your application:

http://www.domain.com/robertp

Which gets rewritten as follows:

http://www.domain.com/Profiles/profile.aspx?AccountID=59

To do this instead of using context.Response.Redirect() you will need to use context.RewritePath() as follows:

string UserURL = "~/Profiles/profile.aspx?AccountID=" + account.AccountID.ToString();
context.RewritePath(UserURL);

... TADA!!

This should ensure that the url being passed through to the server is the one with profiles.aspx?AccountID=59 while the user gets a more friendly robertp on their browser.

As for configuration options, so long as you stick to IIS7 you should be fine with the web config settings above. Its when you try testing on your Dev PC running IIS6 or IIS5 that you might have a problem and this will generally revolve around the fact that robertp does not have a recognizable file extension so your HttpModule code will not be executed unless you add a file extension that uses the .NET ISAPI.

Hope that was useful.


Try the Managed Fusion URL Rewriter, it will save you a Tom of manual programming for rewrites.

http://urlrewriter.codeplex.com

At the very least it shows you how to setup a handler in the config.

Nice thing about MF is that it supports custom modules got doing exactly what you are doing above.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜