Inconsistent results from ASP classic - asp-classic

I have a somewhat unnerving problem when using constant values. I have a simple page called "test.asp" which sets a variable to a constant and then to a querystring value (if it exists). Then a select case checks if the variable matches the constant and outputs a message "matched". The problem is that asp does not recognise when the querystring value is the same as the constant.
I have run 2 attempts, "test.asp" and "test.asp?SortField=1". The first attempt runs as expected but the second attempt reports that 1 is not the same as 1.
The code for this page is as follows.
<%#LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<head></head>
<body>
<%
const cSortFielda = 1
dim vSortField
vSortField = cSortFielda
if not isempty(Request("SortField")) then
vSortField = Request("SortField")
end if
select case vSortField
case cSortFielda
response.write "matched</br>"
case else
response.write "failed</br>"
response.write "vSortField = " & vSortField & "(" & asc(vSortField) & ") </br>"
response.write "cSortFielda = " & cSortFielda & "(" & asc(cSortFielda) & ") </br>"
response.write "vSortField = cSortFielda is " & (vSortField = cSortFielda) & "</br>"
end select
%>
</body>
</html>
Am I missing something blatantly obvious or is asp classic at fault?
Thank you for any assistance.

You're comparing a string with a number. You need to make sure they are consistent. So either change this line:
const cSortFielda = 1
To:
const cSortFielda = "1"
Or change this line:
vSortField = Request("SortField")
To:
vSortField = CLng(Request("SortField"))
The first example compares string to string, and the second example compares number to number.

Comparing string against integer results in false. Add these and you would see.
Response.write TypeName(vSortField) & "<br/>"
Response.Write TypeName(cSortFielda) & "<br/>"
Make sure that both variables are of same type or convert before comparing. Since you are dealing with QueryString, it would be easier to use string type i.e. const cSortFielda = "1".

All variables are variants in VBScript unless you specify a literal value to that variable.
So const CSortFielda is a number.
But vSortField is a variant which holds the STRING of the value of the SortField query string item
Either change the const value to be a string
Const cSortFields = "1"
Or parse SortField as a number
If Not isEmpty(Request("SortField")) then
If IsNumeric(Request("SortField")) then
vSortField = CLng(Request("SortField"))
End If
End If
I would also suggest specifying that the field comes from the querystring, although that's not related to your actual problem:
Request.QueryString.Item("SortField")

Related

vb.net string concat adds vbCrlf literal to the string

I am trying to build a string that includes a newline character and is getting the weirdest result. This string is going to be stored in a SQL database to be later used as part of an email. My code is the following:
Dim strBody As String = "Andy," & Environment.NewLine
When I inspect the value of strBody during a debugging session, it is the following:
"Andy," & vbCrlf
I am obviously expecting is to be more like:
"Andy,"
Knowing that what is after the , is a hidden character.
Ultimately, the problem is... when I include strBody as part of my SQL insert statement, it literally shows up as the following within my SQL insert statement:
'Andy," & vbCrLf & "'
I was using this code yesterday and it worked fine. I am using similar code within another function of the same asp.net project and it works fine. I have tried using + instead of &, I have tried to use vbCrLf instead of Environment.NewLine, I have tried using stringbuilder, I have tried using string.concat. All with the same results where the & vbCrLf is included in strBody.
Is there a setting that I accidentally changed?
I know this is a weird one... Any help is greatly appreciated.
This is only Visual Studio showing you that there is new line character (vbCrLf or Environment.NewLine). If you use that string anywhere, it will be stored correctly.
I believe you will need to use some combination of Char(10) and Char(13):
Dim strBody As String = "'Andy,'" & " + CHAR(13)+CHAR(10) + "
There is a discussion about these and other methods on this thread.
You can do like this if you just need to insert Environment.NewLine inside database.
Dim a As String = """ & Environment.NewLine & """
Dim strBody As String = String.Format("Andy,{0}", a)
'"Andy," & Environment.NewLine & ""

Separating values in a textbox by special character

