What's the simplest way to do URL rewriting?

A

Alan Silver

Hello,

I would like to be able to use an URL like ...

http://www.whatever.com/order/123

and have it translated into ...

http://www.whatever.com/orders.aspx?orderid=123

I have searched for articles on URL rewriting and found loads. The
trouble is, they're all so busy being clever telling you how to do
advanced things, that I can't work out how to do the most basic part!!
In this situation, the incoming URL will be fixed, apart from the number
of course and I always rewrite to the same real URL.

If anyone has a link to a really clear and simple article on the subject
(code in C# please), or even some code snippets, please let me know. I
just want to do this simple task first, I can worry about fancy stuff at
another time.

TIA
 
G

Guest

Hi,

The most 'basic' part is calling either overload of:
HttpContext.Rewrite

I guess the reason why most articles appear tough is because they explain
URL Rewriting using HTTP Modules and Handlers.
 
A

Alan Silver

The most 'basic' part is calling either overload of:
HttpContext.Rewrite

Do you know where I can find more information about how to use it? The
SDK is pretty short on explanation.

I tried adding the following to a page ...

void Page_Load(Object sender,EventArgs e) {
//Create a 'Httpcontext' object using 'Current' property
HttpContext myContext = HttpContext.Current;
//Rewrite the internal path
myContext.RewritePath("/");
}

and loading it, but the page (which is not the site's root page) just
loaded as normal.

How would I achieve what I asked, ie allow the user to request
http://www.whatever.com/orders/123 and have this translated into
http://www.whatever.com/orders.aspx?orderid=123
I guess the reason why most articles appear tough is because they explain
URL Rewriting using HTTP Modules and Handlers.

Probably. That certainly made is confusing. Please could you explain how
the HttpContext.Rewrite is used without modules and handlers.

Thanks for the reply.
 
S

Scott Allen

Hi Alan:
Probably. That certainly made is confusing. Please could you explain how
the HttpContext.Rewrite is used without modules and handlers.

You'll have to use RewritePath before the request reaches the endpoint
(the page). That's why URL rewriting schemes use an HTTP handler - you
need to catch the request in the pipeline, like during the
BeginRequest event.
 
A

Alan Silver

I guess the reason why most articles appear tough is because they explain
You'll have to use RewritePath before the request reaches the endpoint
(the page). That's why URL rewriting schemes use an HTTP handler - you
need to catch the request in the pipeline, like during the
BeginRequest event.

So can I just put an Application_BeginRequest in Global.asax, check if
the URL in Request.Path matches what I want, and if so rewrite to the
real URL?

I'm not clear enough on the details to try this yet, but if this is
right, I think I understand how it works.

Thanks for the reply.
 
A

Alan Silver

I'm not clear enough on the details to try this yet, but if this is right, I
think I understand how it works.

Actually, I just thought about it some more and decided I did understand
it well enough to know where to try, and it worked!!

This is global.asax ...

<%@ Language="C#" %>

<script runat=server>

void Application_BeginRequest(Object sender , EventArgs e) {
string strPath = Request.Path.ToLower();
// Fake URLs will be like https://secure.pixata.co.uk/order123.aspx
// check if the path is to a customer order
if (strPath.StartsWith("/order")) {
// get the order number
strPath = strPath.Substring(6);
if (strPath.Length > 0) {
// so there is more than just /order, knock off the .aspx (if
there is one)
if (strPath.EndsWith(".aspx")) {
string strOrderID = strPath.Substring(0, strPath.Length - 5);
// now check if the order ID is a plain integer.
try {
int intOrderID = Convert.ToInt32(strOrderID);
// got this far, so it must be an integer
Context.RewritePath("/pdap/order.aspx?orderid=" + strOrderID);
} catch {
Response.Redirect("/");
}
}
} else {
Response.Redirect("/");
}
}
}
</Script>

The idea is that if someone enters http://whatever.com/order123.aspx it
will get rewritten to
http://whatever.com/order/pdap/order.aspx?orderid=123

Now, I have two issues left. The first is that I would really like to
use the URL...

http://whatever.com/order/123

without the .aspx, but this gives a page not found error, presumably
because the lack of .aspx extension means that IIS doesn't pass it to
the ASP.NET engine. Is there any simple way around this?

The bigger issue is that the /pdap/ folder (where the real .aspx page
resides) is protected by Forms authentication. At the moment, if someone
tries the URL http://whatever.com/order123.aspx and are not logged in,
it sends them to the log in page. I would prefer they get sent elsewhere
(say to the home page as the other failed requests do now).

I tried adding ...

if (User.Identity.IsAuthenticated) {

and only doing the rewriting if this works. If this is false, I redirect
as with other failures.

Unfortunately it doesn't work. Even when you are not logged in, you get
sent to the log in page.

Can I get round this? I don't want non-users to know there is a log in
page at all.

Thanks for any help
 
S

Scott Allen

Hi Alan:

Now, I have two issues left. The first is that I would really like to
use the URL...

http://whatever.com/order/123

without the .aspx, but this gives a page not found error, presumably
because the lack of .aspx extension means that IIS doesn't pass it to
the ASP.NET engine. Is there any simple way around this?

That one is a pain, one way to get it to work is to create the 123
folder and put a default.aspx document inside. Then IIS will find the
a default document (assuming default.aspx is in the list of defaults
in IIS) and pass control to ASP.NET. Hopefully IIS7 will avoid this
problem but that is a long ways off.
The bigger issue is that the /pdap/ folder (where the real .aspx page
resides) is protected by Forms authentication. At the moment, if someone
tries the URL http://whatever.com/order123.aspx and are not logged in,
it sends them to the log in page. I would prefer they get sent elsewhere
(say to the home page as the other failed requests do now).

I tried adding ...

if (User.Identity.IsAuthenticated) {

My guess is that because the user isn't authenticated until later in
the pipeline processing (AuthenticateRequest comes after BeginRequest)
that IsAuthenticated will always be false at that point. You might
want to push that login into the AuthorizeRequest event...

HTH,
 
A

Alan Silver

The most 'basic' part is calling either overload of:
As usual, MSDN is the place to go:
<snip>

Thanks, but I've read that article several times. As I explained right
at the beginning, I find most of the articles on the subject far too
complex. That one was no exception.

As I posted the other day, I finally managed to work out how to do the
simplest of URL rewriting, but it wasn't with the help of that article!!

Thanks for the link though. I usually find MSDN or the SDK to be fine,
but in this case, I found them to be overly complex.
 
A

Alan Silver

Now, I have two issues left. The first is that I would really like to
That one is a pain, one way to get it to work is to create the 123
folder and put a default.aspx document inside. Then IIS will find the
a default document (assuming default.aspx is in the list of defaults
in IIS) and pass control to ASP.NET. Hopefully IIS7 will avoid this
problem but that is a long ways off.

Trouble with this is that the 123 is an order number, so will be
different for every order. I don't want to have to create a new folder
for every order.

Truth is, the .aspx extension isn't so terrible, I was just looking to
improve even more!! The bigger problem is the one below...
My guess is that because the user isn't authenticated until later in
the pipeline processing (AuthenticateRequest comes after BeginRequest)
that IsAuthenticated will always be false at that point. You might
want to push that login into the AuthorizeRequest event...

I thought that, but if I put the code in AuthenticateRequest, then I get
an error of "The resource cannot be found".

I realised that when they get sent to the log in page, the ReturnUrl
querystring variable is set to the page they requested, in this case the
one that generates the orders. In this case, all I need to do is check
for this in Page_Load and redirect to the home page. That way, if
someone (say a customer who sees the fake URL in the footer of a sales
invoice) types the URL in directly and isn't logged in, they will go
straight to the home page of the site and never know that there is an
orders page. Someone who is logged in will see the page correctly.

I'm not sure this is the neatest way to do it, but it sure works!!

Thanks for the reply.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top