ASP.NET - how to change requested page names transparently? - asp.net

Very new to this subject and under the gun to come up with a solution. The problem is how I could load one of several versions of the same ASPX page, for any given page. E.g. unknown to the unsuspecting user who requests catalog.aspx, I would actually serve one of catalog_1.aspx, catalog_2.aspx, or catalog_3.aspx, etc.
Strange request indeed. It's due to an inherited decade-old product having inlined styles all over the ASPXs. Instead of re-writing the hundreds of ASPXs to be flexible, I'm trying to regexp-replace them to get versions suitable for various screen sizes. I'd then choose the best one after measuring window size at user login (and perhaps store the size in a cookie).
I thought this would involve some lower level object like an http handler. Close?
LJ
Update: I ended up doing this through url rewriting which works much better. The easiest place to do this in asp.net is apparently global.asax, and under Application_BeginRequest event. Call context.RewritePath(newpath, False) to send the request to a different page than requested.
In the way I did it, the destination page can change from request to request, and that apparently upsets postbacks, if the recipient of the postback isn't the exact version of the page that generated the viewstate. I tried to turn off viewstate validation but didn't help. So had to prevent flipping between versions once a user's logged in. Hope this helps someone.

Server.Transfer is probably the quickest way of doing just that.
string TransferTo = string.Empty;
if( Something )
TransferTo = "catalog_1.aspx";
else if( SomethingElse )
TransferTo = "catalog_2.aspx";
else
TransferTo = "catalog_3.aspx";
Server.Transfer( TransferTo, false );
Documentation
Note
If the subsequent pages have postback controls on them, they will reveal the true URL of the page at that point. If that matters, then this method will not work.

I don't like this method, but maybe you could use a full-window IFRAME to hold the appropriate page - catalog.aspx would be nothing but a big frame, and you could set the source of that frame in your codebehind.

Related

Preventing users from skipping pages in an ASP.NET form

