Search code examples
asp.neturl-rewritingwebformsglobal-asaxasp.net-routing

How can Routing for WebForms show a Google Adwords query string?


I've been on this almost 2 days and I'm really feeling stuck. I've been running a site for a few years using MapPageRoute to create urls for several hundred "pages" that are all handled by "~/default.aspx" via database lookups for page data. The entire site is not like this (i.e. it's not a single page site), but a good portion is.

It has been working fine except I am unable to use querystrings on the mapped routes. The RegisterRoutes method in the global.asax is:

   public static void RegisterRoutes(RouteCollection routes)
   {
      routes.Clear();
      routes.Ignore("{resource}.ashx/{*pathInfo}"); //ignore ashx files
      routes.Ignore("{resource}.axd/{*pathInfo}"); //ignore axd files, prevents javascript/routing collisions
      routes.MapPageRoute("SitePage", "{*page_url}", "~/default.aspx", false);
   }

I use a wildcard on the path segment. Unfortunately only one wildcard is allowed. {*page_url} typically represents 1 to 4 segments. I've tried various forms of IRouteHandler and IHttpHandler code, but I don't see how to change the url that appears in the client browser. I can use the wildcard this way because none of the routes interfere with a physical files.

The only reason I want to preserve the querystring is because Google Adwords adds on a ?gclid=xxxxxxxxx string to an ad link, and Google Analytics .js uses that querystring to report back.

A sample URL depiction of the issue is:

/about-us/community/philanthropy  (resolves fine)

/about-us/community/philanthropy?gclid=xxxxxxx  (redirects back to:)
/about-us/community/philanthropy

My web.config is free of url-rewriting settings that might affect this.

A fair amount of my research on SO and elsewhere is for MVC sites. This is a WebForms site.

Example, similar question, but for MVC: How do I route a URL with a querystring in ASP.NET MVC?


Solution

  • I abandoned the routing engine for this altogether and went to path rewriting. My pattern didn't neatly fit routing.

    I got some help from Chris Zhao Is it possible to have Routing maintain a querystring in the browser address bar?

    And this link was really helpful for some more in depth context: URL rewriting in an ASP.NET application

    In global.asax at Application_BeginRequest:

    if (Request.CurrentExecutionFilePathExtension == "" && Request.CurrentExecutionFilePath != "/"
         && g.Global.SITEPAGEROOTS.ContainsKey(Request.Url.Segments[1].Replace("/", "")))
    {
       Context.RewritePath("/default.aspx", false);
    }
    

    The g.Global.SITEPAGEROOTS is a Dictionary singleton with < 30 entries and it just hangs out in memory until garbage collection. It contains the base path, primary url segment for my sitepages that need to be url-rewritten. Also, the "false" turns off rebaseClientPath which helped with images and other items that weren't showing on the pages due to using application root directory references (~/).

    In the /default.aspx page:

    var rawUri = new Uri(Request.Url, Request.RawUrl);
    //using RawUrl because the url is usually rewritten before hitting this page
    //and RawUrl preserves the original url.
    
    if (rawUri.LocalPath != "/" && rawUri.LocalPath != "/default.aspx")
    {
        //lookup the rawUri.LocalPath in the db and pull out all the site page
        //data needed to render the page (html, metas, etc.)
        //querystring found at rawUri.Query if needed.
    }