VB.net anonymous type has incorrect property casing from AJAX call - ajax

We have noticed that sometimes from the results of an AJAX call to a controller action that the case of the JSON result is incorrect. The returned case will actually change if we rebuild our solution and try the exact same call. In the following case, the key's case has been correct for over a year until now when it has decided to start randomly changing depending on some seemingly random circumstances.
As you can see in the picture above, the key for the JSON result is lowercase "success". However when I view the results in Chrome's console, it is an uppercase "Success". This is causing our JavaScript to fail since it is checking for the lowercase version.
What is causing this? And more importantly, how do we stop this?

vb.net is case-insensitive as opposed to C# which is case-sensitive. This means that the compiler will generate only one class (from the first instance) for each of the following anonymous types:
Dim a = New With {.success = True} 'Compiler generate a class based on this type
Dim b = New With {.Success = True} 'Same type as `a`
Dim c = New With {.sUcCeSs = True} 'Same type as `a`
Debug.WriteLine(a.GetType().Name)
Debug.WriteLine(b.GetType().Name)
Debug.WriteLine(c.GetType().Name)
VB$AnonymousType_0'1
VB$AnonymousType_0'1
VB$AnonymousType_0'1
Here's how the complied code looks like when compiled back to vb.net:
<DebuggerDisplay("success={success}"), CompilerGenerated> _
Friend NotInheritable Class VB$AnonymousType_0(Of T0)
' Methods
<DebuggerNonUserCode> _
Public Sub New(ByVal success As T0)
Me.$success = success
End Sub
<DebuggerNonUserCode> _
Public Overrides Function ToString() As String
Dim builder As New StringBuilder
builder.Append("{ ")
builder.AppendFormat("{0} = {1} ", "success", Me.$success)
builder.Append("}")
Return builder.ToString
End Function
Public Property success As T0
<DebuggerNonUserCode> _
Get
Return Me.$success
End Get
<DebuggerNonUserCode> _
Set(ByVal Value As T0)
Me.$success = Value
End Set
End Property
Private $success As T0
End Class

Related

VB6 Subscript Out fo Range - but this is an odd one because a mirror function is working fine

