Can you clear Page.Request.QueryString? - c#

My problem is as follows:
I am adding a variable to the URL that should trigger a search when the page loads, depending on what is in the variable. If you navigate to that same page without the variable then it shouldn't do anything special on page load. I figured that the following would do the trick:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.Request.QueryString["cell"] != null)
{
txtCell.Text = Page.Request.QueryString["cell"];
Lookup_Cell(Page.Request.QueryString["cell"]);
//BUGGED, this keeps running when i try a new search
//Page.Request.QueryString["cell"] = null;
}else{
//do nothing, empty string
}
}
This worked like a charm, but i have a search button of the form that is supposed to call the Lookup_Cell method for a cell you specify in a TextBox. i need to make Page.Request.QueryString empty so next time the page loads it won't fire this special OnLoad. I tried:
Page.Request.QueryString["cell"] = null;
but that didn't work. I looked for other methods, but can't find a definite answer.

You can make a simple PostBack check and when there is a post back, get the string from your text box.
string cFinalQueryString = "";
if(!IsPostBack)
{
if (Page.Request.QueryString["cell"] != null)
{
cFinalQueryString = Page.Request.QueryString["cell"];
}else{
//do nothing, empty string
}
}
else
{
cFinalQueryString = txtCell.Text;
}
txtCell.Text = cFinalQueryString;
Lookup_Cell(cFinalQueryString);
Or alternative, when you have post back, redirect to new page with new 'cell' query
if(IsPostBack && Page.Request.QueryString["cell"] != txtCell.Text)
{
Responce.Redirect("CurrentPage.aspx?cell=" + UrlEncode(txtCell.Text), true);
return ;
}

The querystring is sent by the browser with each request to that URL.
It sounds like you want to redirect to a URL without a querystring.

Related

Is there a way how to step out form method and return page with updated element?

