Populate checklist in another webform - asp.net

I have checklist with multiple selections now the user will preview the form in another webform after press preview button the issue here that the checklist not populated in the other form with all selections and only item selected
In first form I wrote the below code:
Dim Fruit as String = ChkFruit.SelectedValue
Redirect.response(home.aspx?"fruit=" + Fruit)
In second form I wrote the below code:
ChkFruit1.Selectedvalue = QueryString("Fruit")

Well in your example posted code, if we are to ONLY PASS one selected value, then what you have is a good start.
However, VERY NEW BIG LARGE MASSIVE different problem is now we allow "many" selections in the check box list. So with a NEW HUGE LARGE DIFFERENT kind of question and problem?
Then we will as a result need a VERY different solution. The large new big massive problem here is how to pass 1 value, or 15 choices? This of course as noted is quite a more difficult problem and challenge.
For passing a "list" or "array" of a whole bunch of possbile choices, then I suggest we do NOT use the URL parmaters (query parms in the URL).
So, what we need here is to build up some "list" of choices from the check box list, and pass that to the 2nd page. Now there are more ways to do this then there are flavors of ice cream, and we have a LOT of choices.
However, I going to suggest creating a List of chocies, and we pass that to the 2nd page we jump to.
So, our markup and button in the first page can look like this:
<asp:CheckBoxList ID="CheckBoxList1" runat="server">
<asp:ListItem>Apple</asp:ListItem>
<asp:ListItem>Grapes</asp:ListItem>
<asp:ListItem>Bananna</asp:ListItem>
<asp:ListItem>Cherry</asp:ListItem>
</asp:CheckBoxList>
<br />
<br />
<asp:Button ID="Button2" runat="server" Text="Submit" Width="158px" />
Ok, above is quite nice - not complex.
Now, for our button code? We need to build up, get/grab/obtain the list of selected values - that's what we will pass to the 2nd page.
So, above looks like this:
So, now our button/submit code on this web page:
Protected Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim MyCheckList As List(Of String) = New List(Of String)
For Each MyItem As ListItem In CheckBoxList1.Items
If MyItem.Selected Then
MyCheckList.Add(MyItem.Value)
End If
Next
Session("MyCheckList") = MyCheckList
Response.Redirect("Test2.aspx")
End Sub
So, in place of "url messay parmaters"?
We create a List type variable (they are somewhat the same as an array()
We then add all selected items to that new list
We then stuff/place the new list into Session()
We then jump to the 2nd web page with the Reponse.Redirect
Ok, so now, on the target web page, we have to get that list we passed.
Now, on the 2nd page, the code ONLY needs that list.
but, lets assume that we have the same check box list on that 2nd page - and we want to fill out - show/display/have the Check box list show the same choices.
WHAT IS IMPORTANT here is how we are free to use the "list" we passed to that 2nd page. I can do anything with that nice list , but we have this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim MyCheckList As List(Of String) = Session("MyCheckList")
' display the list of passed check box values
For Each MySelected As String In MyCheckList
Debug.Print(MySelected)
Next
' or say fill out a check box list we have on this new page -
' process EACH check box list item
' check if in our list - if yes, then check box/select it
For Each MyItem As ListItem In CheckBoxList1.Items
MyItem.Selected = MyCheckList.Contains(MyItem.Value)
Next
End If
End Sub
So, in this 2nd page, we demonstrate two examples.
First part of code example - JUST display the list of previous selections. You are thus now free to for each loop and process the check box list of selections.
Second part of code example. We actually take that list and check box a whole new check box list we have on the 2nd target page. Now, I doubt the check box list would be the same and duplicated on that 2nd page, but this code example shows how we could display the check box list "again" on the 2nd new target page.
And the code also demonstrates how to loop/process the list of selections, which is really at a the end of the day the most valuable part of this example code
So, in our 2nd page, if we have this markup:
<asp:CheckBoxList ID="CheckBoxList1" runat="server">
<asp:ListItem>Apple</asp:ListItem>
<asp:ListItem>Grapes</asp:ListItem>
<asp:ListItem>Bananna</asp:ListItem>
<asp:ListItem>Cherry</asp:ListItem>
</asp:CheckBoxList>
<br />
Then we would see this:
So when you have MORE then just one value to pass to the next page?
Then you can use session() in place of messy and difficult to use URL "parmaters". And those URL paramters are not all that great for passing "many" values like this new problem required.
If we were to only pass ONE value, and ONE selection, then the URL parmaters would be ok to use. But now since we need to pass "many" values then using session() to pass that information to the 2nd target page becomes a whole lot less work and efforts on your part.

Related

How to store User ID of Logged in User in ASP.net VB.net

I am trying to store the UserId or/and UserName of the user. This is used to record user ID against any changes they make to data, insert, updates and deletes etc.
I have created a module and in that module added a Public variable vUserID. Here Lei the problem.
User A logs in and his id vUserID = 'A'. Another user (User B), the other side of the world logs in User 'B' and that vUserID then = 'B'. So now anything User A does gets recorded as he is User 'B', or that is how I understand it, as a Public variable will be accessible from anyone who logs in.
I understand the problem, or I think I do, please correct me if not, but what I am struggling with is the solution. I have tried to use a Protected and Protected Friend but these do not seem to be accessible throughout the program(website) when a user is logged in.
For completeness I get the User details by the following code which seems to work fine:
Dim mu As System.Web.Security.MembershipUser = System.Web.Security.Membership.GetUser()
Module1.vUserID = mu.ProviderUserKey.ToString()
Well, the issue is that you have ONE web server.
And the web server (for the most part) will process ONE web page at a time.
So, when a user clicks a button on a web page, before they click on a button, the web page is sitting on their desktop computer. it is NOT on the web server.
(and more important, all the code variables (code behind) are GONE! They do not exist yet!).
So, think of a web server as ONE computer. And say 5 users are going to use YOUR computer to edit a word document.
The first user sits down, opens word document, types in some text, and then closes word!
The next user sits down, opens word document, types in some text, and then closes word!
Remember, you don't have a computer for each user, but have ONE computer - the web server, and it has to "some how" service all users.
So, all the web server can do, is "process" a web page, one that is sitting on each end users computer (running the browser).
So, you have this:
And you do NOT have this:
In other words, the web page is NOT sitting "loaded" on the web server. it is out of scope.
Think of when you call a sub, use some variables in that sub, when you return/exit from that sub, ALL VARIABLES are gone!! (out of scope).
You MUST think of web pages like that sub - when you exit, they are gone, don't exist anymore.
So, you don't have this:
the web page is NOT in memory on the server, it is NOT loaded.
Thus, you don't have this either:
So, with above in mind, lets create a super simple web page to show this:
We will have a simple string variable, called MyZooVar.
We will put a button and label on the web page to set this varible.
we will then put another button on the form to show the value of the variable.
So, this:
<asp:Button ID="cmdSetZoo" runat="server" Text="set varable to zoo" />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<br />
<br />
<asp:Button ID="cmdGetZoo" runat="server" Text="get value of var zoo" />
<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
and the code behind is this:
Public MyZooVar As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub cmdSetZoo_Click(sender As Object, e As EventArgs) Handles cmdSetZoo.Click
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
End Sub
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Note VERY close in above, the MyZooVar - we defined it at the top of module, so all buttons and code can use that MyZooVar.
So, we will click the first button, this code:
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
And then we have a 2nd button, and this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
what will happen when we run?
We see this:
So, in above, this is what occured:
we START with this:
You click a button, YOUR web page (not the 20 other users) is sent to the web server.
the page travels up to server,
You now have this:
Now and THEN your code behind runs. When done, your code behind MUST finish, else the page stays stuck up on the server side. When done, the whole page page makes the trip down back to the browser. And THEN the page is re-displayed and THEN any js code can run.
So when done? Your page makes the trip back down to the browser like this:
Note on the server side? Your web code (and MORE important variables) and EVERYTHING is disposed.
We now have this again:
Note HOW THE WEB PAGE IS NOT on the web server!!!!
the web server is waiting now for ANY post-back of a web page from ANY user, not just you the one user!!!!
So, now that I clicked the button to set the variable MyZooVar?
What happens if I click on the 2nd button, this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Well, the whole process starts over again!!!
We will find that the variable MyZooVar is gone, out of scope, and does not have our value!!!
So, the "term" for the above is what we call "state-less".
In other words, your code behind can't assume, hope, pray that the varibles in the web page will persit.
Now you can hope/pray/try to put some variables in a global code module, but as you found out, they are shared amoung all users. But WORSE, the web server will often say, hey, I don't need that memory, I'm just sitting here waiting for someone to click a button and send me THEIR web page.
As a result, not only will you find those so called global variables in that public code module shared between all users, you find that they OFTEN will not even stay in memory all that long. So, your code "sort of works" to try and use some global variables, but you find they OFTEN go out of scope, and will not even stay in memory.
So, web based software is VERY different then desktop software.
One big difference is that for desktop software, each user, each workstation has their OWN copy of the code.
With a web server, you have ONE web server, ONE computer, and it sole job is to process incoming web pages (that occurs due to a page post-back).
the process of a simple button click, whole web page travel up to web server, page is processed, and then whole page is send back to user? We call this a round trip.
So, you really do not have global variables in a web based application. You can try to use some, but as noted, they will be the same for all users, but MUCH worse, is they tend to go out of scope, and can be disposed (go away) at any old time - you have no control over this, and thus you simple can't adopt global variables in a web based system - they are "off limits", and the above so called round tripping, and that you have ONE computer and ONE web site that somehow has to service many users - not just you!!
So, in your case?
Why do you need to store/save the user ID in some variable?
You "already" are able to get the user id with the code you shared:
You can use this:
dim UserID as integer
UserID = Membership.GetUser().ProviderUserKey
So, since you can get the "user" id any old time with above ProviderUserKey, then no need exists to try and "save" the user id into some global variable, but as you found out, you can't rely, or even design your software based around a concept of global variables.
However, you can if you wish place values into what we call "session".
Session is in effect global to the ONE user, and it DOES persist between those so called round trips.
so, you could do this:
Session("MyUserID") = Membership.GetUser().ProviderUserKey
And then in code, any time, use
Session("MyUserID") to get the user "id"
But, since you have ProviderUserKey, then even session() should not be required here.

dropdownlist selectedvalue doesnt change

I have this dropdownlist, this one load with the data that I get from a store procedure, as you can see the load is correct, but when I change the selected value in the debug the selected value doesnt change, it stays in the first loaded value, which in this case is 1. What can I do?
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim adaptador As New SqlDataAdapter
Dim datos As New DataTable
Dim ord As SqlDataReader
Conexiones.AbrirConexion()
Conexiones.Cnn.Open()
Dim cmd As SqlCommand = New SqlCommand("sp_devolver_empresas", Conexiones.Cnn)
cmd.CommandType = CommandType.StoredProcedure
ord = cmd.ExecuteReader
datos.Load(ord)
cbEmpresas.DataSource = datos
cbEmpresas.DataTextField = "Nombre"
cbEmpresas.DataValueField = "Identificador"
cbEmpresas.DataBind()
Conexiones.Cnn.Close()
End Sub
For EVERY web page that you build and write to the end of time?
You MUST always put the load and setup code inside of a check for post back.
every button, every drop down list, and EVERY time you click on a button or do anything, the page load will ALWAYS fire and run. Thus if you change a value, you will lose that value since the page setup and loading of say control (in this case your dropdown list) will fire EACH time - thus overwriteing.
Out of the last 100's of web pages, the FIRST thing I write is the check for postback.
So, your code should look like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData
End If
End Sub
Sub LoadData()
Dim datos = New DataTable
Using onexiones.Cnn
Using cmd As SqlCommand = New SqlCommand("sp_devolver_empresas", onexiones.Cnn)
cmd.CommandType = CommandType.StoredProcedure
onexiones.Cnn.Open()
datos.Load(cmd.ExecuteReader())
End Using
End Using
cbEmpresas.DataTextField = "Nombre"
cbEmpresas.DataValueField = "Identificador"
cbEmpresas.DataSource = datos
cbEmpresas.DataBind()
End Sub
So, only on the "real" first page load do you want to load up your grids, dropdowns etc. Remember, even a simple button dropped on to the page, and you have a click event? (the page load event fires each time - and every time). So once again, you need the IsPostBack test - and I am quite pressed to find any of my web pages that does not have this all important code stub in the on-load event.
So, remember the above rule - always setup your setup code to run on first time - not every time a button or anything else occurs on the web page. So, page load (unlike desktop) fires each and every time you do ANY operations on that page.
Also, note how I setup the data text, and value field BEFORE we give the drop down list a data source. In fact, I would suggest you put the data text, and data value field in the markup and NOT code (since then multiple different code routines can use that setting - not hard coded in code).
eg do this:
<asp:DropDownList ID="cbEmpresas" runat="server"
DataTextField = "Nombre"
DataValueField = "Identificador" >
</asp:DropDownList>
So, now your code becomes :
cbEmpresas.DataSource = datos
cbEmpresas.DataBind()
I suppsoe some out of habt like to set the text + data settings for the dropdown list in code, but then again, in code you might want more then one palce that loads up the combo box - and thus you now have multiple places for those two settings. And better yet, you can even use the property sheet during design time to make the settings. (this is a "minor" issue, but I just perfer those settings in the markup as opposed to writing them in code for text/data settings).
At the end of the day? Just remember that golden rule: have that "test" for postback so you have a REAL first page load event code inside that if/then. In fact, you really can't even build a fnctional working web page if you break this rule. As noted, I count about 1-2 of my web pages out of 100's tht don't have that not postback code stub. It is quite much as important say compared to humans having to breathe air to function.
And why such a long post about this simple issue? Well on a near daily bases, both c# and vb.net questions are posted about how some combo box, grid view or just about anything else is "broken" and not working. And the answer 9 out of 10 times?
The developer forgot to use a Not IsPostBack code stub in their page load code.
If I was teaching asp.net, this would be the first lesson - ALWAYS use and consider the requirement for the Not IsPost back stub. You need that in 99% of your web pages. Or at the very least in ANY web page in which you have code to run on page load to setup grids, dropdowns, repeaters - don't matter what, you will NEED that code stub. So important, I often wonder if they should have create a even called first page load? It would have eliminated the daily posts and questions on SO that fail as a result of not heeding the above simple advice.
Edit: Now how to get selected value in code
Ok, now that we fixed up the code to setup the dropdown list, we now want to get in our code the value when the user makes a choice in the dropdown list.
You of course have code to fill the dropdown, BUT we also have to set autopostback = true for this dropdown.
So, say code to load:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData
End If
End Sub
Sub LoadData()
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL As String =
"SELECT ID, HotelName from tblHotels ORDER BY HotelName"
Using cmdSQL As SqlCommand = New SqlCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
cboHotels.DataSource = rstData
cboHotels.DataBind()
End Using
End Using
End Sub
And now the selected index changed event:
so, our debug output would then look like:
output:
combo selected value = 82
combo selected Text = Canadian Rocky Mountain Resorts
And as noted, make sure you set auto-post back true in the property sheet, or in the markup. The combo box for above in markup thus is this:
<asp:DropDownList ID="cboHotels" runat="server"
DataValueField="ID"
DataTextField="HotelName" AutoPostBack="True">
</asp:DropDownList>

A populated Table returns no rows

In a web application I am writing, I populate a HTML table with a button press; after the table is populated, then the user can click another button to export the table in a CSV file.
The issue is that, while the table is properly populated at he first button pressing, it appears to be empty when the application query it at the second button press.
A few code to explain the issue:
the HTML in ASPX page
<asp:Button ID="BTNPopulate" runat="server" Text="Populate" />
<table id="Table1" style="border-width: 1px; border-color: Black; padding: 5px" cellspacing="0" runat="server" />
<asp:Button ID="BTNExport" runat="server" Text="Export" />
now the first button
Protected Sub BTNTest_Click(sender As Object, e As EventArgs) Handles BTNTest.Click
Dim row As HtmlTableRow
Dim cell As HtmlTableCell
row = New HtmlTableRow()
row.BgColor = "Gray"
cell = New HtmlTableCell()
cell.Controls.Add(New LiteralControl("Test cell"))
row.Cells.Add(cell)
Table1.Rows.Add(row)
end sub
and the table is properly populated.
I was unable to obtain any info from it and in fact if I call the .Rows.Count method anyway in the second button click code-behind
Protected Sub BTNExport_Click(sender As Object, e As EventArgs) Handles BTNExport.Click
Response.ContentType = "text/csv"
Response.AddHeader("Content-Disposition", "attachment; filename='PFExport.csv'")
CSVBuilder.Append(Table1.Rows.Count)
Response.Write(CSVBuilder.ToString)
Response.Flush()
Response.End()
End Sub
the result in the file is always 0.
On the other hand, if I call the same .Rows.Count property at the end of the populate part of the code, it properly returns the result.
I tried to use the ASPTable instead of the HTMLTable, but the issue is the same.
I assume I am missing something basic here, not sure what.
ASP.NET (or anything on the web ftm) works over HTTP. HTTP is stateless. That means that whatever you do in one request is completely lost when you make a new request.
ASp.NET webforms tries to hide this from you by using something called ViewState. It's essentially a hidden field which it sends back and forth to repopulate your page every time you do a roundtrip. When the server reconstructs the page, it reads the info from the ViewState that was sent in and rebuilds the page from those values.
The problem you're having is that the page is not repopulated yet when your click-handler is triggered. There's two ways to fix this.
(preferred): Instead of reading the data from the table in the UI, just look it up in the database again.
Set a flag on the page in the click-handler and populate the CSV on the PreRender-event.
As explained by Kenneth, my error to think the information to be preserved between requests, while HTTP is stateless.
So I investigate this from a different perspecitve and I ended up using View State to store the information locally and retrieve it to generate the CSV at the Export button press.
So, to store the info I use
ViewState("TableResultsState") = CSVBuilder.ToString
immediately after the table is populated.
For the export button, I do
With Response
.ContentType = "text/csv"
.AddHeader("Content-Disposition", "attachment; filename='PFExport.csv'")
.Write(ViewState("TableResultsState").ToString)
.Flush()
.End()
End With
As the text quantity is limited, from my research I understand this should not have adverse effects.
Again, thanks to Kenneth for pointing out my very basic misunderstanding.

IIF statement to determine visibility of ImageButton in GridView not evaluating properly

I have a GridView that displays user info along with two template fields with imagebuttons. One is to open up a detailsview to edit user information. The other is to edit the user's password.
In my Code Behind, I have 3 IIf statements that check for certain criteria. Based on certain combinations of this criteria, I want the ImageButtons to either show/not show appropriately.
Here is my code behind:
Protected Sub gvUsers_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvUsers.RowDataBound
Dim isProvisioned As Boolean
Dim acceptedToS As Boolean
Dim isSuspended As Boolean
'hide password change option for users that have not yet been provisioned or have not accepted ToS Agreement or have been suspended'
If e.Row.RowType = DataControlRowType.DataRow And _
DirectCast(sender, GridView).EditIndex <> e.Row.DataItemIndex Then
isProvisioned = IIf(String.IsNullOrEmpty(e.Row.DataItem(GUser.columns.DATEADDED).ToString), False, True)
acceptedToS = IIf(String.IsNullOrEmpty(e.Row.DataItem(GUser.columns.TOSTIMESTAMP).ToString), False, True)
isSuspended = IIf(String.IsNullOrEmpty(e.Row.DataItem(GUser.columns.SUSPENDDATE).ToString), False, True)
Dim btnAdminEdit As ImageButton = DirectCast(e.Row.FindControl("btnAdminEdit"), ImageButton)
Dim btnAdminSelect As ImageButton = DirectCast(e.Row.FindControl("btnAdminSelect"), ImageButton)
btnAdminEdit.Visible = Not (isSuspended) AndAlso isProvisioned AndAlso acceptedToS
btnAdminSelect.Visible = isProvisioned
Else
gvUsers.EmptyDataText = "No records found matching specified criteria."
End If
End Sub
I don't know what changed because this code DID work at one point. However, when I test the page, both imagebuttons seem to show up no matter what. While debugging, I also saw that it seemed to "evaluate" each row the same way. As in, for each row that went through my IIf statements, it always returned the same values, even if it was not true.
I have a hunch that it's taking the first row's values and reusing it some how, or evaluating the same row; that's why it always returns the same values and always shows the imagebuttons, even though they are not supposed to be visible according to my IIf statements.
Any help is greatly appreciated as I'm not too sure how to resolve it from here.
Well, after delving a little deeper, I found what was causing the problem.
The last change I made before seeing this problem was the addition of another column to be displayed in the GridView. This distorted the index of the columns so my IIF statements were not checking the correct datafields and thus, were evaluating incorrectly.
So, the code behind I posted does work and luckily proved that I wasn't going crazy. The logic is correct!
Thanks to those who took time to glance at this question!

postback in asp doesn't refresh control value

I have a div(runat=server) that contain repeater,this repeater is getting is value from datatable
when the datatable is empty I do this line of code in asp .net function
divname.innerHTML="<img src="...>"
on this page there is also a asp:button that fill the datatable with values.
when pressing the button ,the above line isn't excute,the page offcourse is doing postback, but the div content isn't changing back to his original value(the repeater).
What do I have to do in the postback in order to force the div to get his original values?
This is code example:
sub page_load(..
if ispostback=false then
run_div()
end if
end sub
sub run_div()
if datatable.Rows.Count=0 then
divname.innerHTML="<img src="...>"
end if
end sub
sub filldata(....
fill datatable
repeater.datasource=...
repeater.databind
run_div()
end sub
html look like this
<div runat=servver id=divname><asp:repeater>.....
<asp:button onclick="filldata">
Thanks for any help
Assuming the variable named datatable is a System.Data.DataTable, remember that it only exists and had data in the context of a sibgle run of the page lifecycle. if the page is re-generated (whether it's via a postback or an initial load of the page) the DataTable is empty until it's loaded.
However, the Repeater object is stored in teh ViewState. IT will have values on a postback if there were rows on the previous load.
Instead of looking at the number of rows in the table, you should be looking at the Repteater.Items.Count.
If repeater.Items.Count = 0 Then
divname.innerHTML="<img src="...>"
Else
...
End If

Resources