Request.Querystring is empty - asp.net

Strange one this..I'm looking for areas to investigate as much as an actual solution, but this is the issue:
In my asp.net webform page I am testing for a querystring which then applies some logic, however, the querystring appears to be stripped from the Url.
If I pass this
..blah.aspx?blah=123
then I can see the querystring in the Request.RawUrl no problem, but when I pass my proper querystring
..blah.aspx?Id=123
the querystring is empty. There is no request filtering on IIS either at the site or application level. Where else might this be stripped? Two hours of head scratching and counting....
Update:
There is no redirect, the logic is in the blah.aspx Pre Init event:
protected override void OnPreInit(EventArgs e)
{
if (!string.IsNullOrEmpty(RequestLEID) || !string.IsNullOrEmpty(RequestLEExternalReference))
DisableNavigationContextCheck = true;
base.OnPreInit(e);
}
Breaking on this event, I am testing the Request.RawUrl property in the immediate window

If you're using sharepoint (eg. a sharepoint control) with your solution, then ID is a reserved keyword.

Nasty. Elsewhere in our code we have a navigation module. This had been updated to use RedirectPermanent which in the case of a url with a repeated querystring pattern (note, not the parameter itself) does not send the querystring with the Request object.
RedirectPermanent is a new method in asp.net 4.0 and certainly not something that we should be using here.

are you pulling the value(s) out of the request?
var RequestLEExternalReference = Request.QueryString["LEExternalReference"];

Related

Request param missing on POST

I am re-writing an ASP.NET application and noticed a difference in behaviour ...
In my Page_Load event I have some code such as:
string id = Request["id"]
which gets the id param from the URL. On page load (ie a HTTP GET), this works as expected in both versions. I also have a button onclick event handler. Clearly, this performs a POST to the server, and also invokes the Page_Load handler. The difference is, that in the original version of the app, the id is successfully loaded from the request. In the new version of the app, id comes back as null. I have discovered that I need to use Request.Params["id"] instead, but am totally puzzled as to why Request["id"] works for POST requests in one app but not the other.
The only difference between the apps is that the first was created as File -> New Website and the second File -> New Web Application. I think this is what is causing the difference in behaviour, but am wondering why this subtle difference, and also if there is anything else I should be aware of between the 2.
Any advice greatly appreciated.
As you have mentioned, you have the id parameter coming through twice. This will be because you have one in the query string parameters and one in the form parameters. I'm not sure why this would be occurring in one web app and not the other, but you can make changes to your code to account for it in a more correct way.
If you view the source of the HTML in your browser, you will see that the action value for the form will be current pages URL, including the query string. This is why the first id is being sent through. Evidently, the second id is coming through via the form itself:
HTML Source of basic web form
<form method="post" action="Default.aspx?id=3" id="ctl01">
<input type="text" name="id">
</div>
There are a couple of things you can do here:
first off, I wouldn't use Request.Params["id"] for this, as it combines the query string, form, cookies and server variables into one collection. You should use Request.Querystring and Request.Form properties, based on what you require and when
In your Page_Load handler, use the Page.IsPostBack property to determine whether the page is loading for a GET or POST and use the Request properties described above.
Example of Page.IsPostBack usage:
protected void Page_Load(object sender, EventArgs e)
{
string id = string.Empty;
if (Page.IsPostBack)
{
id = Request.Form["id"];
}
else
{
id = Request.QueryString["id"];
}
}
I always use web applications project but the difference is compilation. Website has a dynamic compilation, which means that the first request will be slower and web app has pre-compiled release dlls.
Check this for pro's and con's : http://maordavid.blogspot.ca/2007/06/aspnet-20-web-site-vs-web-application.html