Thanks for reading.
I have built a VB6 DLL (VB_InterFace just for a name) that talks to a C# DLL (C#_Driver just for a name) that talks to a Bluetooth Device.
The Demo VB6 test app (VB_Demo just for a name) I created as stage one works fine, does what it is supposed to. It calls the VB_Interface and Opens and Closes the BTDevice. Additional functions also work fine.
However on placing the operational code from VB_Interface into another DLL that is the live operations DLL, Open works fine, but Close is throwing an error. "Variable not defined" when returning from the C#_Driver.
I just can't see why, the code is the same, the process is only marginally different. By this I mean ;
In the VB_Demo I have two buttons "Open" "Close" and when I click on these I get the feedback that I expect from the BTDevice.
Private Sub btnOpenPort_Click()
'MsgBox steps(0)
ReDim steps(5)
Dim rc As HF4000_ResultCodes
'rc = driver.OpenSerial(cmbPorts.Text)
If driver.OpenSerial(cmbPorts.Text) = True Then
Private Sub btnClosePort_Click()
Dim rc As HF4000_ResultCodes
If driver.CloseSerial("COM4") = True Then
However in the live DLL it just executes the same functions internally without being initiated by a button click.
' See IScanDevice documentation.
' #see IScanDevice#OpenDevice
Private Function IScanDevice_OpenDevice() As Scanning.Scan_ResultCodes
(truncated slightly)
50 If driver.OpenSerial("COM4") = True Then
rc = READY
MsgBox "Connected to the device successfully."
' See IScanDevice documentation.
' #see IScanDevice#CloseDevice
Private Function IScanDevice_CloseDevice() As Scanning.Scan_ResultCodes
(truncated slightly)
50 If driver.CloseSerial("COM4") = True Then
60 rc = READY
70 IScanDevice_CloseDevice = Scan_Success
clsDriver.cls
Public Event OnStateChanged(newState As String)
Public Event OnDataUpdated()
Dim WithEvents CSharpInteropServiceEvents As CSharpInteropService.LibraryInvoke
Dim load As New LibraryInvoke
Private Sub Class_Initialize()
Set CSharpInteropServiceEvents = load
End Sub
Private Sub CSharpInteropServiceEvents_MessageEvent(ByVal newState As String)
If newState = "OpenForm1" Then
' FormDummy2.Show ' Not required
End If
If State <> newState Then
State = newState
RaiseEvent OnStateChanged(State)
GetDriverData
End If
End Sub
Private Function BluetoothTestInvoke(load, functionName, param)
BluetoothTestInvoke = load.GenericInvoke("BluetoothTest.dll", "BluetoothTest.Class1", functionName, param)
End Function
Function OpenSerial(portNumber) ' "COM4"
Dim param(0) As Variant
Dim retorno As Variant
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "OpenSerial", param)
OpenSerial = retorno(0) <<<<<<< Works fine returns TRUE
End Function
Function CloseSerial(portNumber) ' "COM4"
Dim param(0) As Variant
Dim retorno As Variant
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "CloseSerial", param)
CloseSerial = retorno(0) <<<<<<<<< "Error Subscript Out of Range"
End Function
What I have discovered is this - and I guess this is the reason why the Close is not working. The question is why is this situation occurring ...
When driver.OpenSerial executes, it hits > Function OpenSerial
Within Function OpenSerial it executes BluetoothTestInvoke where "load" is "CSharpInteropService.LibraryInvoke"
From there it moves to - Sub CSharpInteropServiceEvents_MessageEvent
.. and everything is fine.
However when I then execute driver.CloseSerial after that, it hits > Function CloseSerial
Within Function OpenSerial it executes BluetoothTestInvoke where "load" is "CSharpInteropService.LibraryInvoke"
Now here it "should" move to - Sub CSharpInteropServiceEvents_MessageEvent
However No, it just drops to the next line which is CloseSerial = retorno(0)
and this is where I get the "Subscript out of range" error for retorno(0)
For some reason in the CloseSerial it is not invoking "load"
BluetoothTestInvoke(load, "CloseSerial", param)
Thoughts and suggestions much appreciated.
UPDATE
Quite right, one should never assume anything.
On the tips I started digging deeper into the C# Library. It turns out the "param" value that is the Bluetooth port is passed into the CloseSerial call, and from there is is passed around within the external C# library dll. At one stage it is reset so the port number that should be handled is lost, thus it doesn't close but specifically the "expected" data was not returned to the calling app.
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "CloseSerial", param) << param was being reset in the external library.

how to return a object in a function that takes arguments visual basic 6

Hi im trying to write a function that returns an object but it gives me an arguments not optional error, this is my code
Public Function searchVehicle(c As String, v As Variant) As Collection
Dim qur As String
qur = "select * from [vehicle] where ( " & c & " like '%" & v & "%')"
Set mobjRst = conn.execQuery(qur)
Dim tmpV As Vehicle
Dim res As Collection
With mobjRst
Do Until .EOF
Set tmpV = New Vehicle
Call tmpV.popVehicle(!ID, !make, !model, !purchaseyear, !totalmilage, !milageafterservice, !servicemilage, !description)
res.Add (tmpV)
.MoveNext
Loop
End With
searchVehicle = res
End Function
My first thought is that since it's an object reference, you need to use Set to set the return value.
Set searchVehicle = res
It may be more helpful to know what line you're seeing the problem on.
As a side note, you may also want to take a look at when you need to use Call and when you don't: https://blogs.msdn.microsoft.com/ericlippert/2003/09/15/what-do-you-mean-cannot-use-parentheses/
Your problem lies in the following call to the function -
searchVehicle = res
You have specified searchVehicle to have a string (c) and a variant (v) combining a collection. This will error as you have set no values to either c or v and then call your function -
searchVehicle = (c, v) collection
give us some more information on how you call this etc in your button click event, what is returned...

