URL Rewriting - problems with postbacks

J

Jon Maz

Hi All,

I am experimenting with URL Rewriting using the techniques outlined by Scott
Mitchell in his article "URL Rewriting in ASP.NET"
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/htm
l/urlrewriting.asp).

In the article he mentions a problem with postbacks: "If the URLs you are
rewriting contain a server-side Web Form and perform postbacks, when the
form posts back, the underlying URL will be used". His solution is to use a
custom ActionlessForm derived from System.Web.UI.HtmlControls.HtmlForm, but
with the "action" attribute removed.

An alternative solution is outlined by Scott Allen in his blog entry "The
Passion and the Fury of URL Rewriting"
(http://odetocode.com/Blogs/scott/archive/2004/09/22/509.aspx). He proposes
simply adding the following to Page_Load:
Context.RewritePath(Request.RawUrl);

However in my experimenting, it seems that neither of these solutions works
in one particular situation, and I'm wondering if anyone out there can help
out.

The situation is:
Redirect from: ~/products/
Redirect to: ~/Somedirectory/Somepage.aspx
Note that the "Redirect from" url does *not* contain a page name.

I have got this working fine for the first time the page is hit, having
created a /products sub-folder containing an empty Default.aspx page.

The problem is, when Somepage.aspx posts back to itself, using Scott Allen's
technique described above, the URL is rewritten *not* to ~/products/ (which
is what I want), but to ~/products/Default.aspx. While this is better than
the URL being rewritten to ~/Somedirectory/Somepage.aspx on postback, it
still isn't perfect!

And using Scott Mitchell's ActionlessForm, I get: "HTTP 405 - Resource not
allowed, The page you are looking for cannot be displayed because the page
address is incorrect". This is quite a long way from perfect.

Can anyone help?

TIA,

JON
 
S

Scott Allen

Hi Jon:

Here is what I think is happening.

When the browser requests the ~/products/ directory, IIS sees the
request is for a directory, checks the settings for the directory and
moves the request to the default document (default.aspx) since the
file exists on the file system. ASP.NET actually does see the URL as
~/products/default.aspx, because IIS has moved the request to this
location all by itself.

There are ways to get the original request (for the products
directory), which would be to make all requests go through the asp.net
runtime (enter a * in the script mapping). Then you really could
redirect from ~/products/ to /somedirectory/somepage.aspx, the problem
is I'm not sure how to get the action tag set correctly. You might
need to do something along the lines of:
http://weblogs.asp.net/jezell/archive/2004/03/15/90045.aspx
to pull this off.

I hope to get some time to experiment with this interesting problem
this weekend.
 
J

Jon Maz

Hi Scott,

Glad to know you're on the case! Looking forward to seeing what you come up
with...

Cheers,

JON
 
S

Scott Allen

Well, I fiddled around with the second RewritePath and I did not come
up with a way around the problem. I think the solution will involve
overriding the HtmlForm class methods. I'll keep plugging away at this
when I get a chance but I'm afraid it's not going to be an elegant
solution I was hoping to find!
 
J

Jon Maz

Hi Scott,

An inelegant solution is a lot better than no solution at all! Good to know
I'm not alone with this problem...

Thanks for the help,

JON
 
Joined
Dec 19, 2008
Messages
1
Reaction score
0
My Solution

My solution to this was to change the form action in page load.

This is set to this.Request.Url by default. Unfortunately this url is the rewritten one. However if you set it to [page].Request.RawUrl this returns back the requested url.

E.g.
protected void Page_Load(object sender, EventArgs e)
{
this.Form.Action = this.Request.RawUrl;
}

I also added items to the Context.Items collection based on the url rewritting that related to the initial referrer. The initial referrer is lost after the postback because the referrer is itself. To Handle this I called RegisterRequiresControlState and stored the info there.

E.g.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!base.DesignMode)
{
this.RegisterRequiresControlState(this);
}
}

protected override object SaveControlState()
{
//return object to peristed
}

protected override void LoadControlState(object savedState)
{
//initialise state from the persisted object
}

stephenkaye.blogspot.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top