Asp.net session variables get mixed up - asp.net

I have a user control that uses an UpdatePanel. The controls is essentially a table with a Button. When the user clicks the Button, a modal popup opens that allows them to select some value. Data for the table (which uses a Repeater as its DataSource) is stored in a session variable between partial postbacks (when the UpdatePanel fires) as a list of objects. Everything works fine if I have just one control but if I use this control in the same page more than once, the list of objects in the session variables get combined and are not separated for each control. I thought this might be because the session variable names are not unique, so anywhere I call or use the variable, I do it like this:
Dim sessionName as string = Me.UniqueID & "_" & "userNotificationDS"
Session(sessionName) = myListOfObjects
But this has not changed the outcome. Anyone know what I might be doing wrong here? If you believe the full code would be helpful, let me know.
Control Server Code:
Protected Sub delete_click(ByVal sender As Object, ByVal e As EventArgs)
Dim btn As LinkButton = CType(sender, LinkButton)
Dim ds As New List(Of myObject)
sessionName = Me.UniqueID & "_" & "myDataSet"
ds = Session(sessionName.ToString)
Dim id As String = btn.CommandArgument
ds.RemoveAll(Function(userNotification) userNotification.User.NetworkID.Equals(id))
Session(sessionName.ToString) = ds
bindData(ds)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
sessionName = Me.UniqueID & "_" & "myDataSet"
If (Session(sessionName.ToString) IsNot Nothing) Then
bindData(Session(sessionName.ToString))
End If
End Sub
Private Function buildPagedSet(ByVal userNotification As List(Of myObject)) As PagedDataSource
Dim ps As PagedDataSource = New PagedDataSource()
ps.DataSource = userNotification
ps.AllowPaging = True
ps.PageSize = numRows
Return ps
End Function
Public Sub bindData(ByVal commentList As List(Of myObject))
sessionName = Me.UniqueID & "_" & "myDataSet"
Dim currentPage As Integer = 0
Dim ps As PagedDataSource
Dim numLable As Label
Dim denomLable As Label
Dim curPage As Integer = 1
Dim totalPage As Integer = 0
If (Not myObject Is Nothing) Then
Try
ps = buildPagedSet(commentList)
totalPage = ps.PageCount
Session(sessionName.ToString) = commentList
rowTotal = ps.Count
'for paging
If Not (ViewState(Me.UniqueID & "_Page") Is Nothing) Then
currentPage = Convert.ToInt32(ViewState(Me.UniqueID & "_Page"))
Else
ViewState(Me.UniqueID & "_Page") = 1
currentPage = 1
End If
If (currentPage > 0 And currentPage <= ps.PageCount) Then
ps.CurrentPageIndex = currentPage - 1
Me.dataRepeateUsers.DataSource = ps
Me.dataRepeateUsers.DataBind()
ElseIf (currentPage >= ps.PageCount) Then
ViewState(Me.UniqueID & "_Page") = Convert.ToInt32(ViewState(Me.UniqueID & "_Page")) - 1
ElseIf (currentPage <= 0) Then
ViewState(Me.UniqueID & "_Page") = Convert.ToInt32(ViewState(Me.UniqueID & "_Page")) + 1
Else
End If
Catch ex As Exception
Throw
End Try
Else
Dim emptySet As New List(Of myObject)
Me.dataRepeateUsers.DataSource = emptySet
Me.dataRepeateUsers.DataBind()
End If
End Sub
The control is instantiated like this:
Me.notifier1.bindData(notificationList)
In this example, when the user deletes something from notifier1 ( the delete_click event) the object is removed from the list and it gets added back to the session. If anything causes notifier2's update panel to fire, it will display the same exact data as notifier1

My hunch is your are storing your myListOfObjects in the session but reusing that object somwhere and modifying it and storing it in the Session again with a different key. It is probably still the same object being stored for both Session keys.
You can do a simple test by storing an object in the Session with two differnt keys. Then pull it out using the first key and modify that object and don't reassign it back to the Session (not needed anyways). Now pull the other object out from the second key and look at it. It will match the modifications because the object is the same object just stored under two diffeent keys in the Session.

