Property getting incorrect value set - asp.net

I have a bizarre problem. I use a lot of session variables so I don't have to pass it all back and forth every time a page does a postback. I have been doing this for years so I'm at a complete loss.
I have a file called SessionHandler.vb in the App_Code folder that has the following code:
Imports Microsoft.VisualBasic
Public Class SessionHandler
Private Shared _chgLinePkNum As String = "0"
Private Shared _chgStudentIDPk As String = "0"
Public Shared Property chgLinePkNum() As String
Get
' Check for null first
If (HttpContext.Current.Session(SessionHandler._chgLinePkNum) Is Nothing) Then
' Return an empty string if session variable is null.
Return "Nothing"
Else
Return HttpContext.Current.Session(SessionHandler._chgLinePkNum).ToString()
End If
End Get
Set(ByVal value As String)
If (value Is Nothing) Or (value = "") Then
HttpContext.Current.Session(SessionHandler._chgLinePkNum) = "Nothing"
Else
HttpContext.Current.Session(SessionHandler._chgLinePkNum) = value
End If
End Set
End Property
Public Shared Property chgStudentIDPk() As String
Get
' Check for null first
If (HttpContext.Current.Session(SessionHandler._chgStudentIDPk) Is Nothing) Then
' Return an empty string if session variable is null.
Return "Nothing"
Else
Return HttpContext.Current.Session(SessionHandler._chgStudentIDPk).ToString()
End If
End Get
Set(ByVal value As String)
If (value Is Nothing) Or (value = "") Then
HttpContext.Current.Session(SessionHandler._chgStudentIDPk) = "Nothing"
Else
HttpContext.Current.Session(SessionHandler._chgStudentIDPk) = value
End If
End Set
End Property
Simple enough... Then, in my code, I reference the properties by SessionHandler.chgLinePkNum. This block of code has LineItemNumber = 1 and StudentID = [the actual ID number].
If IsParking And checkbox.Checked = True Then
SessionHandler.chgLinePkNum = LineItemNumber
SessionHandler.chgStudentIDPk = StudentID
peParkingRegistration.Show()
End If
When the first line runs, chgLinePkNum is set to 1 as expected. For some strange reason, it is also setting chgStudentIDPk to 1. When the next line is run, it sets chgStudentIDPk to the correct StudentID number. The problem is, it also sets chgLinePkNum to the StudentID number.
I have run it line by line in the debugger and each property set function runs only when it is called. I just can't figure out how "HttpContext.Current.Session(SessionHandler._chgLinePkNum) = value" is setting the value for chgStudentIDPk and vice versa.

Anything to do with these having the exact same value?
Private Shared _chgLinePkNum As String = "0"
Private Shared _chgStudentIDPk As String = "0"

Related

Routine to compare new and old string values, maintain old data if nothing new

I have a Form which allows users to enter new Data for a record. In order to maintain Data Integrity, I copy all the pre-existing Data (if Any) into the Record and overwrite only those fields which the user has added new Data to. This new Record is saved to the database and the old Record Deleted.
I'm merely trying to find the most efficient way of going through each field to :
determine if there is Current Data to Maintain
New Data to Overwrite
I'll need to write the same type of Check for String, Decimal, Date and Integer (all nullable)
Here's my string check
Private Function CreateRecordforSubmission() As Business.Casualty
Dim c As Business.Casualty = Casualty
c.alias = CheckStringValues(c.alias, txtAlias.Text.Trim())
Return c
End Function
Private Function CheckStringValues(OldValue As String, newValue As String) As String
If Not OldValue Is Nothing AndAlso Not String.IsNullOrEmpty(newValue) Then
'<-- There is NEW DATA
If Not String.IsNullOrEmpty(newValue) Then
Return newValue
Else
'<-- No NEW DATA, check of there is CURRENT DATA to maintain
If Not OldValue Is Nothing Then
Return OldValue
Else
Return String.Empty
End If
End If
Else
'<-- NO CURRENT DATA AND no changes have been made
Return String.Empty
End If
End Function
Check out how CSLA does it. Each property in your object could take care of that comparison, if the setter detect a change or new value, you can update your variable and mark your object as modified.
Public Property Alias As String
Get
Return _alias
End Get
Set(ByVal value As String)
If Not String.IsNullOrEmpty(value) AndAlso _alias <> value Then
_alias = value
_objectWasModified = True
End If
End Set
End Property
The If statement could be in the base class, or a helper class.
If you want to have a generic function for other type, here's an example. This assume that you are using nullable values.
Public Property Number As Integer?
Get
Return _number
End Get
Set(ByVal value As Integer?)
If Not IsNullOrSame(Of Integer)(_number, value)Then
_number= value
_objectWasModified = True
End If
End Set
End Property
Public Function IsNullOrSame(Of T As Structure)(ByVal oldValue As Nullable(Of T), ByVal newValue As Nullable(Of T))
If newValue.HasValue Then
If Not oldValue.HasValue OrElse Not oldValue.Value.Equals(newValue.Value) Then
Return False
End If
End If
Return True
End Function

