updating properties of a class with dynamic references - asp.net

Sorry for what is probably a very basic question. I have a vb.net class with properties defined as follows:
Private m_Property1 As String
Public Property Property1() As String
Get
Return m_Property1
End Get
Set(ByVal value As String)
If IsNothing(value) Then
m_Property1 = String.Empty
Else
m_Property1 = value
End If
End Set
End Property
I can then set the values as follows:
classname.Property1 = "myvalue"
How do I set the value of a property that is defined dynmically eg
Dim strPropertyName As String = "Property1"
Hope that makes sense.
Thanks,
Josh

You would use reflection
Dim strPropertyName as string = "Property1"
Dim pi As PropertyInfo = myClass.GetType().GetProperty(strPropertyName)
pi.SetValue(myClass.GetType(), "some string", Nothing)

You want to use Reflection in order to do this. VB.NET provides a way to do this if you know the value at compile-time, but for run-time operations, you need to use the GetType keyword in order to get the type of your class (or, use the GetType method on an instance of it if you don't know it).
Then, with that Type instance, you would call GetProperty, passing the string with the name of the property. It will return an PropertyInfo instance which you then call GetValue on, passing the instance of the object in, which will return an Object which you have to cast back to a type you wish to use (if you are).
VB.NET makes a lot of this easier with the CallByName function.
Also, if you know at compile-time what the name of the property is, you can always cast to object and use VB.NET's inherent late binding:
Dim o As Object = <your object>
o.Property1 = ...
VB.NET will perform the late-binding for you.

Related

How to check both the objects are same in Vb.net

I am trying to compare to two objects of same type and determine they identical. I have
objA IS objB
also
objA.Equals(objB)
but every time I am getting false. Here is the code I am trying
Public Class RowsDetails
Property RelatedEmployee As String = String.Empty
Property RelatedNumberAs String = String.Empty
Property Type As String = String.Empty
Property ReportType As String = String.Empty
Property status As String = String.Empty
Property Term As String = String.Empty
Property Currency As String = String.Empty
End Class
All the properties have same values in objA and objB. I have gone over some of the articles that explained about implementing IEquatable(of T).
But they mostly looked like custom logic.
I was wondering is there a simple way to do this ?
Thanks In advance.
Any time you compare two Objects a method for determining equivalence must be established.
there are 3 main forms of equivalence:
Type equivalence: done with the TypeOf operator. who's behavior can be found here
Reference equivalence: done with the is operator. found here
Value Equality (which seems to be what your trying to do) requires that a comparement method is defined. Other wise it will take its best guess at doing so, by using the default Equals() method.
If none of these work for you then you HAVE to define your own method of comparing.
the only other way of doing so, other than implementing IEquatable() or overloading Equals(), would be taking a hash of both objects and comparing those.
Object.Equals(Object) is what is called when you call objA.Equals(objB). What is compared is, are they pointing to the same object.
Dim objA as New RowDetails()
Dim objB = objA
Now they are both pointing to the same object. So...
objA.Equals(objB)
returns True
But using the New keyword on both will create 2 different references so they will not be equal with the default implementation of .Equals
Add something like the following to you RowDetails class.
Public Overrides Function Equals(obj As Object) As Boolean
Dim rowDet As RowsDetails = TryCast(obj, RowsDetails)
If rowDet Is Nothing Then
Return False
'The AndAlso will short circuit as soon as it finds a false
ElseIf RelatedEmployee = rowDet.RelatedEmployee AndAlso RelatedNumber = rowDet.RelatedNumber AndAlso Type = rowDet.Type Then 'and the rest of the properties
Return True
End If
Return False
End Function

How to obtain values from list

Hi Guys
Can anyone help me out with this problem i have a list of object that is formatted in the image attached above and i have to get the IDNO, Affected Id and the date values
Since deserialization will return anonymous type(in your case), you have two options: Either deserialize it to a strong type (by defining a type) or else fetch the value using Reflection since types and properties are not known.
In your case you can get the value through reflection like this:-
Dim _data As List(Of Object) = ...
Dim firstObject = _data.FirstOrDefault()
Dim type As Type = firstObject.GetType()
Dim idmoValue = type.GetProperty("IDMO").GetValue(firstObject)
Sample Fiddle.

Convert IEnumerable(Of Object) to class that Implements IEnumerable(Of Object)?

Using VB.NET, I have ths class
Public Class MyCollectionClass
Implements IEnumerable(Of MyClass)
Public Property MadeThisClassCuzINeedToSetThis() As String
' code here
End Class
I want to do this, but get an exception saying I can't do this cast.
Dim objColl As MyCollectionClass
objColl = CType(IEnumerable(Of MyClass), MyCollectionClass)
Can anyone tell me how to get this to work. Thanks.
See this VB.NET/C# casting cheat sheet or the documentation on CType. The major problem is that the first parameter should be the instance to convert, not its type. This should work:
Dim myEnumerable As IEnumerable(Of MyObjectClass) = New MyCollectionClass()
Dim objColl = CType(myEnumerable, MyCollectionClass)
' objColl's type is inferred As MyCollectionClass
(note that as MyClass is a keyword, and I assume you actually have a different class name there, I changed it to MyObjectClass in my example)

dynamically change querystring in asp.net

Our client is asking to encrypt the URL because it is passing values in the query string. We have used encryption and are able to encrypt the URL; however, existing code uses querystring["var"] in so many places and fails because of the encrypted URL. Hence, on page load, we will have to decrypt the URL. If I decrypt and alter the query string using response.redirect, then again query string will be visible in the URL and can be misused.
Please help.
EDIT
I was reading about RESTfull web service. I have not yet understood entire concept. I wonder if I can use this with my application to hide query string. Please let me know if so.
Thanks.
One way to achieve this with little headache is to decrypt the query string as you currently do, then set its values to some object which can be stored in the session. Storing it in a session variable would be useful if you wanted to exclude this information (hide) from the query string - you'd essentially be passing the data around behind the scenes.
Once stored in session, you would then change your code, such that wherever you use querystring["var"], you will instead refer to the object that has been stored in the session.
Edit
Note, though, that this doesn't have to be relegated to a single value. This object can have multiple properties each representing a query string value:
MyQueryStringObject myQueryStringObject = new MyQueryStringObject(SomeUrl);
//MyQueryStringObject decrypts the query string and assigns the values to properties in its constructor
string abc = myQueryStringObject.abc;
string xyz = myQueryStringObject.xyz;
Now, that uses properties to represent each query string value. You may have tons of them. In that case, you can store the values into some sort of Dictionary or a NameValueCollection perhaps.
There are various ways to achieve this which I think is beyond topic, but, note that the key to all of this, the very essence is to simply decrypt the url on the server (during postback) and save the unencrypted data into a session variable should you want to hide it from the URL.
There is a much better way of going about this. I deal with a client with that has the same requirement. This class has soared through security scans as well.
Public Class QueryStringManager
Public Shared Function BuildQueryString(ByVal url As String, ByVal queryStringValues As NameValueCollection) As String
Dim builder As New StringBuilder()
builder.Append(url & "?")
Dim count = queryStringValues.Count
If count > 0 Then
For Each key In queryStringValues.AllKeys
Dim value As String = queryStringValues(key)
Dim param As String = BuildParameter(key, value)
builder.Append(param)
Next
End If
Return builder.ToString()
End Function
Public Shared Function DeconstructQueryString(ByVal Request As HttpRequest) As NameValueCollection
Dim queryStringValues As New NameValueCollection
For Each key In Request.QueryString.AllKeys
Dim value As String = Request.QueryString(key)
value = DeconstructParameter(value)
queryStringValues.Add(key, value)
Next
Return queryStringValues
End Function
Private Shared Function BuildParameter(ByVal key As String, ByVal value As String) As String
Dim builder As New StringBuilder()
builder.Append(key.ToString() & "=")
value = GetSafeHtmlFragment(value)
Dim encrypt As Security = New Security()
value = encrypt.Encrypt(value)
builder.Append(value)
builder.Append("&")
Return builder.ToString()
End Function
Public Shared Function DeconstructParameter(ByVal value As Object) As String
Dim decrypt As New Security()
value = decrypt.Decrypt(value)
value = GetSafeHtmlFragment(value)
End Function
End Class
Use
Dim nvc As NameValueCollection = New NameValueCollection()
nvc.Add("value", 1)
Dim builtUrl As String = QueryStringManager.BuildQueryString(url, nvc)
Response.Redirect(builtUrl, false);
Then when you get to the page you simply write:
Dim decryptedValues As NameValueCollection = QueryStringManager.DeconstructQueryString(Request)
The reason why I use NameValueCollection is because that's the same type as QueryString. You can build on to the class to add an object into the QueryString based on it's properties and their values as well. This keeps all of the complex and tedious logic encapsulated away.

Do I Need a Class if I only need 1 Property (at the moment)?

Update: I didn't make it clear but I meant this to be a question about where/how I would use a function to return a list of strings when I'm trying to just work with classes.
I have a class called Account.
I have data access class called AccountDAO.
I have various functions that return lists of objects like GetAllAccounts, GetAccountByID etc.
I want to populate a drop down list with just the account names and nothing else. It's proving rather slow when using lists of objects and databinding them to the dropdownlist.
I feel like I should be using a simple "Select Account_Name From blah" type statement and returning a list of strings but I don't know how to work this into my class and data access class.
How should I handle this predicament?
You can use a list of string,s and bind the list of strings to a dropdownlist no problem... the DDL can support that, just leave out DataTextField and DataValueField props, and it will display the account name as is, which that name would be accessible through the ListItem's Text and Value property.
I like to use objects to be consistent with the rest of the app (which other areas might need a class), and if for some reason you want to add AccountKey later, if you use an object, all you need to do is add a property. Otherwise, if using strings, you'd have to switch up the binding later to point to the object.
HTH.
There is nothing wrong by making a function that only returns a list of strings. YOu could however wonder if it's not better to restrict the number of records you want to put in the list and use some kind of paging.
Assuming that you're using a List<>, you can try something like this:
IEnumerable<string> nameList = accountList.Select(t => t.AccountName);
Or if you need a List:
List<string> nameList = accountList.Select(t => t.AccountName).ToList();
Go with your feelings. Use a datareader to select the list and then load them into an arraylist which can then be bound to the dropdown. Alternately, use something like this method I use to provide both a DisplayMember and a ValueMember which uses a class (with both values) as members of the arraylist. This should give you the general idea. (Note: I normally include this code in a data access class (MyBase) where StartReader, _datRdr, ReadNext and_ReaderValid are a members. But the general idea is intact.)
Public Sub LoadDataSource(ByRef PlantDataSource As PlantSource, Optional ByVal Filter As String = "", Optional ByVal IncludeBlankItem As Boolean = False)
PlantDataSource = New PlantSource
If IncludeBlankItem Then
PlantDataSource.Add(0, "")
End If
If Filter = String.Empty Then
Call StartReader(" Order by PlantName")
Else
Call StartReader(String.Concat(" Where ", Filter, " Order by PlantName"))
End If
If _DatRdr.HasRows Then
While MyBase._ReaderValid
PlantDataSource.Add(PlantId, PlantName)
ReadNext()
End While
End If
Call CloseReader()
End Sub
Private Class PlantListing
Private _PlantList As New ArrayList
Public Sub Add(ByVal PlantId As Integer, ByVal PlantName As String)
_PlantList.Add(New PlantDataItem(PlantId, PlantName))
End Sub
Public ReadOnly Property List() As ArrayList
Get
Return _PlantList
End Get
End Property
End Class
Private Class PlantDataItem
Private _PlantId As Integer
Private _PlantName As String
Public Sub New(ByVal pPlantId As Integer, ByVal pPlantName As String)
Me._PlantId = pPlantId
Me._PlantName = pPlantName
End Sub
Public ReadOnly Property PlantName() As String
Get
Return _PlantName
End Get
End Property
Public ReadOnly Property PlantId() As Integer
Get
Return _PlantId
End Get
End Property
Public ReadOnly Property DisplayValue() As String
Get
Return CStr(Me._PlantId).Trim & " - " & _PlantName.Trim
End Get
End Property
Public Overrides Function ToString() As String
Return CStr(Me._PlantId).Trim & " - " & _PlantName.Trim
End Function
End Class

Resources