If Kelsey's hunch is correct, you could store each of the instances of myListOfObjects in a Dictionary(Of String, myListOfObjectsType) and use the .UniqueID as the key (the Of String part).

Related

How to pass variables between 2 procedures in VB.NET (Web Application)

I am basically creating textboxes dynamically for adding a test to the database. The number of textboxes to be created was passed as a query string from the web page before. Here is the code:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim NoOfQuestions As Integer = Request.QueryString("NoOfQuestions")
Dim txtboxQ(NoOfQuestions - 1) As TextBox
Dim txtboxA(NoOfQuestions - 1) As TextBox
For i = 1 To NoOfQuestions
Placeholder.Controls.Add(New LiteralControl("<span>Question " & i & "</span>"))
Placeholder.Controls.Add(txtboxQ(i - 1))
Placeholder.Controls.Add(New LiteralControl("</br>"))
Placeholder.Controls.Add(New LiteralControl("<span>Correct Answer</span>"))
Placeholder.Controls.Add(txtboxA(i - 1))
Placeholder.Controls.Add(New LiteralControl("</br>"))
Next
End Sub
Protected Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
'Some SQL stuff
Response.Redirect("HomePage.aspx")
End Sub
I am trying to pass both the textbox arrays that were declared in Page_Load to the other sub btnSubmit_Click. I tried to pass it as parameter like this but it didn't seem to work:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs, ByRef txtboxQ() As TextBox, ByRef txtboxA As TextBox) Handles btnSubmit.Click
'Some SQL stuff
Response.Redirect("HomePage.aspx")
End Sub
Quiet lost here, thanks for your help!
You can pass the textboxes content as output parameters in the querystring, as you did with your input parameter NoOfQuestions
Dim sQuery As String
For i = 1 To NoOfQuestions
sQuery &= "Question" & i & " & txtboxQ(i - 1).Text & "Answer" & i & "=" & txtboxA(i - 1).Text
Next i
Response.Redirect("HomePage.aspx?" & sQuery)
And the parse the query string in the Page Load event of HomePage.aspx. You can also pass the values as session variables
Session("Question1") = txtboxQ(i - 1).Text
...
And then
Dim question1 As String = Session("Question1")
....
Declare a list of text boxes on page level
Public textQ = New List(Of TextBox)
Public textA = New List(Of TextBox)
Change your code to following
For i = 1 To NoOfQuestions
Placeholder.Controls.Add(New LiteralControl("<span>Question " & i & "</span>"))
Dim txtboxq = New TextBox()
txtboxq.ID = "txtq_" & i
Placeholder.Controls.Add(txtboxq)
textQ.Add(txtboxq)
Placeholder.Controls.Add(New LiteralControl("</br>"))
Placeholder.Controls.Add(New LiteralControl("<span>Correct Answer</span>"))
Dim txtboxa = New TextBox()
txtboxa.ID = "txta_" & i
Placeholder.Controls.Add(txtboxa)
textA.Add(txtboxa)
Placeholder.Controls.Add(txtboxa)
Placeholder.Controls.Add(New LiteralControl("</br>"))
Next
then access the values in the list for any purpose, may be print values on submit or whatever..
eg:
For Each tb As TextBox In Me.textQ
Me.label1.Text = Me.label1.Text & tb.Text.Trim()
Next
Wondering why would you want to pass the variables like that when you can declare the variables in page level and access it from any method/function. Any special requirement?
what you are trying to do here is unclear as well.
You can use global variable inside you class, and place it below your class code. And if you want to use it, you just call that global variable.

ASP.NET Control added to Placeholder lost values right after adding