SQL server reporting Validate parameter is in correct format

On my reporting application which is developed using SSRS 2005, I have a parameter of type string which accepts time. the time should be in the format "HH:mm:ss" How can I check if the input string is of correct format?
I tried to do the following
IsDate(TimeValue(parametr!stime.Value))
This returns true as long as the value is within range. But if the value is 24:00:00 or a wrong value then an exception is thrown.
I also tried to create a function in the report code as follows:
Public Function CheckNum(sNum as String) as Boolean
Dim msg as String
msg = ""
Try
If IsDate(TimeValue(sNum))=1 Then
Return True
Else
msg="Parameter must be a number"
End If
Catch ex as Exception
Return False
End Try
If msg <> "" Then
MsgBox(msg, 16, "Parameter Validation Error")
Err.Raise(6,Report) 'Raise an overflow
End If
End Function
And when I input a value 24:00:00 I still get an error
" The conversion of a char type to datetime data type resulted in an out of range date time value"
How can I handle the exception so that I don't the error?
EDIT:
public Function CheckNum(sNum as String) as Boolean
Dim REGEX_TIME = "^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(:([0-5]?[0-9]))?$"
If System.Text.RegularExpressions.Regex.IsMatch(sNum, REGEX_TIME) Then
Return True
Else
Return False
End If
End Function
Then I assigned a parameter(validateTime) value as =Code.CheckNum(Parameters!sTime.Value)
But the value of the parameter is always true. When I specify a value greater than 23, I still see the error. Please see the image
Instead of using IsDate function, use VB.NET regular expressions. SSRS allows full use of .NET functions.
See an example of time regex.
A good tutorial on regex.
Example Code Console Application
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim REGEX_TIME = "^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(:([0-5]?[0-9]))?$"
Dim InputList As List(Of String) = New List(Of String)
InputList.Add("25:00:21")
InputList.Add("22:00:21")
InputList.Add("AA:00:21")
InputList.Add("17:21:02")
For Each input As String In InputList
If Regex.IsMatch(input, REGEX_TIME) Then
Console.WriteLine("TIME " + input + " IS OK")
Else
Console.WriteLine("TIME " + input + " IS NOT OK")
End If
Next
End Sub
End Module
Output is :
TIME 25:00:21 IS NOT OK
TIME 22:00:21 IS OK
TIME AA:00:21 IS NOT OK
TIME 17:21:02 IS OK
I think, you can capture a InvalidCastException.

Returning Null or Nothing from VBScript function?

I'm trying to write the VBScript equivalent of a function similar to what's below:
object getObject(str)
{
if ( ... )
{
return object_goes_here;
}
return null;
}
My guess would be below, except that I'm not understanding the difference between Nothing and Null. As a caller, I'd rather test if the return value is set by using IsNull() versus X Is Nothing.
Function getObject(str)
If ... Then
Set getObject = object_goes_here
Exit Function
End If
Set getObject = Nothing // <-- or should this be Null?
End Function
The correct way to not return an object is to return Nothing and test for Is Nothing.
VB's Null is a special value of type Variant/Null. There are other special values, such as Variant/Empty or Variant/Error. They all have their use, but it's not the one.
Use the second Function skeleton. Avoid Null when dealing with objects, because of the Set Assignment abomination.
Dim oX : Set oX = getObject(...)
If oX Is Nothing Then
...
Else
nice object to work with here
End If
vs
Dim vX : vX = getObject(...) ' <-- no Set, no object
If IsNull(vX) Then
...
Else
no object to work with here
End If
In your sample code, the object gets always Nothing because that is the last action. This is how it should be:
Function getObject(str)
If ... Then
Set getObject = object_goes_here
Exit Function
End If
Set getObject = Nothing
End Function
or:
Function getObject(str)
Set getObject = Nothing
If ... Then
Set getObject = object_goes_here
End If
End Function
The answer of GSerg is correct: you should use Nothing. Additionally, to see if an object has a null reference, use:
If Not object Is Nothing Then
' do something
End If

