Can a VBScript function return a dictionary? - asp-classic

I have a dictionary of form data that I want to modify using a function.
function queryCleanForm(myDictForm)
dim arrayKeys
arrayKeys = myDictForm.keys
for i=0 to myDictForm.count-1
myDictForm(arrayKeys(i)) = replace(myDictForm(arrayKeys(i)), "'", "''")
response.write myDictForm(arrayKeys(i))
next
queryCleanForm = myDictForm
end function
The problem is the line queryCleanForm = myDictForm errors as
Wrong number of arguments or invalid property assignment
Is there a way to do this in VBScript?

Try this:
SET queryCleanForm = myDictForm
With objects you need to use SET to tell VBScript that it is an object reference you are assigning not a value type.

Yes, you need to use the SET command:
Set queryCleanForm = myDictForm

You can also use the ByRef or ByVal values in the function. ByVal, the object you sent to a function or sub is copied into private memmory to be used inside the function and discarded after the function is completed. ByRef, the object you sent to a function is referenced to and all manipulations you make, removing keys, setting the object etc, is directly done to the object you sent.
E.g.
Sub test
DIM testDict as variant
call setdict(testDict)
testDict.Add "test", "value"
call addValue(testDict, "test2","another value")
msgbox testDict.Count
Set testDict = Nothing
End Sub
Sub setdict(ByRef in_Dict as Variant)
If Typename(in_Dict) <> "Dictionary" Then
SET in_Dict = CreateObject("Scripting.Dictionary")
end if
end sub
sub addValue(ByRef in_Obj as Variant, ByVal in_Key as String, ByVal in_Value as String)
if not in_Obj.Exists(in_Key) then
in_Obj.Add in_Key, in_Value
end if
end sub
The test sub calls with a variable of type variant to the sub setdict. In the function I validate the type of the object sent to the sub. If the object type is not a dictionary object (which it is not) then the object in_Dict which is actually the testDict object declared in the sub test, will be set to a dictionary object.
To demonstrate the reference better I also included the second sub called addvalue. I pass the object to the function again as reference and add another key to the dictionary object. In the main test sub ill then post the count. In this case there are 2 keys present.

Related

Can deserialize accept further parameter?

Usually this is how I created objects
Public Shared Function createBasicSimpleOrder(ammountOfQuoteCurrencyBeingOrdered As Decimal, priceInBasecoin As Decimal, Base As String, Quote As String, exchangeObject As ExchangesClass, isSellingInsteadOfBuying As Boolean, customIdentifier As String) As BasicSimpleOrder
Dim exchangeString = exchangeObject.ExchangeStringName
Dim a = New BasicSimpleOrder(ammountOfQuoteCurrencyBeingOrdered, priceInBasecoin, Base, Quote, exchangeString, isSellingInsteadOfBuying, customIdentifier)
a.initializeComplexObjects(exchangeObject)
Return a
End Function
Basically one of the parameter is an object
exchangeObject As ExchangesClass
That is the only non primitive Object that is a member of BasicSimpleOrder
So after I set up the primitive Public Read Only properties, I called this function.
Public Sub initializeComplexObjects(exchangeObject As ExchangesClass)
_exchangeObject = exchangeObject
If exchangeObject Is Nothing Then Exit Sub
Dim mark = CoinClass.MarketBaseQuoted(exchangeObject.ExchangeStringName, Base, Quote)
If mark Is Nothing Then Exit Sub
setMarket(mark)
End Sub
Now say I want to deserialize
I then do
gridOrderOldState = Newtonsoft.Json.JsonConvert.DeserializeObject(Of futureStateForGrid)(settingsFromBefore)
Basically futureStateForGrid is a class that contain some derived class of BasicSimpleOrder
For that DeserializeObject to work I already set a constructor
Protected Sub New(ammountOfQuoteCurrencyBeingOrdered As Decimal, priceInBasecoin As Decimal, Base As String, Quote As String, exchangeString As String, isSellingInsteadOfBuying As Boolean, customIdentifier As String)
_ammountOfQuoteCurrencyBeingOrdered = ammountOfQuoteCurrencyBeingOrdered
_Base = Base
_Quote = Quote
_priceInBasecoin = priceInBasecoin
_exchangeString = exchangeString
_isSellingInsteadOfBuying = isSellingInsteadOfBuying
_customIdentifier = customIdentifier
'initializeType0(ammountOfQuoteCurrencyBeingOrdered, priceInBasecoin, Base, Quote, exchangeString, isSellingInsteadOfBuying, customIdentifier)
End Sub
The problem is if I use DeserializeObject, I cannot run initializeComplexObjects(exchangeObject As ExchangesClass)
That's because my new (constructor) function does not accept exchangeObject as ExchangeClass as parameter.
If Protected Sub New accept exchangeObject as ExchangeClass as a parameter, newtonsoft won't know which object should be put on parameter. After all ExchangeClass is a complex object and not a primitive type. Hence, they're not really there.
So how can I set the exchangeObject as parameter so the constructor know?

