Updated Routing With WebForms

asp.net 0 comments suggest edit

A while back I wrote a sample that demonstrated how to use Routing with WebForms.

If you missed it, you can download the code here

With the recent announcement that Routing will be included with .NET 3.5 SP1, you can see why I wanted to put that demo together.

I have since updated that sample to work with the versions of Routing that comes with the April CodePlex build of MVC. This should also work with the SP1 Beta. I’ll verify that when I get a moment.

As part of this update, I added a new feature which allows applying a simple substitution. For example, suppose you want URLs such as /forms/whatever to route to a physical file /forms/whatever.aspx. You can do the following:

routes.Map("forms/{whatever}").To("~/forms/{whatever}.aspx");

One mistake a lot of people make when looking at URL Routing is to think of it as URL Rewriting. The difference is subtle, but important. There is no URL rewriting going on with Routing.

What happens here is when an incoming request URL matches this route (aka the URL pattern on the left), the WebFormRouteHandler will instantiate the physical ASPX Page specified in the virtual path on the right and use that http handler to handle the request (Recall that the Page class implements the IHttpHandler interface). As far as the page is concerned, the URL is /forms/whatever/. For example, this means that the URL rendered by your form will match the current URL, unlike what typically happens with URL rewriting.

This is why the above won’t work if you try to map a route to a virtual path that contains a query string:

//WRONG!!!
routes.Map("forms/{whatever}").To("~/{whatever}.aspx?what={whatever}");

The reason the above route won’t work is that the virtual path on the right isn’t valid. The path needs to specify a page we can instantiate, not a request for an URL.

To save you from having to visit the previous post, here is a link to download the code

Technorati Tags: routing,aspnetmvc

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