Understanding how Public Properties are set in VB.NET

I am trying to understand how a value in a Public property is set. There does not seem to be anything passed or any kind of lookup.
Public Shared Property IsUser() As String
Get
If HttpContext.Current.Session("IsUser") IsNot Nothing Then
Return HttpContext.Current.Session("IsUser").ToString()
Else
Return Nothing
End If
End Get
Set(value As String)
HttpContext.Current.Session("IsUser") = value
End Set
End Property
I have tried searching for the ClassName i.e. UserSession.IsUser = and also the only place the session value is set is in the property. HttpContext.Current.Session("IsUser") = value
What do I need to understand better.. I mean at the end of the day the User has to be True or False so where is the Lookup or passed parameter?

Can i use a single session variable to store all the field values

I have 9 pages with 10 fields in each page. Can i use a single session variable to store all the field(textbox,drop downlist,radiobuttons) values of 9 pages? If so could you give me small example inorder to proceed. Im kind of stuck.
Could you? Yes. Should you? Most likely not - though I can't say for sure without understanding what problem you are intending to solve.
Update with one sample solution
OK, I'm going to assume you want to store the values from the controls and not the controls themselves. If so, the easiest solution is stuff them in using some meaningful token to separate them. Like:
Session("MyControlValueList") = "name='txt1',value='hello'|name='txt2', value'world'"
To retrieve you would split them into a string array:
myArray = Session("MyControlValueList").Split("|")
And then iterate through to find the control/value you want.
So strictly speaking that's an answer. I still question whether it is the best answer for your particular scenario. Unfortunately I can't judge that until you provide more information.
Create a custom class with all the fields you want to save, then populate an instance of that and save that instance as a session variable.
I have something similar, but not identical - I'm saving various shipping address fields for an order, and I'm allowing the admins to update the order, either the shipping information or the order line items. Since that information is kept on separate tables, I store the shipping information in a session variable, and then compare it to what's on the form when they hit the "Update" button. If nothing has changed, I skip the update routine on the SQL Server database.
The easiest way for me to do this was to create a "OrderInfo" class. I saved the shipping information to this class, then saved that class to a session variable. Here's the code showing the class -
Public Class OrderInfo
Private v_shipname As String
Private v_add1 As String
Private v_add2 As String
Private v_city As String
Private v_state As String
Private v_zipcd As String
Private v_dateneeded As Date
Private v_billingmeth As Integer
Public Property ShipName() As String
Get
Return v_shipname
End Get
Set(value As String)
v_shipname = value
End Set
End Property
Public Property Add1() As String
Get
Return v_add1
End Get
Set(value As String)
v_add1 = value
End Set
End Property
Public Property Add2() As String
Get
Return v_add2
End Get
Set(value As String)
v_add2 = value
End Set
End Property
Public Property City() As String
Get
Return v_city
End Get
Set(value As String)
v_city = value
End Set
End Property
Public Property State() As String
Get
Return v_state
End Get
Set(value As String)
v_state = value
End Set
End Property
Public Property ZipCd() As String
Get
Return v_zipcd
End Get
Set(value As String)
v_zipcd = value
End Set
End Property
Public Property DateNeeded() As Date
Get
Return v_dateneeded
End Get
Set(value As Date)
v_dateneeded = value
End Set
End Property
Public Property BillingMeth() As Integer
Get
Return v_billingmeth
End Get
Set(value As Integer)
v_billingmeth = value
End Set
End Property
End Class
Here's the code for when I tested the concept to see if I could store a custom class in a session variable. This routine gets the order record, populates the fields in an instance of the custom class, and on the web form, as well. I save that instance to a session variable, then I initialize another new instance of that custom class, load the session variable to it. I then display the field values from the "retrieved" custom class, and what showed on the label matched what it should be -
Protected Sub LoadOrderInfo(ByVal ordID As Integer)
Dim connSQL As New SqlConnection
connSQL.ConnectionString = ConfigurationManager.ConnectionStrings("sqlConnectionString").ToString
Dim strProcName As String = "uspGetOrderInfoGeneral"
Dim cmd As New SqlCommand(strProcName, connSQL)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("OrderID", ordID)
If connSQL.State <> ConnectionState.Open Then
cmd.Connection.Open()
End If
Dim drOrderInfo As SqlDataReader
drOrderInfo = cmd.ExecuteReader
If drOrderInfo.Read Then
Dim orgOrder As New OrderInfo
orgOrder.ShipName = drOrderInfo("shipName")
orgOrder.Add1 = drOrderInfo("ShipAdd1")
orgOrder.Add2 = drOrderInfo("ShipAdd2")
orgOrder.City = drOrderInfo("ShipCity")
orgOrder.State = drOrderInfo("ShipState")
orgOrder.ZipCd = drOrderInfo("ShipZip")
orgOrder.DateNeeded = drOrderInfo("DateNeeded")
orgOrder.BillingMeth = drOrderInfo("BillingMethodID")
If Session.Item("orgOrder") Is Nothing Then
Session.Add("orgOrder", orgOrder)
Else
Session.Item("orgOrder") = orgOrder
End If
' I could just as easily populate the form from the class instance here
txtShipName.Text = drOrderInfo("shipName")
txtAdd1.Text = drOrderInfo("ShipAdd1")
txtAdd2.Text = drOrderInfo("ShipAdd2")
txtCity.Text = drOrderInfo("ShipCity")
txtState.Text = drOrderInfo("ShipState")
txtZipCd.Text = drOrderInfo("ShipZip")
selDate.Value = drOrderInfo("DateNeeded")
ddlBillMeth.SelectedValue = drOrderInfo("BillingMethodID")
End If
cmd.Connection.Close()
Dim retOrder As New OrderInfo
retOrder = Session.Item("orgOrder")
lblWelcomeMssg.Text = retOrder.ShipName & ", " & retOrder.Add1 & ", " & retOrder.City & ", " & retOrder.DateNeeded.ToShortDateString & ", " & retOrder.BillingMeth.ToString
End Sub
This might not be practical or desirable, given the number of fields you are trying to hold onto that way, but I'm not here to judge, so this is one possibility. I've worked with other projects where you create a table, and save that table as a session variable, so whatever structure you put into an object is retained if you save that object as a session variable.