I have couple of method in code behind on asp.net application. I would like to return messages to user in Label in case of something happen during execution and stop execution.
Code is just as sample what I'm trying to achieve.
I already tried:
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
Response.Redirect("to same page");
Example: (I don't want to execute unzipFile method. I would like to reload current page with updated label)
protected void btnUpload_Click(object sender, EventArgs e) {
uploadFile(Server.MapPath("~/") + filename);
unzipFile(string newFile);
}
protected void uploadFile(string newFile) {
if (newFile != null)
{
Label.Text="This is not valid file!"
//stop processing load file with updated label
}
if (newFile.ContentType != "application/x-zip-compressed") {
Label.Text="This is not valid file!"
//stop processing load file with updated label
}
}
Just don't redirect. The postback is already to the current page and should render the current page unless anything tells is not to. Consider a simple case:
protected void Page_Load(/.../)
{
// set some values on the page
}
protected void btnClick(/.../)
{
label1.Text = "This is a test";
}
With only that code in the button click handler, the current page will reload after clicking the button and the only visible change will be that text output.
Your case isn't really different. Set the labels and don't redirect. For example:
if (newFile != null)
{
Label.Text = "This is not valid file!";
}
else if (newFile.ContentType != "application/x-zip-compressed")
{
Label.Text = "This is not valid file!";
}
else
{
// process the file
Response.Redirect("SomewhereElse.aspx");
}
However you structure the logic, ultimately your goal is to not do any more processing once you have your error condition and just allow the event handler to complete and the page to re-render.
Note: I think you also meant == null, and you can simplify the conditions. Consider:
if (newFile == null || newFile.ContentType != "application/x-zip-compressed")
{
Label.Text = "This is not valid file!";
}
else
{
// process the file
Response.Redirect("SomewhereElse.aspx");
}
If you don't want the else, you can accomplish the same with a return:
if (newFile == null || newFile.ContentType != "application/x-zip-compressed")
{
Label.Text = "This is not valid file!";
return;
}
// process the file
Response.Redirect("SomewhereElse.aspx");

Using Window.Open instead of Response.Redirect to open new window?

My page code looks like this:
<asp:Button ID="btnSearch" runat="server" Text="Search" onclick="btnSearch_Click"/>
My method looks like this:
protected void btnSearch_Click(object sender, EventArgs e)
{
var value = lblGraphicNameValue.Text.ToString();
Response.Redirect("Search.aspx?txtGraphicName=" +
value);
}
Currently, when the user press the 'Search' button the page refreshes and loads the Search.aspx page. What I'd like to happen is have the Search.aspx open in a new window, instead. I've looked at using Window.Open, but I'm not sure if this is the correct route, or if I can use the same method of passing in my variable (querystring). Can someone point me in the right direction? What I have works, I just want it to open in a new page while leaving the prior page alone.
EDIT: I should mention that I cannot use javascript (secure environment, every browser has javascript disabled).
From what I'm reading, it seems to indicate that opening a new web page from within an asp.net page and having parms passed in is not do-able without javascript? Is this correct?
This code below ultimately does exactly what I needed it to:
<a href="<%= this.ResolveUrl("Search.aspx?id=" + lblGraphicNameValue.Text.Remove(lblGraphicNameValue.Text.Length -4)) %>"
target="_blank">Search Related</a>
This code does three things:
1) Opens Search in new page.
2) Truncates the search value by four
characters (I only needed part of the search string)
3) Passes in
parameter to new page.
This accomplished exactly what I needed without resorting to custom classes or javascript, although it did make me have to use a link instead of a button.
Use this class.
ResponseHelper .Redirect("popup.aspx", "_blank", "menubar=0,width=100,height=100");
public static class ResponseHelper {
public static void Redirect(string url, string target, string windowFeatures) {
HttpContext context = HttpContext.Current;
if ((String.IsNullOrEmpty(target) ||
target.Equals("_self", StringComparison.OrdinalIgnoreCase)) &&
String.IsNullOrEmpty(windowFeatures)) {
context.Response.Redirect(url);
}
else {
Page page = (Page)context.Handler;
if (page == null) {
throw new InvalidOperationException(
"Cannot redirect to new window outside Page context.");
}
url = page.ResolveClientUrl(url);
string script;
if (!String.IsNullOrEmpty(windowFeatures)) {
script = #"window.open(""{0}"", ""{1}"", ""{2}"");";
}
else {
script = #"window.open(""{0}"", ""{1}"");";
}
script = String.Format(script, url, target, windowFeatures);
ScriptManager.RegisterStartupScript(page,
typeof(Page),
"Redirect",
script,
true);
}
}
}
I think your on the right track, but you're confusing server side code, and client side code. window.open is a Javascript function which works on the client side. So you'll need to render some Javascript from C# to make the window popup. Try:
protected void btnSearch_Click(object sender, EventArgs e)
{
var value = lblGraphicNameValue.Text.ToString();
ClientScript.RegisterStartupScript(this.GetType(), "newWindow", String.Format("<script>window.open('Search.aspx?txtGraphicName={0}');</script>", value));
}
That will re-render the page, and then add a script on pageload that will popup the window. A little warning, this will probably be blocked by a browser popup blocker. If you want to get around that, you can probably achieve this without posting back to the server by using Javascript.
A better option would be to create a javascript function like:
function PreviewPOSTransaction(Id)
{
if (Id != null)
{
window.open('POSTransReport.aspx?TransID=' + Id);
return true;
}
}
</script>
and call this function on button "OnClientClick" event like:
OnClientClick="PreviewPOSTransaction(1);

Winform WebBrowser Pass Cookie Then Process Links?