24 responses

  1. Avatar for Andrew Steele (ahsteele)
    Andrew Steele (ahsteele) May 19th, 2008

    Is there a solution then to provide a query string? I mean routing is huge but built in rewriting would be real boon!

  2. Avatar for Haacked
    Haacked May 19th, 2008

    No, but you could make whatever data you wanted in the URL to be available to the page via RouteData. So there's no need for a query string.

  3. Avatar for Lee
    Lee May 19th, 2008

    Thanks again for the download.. I'm determined to get my head round this routing stuff!

  4. Avatar for Sudhakar
    Sudhakar May 19th, 2008

    Excellent technique.Can it be work for querystrings in near future.

  5. Avatar for Sudhakar
    Sudhakar May 19th, 2008

    Excellent technique.Can it be work for querystrings in near future.

  6. Avatar for Betty
    Betty May 19th, 2008

    [quote]No, but you could make whatever data you wanted in the URL to be available to the page via RouteData. So there's no need for a query string.[/quote]
    What if you were trying to SEO an old site you didn't have access to the source for? I would have imagined adding some form of http module (or the like) to register some routes could have been an easy way to do this, however sounds like we're out of luck if the old page used querystrings.

  7. Avatar for Haacked
    Haacked May 19th, 2008

    @Betty in that case, routing wouldn't probably work for you. It's a programmatic technique for responding to requests with a resource. It's like URL rewriting, in a sense, but it's bidirectional and doesn't rewrite. If you don't have access to the source, I'd think you'd want to use a URL rewriting solution at the web server level.

  8. Avatar for Mojtaba Vali
    Mojtaba Vali May 20th, 2008

    it is only for mvc isn't it?

  9. Avatar for Andrew Steele (ahsteele)
    Andrew Steele (ahsteele) May 20th, 2008

    [quote]No, but you could make whatever data you wanted in the URL to be available to the page via RouteData. So there's no need for a query string.[/quote]
    An example article on how to do this would be really helpful.

  10. Avatar for Haacked
    Haacked May 20th, 2008

    @Andrew - I did. This post links to another post: Using Routing with WebForms.
    Download the source code and play around with it. You'll see that you can access route data within the RoutablePage class I provided.

  11. Avatar for Jon
    Jon May 25th, 2008

    Hi Phil, when I tried the demo project I had problems accessing the default page. Despite the mapping of "" to "Default.aspx", requests for "/" did not activate the WebFormRouteHandler. Instead, when using the ASP.NET Development Server they returned a 404 error, and when using IIS 7 they reached Default.aspx, but it appeared to be loaded as a standard .aspx page, without a populated RouteData field, causing it error trying to generate the links with this.RouteLink.

  12. Avatar for Jon
    Jon May 25th, 2008

    As an update to the above: I managed to get it working in IIS 7, but only by setting routes.RouteExistingFiles = true in the Global.asax. It seems that if RouteExistingFiles is set to false (its default value), then any mapping on the root of the application will not be honoured. This will even hold if there is no default document available, as when I renamed Default.aspx to Home.aspx, it tried to list the contents of the folder instead of routing.

  13. Avatar for C0der
    C0der May 29th, 2008

    Is it possible to use mvc without installing sp1?

  14. Avatar for Haacked
    Haacked May 30th, 2008

    @C0der yes, it is. SP1 is not required.

  15. Avatar for C0der
    C0der May 30th, 2008

    im want to use mvc in my WebSite project but the word is that mvc is compatible only with Web Application project. if i add the 3 mvc assemblies to my WebSite bin dir and merge my web.config with a mvc's, will this work? if not, what else do i need? im using Visual Studio 2008 Express.
    Thanks

  16. Avatar for Oskar Austegard
    Oskar Austegard June 4th, 2008

    Are you aware of any best practices/white paper/blog post about how to best integrate a webforms and mvc application - or how to migrate from webforms to mvc?
    Matt Hawley talks about his experiences with migrating CodePlex in his post ASP.NET MVC - Living in a Web Forms World, but the gyrations they go through strike me as overly complex - as he says himself:


    ...if at all possible SPIKE! Yes, spike your master pages so that you can have a Web Forms master page AND a MVC master page. By doing this, you do not have to follow the single form pattern thus negating almost all this post.


    Is this indeed the recommended approach?

  17. Avatar for Haacked
    Haacked June 4th, 2008

    I think it's challenging to try and use the same MasterPage for both WebForms and MVC pages, unless the master page does not have any postback controls. In that case, it's pretty easy.
    I believe they have postback controls on their master pages, but they still want to use the same one for both their MVC pages and WebForm pages. That is why theirs is complex.
    Ideally, try and avoid that situation. :)

  18. Avatar for FTeR
    FTeR July 18th, 2008

    Can I somehow use RouteLink or something similar inside a server tag, for ex. PostBackUrl=""?
    The routes.Map("").To("~/Default.aspx"); not working for me.
    I have sp1 and mvc prev4 installed. I'm using the built in VS dev server.
    Setting routes.RouteExistingFiles = true not helped.

  19. Avatar for dkarantonis
    dkarantonis September 16th, 2008

    Hi Phil,
    where exactly do you put the routing code in order for all pages to follow the same rule?
    Also, you mention that you could avoid query string url's, by passing parameters to the page via RouteData. Could you provide a link to an example demonstrating the way to implement it?
    Is it possible to use routing in order to point to different urls based on selected language? For example: routes.Map("forms/{whatever}.aspx").To("~/{language}-{locale}/forms/{whatever}.aspx");
    thanks in advance

  20. Avatar for HakonB
    HakonB October 7th, 2008

    Hi Phil
    Is there any chance that you will make this work with ASP.NET 3.5 sp 1 (and without ASP.NET MVC). Currently there is a dependency on HttpContextWrapper2 which is not available in the later MVC previews.
    Thanks,
    Hakon

  21. Avatar for Bruce
    Bruce October 15th, 2008

    I want to do something similar to:


    routes.Map("forms/{whatever}/{somedata}").To("~/forms/{whatever}.aspx")

    and get {somedata} as route data. But {somedata} is appended as a query string which as you stated above is invalid. Any suggestion? Thanks.

  22. Avatar for prabhjot singh
    prabhjot singh October 31st, 2008

    respected sir,
    I am new to ASP.NET. I am working on URL routing for last couple of weeks, although i have implemented routing on the static pages in my site, but i get stuck when i have to implement it on dynamic URL's.
    eg
    If i have to generate url's for the each user profile in my site, then the relative URL which needs to be generated should not contain the query string values such as the user id.
    secondly
    if i have two pages( home.aspx and profile.aspx) in my site in the same folder eg "logged". The actual Url is mysite/logged/home.aspx.
    i want the relative url to be mysite/index, which i have achieved using your code but now when i click on some other page and then when again i hit in the home tab the url displayed is mysite/logged/index which is wrong. The folders name is shown again in the url.
    what should i do? hope you understand what i want to achieve.
    regards
    prabhjot

  23. Avatar for Stefan
    Stefan November 11th, 2008

    Has anyone tried output caching with routing on webforms? I have page Test.aspx with a user control on it the user control is set to use fragment caching varybyparam="id" now I have a route /test/{id}.
    /test/1 and /test/2 do not give me different versions of the control, am I missing something MVC seems to handle varybyparam fine for action parameters and I see that is using nothing special for caching or am I blind :P??

  24. Avatar for Stefan
    Stefan November 11th, 2008

    Even if I just use output caching on the page with a route like /Test/{id}/{name} and I set a varybyparam="id" on the page, changing the id value will give me a new cache version but also changing the name will give a new cache item. I would expect only the id to change the cached page instance.