How to hide asp.net querystring displayed in address bar as default.aspx?id=2&name=sanjay [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Removing a querystring from url in asp.net
How to hide asp.net querystring displayed in address bar as default.aspx?id=2&name=sanjay
If you want to hide the data passed in parameters in the query string.
Use a form and POST the information. This might require additional code in source pages, but should not require logic changes in the target pages (merely change Request.QueryString to Request.Form). While POST is not impossible to muck with, it's certainly less appealing than playing with QueryString parameters.
Use session variables to carry information from page to page. This is likely a more substantial effort compared to (1), because you will need to take session variable checking into account (e.g. the user might now have a difficult time navigating around using their Back and Forward buttons, if you are constantly checking state). You will also need to deal with the case where session cookies are not enabled (this solution will not work for these people).
Use "encoded" or non-sensical information in the QueryString in place of the real data. This will require the effort of creating an encoding and decoding scheme on either end of all page submissions. Sure, users can still experiment and reverse engineer your scheme, however they will be less likely to quickly come up with meaningful changes to the existing QueryString.
Use framesets. I really don't recommend this approach, though it is quite common. If you're trying to hide the information as opposed to making it more difficult to modify, users can still right-click the individual frames and click properties, in order to retrieve all of the information passed via QueryString.
Use Server.Transfer to move control to a second page, which will still have access to the QueryString parameters passed to the first page (the URL of which was visible only briefly)
You really need to POST the data -- directly to default.aspx, if possible. If the caller is a different page, this gets a little wonky with web forms, especially if you're relying on sitemap functionality. In any case, you could post the data using "cross page posting" or you could use "server.transfer". Using session state with a redirect is somewhat inefficient (an extra round trip for the client), but often expedient. So for example, the calling page may look like:
Web Form (caller):
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">Click Me!</asp:LinkButton>
Code-behind (caller):
protected void LinkButton1_Click(object sender, EventArgs e)
{
Session["id"] = 2; // pull the data from the control or use OnCommand?
Session["name"] = "Sanjay";
Response.Redirect("~/Default.aspx");
}
And the receiving page, default.aspx would look like:
Web Form:
Name: <%=_name %>
<br />
Id: <%= _id %>
Code-Behind:
protected int? _id
{
get { return Session["id"] as int?; }
set { Session["id"] = value; }
}
protected string _name
{
get { return Session["name"] as string; }
set { Session["name"] = value; }
}
Good luck!

ASP.NET Caching - Programatically Invalidating Server Cache...confusion on example

I'm reading how to programmatically invalidate cached pages on the server in ASP.NET, and the book ("MCTS Self-Paced Traing Kit (Exam 70-515)") says:
To directly control whether a cached
version of a page is used or whether
the page is dynamically generated,
response to the ValidateCacheOutput
event and set a valid value for the
HttpValidationStatus attribute.
The code segments look like the following:
public static void ValidateCacheOutput(HttpContext context, Object data,
ref HttpValidationStatus status)
{
if (context.Request.QueryString["Status"] != null)
{
string pageStatus = context.Request.QueryString["Status"];
if (pageStatus == "invalid")
status = HttpValidationStatus.Invalid;
else if (pageStatus == "ignore")
status = HttpValidationStatus.IgnoreThisRequest;
else
status = HttpValidationStatus.Valid;
}
else
status = HttpValidationStatus.Valid;
}
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.AddValidationCallback(
new HttpCacheValidateHandler(ValidateCacheOutput),
null);
}
Could someone please explain to me what this code is doing? Also, the main question I have is that I thought Cached pages were simply returned from the server, but the code below indicates that the page life-cycle is being invoked (Page_Load event); I'm confused because the page life-cycle isn't invoked if a cached page is returned, so how would the code in the Page_Load event even fire?
Note: Here's the same example that the book has
I also came across this question. It is too bad that almost every blog post and article I find about this subject dutifully replicates the MSDN example without really explaining how it works.
I don't have a definite answer but I think this works because the page life cycle is invoked at least once. Namely when the page is requested for the first time and thus isn't cached yet.
During that first request the Page_Load is called and the HttpCacheValidateHandler is registered with the Cache object. During all subsequent request for that page, the Cache object is able to call your ValidateCacheOutput() method. And because this method is static the page life-cycle doesn't have to be invoked.
I hope that someone who knows more about this can comment on it but in my opinion this also implies the following:
In the given example the HttpCacheValidateHandler doesn't need to be a static method of the page because it doesn't use any properties of the Page object. It can be a static method on any other object you like.
The ValidateCacheOutput() method will probably be called for every page request, not just for the page which is (ab)used to call Response.Cache.AddValidationCallback(). Maybe i'm missing something obvious but I don't see how the Cache "knows" which HttpCacheValidateHandler belongs to which page.
You are right in that typically cached pages are just returned frm the server but this changes when you use AddValidationCallback. In this case, ASP.NET will call this method to determine whether to returned a cached copy or not. This method should therefore be very light or you will negate the effect of caching.
The code you have listed just checks the querystring for a Status variable and uses the value of this to determine whether to either (1) pull the page from the cache, (2) clear the cached page, re-render it and cache it or (3) just ignore the cache and re-render the page.
See http://msdn.microsoft.com/en-us/library/system.web.httpvalidationstatus.aspx for the status options.