add dataitem(from string array) to listview

To preface this, I've looked through several of the postings containing listviews and nothing really is comparing to what I'm trying to do.
I'm trying to take values determined through a loop that has several If Statements similar to what follows:
If Convert.ToInt32(GetData(ds.Tables("HRIS").Rows(i), "ABS_CO_RULE_DAYS", DefaultValue)) > 0 Or _
Convert.ToInt32(GetData(ds.Tables("HRIS").Rows(i), "ABS_CO_RULE_HRS", DefaultValue)) > 0 Or _
Convert.ToInt32(GetData(ds.Tables("HRIS").Rows(i), "ABS_CO_RULE_MINS", DefaultValue)) > 0 Then
msChargeDays = GetData(ds.Tables("HRIS").Rows(i), "ABS_CO_RULE_DAYS", DefaultValue)
msChargeHours = GetData(ds.Tables("HRIS").Rows(i), "ABS_CO_RULE_HRS", DefaultValue)
msChargeMins = GetData(ds.Tables("HRIS").Rows(i), "ABS_CO_RULE_MINS", DefaultValue)
msHowPaid = "CR DAYS"
AbsenceLine() 'calls sub
End If
This block of code returns valid results from the dataset that it calls from. Now in the following code block, I am trying to assimilate values that are determined by the main code block which is about 40 if statements similar in structure to the block above, all contained within a For loop.
In the following code block I am trying to insert an object of ListViewItem type into the ListView. This is where I'm getting my error denoted by comment string following it. The function that fills the ListViewItem is at the bottom, all of the variables returned are all class variables and return valid values to the ListViewItem. I have double checked this via the debugger.
Private Sub AbsenceLine()
Dim sTypeReason As String
If msType = "" Then
sTypeReason = Left(msReason, 25)
Else
sTypeReason = msType & "--" & msReason
End If
Dim item As ListViewItem
item = New ListViewItem(ListViewItemType.DataItem)
item.DataItem = FillListView(sTypeReason)
absence_lv.Items.Add(item) 'this line here is what is givine me issues
End Sub
Private Function FillListView(typeReason As String) As IEnumerable(Of String)
Return {msDate, msVoid, msCont, msDays, msHours, msMinutes, typeReason, msChargeDays, msChargeHours,
msChargeMins, msHowPaid} 'all values returned are of String type
End Function
Now with the background:
Am I completely off base with what I'm trying to do?
Is there an easier way to do this with a gridview instead?
I think you're misusing the DataItem property of the ListViewItem class. That's really used to get the underlying object that the ListViewItem represents when the ListView itself is bound.
Since your FillListView function is returning an IEnumerable(Of String), you can just set the ListView's DataSource property to the function call.
absence_lv.Datasource = FillListView(sTypeReason)
absence_lv.Databind()
As you can see, there is no need to manually add each item.

How to check if sqlParameter is empty?

I have a class, which has many "New()" functions to initiate it with various parameters. I would like to create a New() function that will init the class with no arguments. The problem is there is a "fillData" function which fills the data for the class, and takes in the stored procedure to do the work, but has a stored procedure parameter. I don't want to create a new fillData function, but would like to use the fillData function with no additional need for a stored procedure. My way of going about this was to pass an empty SqlParameter var to the fillData function, but no mater what I do, when I check the params parameter for being empty, it always seems to think there's stuff in there.
I would like to check if this "params" parameter is empty:
Public Sub New()
'just created this so i could pass something
'and continue using fillData as is.
Dim p(1) As SqlParameter
Dim db As sqldb.command
db = New sqldb.command(ConfigurationManager.ConnectionStrings("sqlConnectionString").ConnectionString)
fillData("r2m_getAllListingsSorted", p)
End Sub
...
Private Sub fillData(ByVal sp As String, ByVal params As SqlParameter())
Dim db As sqldb.command
Dim r As SqlDataReader
db = New sqldb.command(ConfigurationManager.ConnectionStrings("sqlConnectionString").ConnectionString)
'right here, im having the trouble, seems no matter how I try to "params",
'the code always defaults to db.executeReader(sp, p)
'I've tried params.Length = 0 and params.ToString = "" also.
If params.Value Then
r = db.executeReader(sp)
Else
r = db.executeReader(sp, params)
End If
How would I modify this so i could continue to use the fillData function, without passing a SqlParameter parameter to it?
Thank you!
You can make your SqlParameter Optional and give it a default value of Nothing:
Private Sub fillData(ByVal sp As String,
ByVal Optional params As SqlParameter() = Nothing)
Then call the method without the params argument:
fillData("StoredProcName")
You can then check the parameter inside the fillData method to see if it's Nothing before using it.
If params is Nothing Then
// Do something if there's no params
Else
// Do something if there is params
End If