Working over 5 hours on the following problem:
Private Sub ModulEdit_PreInit(sender As Object, e As EventArgs) Handles Me.PreInit
Dim modulid As Integer = 1
loadeditors(modulid)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Public Sub loadeditors(modulID As Integer)
PlaceHolder1.Controls.Clear()
Using dbContext As New EntitiesModel()
Dim mps As List(Of ef.Modulparameter) = dbContext.Modulparameters.Where(Function(c) c.ModulID = modulID).ToList
Dim mmid As Int16
If EditMode.Checked = True Then
mmid = RadComboBox3.SelectedValue
End If
Dim mp As ef.Modulparameter
For Each mp In mps
Dim lbl As New Label
lbl.Text = "<BR>" & mp.Name & "<BR>"
PlaceHolder1.Controls.Add(lbl)
Select Case mp.Editor.Name
Case "textbox1line"
Dim con As New TextBox
con.ID = mp.ID
If EditMode.Checked = True Then
Using dbContext2 As New EntitiesModel
Try
Dim mpa As ef.Menu_modul_paramvalue = dbContext2.Menu_modul_paramvalues.Where(Function(c) c.ModulparameterID = mp.ID And c.Menu_modulID = mmid).First
con.Text = mpa.Valuestring
Catch ex As Exception
con.Text = "AAAA"
End Try
End Using
End If
PlaceHolder1.Controls.Add(con)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(Panel1, con, Nothing)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(con, con, Nothing)
Case "radeditor"
Dim con As New RadEditor
con.ID = mp.ID
con.ToolsFile = "\admin\controls\ToolsFile.xml"
'con.CssFiles.Add("\Content\frenzy\css\frenzy-orange.css")
If EditMode.Checked = True Then
Using dbContext2 As New EntitiesModel
Try
Dim mpa As ef.Menu_modul_paramvalue = dbContext2.Menu_modul_paramvalues.Where(Function(c) c.ModulparameterID = mp.ID And c.Menu_modulID = mmid).First
con.Content = mpa.Valuestring
Catch ex As Exception
con.Content = "BBBB"
End Try
End Using
End If
PlaceHolder1.Controls.Add(con)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(Panel1, con, Nothing)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(con, con, Nothing)
End Select
Next
End Using
End Sub
I add the control dynamicly, calling the codepart above in pre_init (tryed in load and init too with same result)
The value (text) for the control is there until that line PlaceHolder1.Controls.Add(con)
After the con.text is empty.
The control is added after, but with no value.
Strange, that in the same proc i add another control (label), where the text value is on the page after.
Adding additional info:
the control value (text or content), when debugging the LoadEditors), is allways correctly set. But then on the page both (textbox and radeditor) are empty
The routing is called from pre init, as described in a lot of related posts.
You are calling loadeditors in ModulEdit_Init. Shouldn't this be LoadControls ?
I fixed it myself:
Adding "con.ViewStateMode = System.Web.UI.ViewStateMode.Disabled" before adding control to placeholder
Calling "loadeditors()" in RadComboBox3 too
much probably the problem was, that i loaded editors in page-load or init, which got the correct values, but then the RadComboBox3.SelectedIndexChanged event was called, which overwrote the values somehow
So my answer is not a real answer, but it works now (I hate such: it works, but i dont know why) ;)

How to delete row from gridview's RowDataBound event