I asked this question a while ago but seems that there are no answers, so i tried to go with an alternative solution but i am stuck now, please see the following code:
WebBrowser objWebBrowser = new WebBrowser();
objWebBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(objWebBrowser_DocumentCompleted);
objWebBrowser.Navigate("http://www.website.com/login.php?user=xxx&pass=xxx");
objWebBrowser.Navigate("http://www.website.com/page.php?link=url");
And here is the event code:
WebBrowser objWebBrowser = (WebBrowser)sender;
String data = new StreamReader(objWebBrowser.DocumentStream).ReadToEnd();
Since it's impossible for me to use the WebBrowser.Document.Cookies before a document is loaded, i have first to navigate the login page, that will store a cookie automatically, but after that i want to call the other navigate in order to get a result. Now using the above code it doesn't work cause it always takes the second one, and it won't work for me to put it in the event cause what i want is like this:
Navigate with the login page and store cookie for one time only.
Pass a different url each time i want to get some results.
Can anybody give a solution ?
Edit:
Maybe the sample of code i provided was misleading, what i want is:
foreach(url in urls)
{
Webborwser1.Navigate(url);
//Then wait for the above to complete and get the result from the event, then continue
}
I think you want to simulate a blocking call to Navigate if you are not authorized. There are probably many ways to accomplish this and other approaches to get what you want, but here's some code I wrote up quickly that might help you get started.
If you have any questions about what I'm trying to do here, let me know. I admit it feels like "a hack" which makes me think there's a smarter solution, but anyway....
bool authorized = false;
bool navigated;
WebBrowser objWebBrowser = new WebBrowser();
void GetResults(string url)
{
if(!authorized)
{
NavigateAndBlockWithSpinLock("http://www.website.com/login.php?user=xxx&pass=xxx");
authorized = true;
}
objWebBrowser.Navigate(url);
}
void NavigateAndBlockWithSpinLock(string url)
{
navigated = false;
objWebBrowser.DocumentCompleted += NavigateDone;
objWebBrowser.Navigate(url);
int count = 0;
while(!navigated && count++ < 10)
Thread.Sleep(1000);
objWebBrowser.DocumentCompleted -= NavigateDone;
if(!navigated)
throw new Exception("fail");
}
void NavigateDone(object sender, WebBrowserDocumentCompletedEventArgs e)
{
navigated = true;
}
void objWebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if(authorized)
{
WebBrowser objWebBrowser = (WebBrowser)sender;
String data = new StreamReader(objWebBrowser.DocumentStream).ReadToEnd();
}
}

Accessing the Form collection in an IHttpModule causes event Handler not to get called on Default page

Ok, this is a weird one. I've created a simple sample site to demonstrate the issue. In it, I have a Default.aspx Page that has a button on it:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<p><asp:Button OnClick="ButtonClick" Text="Button" runat="server" />
</p>
<asp:Label ID="output" runat="server" />
</asp:Content>
The code behind just sets the label text on the button click:
protected void ButtonClick(object sender, EventArgs e)
{
output.Text = "Button Click!!";
}
I then have an IHttpModule that gets called for every request:
public class SampleModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
if(application == null)
{
return;
}
HttpContext context = application.Context;
if(context == null)
{
return;
}
string text = "queryStringParam";
var value = context.Request[text];
var boolValue = value == null;
}
}
Again, this is just a demo, but the point here is, I'm accessing the Request, to get the value off the query string. If I run this in Cassini, it all works fine. However when I run this in IIS, this is what happens. When I run the site at:
http://mysamplesite.dev/
and then click on the button, nothing happens. The page just reloads, but my event handler for the button never gets called, and subsequently the label text never gets updated. However if I then run it at:
http://mysamplesite.dev/Default.aspx
and then click the button, it works fine and my event handler does get called!
After digging around some I changed the code in the module to this:
string text = "queryStringParam";
var value = context.Request.QueryString[text];
var boolValue = value == null;
Notice, here I'm accessing the QueryString property directly, and not going to context.Request. When I changed it to this, it works fine regardless of whether or not I had Default.aspx in the url?!
Next step I did was, I looked at Reflector to see what the code of the HttpRequest indexer property actually does:
public string this[string key]
{
get
{
string str = this.QueryString[key];
if (str != null)
{
return str;
}
str = this.Form[key];
if (str != null)
{
return str;
}
HttpCookie cookie = this.Cookies[key];
if (cookie != null)
{
return cookie.Value;
}
str = this.ServerVariables[key];
if (str != null)
{
return str;
}
return null;
}
}
Seems harmless enough, it just checks various collections for me, so I don't need to check each one individually. So then I'm wondering, which one of those calls breaks it. I then changed my module to this:
string text = "queryStringParam";
var value = context.Request.QueryString[text];
var boolValue = value == null;
var value2 = context.Request.Form[text];
var boolValue2 = value2 == null;
And now it's broken again! So to make a long story short, just by accessing the Form collection on the request in the IHttpModule, I somehow screw up the PostBack, and the event never gets fired.
Does anyone have any idea why this is happening? I'm more of an ASP.Net MVC guy, I don't know ASP.Net and all the shtick it pulls behind the scenes well enough to really have a clue as to why this is happening.
give your button an ID (no luck)
try fiddler and see what the traffic looks like - something funny is going on here.
When a request is made to "http://mysamplesite.dev/Default.aspx", the context_BeginRequest event handler is only called once, as you would expect. However, when a request is made to "http://mysamplesite.dev/", for some reason context_BeginRequest is called twice.
For "http://mysamplesite.dev/", the first pass through context_BeginRequest loads the Form values properly when context.Request["queryStringParam"] is executed, but the second pass through does not (I checked the private _form value on context.Request using reflection). During this time, the Page_Load method for the page is only called once.
So, the event is not being handled properly because ASP.NET handles a request for "/" a little bit differently than it handles a request for "/Default.aspx", by firing the BeginRequest for the module twice instead of once. As to why ASP.NET does this, I'm not really sure. You would probably need to profile the ASP.NET request and see what methods are being called on HttpRequest to see why the form values don't get passed properly the second time context_BeginRequest is called (and additionally why this second call is even made in the first place).
Note: this must be an internal ASP.NET thing (maybe a Server.Transfer from "/" to "/Default.aspx" or something like that) because Fiddler2 only shows one request coming from the browser for "http://mysamplesite.dev/".

