UPDATE: While the approach listed in this post is still a valid option, Scott Guthrie provide an even clean approach that make this even easier to implement. I've blogged about those improvements and provided a link to his post here.
First of all, thanks to fellow ASPInsider Scott Mitchell for his insanely thorough article on how to configure Url Rewriting with ASP.NET 1.1. What follows is an overview of the additional tweaks I needed to put in place to get Url Rewriting to work SEAMLESSLY with ASP.NET 2.0 and ASP.NET AJAX.
I'm currently involved in building a website that requires a LOT of url rewriting. Initially I didn't plan on having any post-backs, so I pretty much ignored the fact that Url Rewritten pages will post-back, by default, to the 'translated' url. So, if I rewrite:
http://mysite.com/name_of_product_here
to
/pages/products.aspx?id=name_of_product_here
any time a user issues a postback from that page, they'll be posting back to:
http://mysite.com/pages/products.apx?id=name_of_product_here
That's not a huge deal, I guess - unless you really want the urls on your site to be 'hackable' (i.e., you want to treat the urls on your site as a type of navigational interface that end-users can use if they want). Scott Mitchell's Url Rewriting article showed how to deal with that by creating a custom implementation of System.Web.UI.HtmlControls.HtmlForm. The gist was just to override how it rendered its attributes, and strip out the action attribute.
The nice thing too, is that with ASP.NET 2.0 Master Pages, I only had to 'swap out' the standard HtmlForm tags with the tags for my over-ridden/inherited HtmlForm class once. Even better, there was no need to compile my overridden class as I was able to just dump it in the App_Code folder. To reference code in the App_Code folder, you just need to remember that it will be compiled on your server, and output to "App_Code.dll"... which means you can register your own tags like so:
And, hooking that form into my master page was simple, I just had to replace the opening tag:
and closing tag:
Using Scott's method of overriding a form control that doesn't emit an action attribute completely solved my issue with Post-backs and url-rewriting in ASP.NET 2.0. But with ASP.NET AJAX installed and running on some of my rewritten pages (especially coupled with an UpdatePanel), having a blank/default action attribute just wasn't working.
Using Fiddler I could see that my AJAX requests were actually attempting to access: /pages/ - with nothing else specified (i.e. not /pages/products.aspx or anything - clearly something was messed up). Accordingly (since I had a default document set up in the specified location), I was getting ViewStateMac errors/warnings. In other words, my AJAX requests were getting warnings that were 500 errors. The net result though, was that my update panels/ASP.NET AJAX was broken.
Happily, my Url Rewrite Module made use of the following logic to store the 'original' (as in un-rewritten' url). Storing it in Context.Items is a light-weight way to ensure that it sticks through the entire request-response cycle:
Knowing that I had access to the 'pretty' url stored in Context.Items, I just made a minor tweak to the code that Scott provided in his article. The purpose of my tweak was to explicitly set the location of the action attribute - without having to add an 'Action' property or any other thing to my custom class. The entire class is listed below (with it's namespace):
using System; using System.Web; using System.Web.UI.HtmlControls;namespace SSV.Rewrite
{
/// <summary>
/// Summary description for ActionlessForm
/// </summary>
public class RewriteForm : HtmlForm
{
protected override void RenderAttributes(
System.Web.UI.HtmlTextWriter writer)
{
writer.WriteAttribute("name", this.Name);
base.Attributes.Remove("name");writer.WriteAttribute("method", this.Method);
base.Attributes.Remove("method");this.Attributes.Render(writer);
string action = Context.Items["Original_Path"] as string;
if(action != null)
writer.WriteAttribute("action", action);
base.Attributes.Remove("action");if (base.ID != null)
writer.WriteAttribute("id", base.ClientID);
}
}
}
Not much there, as you can see (the whole process was pretty painless). The beauty though is that my rewritten pages are now served up with a rewritten action attribute. So pages now totally post back to their rewritten location, and ASP.NET AJAX works perfectly with my Url Rewriting Scheme. So now I've got the best of everything: url-rewritting or tidying, hackable urls, and ASP.NET AJAX goodness.
Shiny.
Oh, thank you! I was previously overriding the Render() method on my master page to fix the action, but it wasn't working with the UpdatePanel. Now I'm back on track...
Posted by: David | February 14, 2007 at 09:34 AM
huteonahtn uehant uehtna ueao u htnueatnh http://www.google.com/search?hl=en&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial&hs=pLt&q=url+rewriting+asp.net+ajax+form+action+&btnG=Search
Posted by: foo | April 03, 2007 at 06:18 PM
Thanks for this tip. My home grown UrlRewrite is now working perfectly with ASP.NET Ajax.
Posted by: Nick H | April 20, 2007 at 06:07 AM
Great tip. Also overwriting the render to fix the action. Works great now.
Posted by: Peter | July 29, 2007 at 08:07 AM
Brilliant. I was using both similar methods but couldn't get ajax methods to work with url rewriting. I only had to add the context.items... lines into my exising code to get everything working.
Works with telerik RadAjaxManager as well.
Posted by: James | September 12, 2007 at 09:55 AM
Hi,
The code works great with AJAX. However when I have AJAX as well as POSTBACK events on the same page the code starts giving problems. Can you help me with this??
Posted by: Sagar Kathiara | January 25, 2008 at 06:33 AM
Great tip. Also overwriting the render to fix the action. Works great now.
thank you
Posted by: kral oyun | November 04, 2008 at 10:29 AM
Thanks for this tip. My home grown UrlRewrite is now working perfectly with ASP.NET Ajax.
Posted by: Oyun | March 24, 2009 at 09:50 AM
very good post thank you
Posted by: Estetik | April 02, 2009 at 09:12 AM
Very good post indeed. I will try your solution.
Posted by: Kiên | June 14, 2009 at 08:36 PM
Just put in
form.Action=Request.RawUrl;
in page_load of the master page(if used) or on the page_load of the respective page.
I used it and it works amazingly. No need to put in any code. Your postbackurl will be exactly what you want.
Posted by: Prabhjot Singh | August 25, 2009 at 05:31 AM
this code works great with AJAX.thankss
Posted by: estetik | February 14, 2010 at 03:58 PM
Hey thanks for sharing this information and i have tried this solution and its working great AJAX, and others should try this solution if they are facing the same problem!
Posted by: refurbished hp desktop computers | April 07, 2010 at 01:38 AM
Great tip. Also overwriting the render to fix the action. Works great now.
Posted by: Oyunlar | January 05, 2012 at 12:00 PM