I am trying to delete a row from a gridview (based on a condition) and then add than row to another gridview inside of the "master" gridview's RowDataBound event. Originally I did not know that in order to call .DeleteRow(i) you needed to have an "ondelete" event handler. However, since all the gridview's .DeleteRow method does is call this event handler, I am confused as to how to use it. Can someone please help point me in the right direction?
Protected Sub grdProduct_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles grdProduct.RowDataBound
' Grey out expired products
Dim row As GridViewRow
row = e.Row
Dim incomingDate As String
Dim incomingStatus As String = ""
incomingDate = row.Cells(3).Text.ToString()
incomingStatus = row.Cells(5).Text.ToString()
If (e.Row.RowType <> DataControlRowType.DataRow) Then
Exit Sub
End If
Try
Dim expDate As Date = incomingDate
If (expDate < DateTime.Today Or incomingStatus.Equals("D")) Then
'Create object for RowValues
Dim RowValues As Object() = {"", "", "", "", "", ""}
'Create counter to prevent out of bounds exception
Dim i As Integer = row.Cells.Count
'Fill row values appropriately
For index As Integer = 0 To i - 1
RowValues(index) = row.Cells(index).Text
Next
'create new data row
dProdRow = dProdtable.Rows.Add(RowValues)
dProdtable.AcceptChanges()
grdProduct.DeleteRow(e.Row.RowIndex)
End If
Catch ex As Exception
End Try
End Sub
Protected Sub grdProduct_Delete(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles grdProduct.RowDeleting
'Not sure what to do here
End Sub
The best way to do this is to manipulate this at the datasource level rather than manipulating the UI components themselves.
For example:
if(!IsPostback)
{
DataTable one = ...
DataTable two = ...
var removeRows = (from c in one.AsEnumerable()
where c.Field<DateTime>("incomingDate")< incomingDate ||
c.Field<string>("incomingStatus")=="D"
select c).ToList();
for(var item in removeRows)
{
two.ImportRow(item);
}
//now delete from initial table
foreach(var item in removeRows)
{
one.Rows.Remove(item);
}
//Now bind both grids
grid1.DataSource=one;
grid1.DataBind();
grid2.DataSource=two;
grid2.DataBind();
}
Update - Sample toy program in VB.NET Hopefully you can adapt it to your situation.
Sub Main
Dim one As New DataTable()
one.Columns.Add("one", GetType(Integer))
For i As Integer = 0 To 9
Dim r As DataRow = one.NewRow()
r.ItemArray = New Object() {i}
one.Rows.Add(r)
Next
Dim two As New DataTable()
two.Columns.Add("one", GetType(Integer))
For i As Integer = 0 To 9
Dim r As DataRow = two.NewRow()
r.ItemArray = New Object() {i}
two.Rows.Add(r)
Next
Dim removeRows = (From c In one.AsEnumerable() Where c.Field(Of Integer)("one") = 5).ToList()
For Each item As DataRow In removeRows
two.ImportRow(item)
Next
For Each item As DataRow In removeRows
one.Rows.Remove(item)
Next
End Sub
I just realized that you are using VB.NET. You should be able to translate the above from C# to VB.NET. The general idea is there, anyway.

ASP.net/jQuery: JSTree, selecting Node, can't seem to get ID

Currently, I'm using an AJAX Handler to populate the JSTree:
$(function () {
$("#jstree").jstree({
"json_data": {
"ajax": {
"url": "AJAXHandler.aspx?action=GetMenu"
}
},
"plugins": ["themes", "json_data", "dnd"]
})
.bind("move_node.jstree", function (node, ref, position, is_copy, is_prepared, skip_check) {
console.log(node); });
});
The handler actually makes a database call, loops through the menu items, creates a JSON object that is serialized, sent back, and rendered:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Select Case Request("action")
Case "GetMenu"
GetMasterMenu()
Case "UpdateMenuHiearchy"
UpdateMenuHiearchy()
End Select
End Sub
Private Sub GetMasterMenu()
Dim dt As DataTable = GetMenu()
Dim nodesList As New List(Of JsTreeNode)()
PopulateNodes(dt, nodesList)
Dim ser As New JavaScriptSerializer()
Dim res As String = ser.Serialize(nodesList)
Response.ContentType = "application/json"
Response.Write(res)
Response.[End]()
End Sub
Private Sub PopulateNodes(ByRef dt As DataTable, ByVal nodes As List(Of JsTreeNode))
Dim parents() As DataRow = dt.Select("PARENT_MENU_ID = 0")
'Root Nodes
For Each dr As DataRow In parents
Dim node As New JsTreeNode()
node.attributes = New Attributes()
node.attributes.id = dr("APPLICATION_MENU_ID").ToString
node.attributes.rel = "root" & dr("APPLICATION_MENU_ID").ToString
node.data = New Data()
node.data.title = dr("DESCRIPTION")
node.state = "open"
'Check for Children
Dim strSQL As New StringBuilder
With strSQL
.Append(" SELECT * FROM APPLICATION_MENU WHERE PARENT_MENU_ID = " & dr("APPLICATION_MENU_ID") & "")
End With
Dim dtChildren As DataTable = DatabaseManager.Query(strSQL.ToString)
If dtChildren.Rows.Count > 0 And dtChildren IsNot Nothing Then
For Each drChild As DataRow In dtChildren.Rows
AddChildNodes(dt, dr("APPLICATION_MENU_ID"), node)
Next
End If
node.attributes.mdata = "{draggable : true}"
nodes.Add(node)
Next
End Sub
Private Sub AddChildNodes(ByRef dt As DataTable, ByVal parentID As Integer, ByVal node As JsTreeNode)
Dim strSQL As New StringBuilder
With strSQL
.Append(" SELECT * FROM APPLICATION_MENU WHERE PARENT_MENU_ID = " & parentID.ToString & "")
End With
Dim dtChildren As DataTable = DatabaseManager.Query(strSQL.ToString)
node.children = New List(Of JsTreeNode)()
For Each drChild As DataRow In dtChildren.Rows
Dim cnode As New JsTreeNode()
cnode.attributes = New Attributes()
cnode.attributes.id = drChild("APPLICATION_MENU_ID").ToString
node.attributes.rel = "folder"
cnode.data = New Data()
cnode.data.title = drChild("DESCRIPTION")
cnode.attributes.mdata = "{draggable : true }"
strSQL = New StringBuilder
With strSQL
.Append(" SELECT * FROM APPLICATION_MENU WHERE PARENT_MENU_ID = " & drChild("APPLICATION_MENU_ID") & "")
End With
Dim dtChildren2 As DataTable = DatabaseManager.Query(strSQL.ToString)
If dtChildren.Rows.Count > 0 And dtChildren IsNot Nothing Then
AddChildNodes(dt, drChild("APPLICATION_MENU_ID"), cnode)
End If
node.children.Add(cnode)
Next
End Sub
The idea here is to bind the move_node to a function that will hit the handler and update the database as to where I moved the object. I've been able to create the bind to do that. The problem, however, is that I can't seem to obtain the ID. I'm setting it in the attributes in the population of the JSON object, but when I do a watch on the NODE and REF objects via console.log, the id field is empty.
What gives? Any ideas? Am I missing something vital?
After fiddling with it once again, I found the answer:
cnode.attributes
node.attributes
It must be name specific underneath, these must be cnode.attr and node.attr to work.
You are indeed correct-
JSTree V1+ uses the jquery bindings,etc.. Therefore you need to use the attr to obtain the objects attributes - also on a side note, IE7- are case sensitive with the node data, eg:
$("#node").attr("id")!=$("#node").attr("ID")

How to sort a gridview once a radio button is selected

I'm trying to sort records in the gridview right after a radio button is selected. My approach is with the dataview, but because the dataset variable doesn't survive a round trip to the server, I don't know how to make this happen. please help!
Public Sub GetCustomers()
db.RunProcedure("usp_customers_get_all")
db.doSort(radList.SelectedValue)
gvCustomers.DataSource = db.MyView
End Sub
Protected Sub radList_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles radList.SelectedIndexChanged
If radList.SelectedValue = 0 Then
db.doSort(0)
gvCustomers.DataSource = db.MyView
End If
If radList.SelectedValue = 1 Then
db.doSort(1)
gvCustomers.DataSource = db.MyView
End If
End Sub
Public Sub doSort(ByVal strIn As Integer)
If strIn = 0 Then
MyView.Sort = "lastname, firstname"
Else
MyView.Sort = "username"
End If
End Sub
Public Sub RunProcedure(ByVal strName As String)
Dim objConnection As New SqlConnection(mstrConnection)
Dim mdbDataAdapter As New SqlDataAdapter(strName, objConnection)
Try
mdbDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure
Me.mDataset.Clear()
mdbDataAdapter.Fill(mDataset, "tblCustomers")
MyView.Table = mDataset.Tables("tblCustomers")
Catch ex As Exception
Throw New Exception("stored procedure is " & strName.ToString & " error is " & ex.Message)
End Try
End Sub
You could store the dataset in one of the following places and then when the post back happens just load it again from there. I have done many of these on a corporate intranet.
Session Variable
ViewState
QueryString
Cache
I cant really provide more help as you didn't specify if this is done in Ajax or if you do a full postback etc. If you provide more info I would love to help you.

Resources