How can I set the value of this cookie property from code behind?

I would like to do this: Dim str As String = class.isGuest("yes") but it won't work.
Public Property IsGuest(ByVal guestStatus As String) As String
Get
Dim guestCookie As New HttpCookie("g")
For Each key As String In Context.Response.Cookies.Keys
If key = MYACCOUNT_SESSION_COOKIE_NAME Then
guestCookie = Context.Response.Cookies.Item(MYACCOUNT_SESSION_COOKIE_NAME)
Exit For
End If
Next
guestCookie.Value = guestStatus
Response.Cookies.Add(guestCookie)
Return guestCookie.Value.ToString
End Get
Set(ByVal value As String)
Dim guestCookie As New HttpCookie("g")
guestCookie.Value = value
Response.Cookies.Add(guestCookie)
End Set
End Property
There are a few issues in your code, but I think the primary problem is that you are setting / creating a cookie called "g", but you are then attempting to retrieve a cookie called MYACCOUNT_SESSION_COOKIE_NAME.
You can also simplify your code by replacing your loop through the keys with a call to the property on the cookie collection that does the same thing.
Public Property IsGuest(ByVal guestStatus As String) As String
Get
Return Context.Response.Cookies(MYACCOUNT_SESSION_COOKIE_NAME).Value
End Get
Set(ByVal value As String)
Response.Cookies.Add(New HttpCookie(MYACCOUNT_SESSION_COOKIE_NAME, value)
End Set
End Property

How to get the value of an XML element using Linq even when empty

Please excuse my stupidity, I tend to find the traversing XML overly complicated.
I am using ASP.NET in VB.
I have an XML document which contains all the details of staff in my company...
<staff>
<staffName>Test Staff</staffName>
<staffTitle>Slave</staffTitle>
<staffDepartmentName>Finance</staffDepartmentName>
<staffOffice>London</staffOffice>
<staffEmail>t.staff#company.co.uk</staffEmail>
<staffPhone>0207 123 456</staffPhone>
<staffNotes>Working hours Mon to Thurs 9.15 - 5.15</staffNotes>
<staffBio></staffBio>
</staff>
As you can see, some nodes do not always contain data for ever member of staff; only Directors have biographies.
I access the values like this...
For Each staff In ( _
From matches In myXMLFile.Descendants("staff").Descendants("staffName") _
Where matches.Nodes(0).ToString.ToLower.Contains(LCase(search)) _
Order By matches.Value _
Select matches)
staffName = staff.Descendants("staffName").Nodes(0).ToString)
staffTitle = staff.Descendants("staffTitle").Nodes(0).ToString)
staffOffice = staff.Descendants("staffOffice").Nodes(0).ToString)
staffEmail = staff.Descendants("staffEmail").Nodes(0).ToString)
staffPhone = staff.Descendants("staffPhone").Nodes(0).ToString)
staffNotes = staff.Descendants("staffNotes").Nodes(0).ToString)
staffBio = staff.Descendants("staffBio").Nodes(0).ToString)
' Do something with that data...
Next
Once it gets to staffBio I get an error saying "Object reference not set to an instance of an object." obviously because that node does not exist.
My question is how can I assign the value to a variable even when it is empty without having to do a conditional check before each assignment?
First, myXMLFile.Descendants("staff").Descendants("staffName") is redundant. Descendants returns all the elements at any level within an XDocument or XElement. So, myXMLFile.Descendants("staffName") would give the same result.
Second, you can just use the Element property and the Value property like this:
staffBio = staff.Element("staffBio").Value
staff will only have one staffBio element, so there's no need to use the Descendants property. Value is a string, so you don't need to call Value.ToString. If the element is empty, then Value will return an empty string, which is what you're looking for!
Third, there is a much better (and I believe more straight forward) way of doing this in VB.NET. Here's a console app that demonstrates how I would do this:
Module Module1
Sub Main()
Dim myXMLFile = <allStaff>
<staff>
<staffName>Test Staff</staffName>
<staffTitle>Slave</staffTitle>
<staffDepartmentName>Finance</staffDepartmentName>
<staffOffice>London</staffOffice>
<staffEmail>t.staff#battens.co.uk</staffEmail>
<staffPhone>0207 123 456</staffPhone>
<staffNotes>Working hours Mon to Thurs 9.15 - 5.15</staffNotes>
<staffBio></staffBio>
</staff>
<staff>
<staffName>Other Staff</staffName>
<staffTitle>Master</staffTitle>
<staffDepartmentName>IT</staffDepartmentName>
<staffOffice>Oxford</staffOffice>
<staffEmail>o.staff#battens.co.uk</staffEmail>
<staffPhone>0207 123 789</staffPhone>
<staffNotes></staffNotes>
<staffBio>Some guy.</staffBio>
</staff>
</allStaff>
Dim search = "Test"
Dim searchQuery = From staff In myXMLFile...<staff> _
Where staff.<staffName>.Value.Contains(search) _
Select si = New StaffInfo With {.Name = staff.<staffName>.Value, _
.Title = staff.<staffTitle>.Value, _
.Department = staff.<staffDepartmentName>.Value, _
.Office = staff.<staffOffice>.Value, _
.Email = staff.<staffEmail>.Value, _
.Phone = staff.<staffPhone>.Value, _
.Notes = staff.<staffNotes>.Value, _
.Bio = staff.<staffBio>.Value}
For Each staff In searchQuery
Console.WriteLine("Name: {0}", staff.Name)
Console.WriteLine("Title: {0}", staff.Title)
Console.WriteLine("Department: {0}", staff.Department)
Console.WriteLine("Office: {0}", staff.Office)
Console.WriteLine("Email: {0}", staff.Email)
Console.WriteLine("Phone: {0}", staff.Phone)
Console.WriteLine("Notes: {0}", staff.Notes)
Console.WriteLine("Bio: {0}", staff.Bio)
Console.WriteLine()
Next
Console.ReadLine()
End Sub
Private Class StaffInfo
Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Private _title As String
Public Property Title() As String
Get
Return _title
End Get
Set(ByVal value As String)
_title = value
End Set
End Property
Private _department As String
Public Property Department() As String
Get
Return _department
End Get
Set(ByVal value As String)
_department = value
End Set
End Property
Private _office As String
Public Property Office() As String
Get
Return _office
End Get
Set(ByVal value As String)
_office = value
End Set
End Property
Private _email As String
Public Property Email() As String
Get
Return _email
End Get
Set(ByVal value As String)
_email = value
End Set
End Property
Private _phone As String
Public Property Phone() As String
Get
Return _phone
End Get
Set(ByVal value As String)
_phone = value
End Set
End Property
Private _notes As String
Public Property Notes() As String
Get
Return _notes
End Get
Set(ByVal value As String)
_notes = value
End Set
End Property
Private _bio As String
Public Property Bio() As String
Get
Return _bio
End Get
Set(ByVal value As String)
_bio = value
End Set
End Property
End Class
End Module
If you have a schema (.xsd file) for your XML, then you can import a reference to that xmlns to your VB source file, which will give you intellisense for writing your LINQ to XML queries.
(Edit: A quick way to create a schema is to open up an XML file in Visual Studio and choose Create Schema from the XML menu.)
For more information and help, please check out the "How Do I" video series on LINQ by Beth Massi.
OK think this is how to do it.
...
staffBio = staff.Descendants("staffBio").ElementAtOrDefault(0).Value.ToString)
...
Using .ElementAtOrDefault(0) instead of .Nodes(0) just returns "" if it's empty or <staffBio>whatever</staffBio> if it is not.
.Value just returns the content of the tags like "whatever" in the example above.
Is this right? Can anyone see any problems with this?

Resources