BestPractices: Out parameters vs complex return types in methods

Using complex return type:
Public Type TimeType
hours As Integer
minutes As Integer
End Type
Public Function ParseTimeField(time As String) As TimeType
Dim timeObject As TimeType
Dim amountOfDigitHours As Integer
If time = "" Then time = "0"
If HasHoursAndMinutesParts(time) Then
amountOfDigitHours = GetAmountOfDigitHours(time)
timeObject.hours = CInt(Left(time, amountOfDigitHours))
timeObject.minutes = CInt(Right(time, 2))
Else
timeObject.hours = 0
timeObject.minutes = CInt(time)
End If
ParseTimeField = timeObject
End Function
Private Function HasHoursAndMinutesParts(time As String) As Boolean
HasHoursAndMinutesParts = Len(time) > 2
End Function
Private Function GetAmountOfDigitHours(time As String) As Integer
GetAmountOfDigitHours = Len(time) - 2
End Function
Call:
Dim timeObj As TimeType
timeObj = ParseTimeField(strTime)
OR using out parameters:
Public Function ParseTimeField(time As String, ByRef hours As Integer, ByRef minutes As Integer)
Dim timeObject As TimeType
Dim amountOfDigitHours As Integer
If time = "" Then time = "0"
If HasHoursAndMinutesParts(time) Then
amountOfDigitHours = GetAmountOfDigitHours(time)
hours = CInt(Left(time, amountOfDigitHours))
minutes = CInt(Right(time, 2))
Else
hours = 0
minutes = CInt(time)
End If
ParseTimeField = timeObject
End Function
Private Function HasHoursAndMinutesParts(time As String) As Boolean
HasHoursAndMinutesParts = Len(time) > 2
End Function
Private Function GetAmountOfDigitHours(time As String) As Integer
GetAmountOfDigitHours = Len(time) - 2
End Function
Call:
Dim hours As Integer
Dim minutes As Integer
Call ParseTimeField(strTime, hours, minutes)
BTW this is VB6 code =)
If you have a single return type, do not use an out parameter to return it.
In general, I find multiple ref/out parameters to be a code smell. If you need to return data from your method, it is better if it is in one coherent object.
I have a feeling we're going to see different opinions on this matter. Not sure there exists a best practice.
I usually prefer complex datatypes because I feel that is more in line with the original structure of functions where output parameter preceed the input parameters in the signature. Basically I don't like out parameters - they're superfluous. Whenever there's two ways of doing a thing in a programming language, you complicate unneccessary (guess I'm gonna get killed by Perl-fanatics stating this). You return data with the return statement. Period.
This said, I still find myself using out parameters often when I need to return two parameteres that have no natural grouping - i.e. would end up in a class which would be used solely in the return value of this specific function.
Whenever there's three or more parameters in the return data, I never use out simply because I find the calling code to be excessive verbose - needing to Dim the variables (or var'em in C#)
I tend to use out params as the universal style. Rarely need to implement helper functions that return UDT but these are usually private to the module so I can keep the scope of the UDT private to the module too.
In the latter case usually consume the retval like this
With ParseTimeField(strTime)
Debug.Print .hours, .minutes
End With
... and most probably would keep TimeType with private scope.
Definately a matter of opinion. I do use ByRef parameters from time to time, especially for utility functions which require a success/fail type scenario. For example, the TryParse functions in the .net framework do exactly this. Your parametrised function could look like:
Public Function ParseTimeField(time As String, ByRef hours As Integer, ByRef minutes As Integer) As Boolean
'Do stuff'
ParseTimeField = True 'or false depending on output success'
End Sub
Meaning you can call it like:
Dim hours As Integer
Dim mins as Integer
If ParseTimeField(time, hours, mins) = True Then
'It worked'
End If
However as things start to get more complicated, and you're actually returning business items as opposed to doing logical commands, then a separate class and a return type is more desirable. It also makes calling AND returning easier to maintain.

Resources