Url Rewriting And Form Actions

posted on 06/11/08 at 08:00:00 pm by Joel Ross

I have been working on a site for the past couple of months, and as part of that, we wanted to make our URLs prettier and more "hackable" - users are easily able to figure out how to get to the info they want.

Well, we ran into an issue with that. The page we rewrite to has a form on it and when that form posts back, we get Viewstate validation errors. That's a problem! Basically, the form has the wrong URL in the action, and we needed to somehow change the form's action.

Not that I'm surprised, but ScottGu already knows the solution. Towards the end of his post is a section titled "Handling ASP.NET PostBacks with URL Rewriting" and he mentions the problem I was seeing. He even has the source control for the form control adapter that solved our problem. It's written in VB.NET, and I needed it in C#, so I ported it. Here's the port:

   1:  public class UrlRewriterFormWriter : HtmlTextWriter
   2:  {
   3:    public UrlRewriterFormWriter(HtmlTextWriter writer) : base (writer)
   4:    {
   5:      base.InnerWriter = writer.InnerWriter;
   6:    }  
   7:    
   8:    public UrlRewriterFormWriter(System.IO.TextWriter writer) : base(writer)
   9:    {
  10:      base.InnerWriter = writer;
  11:    }
  12:   
  13:    public override void WriteAttribute(string name, string value, bool fEncode)
  14:    {
  15:      if (name == "action")
  16:      {
  17:        HttpContext Context;
  18:        Context = HttpContext.Current;
  19:   
  20:        if (Context.Items["ActionAlreadyWritten"] == null)
  21:        {
  22:          value = Context.Request.RawUrl;
  23:          Context.Items["ActionAlreadyWritten"] = true;
  24:        }
  25:      }
  26:      base.WriteAttribute(name, value, fEncode);
  27:    }
  28:  }

The code isn't that complicated. Basically it looks for attributes named "action". Once it finds one, it updates the action to be the RawUrl - the pre-rewritten Url. Then it ensures that it doesn't do anything else (the ActionAlreadyWritten part). That way, the post backs work, and the "pretty Url" stays in the browser's address bar.

To use this class, you just override Render:

   1:  protected override void Render(HtmlTextWriter writer)
   2:  {
   3:    base.Render(new UrlRewriterFormWriter(writer));
   4:  }

That's it! Now your Urls stay pretty, and it got rid of our nasty viewstate issues.

Tags: | |

Categories: Development, C#