Must I use parameters with an ObjectDataSource update?

I have a business object that I've been using, which has a bunch of properties and a Save method, which inserts/updates to the database. The save method is NOT status, so the object needs to be instantiated, and the properties for the DB update/insert get pulled from the object.
Now I'm trying to bind the object to a FormView with the ObjectDataSource. I have it working so it instantiates based on the QueryString parameter, no problem, and populates the textboxes just fine. The UpdateMethod I have set to the Save function. Now it gets stuck.
It seems the ObjectDataSource needs a method with all the fields/properties/textboxes as parameters. I would have thought it would update the object's properties and then call the parameterless Save function. Is this wishful thinking?
Do I now need to change my Save function to include parameters, and change all the instances where it's getting used to this new method, just for this reason?
Thanks
Sean
Unfortunatly it does require params.
I overloaded my insert/update methods to include a few params. Attach the ObjectDataSource to the method with params.
The overloaded Update method calls the original Update method saving all the data. Seems kind of hackish to me, but it works.
Public Sub Update()
Dim isUpdated As Boolean = False
sql = "UPDATE AudioFiles SET Title = #Title, [desc] = #desc, Active = #Active WHERE fileID = #fileID"
conn = New SqlConnection(connString)
conn.Open()
...
End Sub
Public Sub Update(ByVal upFileID As Integer, ByVal upTitle As String, ByVal upDesc As String, ByVal upActive As Boolean)
Dim isUpdated As Boolean = False
Dim audioFile As New AudioFiles(fileID)
If Len(upTitle) > 0 Then
_title = title
End If
...
audioFile.Update()
End Sub

Find locally declared Procedures and Methods in a webform code behind (GetMethods)

I am trying to get a subset of locally declared methods in a webform code behind using GetMethods but cannot figure out the proper BindingFlags settings (see code below)....and some further specific questions:
1) Is it possible to differentiate between Procedures and Functions?
2) Furthermore, I only want to fetch a certain subset of these....is there some way I can decorate the ones I want with an attribute, and then further filter based on that?
Private Sub LoadFunctions()
Dim thisClass As Type = Me.GetType
For Each method As MethodInfo In thisClass.GetMethods(BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.DeclaredOnly)
If method.Name.Substring(0, 3) = "Get" Then
Me.ddlCodeSamples.Items.Add(method.Name)
End If
Next
End Sub
a) The real source of the problem seemed to be reflecting on the wrong class.....from a webform, you must do:
Dim thisClass As Type = GetType(yourWebFormName)
...not:
Dim thisClass As Type = Me.GetType
b) I think method.ReturnType could be examined to differentiate between a procedure or method.
c) Here is how custom attributes could be used:
More or less working code:
Private Sub LoadFunctions()
'....When run from a webform that you want to reflect on the locally defined functions:
' This is *incorrect*:
' Dim thisClass As Type = Me.GetType
' This is *correct* (I'm not sure why though):
Dim thisClass As Type = GetType(CodeSamples) '<-- "CodeSamples" is the webform name
For Each method As MethodInfo In thisClass.GetMethods(BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
If Not method.IsSpecialName Then '<-- to exclude property getter/setters, etc
' Rather than filtering on function name, could use custom attributes as discussed here:
' http://www.codeguru.com/vb/gen/vb_general/attributes/article.php/c6073
If method.Name.Substring(0, 3) = "Get" Then
Me.ddlCodeSamples.Items.Add(method.Name)
End If
End If
Next
End Sub

Resources