I have an asp.net/vb.net web app that requires information to be put into a multiline text box. If the user hits enter while in the textbox it drops down to next line, and they can enter more data in. When it tries to go to the database it fails because of the way the data is represented. I need help with looping through the field and getting each value.
This is how the data is represented in the DataTable
0;0.123;0.234;0.345;...
I need each value between the ; character... so I was thinking something like this?
If dbRow.Item("PV").ToString.Contains(";") Then
For Each symbol As String In DBTable.Rows
'get data b/w the ';'
Next
End If
Any help would be greatly appreciated
Edit:
If dbRow.Item("PV").ToString.Contains(";") Then
For Each s As String In dbRow.Item("PV").ToString
Dim fields() As String = s.Split(";"c)
For Each value As String In fields
.Append("'" & CDbl(value) & "'," & "SysDate,1)")
DBCommand.CommandText = myInsertIntoProperty_DataStringBuilder.ToString
DBCommand.ExecuteNonQuery()
myInsertIntoPropertyStringBuilder = New StringBuilder
Next
Next
Else
.Append("'" & CDbl(dbRow.Item("PV")) & "'," & "SysDate,1)")
End If
You mean something like this?
Dim s As String In dbRow.Item("PV").ToString()
Dim fields() As String = s.Split(";"c)
For Each value As String In fields
' Do what you want with the value
Next
Then access each value with field(0), fields(1), etc. You can then convert it to the appropriate type, for example:
Dim value As Double = Double.Parse(fields(0), CultureInfo.InvariantCulture)

Picking specific parts out of a query string

I have a query string which has more than one value being passed through it and I need to access the second passed value... I have this as of now:
If Request.QueryString("ANBOS") IsNot Nothing Then
Dim url As String = HttpContext.Current.Request.Url.AbsoluteUri
Dim index As Integer = url.IndexOf("-")
If index > 0 Then
url = url.Substring(0, index)
End If
DBTable = MaterialStuff.GetComponentsForMaterial(CInt(Request.QueryString(url)))
I'm attempting here to dumb everything after the first value I need, then go back and look at the query string where it's equal to ANBOS and get its value, but when I go get the value of it, the whole query string is still there, both values...
How do I make it so I just get the first value? Any help is greatly appreciated :)
Edit: Query String being passed through
Response.Redirect("Edit.aspx?ANBOS=" & CType(flxSearchResults.SelectedItem.Cells(1).Text, Integer) & "MaterialNumberToUpdate=" & NextMaterialID)
Your query string is being generated incorrectly
Response.Redirect("Edit.aspx?ANBOS=" & CType(flxSearchResults.SelectedItem.Cells(1).Text, Integer) & "MaterialNumberToUpdate=" & NextMaterialID)
should be..
Response.Redirect("Edit.aspx?ANBOS=" & CType(flxSearchResults.SelectedItem.Cells(1).Text, Integer) & "&MaterialNumberToUpdate=" & NextMaterialID)
This is because the query string uses ampersand signs (&) to separate key value pairs.

Boolean values in local language