ASP.NET: Why is "_requestValueCollection" empty on PostBack?

Why is "_requestValueCollection" empty on PostBack?
I have a really strange problem with post backs. In some cases on post backs (this.Request.RequestType == "POST") have null "_requestValueCollection" member. And for ASP.NET that means this.IsPostBack == false.
So I have modified the Page_Load in the following way:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack && this.Request.RequestType != "POST")
{
//REGULAR INIT STUFF
}
else
{
//REGULAR SITE POSTBACK STUFF
}
}
What is possible danger of this approach? So far everything is doing OK (and is pretty rich and complicated page).
It isn't clear from your example what you are attempting to do with this code, so this is mostly a short in the dark.
You probably don't need the second part of the if statement. Checking IsPostBack alone should be sufficient.
_requestValueCollection is not a property, it is a field and probably isn't a good place to get at the data submitted by the client. I suggest instead that you consider using the Form property (this.Request.Form) or the Headers property (this.Request.Headers) depending on what you are looking for. Keep in mind that most of the time you can just get form values from the asp.net controls on the form directly.
You may also want to look at the Request.HttpMethod property if you need to determine the exact http method used to invoke the page.
Edit: Adding info about _requestValueCollection
The mechanics behind the _requestValueCollection being loaded are quite complex, but I took a look at the MS source and from what I can determine the page calls on every control on the page that implements the IPostBackDataHandler interface. For each of these it will call the LoadPostData method which adds the data for that control to the collection.
The main things that I can think of off the top of my head that might cause the collection to be null would be:
no server controls on the page implement IPostBackDataHandler
there is no server form, or the contents of the form weren't sent by the client
Alternately, the page may be using query strings to convey the data to the server, and the query string doesn't contain anything
As I said, this is a bit fuzzy. The Page class is very complex internally and so there could be other ways data gets put into that collection too, but this was all I could find on a casual examination.

ASP.NET: How to redirect, prefilling form data?

i want a handler to redirect to a web-forms page, pre-filling in the values of some controls on the form.
i tried setting my current Request.Form data:
if (theyWantToDoSomething)
{
//pre-fill form values
context.Request.Form["TextBox1"] = "test";
context.Request.Form["ComboBox1"] = "test 2";
context.Request.Form["TextBox2"] = GetTheTextForTheThing();
//tell the client to go there
context.Response.Redirect("~/SomeWebForm.aspx");
return;
}
But i get an exception that Form values are read only.
What would be a way to send the client to another page, pre-filling form data?
Answer
i used the Session state to store values. It's important to note that by default a Handler doesn't have access to Session (the Session object will be null). You have to tell IIS to give you the Session object by adding the IRequiresSessionState marker interface to your handler class:
public class Handler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
...
if (theyWantToDoSomething)
{
//pre-fill form values
context.Session["thing1"] = "test";
context.Session["thing2"] = "test 2";
context.Session["thing3"] = GetTheTextForTheThing();
//tell the client to go there
context.Response.Redirect("~/SomeWebForm.aspx");
return; //not strictly needed, since Redirect ends processing
}
...
}
}
You can only populate your Response, the Request is input data and is indeed read-only.
If you are using ASP.NET, there are a variety of ways you could accomplish what you need:
The best way would probably be to pass the data you need to be pre-populated to SomeWebForm.aspx via the Session object, and on that pages Load method, populate your form. Keep in mind that when you do Response.Redirect, a 302 response is sent to the client with the URL the client should redirect to. The process is transparent to the user...but there is a full round trip involved.
Another alternative to populating the users Session would be to add GET parameters via a query string to the redirect to SomeWebForm.aspx.
If you need to transfer processing to the SomeWebForm.aspx page without round tripping, you could use Server.Transfer. This will transfer execution from the current page to the page you choose...however, this can cause some odd behavior on the client end because the URL does not update. As far as the user is concerned, it will still appear as though they are on the same page they started on.
A few ideas that might get you started:
Pass the values in the query string
Store the values in the session state or in a seperate cookie
Store the values in HttpContext.Items and use Server.Transfer instead of Response.Redirect
Another approach that hasn't been mentioned yet is using Server.Transfer makes it possible to use the Page.PreviousPage property, allowing access to the controls on the page that transferred control.
As jrista mentioned though, using Transfer doesn't update the URL shown to the user, which may or may not be an issue. For example, a user can't precisely bookmark a page they got transferred to since the URL will be that of the original transferring page.

Resources