I'm a new C# programmer and have just created a simple program. I first wanted it to count button clicks, maintaining the cumulative count across clicks (post backs). This worked.
Now I want to turn off EnableViewState and see that the clicks do NOT accumulate. So I turned off EnableViewState (EnableViewState="False") for the text box (named txtCount), but somehow it still keeps counting and accumulating my clicks across posts. Am I missing something here? How can it be maintaining the state of this text box without ViewState on?
protected void Button1_Click(Object sender, EventArgs e)
{
int count = int.Parse(txtCount.Text);
count++;
txtCount.Text = count.ToString();
}
You're not using ViewState, you're using the form element itself. Here you read from the form element:
int count = int.Parse(txtCount.Text);
And here you write back to the form element:
txtCount.Text = count.ToString();
So the value is being stored in the input that's emitted to the HTML, and posted back as part of the HTTP form post.
If you want to examine this more closely, take a look at your browser's debugging tools. (FireBug, Chrome developer tools, IE developer tools, etc.) Look for the tab/panel/etc. where the network activity is captured. When you click your button, you'll want to watch the POST request that's being sent to the server.
Within that POST request is a series of key/value pairs. Every active form element on the page sends a key/value pair, and the entire viewstate is itself just a key/value pair from a hidden form element. (Where the value is a base-64 encoded string.) If the form element has the value in question, it's in the POST request and, thus, available server-side.
Remove the text from the text box between posts and it should stop counting. (Probably even throw an exception on int.Parse().
Both really good answers above. A good way to remember it (and to realize why ViewState is required at all) is that standard HTML form elements (such as asp:TextBox which renders as an HTML input) will be included in the POST, whereas non-standard HTML form elements (such as asp:Label which renders as an HTML span) won't be so you have to use them with ViewState.
Try switching your asp:TextBox to an asp:Label. You'll see that it breaks when you turn off ViewState, but it works with ViewState on. This is because HTML span values are not included in HTML form posts.
This is a pretty good article that discusses ViewState, even though it's pretty old: http://msdn.microsoft.com/en-us/library/ms972976.aspx
You are misunderstanding the difference between post back data (Form) and ViewState.
ViewState is actually a hidden field with encoded data that is used by ASP.NET to reconstruct certain parts of the page on postback, which is why you think you need it to be turned on for your text box example to work.
While you did not show your markup, I will pretend that this is what you have:
<asp:TextBox id="txtCount" runat="server" text="Enter a number here" />
Now the user types in a number at run-time (say 7 for argument's sake) and posts the page back to the server.
The server receives two pieces of data, the post back data (7) via the Form and ViewState, which is the hidden field.
In your example, the ViewState from the text box's point of view, contains the data Enter a number here, while the Form contains the value the user actually typed into the text box.
Note: As an aside, if you look into ASP.NET MVC you will find that ViewState does not even exist. After learning some of the ASP.NET WebForms constructs, I recommend you read Compatibility of ASP.NET Web Forms and ASP.NET MVC.
Related
I was reading about the difference between Disabled vs Read only and I learned that with a disabled field the data is not send back on postback.
However I have a webforms page with a textbox like below:
<asp:TextBox runat="server" ID="vPlantNameTB" Text="" Enabled="false"></asp:TextBox>
On page load I set the value of vPlantNameTB to some value. (instead of blank).
Since I have this TextBox disabled. I expect the value of the TextBox to be blank on post-back. But that is not the case...
I am able to get the value I set it to on page load during post-post back.
Is this behavior normal for web-forms?
In short:
yes, because the value is coming from your viewstate, not the form.
For a slightly more involved answer...
The form data that gets submitted (accessible through Request.Form) will be missing for vPlantNameTB as it is disabled and therefore not sent by the browser to the server.
Also included in the form data sent to the server is a hidden input (generated by the .Net engine) called __VIEWSTATE and it's value is a base64-encoded string that represents the current state of the page.
The page state automatically serialized out to the rendered web page and automatically deserialized when the form is posted (the deserialization process also handles re-association with your page controls which is why vPlantNameTB has a value again in your postback handler).
Scott Mitchell has a decent article about ViewState on MSDN which describes the process quite well.
I am using c# winforms and the WebBrowser Control from the toolbox to routinely navigate to a url and scrape its data. I have binded the event webbrowser_documentcomplete event and once in the event I am using the line
HtmlElement element= WebBrowser.Document.GetElementById("MainRadGrid_ClientState");
to get the element. Once I have the HtmlElement I was able to use the OuterText property to see what is in the element as so
element.OuterText.Trim()
My issue is that the code above was working even when the input type that I was looking at was set to 'hidden'. Things seem to have changed at this point and I am no longer able to get the outertext value. Can someone help me be able to get the outertext of the element or just get into the hidden element to gets its data
<input id="MainRadGrid_ClientState" name="MainRadGrid_ClientState" type="hidden" /> </div>
There might be difficulty depending on how tricky the page author was.
Input type='hidden' is one thing, but there might be other fields that are visually hidden with a CSS style or simply positioned off the screen. Finally, there may be values that are composed at the last second as the page is submitted, so you have to think deep about what values you want. Additionally, some fields may be opened, generated, or removed after a page is loaded, defeating simple fetch-the-page scraping.
But in the case of input tags of type hidden, an XSLT search can get you a list of those nodes pretty quickly.
You didn't specify how exactly you're scraping, but in general the answer to your question should be a resounding "YES." If you're scraping web content that means you're downloading the same content (HTML source, etc) that would get sent to any browser by the web server. In your scraper, you don't need to honor "hidden" styles or anything of the sort. To your code, it's just a really big string or a series of strings. You can parse them however you see fit.
I'm trying to build a very specific search page for a project and I'm having lot of trouble dealing with multiple postbacks invoked by dynamically-generated controls on a single page.
The page has to work like this:
There is a single checkbox, "Detailed search", that causes a postback on checking/unchecking.
When detailed search is not active, a simple grid with contents and buttons is displayed. Nothing special.
When detailed search is active, N checkboxes must be generated from some dynamic data, that represent the sections where you want the search to happen. Below the checkboxes, an AJAX-enabled tab control will appear, initially with no tab pages.
When checking one of the section checkboxes, a postback will occur. After the postback, data will be searched in the section selected by the user, then a new tab page containing a grid view of results and the name of the section will be added to the tab control. If the checkbox is unchecked, the tab page will disappear from the control, again, after a postback.
Now, the issue is that pretty much everything has to be generated dynamically, and that pretty much everything is connected to something else.
First issue: dealing with the "Detailed search" checkbox. Sounds easy, doesn't it? My initial idea was to set Page.Viewstate["DetailedSearchEnabled"] to true or false during the check/uncheck event handler, then create controls dynamically checking the value of DetailedSearchEnabled during Page_Load.
Nope. The postback event-handling happens between Page_Load and Page_LoadComplete. It would take an additional refresh for things to work as intended.
<< Then I'll just generate the controls on Page_LoadComplete! >>
Nope. Those controls need event handling as well, and if they're generated after Page_Load they will not be wired up correctly.
A possible solution would be generating everything in advance, on Page_Load, and only hiding/showing controls on Page_LoadComplete. But that is inefficient, and one important point of this search page is that only the minimum amount of controls should be generated.
The difficulty of this task seems to come from the way event wiring and the page life cycle work.
Surely there must be a better way of approaching this problem.
First issue: dealing with the "Detailed search" check box.
The correct approach (if you want to use page post-backs) is as follows:
In the CheckChanged event handler, save the value of the Checked property to ViewState["DetailedSearchEnabled"]. If the value is true, add the dynamic check boxes to the page. If the value is false, find and remove them.
Override LoadViewState. After calling base.LoadViewState, re-create the dynamic check boxes and wire up their events if ViewState["DetailedSearchEnabled"] is true. Note that neither Page_Load nor Page_LoadComplete is the appropriate place to do this.
Yes, you should create the dynamic check boxes at two points in the page life cycle. I recommend a helper method.
In general, your event handlers should add or remove just the dynamic controls (if any) affected by those particular events, but LoadViewState should re-create all dynamic controls that existed from the previous page request. You must store enough information in view state for LoadViewState to do so.
My answer to this other question demonstrates how to add and remove dynamic controls. You may want to use it as a reference.
Sounds to me like you should be using a CheckBoxList control to handle your dynamic checkboxes. You can add an remove items to the CheckBoxList during your post back and not have to worry about dynamically adding/removing actual controls/events to the form.
Here is a link to the msdn:
https://msdn.microsoft.com/en-us/library/14atsyf5(v=vs.85).aspx
Here is some sample code:
Protected void Button1_Click (object sender, System.EventArgs e)
{
CheckBoxList.Items.Add(new ListItem("TextValue1", "Value1"));
CheckBoxList.Items.Add(new ListItem("TextValue2", "Value2"));
}
If all else fails, you could still fall back on the quick-and-dirty old-fashioned ASP way.
Use Response.Write or <%...%> to generate your dynamic controls as plain old HTML (simple form fields, e.g. <input type="checkbox" name="foo" value="1" />).
Make sure you have a form field for every piece of information you may need after the postback(s). If necessary, use hidden form fields to 're-post' values across subsequent postbacks.
After postback, retrieve the values of the controls with the Request object.
Use those values to adjust the generation of controls as you see fit.
You should be able to do all of this in Page_Load. The advantage is total freedom. The disadvantage is total freedom to make a big mess of your aspx. So you may want to migrate all this dirty code out of your aspx, and into a custom-made control, which you can then add to your aspx.
When generating your own HTML, be careful not to introduce XSS vulnerabilities. Use HtmlEncode where necessary.
As you suggested yourself, there is a better way to tackle it.
If I was in the same situation, I would create web methods for interacting with the page, and use client side to do the UI. I'm currently working mostly with angular JS, although it does come with a learning curve. You could use ng-hide/ng-show to bind to the checkbox event to display the detailed search. When the n number of checkboxes needs to be displayed, you can then just fill them in with ng-repeat, for each of the items you need to display, after a check/uncheck you can dynamically populate new controls etc. through web method calls if extra data is needed.
Pure ASP postbacks are quite clunky from my experience, and not really suited for building a maintainable dynamic UI.
Instead of making so many postbacks, it would be better to use jquery and ajax calls to load the controls as needed and then attach events to it or you can even use UpdatePnael for that. Help Links:
https://www.simple-talk.com/dotnet/asp.net/ajax-basics-with-jquery-in-asp.net/
http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
I'm new to ASP.NET. I'm designing a user interface in Asp.NET and C# where the user can login and then launch an application. When using this application the user has to fill out a form that is 10 pages long.
So, I have used navigation menu and designed the interface in such a way where every page is different menu item and it is a static menu. The user fills out the details on the first page of the form and saves it and the data gets saved in the database.
The problem is he moves to the other page by clicking the menu tab; when he comes back to the first page by using the menu tab for that page all the filled in data is gone and he sees a blank page. I know that is how it works but I want it in such a way that in one sitting when he is filling out the data on the second page (after filling the data on first page) on reverting back to the first page he should be able to see the data that he had filled out.
What concept can I use? I'm not sure view state will be helpful in this scenario.
You should look into using the Session State variable for storing his information over the entire session. If the user is logged in you should think about storing his information that he enters in a database and having a Boolean state of "ApplicationFinished" to check if he has finished it or not. Otherwise I would have a call on each page to retrieve information from the database that has already been added, so that he can fill out information at different sittings or all at once.
http://msdn.microsoft.com/en-us/library/ms178581.aspx
Session State may be too long term for you, and if that is the case do some research on ViewState. There are a lot of different ways to tackle a problem like this. It all depends on which technology will fit your needs the best.
http://msdn.microsoft.com/en-us/library/ms972976.aspx
Also, if you're using a tab system think about using the AJAX tabs so that the data will remain on the forms even while tabbing through the different tabs.
http://www.dynamicdrive.com/dynamicindex17/ajaxtabscontent/
Well, if you are write the data on database, i guess the best (fast) workaround is to add a column named "completed" to the table the hold this informations. If the flag "completed" is not setted to 1, you load the database information and fills the page controls.
When you create a new record in the database, get the ID of the record and set it on Session. If the user gets back to the first page (previous page), you can recover the information ID and load the data.
As long as you are learning new things... add jquery to the list and leverage the JQuery Wizard Plug In. It will allow you to integrate your "10 page form" into a single unit, which can then be sub divided, routed and managed more easily. You can leverage AJAX to save each step, while offering built in navigation and validation methods.
I would suggest that you switch to using client-side javascript to control your tabs. That way your form data stays in the fields when you switch back and forth between tabs. You can use javascript buttons to guide the user from tab to tab.
I've done this using JQuery. I actually had 150 fields that needed to be captured (they were all required). I group like data on different tabs and then had buttons ('< Previous', 'Next >') which would activate different tabs.
When they are done, then display the 'Save' button.
This not be what you are looking for, but if your problem is that you want all of the input of a previously filled page to show up when a user navigates back to it, and you have already saved all that information, then you can try something like this:
HTML
<input type="text" id="yourID" name = "yourName" value = "<%=data%>"/>
Then all you need to do is set data to public in the code behind. Then to get the value for data just make a call to your database.
Make sure that you make data empty on the init call public string data = ""; or whatever type it is. This way if there is no info, then it will be blank, and if there is saved info, then it will be filled in.
You can also attempt to pass all the data through params in the url like so:
C#
Response.Redirect("webpage.aspx?data=" + data + "&data1=" + data1);
Or though javascript:
window.location = ("webpage.aspx?data=" + data + "&data1=" + data1);
To get the request do this:
if (Request.Params.AllKeys.Contains("data"))
{
data = Request.Params["data"];
}
This way is less ideal though if there is a lot of data being passed.
When page is to be posted back to the server, browser collects the current values of each control and pastes it together into a string. This postback data is then sent back to the server via HTTP POST.
Q1 - Besides control’s Text attributes and SelectedIndexchanged ( thus besides user input data), are there other attributes/values of a control which are saved by a browser as postback data?
Q2 - In case of GridView, which values are saved by a browser on a postback? Only those in a row which the user chooses to edit?
byte
The values of textarea, select, input and button fields are returned in the post. Each value is a key-value pair where the key is the name property of the element.
I think that I have got all the elements that include data in the post:
textarea: The value propery is included, i.e. what's typed in the textarea.
select: The value property of the selected option is included. If the selected option doesn't have a value property specified, the text of the option is used.
input type="text": The value property is included, i.e. what's typed in the input field.
input type="password": The value property is included, i.e. what's typed in the input field.
input type="submit": If the button was used to send the form, the value property is included, i.e. the text of the button.
input type="image": If the button was used to send the form, the coordinates of the mouse click within the image is sent in the post. Names for the x and y coordinates are created by adding ".x" and ".y" to the name of the element.
input type="checkbox": If the checkbox is checked, the value property is included. If the element has no value property specified, the value "on" is used.
input type="radio": The value property is included from the selected item from each group. (A group is all radio buttons with the same name.)
input type="file": The content of the selected file is included, along with the original file path (or only the file name, depending on browser and security settings).
input type="hidden": The value property is included.
button: If the button was used to send the form, the innerText property is included, i.e. the text of the button with any html markup removed.
A TextBox control is rendered either as an input type="text", an input type="password" or a textarea, depending on the TextMode property. A DropDownList control is rendered as a select element. A Button control is rendered as an input type="submit". A CheckBox control is rendered as an input type="checkbox". And so on... check the rendered html code to see what the actual html elements rendered are.
A GridView only includes any data in the post if it contains any editable form fields, or if it causes a postback (by navigating in the list for example). When doing a postback there is some information stored in a pair of hidden fields, so any control that causes a postback but doesn't send any form data by itself (like a LinkButton for example) does include information about what caused the postback.
Controls may also put data in the ViewState, which is kept in a hidden field in the form. This is also included in the post, but it's just sent to the browser and back again without being changed by the browser.
I'm not asp programmer, so i can't give exact answer, but I'd suggest you to use firefox with addons Live Http Headers, and Firebug (console section).
With this setup you will be able to see exact data sended by browser to your server.
You'd probably want to use a ViewState decoder as well. You can get them in Browser extensions, and use ones off the web. Scott Gu recommends one here: http://weblogs.asp.net/scottgu/archive/2003/02/16/2495.aspx. The ViewState should tell you all you need to know of persisted server properties.