This question has been asked long time ago on serverfault but no working awnser. I'm hoping somebody has encountered it and found a solution since then.
Example:
<%
Response.Write True
Response.Write "<hr>"
Response.Write "test:" & True
%>
Output:
True
--------------
test:Waar
As you can see, as soon as you combine the output, its turned into a local string ('Waar' is dutch for true). I need it to stay "True".
How can I change this? I dont mind putting some code at the beginning of the pages, but I cannot change all instances of True in the entire code. So creating a function like below to return the correct string wont do.
Function PB(pVal)
If pVal Then
PB = "true"
Else
PB = "false"
End If
End Function
Strange, I cannot get my IIS to output a boolean value in my local language no matter which locale is set.
Did you find this KB article already?
There is a description of a registry setting that could do the trick:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLEAUT
I don't want to mess with my production server, so I didn't try this yet.
FIRST ANSWER:
You could 'trick' VB to use your own functions. If you add these functions to the top of your page, VB will prefer these over the builtin ones, in this case CStr and Trim. Maybe this helps.
Function PB(pVal)
If pVal Then
PB = "true"
Else
PB = "false"
End If
End Function
Function CStr(pVal)
CStr = PB(pVal)
End Function
Function Trim(pVal)
Trim = PB(pVal)
End Function
Output:
True
--------------
test:true
--------------
test:true
--------------
test:true
I do something like this, but currently don't have a machine to test your case:
<%
Response.Write FormatDateTime(Now) & "<br />"
oldLocale = SetLocale(1026) 'Bulgarian
Response.Write FormatDateTime(Now) & "<br />"
SetLocale oldLocale
Response.Write FormatDateTime(Now) & "<br />"
%>
... from another SO question, it looks the above doesn't work.
What hapopens if you try these:
Response.Write "test:" & CStr(True)
or
Response.Write "test:" & Trim(True)
with or w/o SetLocale?
that is just like string concatenation works in vbscript.
from the vbscript language reference:
"Whenever an expression is not a string, it is converted to a String
subtype. If both expressions are Null, result is also Null. However,
if only one expression is Null, that expression is treated as a
zero-length string ("") when concatenated with the other expression.
Any expression that is Empty is also treated as a zero-length string."
If the SetLocale didn't work, then I think your best bet is to create a function.
Function TF(B)
If B Then
TF = "True"
Else
TF = "False"
End If
End Function
Then instead of saying this:
Response.Write "test:" & True
You'd say this:
Response.Write "test:" & TF(True)
You could try setting Response.LCID or Session.LCID to 1033 at the beginning of your page, but this also influences how others things (likes dates and currency variables) are displayed.
1033 is the Locale Id for the US
Attempt 2:
<%
arr=Array("False","True")
Response.Write True
Response.Write "<br /><br />"
Response.Write "" & arr( abs(True) ) & "<br />"
Response.Write "" & arr( abs(False) ) & "<br />"
%>
I found a solution if you dont mind changing regional settings to united states one. It involves changing the registry. This has been tested in windows 7 spanish and now it give native True/False instead of Verdadero/Falso.
Navigate to HKEY_USERS/.Default/Control Panel/International and take a nice picture with your phone in case you mess things up. you can also make a backup of the registry keys by clicking "international" and then File/export
Open a notepad and paste this inside (you can alternatively change values by hand one by one in the registry):
----------------- paste what is below this line -------------
Windows Registry Editor Version 5.00
[HKEY_USERS\.DEFAULT\Control Panel\International]
"Locale"="00000409"
"LocaleName"="en-US"
"s1159"=""
"s2359"=""
"sCountry"="United States"
"sCurrency"="$"
"sDate"="/"
"sDecimal"="."
"sGrouping"="3;0"
"sLanguage"="ENU"
"sList"=","
"sLongDate"="dddd, MMMM dd, yyyy"
"sMonDecimalSep"="."
"sMonGrouping"="3;0"
"sMonThousandSep"=","
"sNativeDigits"="0123456789"
"sNegativeSign"="-"
"sPositiveSign"=""
"sShortDate"="M/d/yyyy"
"sThousand"=","
"sTime"=":"
"sTimeFormat"="h:mm:ss tt"
"sShortTime"="h:mm tt"
"sYearMonth"="MMMM, yyyy"
"iCalendarType"="1"
"iCountry"="1"
"iCurrDigits"="2"
"iCurrency"="0"
"iDate"="0"
"iDigits"="2"
"NumShape"="1"
"iFirstDayOfWeek"="6"
"iFirstWeekOfYear"="0"
"iLZero"="1"
"iMeasure"="1"
"iNegCurr"="0"
"iNegNumber"="1"
"iPaperSize"="1"
"iTime"="0"
"iTimePrefix"="0"
"iTLZero"="0"
[HKEY_USERS\.DEFAULT\Control Panel\International\Geo]
"Nation"="244"
----------------- do not paste this line -------------
Save it as english.reg (or whatever.reg)
Double click it.
I didnt have to restart my computer for changes to take effect.
-------- UPDATE ----------
Does not work. If I make a blank asp page with this: <%=isnumeric(6)%> it answers True (in english) but as soon as I concatenate a True in a string it becames Verdadero again.
I was "caught" too with this "issue".
Indeed, this is not an issue :
THE PROBLEM (EXAMPLE)
I had the same problem when using a boolean data in a SQL Statement.
On my French server, my SQL statement was the following :
<%
'Set my boolean value
Dim myBoolean
myBoolean = True
'Set my SQL Statement
Dim MySQLStatement
MySQLStatement = "SELECT * FROM MyTable WHERE MyBooleanField = " & myBoolean
'=> Here, as MySQLStatement is a STRING, the boolean data was "converted/rendered" as a localized string. So that leads to this output :
'=> SELECT * FROM MyTable WHERE MyBooleanField = Vrai
'Obviously, that SQL Statement is incorrect, because the SQL Engine does NOT understand what is the "Vrai" word - It should be "True" instead.
%>
THE EXPLANATIONS :
It does not matter which regional settings are set on your Windows System : Nothing happens to the underlying data. A boolean data type is STILL a BOOLEAN, in English, or French, or German, Russian, Thai, ..or any language you want.
The fact is that the data is simply being RENDERED as a localized STRING (like dates).
THE SOLUTION
After a lot of reading over forums threads, the solution is not to change regional settings on the Windows system, nor changing Registry keys, nor changing Session.LCID, ...
The absolute and code-only solution is to convert the Boolean value (True|False) to an Integer (0|1). Then, this Integer will be safely usable in a string, and will remain (0|1).
Here is the safe way to use/convert/render a Boolean value in a non-localized form : Use an Integer value.
<%
'Set my boolean value
Dim myBoolean
myBoolean = True
'Set my SQL Statement
Dim MySQLStatement
MySQLStatement = "SELECT * FROM MyTable WHERE MyBooleanField = " & BoolToInt(myBoolean)
'=> Here, as MySQLStatement is a STRING, and as the boolean data was previously "converted/rendered" as an integer, we got this correct SQL Statement :
'=> SELECT * FROM MyTable WHERE MyBooleanField = 1
'This SQL Statement is correct, as the SQL Engine DOES understand that 1 is a boolean.
'This Function Returns an INTEGER value based on a BOOLEAN value
Function BoolToInt(v)
'INPUT:
'v Boolean value
'OUTPUT:
'Integer (0|1)
Dim b_OUT
b_OUT = v
'If the Input value is a "True" boolean value (in any language)
if (b_OUT = True) then
BoolToInt = cint(1)
'If the Input value is a "False" boolean value (in any language)
elseif (b_OUT = False) then
BoolToInt = cint(0)
end if
End Function 'BoolToInt
%>
I really hope it save your day !