Context.Items clears during page refresh/transfer

I am working on a class project and I've run into a problem I can't figure out. I have a feeling it's actually pretty easy, but I've been working on stuff so long I can't think straight anymore.
I have a login page that allows a user to login and pass 2 data items to the next page using Context.Items and Server.Transfer. Here is the code snippet:
Context.Items["preferred"] = true;
Context.Items["pageNum"] = 1;
Server.Transfer("ProductsShelf.aspx");
On the "ProductsShelf" page I can access those two items and use the data like so:
pageNumber = (int)Context.Items["pageNum"];
I am then using a switch-statement with pageNumber to display certain information:
switch (pageNumber)
{
case 1:
imgProd.ImageUrl = "assets/laptop.bmp";
lbl_Name.Text = "Laptop";
lbl_desc.Text = "This is a cheap laptop!";
lbl_price.Text = "199.99";
break;
}
Obviously there's other entries I'm omitting. What I want to do is click a next or previous button and use the event to change the Context.Items["pageNum"] data so the Page_Load() event uses different data in the switch-statement. Hope that makes sense. Here is one of the button click events:
protected void btn_Prev_Click(object sender, EventArgs e)
{
if (pageNumber == 1 || pageNumber == 2)
{
Context.Items["pageNum"] = 1;
}
else if (pageNumber == 3)
{
Context.Items["pageNum"] = 2;
}
Context.Items["preferred"] = preferredCustomer;
Server.Transfer("ProductsShelf.aspx");
}
The problem is that before the button click event fires, the form posts and clears the Context.Items and pageNumber values. This means that the button event if-statements never fire and it results in:
pageNumber = (int)Context.Items["pageNum"];
Being null, throwing an exception and making me very sad. So my question is, how can I go about retaining the values? Should I switch to Response.Redirect and have something like ?page=1 in the URL? Or will that clear too when the form posts? Hopefully I'm not doing this completely wrong.
If TL;DR, here's a quick summary:
Context.Items has 2 values passed with Server.Transfer
These values determine what's shown on the next page
The form clears Context.Items and variables before button click event fires
The values are null, the if-statement doesn't run, and the app throws an exception
Question: how should I go about retaining those values?
Thanks a lot. :)
HttpContext items can be used within one request only - it will be recreated for next request so your values are bound to lose. You should use view-state to preserve data across post-backs. In page load, you should check if data exists in context and then copy it to view-state. Then in button click events, you can read the data from view-state, put into the context items and do server.transfer.
Here's simple sample code:
private int PageNumber
{
get
{
var value = ViewState["pageNum"];
return null == value? 1: (int)value;
}
set
{
ViewState["pageNum"] = value;
}
}
private bool IsPreferredCustomer
{
get
{
var value = ViewState["preferred"];
return null == value? false: (bool)value;
}
set
{
ViewState["preferred"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
var preferred = Context.Items["preferred"];
if (null != preferred)
{
IsPreferredCustomer = (bool)preferred;
}
var pageNum = Context.Items["pageNum"];
if (null != pageNum )
{
PageNumber = (int)Context.Items["pageNum "];
}
}
Use the same PageNumber property in event code.

Categories

Resources