I have a data entry form that I've broken apart into 5 pages and I want to make sure that the users go through the pages in the proper order each time. The navigation is set up to take them through it properly, including a breadcrumb to go back and change previous pages. I want to make sure, however, that they don't get to a later page without going through the earlier pages first (i.e., go through pages A and B then skip to D by entering the URL directly, or start out on D using a bookmark).
I've made some attempts to prevent this, with my latest one being this, which checks for required session variables specific to each page:
public static string CheckForPageSkipping()
{
var redirectTo = "";
if (HttpContext.Current.Session["TestDate"] == null) redirectTo = "~/Auth/SignOff.aspx";
if (HttpContext.Current.Session["Repairs"] == null) redirectTo = "~/Auth/RepairNotes.aspx";
if (HttpContext.Current.Session["MeterNum"] == null) redirectTo = "~/Auth/TestResults.aspx";
if (HttpContext.Current.Session["PremiseOwner"] == null) redirectTo = "~/Auth/PremiseInfo.aspx";
return redirectTo;
}
I called this during each Page_Load event and redirected to the page it returned if it was not the page they were on. This almost worked, until I realized that it prevents you from being able to navigate backwards (it always sends you back to the latest page you haven't completed). I'm sure I can cobble something together to make this work, but I wanted to see if there is a better way to do it. Something either built in to ASP.NET, or something more elegant that someone had built in the past.
My search attempts, both in Google and on StackOverflow, yielded no useful results. Maybe I was using the wrong terms, but it was mostly stuff like I've written here (the suggestions made at the top now have not been helpful either).
It seems like you have control of the pages so why not get rid of them and put the code into user controls, register these controls in one page in panels or placeholders and control the visibility of these panels in the code so that you can properly enforce the order in which these are visited?
Have you looked at the <asp:wizard> built-in control? I think it will fit your needs and you can configure it for many different scenarios.
Here is a link describing its use: http://msdn.microsoft.com/en-us/magazine/cc163894.aspx
Also see the current official documentation: MSDN Library
There is a good pattern explained here for using multi-part forms using panels.
Multi-Part Form using Panels
If you don't want to use the Wizard control and you don't want to use Panels, either Server.Transfer or Cross Page Posting should work. With either method, checking the PreviousPage should cover your page skipping concerns.
Server.Transfer has the URL oddity you mentioned, but is otherwise pretty straightforward.
Cross-Page Posting is quite appropriately tailored to your needs as well.
Post each form to the next form page.
Receive and process the data there (with strong typing if you set it
up correctly).
Only load the new page if everything checks out (PreviousPage is
correct, data is valid).
I admit, I don't have direct experience using either of these methods myself, but I can see how they could be implemented to handle your situation.

Classic ASP Redirecting Title Issue

Just wondering what limitations there are in ASP doing a Server.Transfer two levels? So a page transferring to another page that then transfers to one more page.
Here is our current setup. In an attempt to please SEO, we have created "fake" URLs containing keywords. We then have a 404 error handler (IIS) picking these up, redirecting to another ASP page which pulls out some key information from the URL, and does a Server.Transfer to our "real" page. For reasons outside the scope of this post, it is required that I make a further Server.Transfer from this page. The page we are now on needs to set the page title.
Is this possible?
What you want is certainly possible.
Sure, there are some limitations... but, the limitations are not on the number of server transfers which you plan to daisy chain... Just make sure you don't end up creating a vicious cycle :)
the limitation is as follows;
server.transfer ( and server.execute too for that matter ) cannot access the previous page's variable context.
so if you set a variable say Age=50 in page1 and page1 does a server.transfer to page2, do not expect page2 to know anything about that Age variable declared & set by the page1. In fact, you can even Dim the same variable (Age) in page2, you won't get an error. This is because, neither the .transfer'ed, nor the .execute'd pages work like the [!--include...] files...
So what to do? How do you share information among those pages that you plan to daisy chain using server.transfer? The answer is to use session variables!. That's one effective way.. ( of course you may go out of your way to write to db or text files, but why? )
The only the other thing that your page2, and page3 could share from the the original page1 is the querystring, and post & cookie data! Those request collections will still be available in the transferred ( or executed ) pages.. This means that you can do request("age") in both page2 and page3 if the original page ( page1) was hit as page1.asp?age=99
anyway, coming back to your org. question... what you want is certainly doable...
just don't set any variables in page1, simply work with session variables...
and don't forget to clean up the session vars when you are done on the final page.
hope this helps you...

What is the alternative to Response.Redirect() asp.net?

Hi One of the tips in "website performance tips" in various blogs says "Avoid Redirects". In my case, I am using Response.Redirect for the same page. I am passing a querystring and displaying appropriate information to the user.
Response.Redirect("FinalPage.aspx?NextID=" + ID);
So in our business logic, i am reloading the same page with different information.
So how do i avoid redirect? Is there any other alternative? BTW, my aim is to gain some performance there.
Redirect is the R in the PRG pattern which is an accepted pattern for processing posted requests. So it is definitely not evil.
However, there used to be a common interview question: "What is the difference between Server.Redirect() and Server.Transfer() and which one must be used?". People used to say Transfer because it did not involve a round-trip but web has changed so much since then. In those days you could not re-use the the common logic in the views unless you use Transfer or Redirect, but nowadays especially with ASP NET MVC there are tons of a ways to do that.
In your case, I am all for PRG and I believe redirect is semantically more correct. Also it prevents the form being re-submited if user clicks F5 or refresh.
The recommendation is for unnecessary redirects.
Your case is different - you are passing in information to the page, this is not strictly the same thing as a regular redirect (i.e. a page that moved).
You can also do a Server.Transfer, which does not require a new request to come in, thus lessening the load on the server. More information comparing the two is here.
In your case, you do want to do a Redirect because you are modifying the query string and changing something on the page, as opposed to shifting processing of the initial request to another page.
The main "evil" if it could be called such is that redirects require an extra round trip; the client requests one page (usually the same page, specifying that a particular button was clicked), and the server responds saying "request this page instead", and the browser then complies, resulting in the server actually serving up the next page.
It's sometimes necessary to do this, however there are now much better ways to control navigation in a website. For instance, instead of a "form" button that causes a postback and redirect, you could use a LinkButton that will behave like a hyperlink, allowing the browser to request the new page directly. You could also use a MultiView that shows different ASCXs, and control navigation by view-flipping (however, understand that this can have its own performance implications, especially when using them in a nested fashion).
I think if you want to redirect to same page then instead of doing Response.Redirect("FinalPage.aspx?NextID=" + ID); you could use NextID in ViewState also or Hidden Field so that you would not required to redirect SAME page and then check that hidden field or viewstate instead of checking QueryString
:D

Can a control blindly proxy another URL, including PostBack?

It is possible to have a control that would proxy requests to another domain/Web site, including postback?
In this control, you would specify the URL you wanted to execute, and whenever the control executed, it would make a GET request to this other URL, and render the HTML return. (This part is not hard.)
However, when the page is posting back, it would make a POST request, with all of its postback variables intact, to this other page.
I'm really looking for a blind proxy. Some control that will take the incoming request and throw it another URL, and render the results. The other page would really have no idea it wasn't interacting with a human.
I want to think I could develop this, but I can't be the first person who wants to do it, so there has to be some reason why Google isn't revealing the solution to me. I suspect I'm going to run into the same Big Problem that anyone else with this idea has run into.
I'm not exactly sure what the value of this is; which is probably why you haven't found a solution yet.
However, it seems to me that there are two possible solutions.
When the page is rendered have the control modify the form action to point elsewhere; or,
on post back, have the control execute a web request to the alternate URL with the post variables and decide what to do with the results at that time.
In this end, this never had much of a chance of working. I experimented with it for a while, but Postback requires intimate knowledge of the control tree, and there's no way that you're going to be able to apply a postback from the calling page to the other page and have it overlay correctly because the control trees between the two pages are totally different.
Now, if you wanted to write the backend app as a more traditional Web app (even something not in ASP.Net), it might work. During postback, you could iterate the Request.Form values and send them back, and just have your backend app prepared to accept those incoming values and deal with them, but this wouldn't be a traditional postback.

Can a URL change on postback?

I only need to parse URL Request.Querystrings on GET, not on postback, right?
if(!IsPostBack)
{
Viewstate["magic_number"] = Parse(Request.Query);
}
The user can't be expected to modify the URL in the Request for subsequent postbacks, or can they?
Motivation for question-- I don't control the javascript snippet that does the postback, so it's something of blackbox to me.
The URL is not expected to change. But remember that each postback is a new instance of your page class. So if you didn't save the results somewhere on the first view you need to be prepared to do it again on the next one, and so on. In this case you saved it to ViewState, and so that should be fine.
However, I suspect you wouldn't be asking the question unless you had observed behavior that led you to suspect otherwise. So let's consider for a moment what things could cause this to break:
It is possible to modify ViewState at the client where you saved your results (though not trivial and definitely not recommended).
You can fake a postback before the initial page view.
You can use javascript to alter the posted url.
However, for all these things you would certainly know if you have written anything to do that.
Your assumption is correct, the URL is not expected to be modified in subequent post backs and you need to parse the query string only on the GET, which happens the first time the page is loaded.
The URL does not normally change for a postback.
It's of course possible to use a tool like FireBug to edit the URL in the form tag before the postback, but then you probably don't want the value that the user injected anyway, but the original value.
As others have pointed out, The URL is not expected to change. Of course if we lived in a perfect world you would never get email spam and noone would ever attempt to do anything malicious to your website.
In the real world you should expect that malicious people will attempt to hijack your website and need to be concerned with things like injection attacks
You should never make any assumptions that the data received on a postback is valid.

Resources