Math operators as dynamic variables

I have no idea how I'm going to accomplish this BUT someway, somehow I have to perform calculations dynamically in ASP/VB.NET (Possibly SQL Server). Something like this:
Dim var1, var2 as Integer
Dim Optr as string
var1 = 15
var2 = 25
Optr = +
MyResult(var1, var2, Optr)
...and MyResult should equal 40. How can I do this? Anyone have any ideas? Thanks!
The only way I can think of is a switch case which deals with all possible operators.
If you want to implement something more complicated(with operator presedence) you can use the Shunting Yard Algorithm
I don't have the code specifics, but you if have your vars and operations concatenated as a single string you could parse the string and compile it, given you the proper result.
Check this SO questions and answers here, they discuss a very similar problem (if not the exact same)
I like Paul Sasik's example for a purely .net solution, but another alternative would be to make use of the VBScript engine that's part of windows.
For example (you'll need to add a reference to the COM MSScript control)
Static sc As MSScriptControl.ScriptControl
'---- init the script control once
If sc Is Nothing Then
sc = New MSScriptControl.ScriptControl
sc.Language = "VBScript"
sc.AllowUI = False
End If
Try
Return sc.Eval(Expr)
Catch ex As Exception
'Deal with any error conditions here
End Try
Where Expr is any expression you might want to evaluate.
Granted, this leverages VBScript support, which you might want to avoid, but, depending on your audience, they might be more comfortable with that than .net coding
To allow for arbitrarily complex calculations you could take advantage of .NET's on-fly-compilation features. Here's an article for starters.
For your particular implementation you would construct a calculation string from your input like this:
Dim toCalc as string = var1 & " " & Optr & " " & var2
...and use a process where the calculation would get injected into a dynamically created class that would look something like this: (working console sample based on the CP article)
Imports System.CodeDom.Compiler
Imports System.Reflection
Module Module1
Sub Main()
Dim var1 As Integer = 50
Dim var2 As Integer = 65
Dim Optr As String = "+"
Dim equation As String = var1 & " " & Optr & " " & var2
Dim nl As String = System.Environment.NewLine
Dim dynClass As String = ""
dynClass &= "public class DynamicClass" & nl
dynClass &= " public shared function Calc() as double" & nl
dynClass &= " return " & equation & nl
dynClass &= " end function" & nl
dynClass &= "end class" & nl
Try
Dim params As New CompilerParameters
params.ReferencedAssemblies.AddRange(New String() {"Microsoft.VisualBasic.dll"})
Dim mAssembly As Assembly = New VBCodeProvider().CreateCompiler. _
CompileAssemblyFromSource(params, dynClass).CompiledAssembly
Console.WriteLine("Calculating: " & equation)
Console.WriteLine("SUCCESS! Result: " & mAssembly. _
GetType("DynamicClass"). _
InvokeMember("Calc", _
BindingFlags.InvokeMethod Or _
BindingFlags.Public Or _
BindingFlags.Static, _
Nothing, Nothing, Nothing).ToString())
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
End Module

Resources