Converting Fixed length statement from VB6 to VB.Net - vb.net

We perform a protocol based data sending to device where the device requires a formatted data packets.
the sample packet data is XXFSXXXFSXXXXXXXFSXXXXXX. The X mentioned is the max length size of each string. if data is less than string max length it should be filled with NULL character like ..11FS123FS1234XXXX (the remaining X will be filled with NULL).
I am just trying to convert one of VB6 function to VB.Net and below is the converted statement where i am facing issue
Option Strict Off
Option Explicit On
Imports Microsoft.VisualBasic.Compatibility.VB6
Imports System
Imports System.Runtime.InteropServices
Module FunctionCmd_Msg
Public FunCommand_Msg As Fun_CommandMessage = Fun_CommandMessage.CreateInstance()
'Function Command Message
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ _
Public Structure Fun_CommandMessage
<VBFixedString(1)> Public one As String
<VBFixedString(1)> Public two As String
<VBFixedString(3)> Public three As String
Dim five As String
<VBFixedString(8)> Public four As String
Public Shared Function CreateInstance() As Fun_CommandMessage
Dim result As New Fun_CommandMessage
result.one = String.Empty
result.two = String.Empty
result.three = String.Empty
result.four = String.Empty
result.five = String.Empty
End Function
End Structure
End Module
assuming:
one = "1"
two = "1"
three = "123"
four = "5678"
five = "testing"
FS = character (field separator)
on concatenating the strings i need a fixed length string such like this:
one & two & FS & three & FS & five & FS & four
output: since four is a fixed length string of 8 length remaining 4 characters should be filled with null as below
11 FS 123 FS testing FS 5678XXXX

Fixed-length strings simply make no sense in .NET any more. Microsoft tried to provide a similar class for easier upgrade but the truth is that you should change your code depending on usage:
What did the fixed-length string do in your VB6 code? Was it for no good reason? Then use a normal String in .NET.
Was it for interop with a C API? Then use marshalling to set a size for an array in the C API call.

Just forget about the fixed length, and use regular vb.net strings. They will return fine to whatever calls that code, including interop.
So, just pad your strings, and you off to the races.
In fact, build a Msg class that does the dirty work for you.
This looks quite nice to me:
NOTE how I set this up that you ONLY define the length of the string in ONE place. (so I use len(m_string) to determine the length from THEN on in the code.
Also, for debug and this example, in place of vbcharNull (which you should use), I used X for testing.
Now, in your code?
Just use this:
Dim Msg As New MyMsg
With Msg
.one = "A"
.two = "B"
.three = "C"
.four = "D"
.Five = "E"
End With
Debug.WriteLine(Msg.Msg("*") & vbCrLf)
Debug.WriteLine("total lenght = " & Len(Msg.Msg("X").ToString))
Output:
A*B*CXX*EXXXXXXX*DXXXXXXX
total lenght = 25
I note in your code that you have FIVE before FOUR - but if that is what you want, then no problem
Note that the class ALWAYS maintains the lengths for you.
So just paste this code into your module or even a new separate class.
Public Class MyMsg
'Dim cPad As Char = vbNullChar
Dim cPad As Char = "X"
Private m_one As String = New String(cPad, 1)
Private m_two As String = New String(cPad, 1)
Private m_three As String = New String(cPad, 3)
Private m_four As String = New String(cPad, 8)
Private m_five As String = New String(cPad, 8)
Public Property one As String
Get
Return m_one
End Get
Set(value As String)
m_one = MyPad(value, m_one)
End Set
End Property
Public Property two As String
Get
Return m_two
End Get
Set(value As String)
m_two = MyPad(value, m_two)
End Set
End Property
Public Property three As String
Get
Return m_three
End Get
Set(value As String)
m_three = MyPad(value, m_three)
End Set
End Property
Public Property four As String
Get
Return m_four
End Get
Set(value As String)
m_four = MyPad(value, m_four)
End Set
End Property
Public Property Five As String
Get
Return m_five
End Get
Set(value As String)
m_five = MyPad(value, m_five)
End Set
End Property
Public Function Msg(FS As String) As String
Return m_one & FS & m_two & FS & m_three & FS & m_five & FS & m_four
End Function
Private Function MyPad(str As String, strV As String) As String
Return Strings.Left(str & New String(Me.cPad, Len(strV)), Len(strV))
End Function
End Class
As noted, change the commented out line of "X" for the char back to vbCharNull.
And of course you STILL get to choose the delimiter. I used
Msg.Msg("*")
so I used a "*", but you can use space, or anything you want.

Related

Get a specific value from the line in brackets (Visual Studio 2019)

I would like to ask for your help regarding my problem. I want to create a module for my program where it would read .txt file, find a specific value and insert it to the text box.
As an example I have a text file called system.txt which contains single line text. The text is something like this:
[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]
What i want to do is to get only the last name value "xxx_xxx" which every time can be different and insert it to my form's text box
Im totally new in programming, was looking for the other examples but couldnt find anything what would fit exactly to my situation.
Here is what i could write so far but i dont have any idea if there is any logic in my code:
Dim field As New List(Of String)
Private Sub readcrnFile()
For Each line In File.ReadAllLines(C:\test\test_1\db\update\network\system.txt)
For i = 1 To 3
If line.Contains("Last Name=" & i) Then
field.Add(line.Substring(line.IndexOf("=") + 2))
End If
Next
Next
End Sub
Im
You can get this down to a function with a single line of code:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Return File.ReadLines(fileName).Where(Function(line) RegEx.IsMatch(line, "[[[]Last Name=(?<LastName>[^]]+)]").Select(Function(line) RegEx.Match(line, exp).Groups("LastName").Value)
End Function
But for readability/maintainability and to avoid repeating the expression evaluation on each line I'd spread it out a bit:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Dim exp As New RegEx("[[[]Last Name=(?<LastName>[^]]+)]")
Return File.ReadLines(fileName).
Select(Function(line) exp.Match(line)).
Where(Function(m) m.Success).
Select(Function(m) m.Groups("LastName").Value)
End Function
See a simple example of the expression here:
https://dotnetfiddle.net/gJf3su
Dim strval As String = " [Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim strline() As String = strval.Split(New String() {"[", "]"}, StringSplitOptions.RemoveEmptyEntries) _
.Where(Function(s) Not String.IsNullOrWhiteSpace(s)) _
.ToArray()
Dim lastnameArray() = strline(1).Split("=")
Dim lastname = lastnameArray(1).ToString()
Using your sample data...
I read the file and trim off the first and last bracket symbol. The small c following the the 2 strings tell the compiler that this is a Char. The braces enclosed an array of Char which is what the Trim method expects.
Next we split the file text into an array of strings with the .Split method. We need to use the overload that accepts a String. Although the docs show Split(String, StringSplitOptions), I could only get it to work with a string array with a single element. Split(String(), StringSplitOptions)
Then I looped through the string array called splits, checking for and element that starts with "Last Name=". As soon as we find it we return a substring that starts at position 10 (starts at zero).
If no match is found, an empty string is returned.
Private Function readcrnFile() As String
Dim LineInput = File.ReadAllText("system.txt").Trim({"["c, "]"c})
Dim splits = LineInput.Split({"]["}, StringSplitOptions.None)
For Each s In splits
If s.StartsWith("Last Name=") Then
Return s.Substring(10)
End If
Next
Return ""
End Function
Usage...
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = readcrnFile()
End Sub
You can easily split that line in an array of strings using as separators the [ and ] brackets and removing any empty string from the result.
Dim input As String = "[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim parts = input.Split(New Char() {"["c, "]"c}, StringSplitOptions.RemoveEmptyEntries)
At this point you have an array of strings and you can loop over it to find the entry that starts with the last name key, when you find it you can split at the = character and get the second element of the array
For Each p As String In parts
If p.StartsWith("Last Name") Then
Dim data = p.Split("="c)
field.Add(data(1))
Exit For
End If
Next
Of course, if you are sure that the second entry in each line is the Last Name entry then you can remove the loop and go directly for the entry
Dim data = parts(1).Split("="c)
A more sophisticated way to remove the for each loop with a single line is using some of the IEnumerable extensions available in the Linq namespace.
So, for example, the loop above could be replaced with
field.Add((parts.FirstOrDefault(Function(x) x.StartsWith("Last Name"))).Split("="c)(1))
As you can see, it is a lot more obscure and probably not a good way to do it anyway because there is no check on the eventuality that if the Last Name key is missing in the input string
You should first know the difference between ReadAllLines() and ReadLines().
Then, here's an example using only two simple string manipulation functions, String.IndexOf() and String.Substring():
Sub Main(args As String())
Dim entryMarker As String = "[Last Name="
Dim closingMarker As String = "]"
Dim FileName As String = "C:\test\test_1\db\update\network\system.txt"
Dim value As String = readcrnFile(entryMarker, closingMarker, FileName)
If Not IsNothing(value) Then
Console.WriteLine("value = " & value)
Else
Console.WriteLine("Entry not found")
End If
Console.Write("Press Enter to Quit...")
Console.ReadKey()
End Sub
Private Function readcrnFile(ByVal entry As String, ByVal closingMarker As String, ByVal fileName As String) As String
Dim entryIndex As Integer
Dim closingIndex As Integer
For Each line In File.ReadLines(fileName)
entryIndex = line.IndexOf(entry) ' see if the marker is in our line
If entryIndex <> -1 Then
closingIndex = line.IndexOf(closingMarker, entryIndex + entry.Length) ' find first "]" AFTER our entry marker
If closingIndex <> -1 Then
' calculate the starting position and length of the value after the entry marker
Dim startAt As Integer = entryIndex + entry.Length
Dim length As Integer = closingIndex - startAt
Return line.Substring(startAt, length)
End If
End If
Next
Return Nothing
End Function

How to harness auto-completion of strings?

I'm writing an application in which I have to pass strings as parameters. Like these:
GetValue("InternetGatewayDevice.DeviceInfo.Description")
GetValue("InternetGatewayDevice.DeviceInfo.HardwareVersion")
CheckValue("InternetGatewayDevice.DeviceInfo.Manufacturer")
ScrambleValue("InternetGatewayDevice.DeviceInfo.ModelName")
DeleteValue("InternetGatewayDevice.DeviceInfo.ProcessStatus.Process.1")
The full list is about 10500 entries, and i tought that i'd be really lost in searching if i misspell something.
So I am trying to declare a namespace for every string segment (separated by ".") and declare the last as a simple class that widens to a String of its FullName (except the base app namespace):
Class xconv
Public Shared Widening Operator CType(ByVal d As xconv) As String
Dim a As String = d.GetType.FullName
Dim b As New List(Of String)(Strings.Split(a, "."))
Dim c As String = Strings.Join(b.Skip(1).ToArray, ".")
Return c
End Operator
End Class
So I'd have these declarations:
Namespace InternetGatewayDevice
Namespace DeviceInfo
Class Description
Inherits xconv
End Class
End Namespace
End Namespace
This way IntelliSense is more than happy to autocomplete that string for me.
Now I'd have to do this for every possible string, so I opted (in order to retain my sanity) to make a method that does that:
Sub Create_Autocomlete_List()
Dim pathlist As New List(Of String)(IO.File.ReadAllLines("D:\list.txt"))
Dim def_list As New List(Of String)
Dim thedoc As String = ""
For Each kl As String In pathlist
Dim locdoc As String = ""
Dim el() As String = Strings.Split(kl, ".")
Dim elc As Integer = el.Length - 1
Dim elz As Integer = -1
Dim cdoc As String
For Each ol As String In el
elz += 1
If elz = elc Then
locdoc += "Class " + ol + vbCrLf + _
"Inherits xconv" + vbCrLf + _
"End Class"
Else
locdoc += "Namespace " + ol + vbCrLf
cdoc += vbCrLf + "End Namespace"
End If
Next
locdoc += cdoc
thedoc += locdoc + vbCrLf + vbCrLf
Next
IO.File.WriteAllText("D:\start_list_dot_net.txt", thedoc)
End Sub
The real problem is that this is HORRIBLY SLOW and memory-intense (now i dot a OutOfMemory Exception), and I have no idea on how Intellisense would perform with the (not available in the near future) output of the Create_Autocomlete_List() sub.
I believe that it would be very slow.
So the real questions are: Am I doing this right? Is there any better way to map a list of strings to auto-completable strings? Is there any "standard" way to do this?
What would you do in this case?
I don't know how Visual Studio is going to perform with thousands of classes, but your Create_Autocomlete_List method can be optimized to minimize memory usage by not storing everything in memory as you build the source code. This should also speed things up considerably.
It can also be simplified, since nested namespaces can be declared on one line, e.g. Namespace First.Second.Third.
Sub Create_Autocomlete_List()
Using output As StreamWriter = IO.File.CreateText("D:\start_list_dot_net.txt")
For Each line As String In IO.File.ReadLines("D:\list.txt")
Dim lastDotPos As Integer = line.LastIndexOf("."c)
Dim nsName As String = line.Substring(0, lastDotPos)
Dim clsName As String = line.Substring(lastDotPos + 1)
output.Write("Namespace ")
output.WriteLine(nsName)
output.Write(" Class ")
output.WriteLine(clsName)
output.WriteLine(" Inherits xconv")
output.WriteLine(" End Class")
output.WriteLine("End Namespace")
output.WriteLine()
Next
End Using
End Sub
Note the use of File.ReadLines instead of File.ReadAllLines, which returns an IEnumerable instead of an array. Also note that the output is written directly to the file, instead of being built in memory.
Note Based on your sample data, you may run into issues where the last node is not a valid class name. e.g. InternetGatewayDevice.DeviceInfo.ProcessStatus.Process.1 - 1 is not a valid class name in VB.NET. You will need to devise some mechanism to deal with this - maybe some unique prefix that you could strip in your widening operator.
I'm also not sure how usable the resulting classes will be, since presumably you would need to pass an instance to the methods:
GetValue(New InternetGatewayDevice.DeviceInfo.Description())
It seems like it would be nicer to have Shared strings on a class:
Namespace InternetGatewayDevice
Class DeviceInfo
Public Shared Description As String = "Description"
Public Shared HardwareVersion As String = "HardwareVersion"
' etc.
End Class
End Namespace
So you could just reference those strings:
GetValue(InternetGatewayDevice.DeviceInfo.Description)
However, I think that would be a lot harder to generate without creating name clashes due to the various levels of nesting.

Looping through a list gives me repeation of items, xml serializer

I have two lists. Both are made of structures I have defined, and this loop is meant to convert the two. I.e., convert and then add to the second list of the other type. Here is what I have:
Dim tempList As New List(Of CameraTemplateProduct)
tempList.Clear()
For j As Integer = 0 To EditCamerasNEW.templateList.Count - 1
'Set up product object.
Dim temp As New CameraTemplateProduct()
'equal properties
temp.Name = EditCamerasNEW.templateList.Item(j).mac
temp.Bitrate = EditCamerasNEW.templateList.Item(j).bitrate
temp.CamDate = EditCamerasNEW.templateList.Item(j).camdate
temp.CamTime = EditCamerasNEW.templateList.Item(j).camtime
temp.Encoder = EditCamerasNEW.templateList.Item(j).encoder
temp.FPS = EditCamerasNEW.templateList.Item(j).fps
temp.Hostname = EditCamerasNEW.templateList.Item(j).hostname
temp.MD = CBool(EditCamerasNEW.templateList.Item(j).MDen)
temp.OSD = CBool(EditCamerasNEW.templateList.Item(j).OSD)
temp.Resolution = EditCamerasNEW.templateList.Item(j).res
tempList.Add(temp)
Next
'Serialize object to a text file.
Dim x As New XmlSerializer((tempList.GetType))
x.Serialize(objStreamWriter, tempList)
Very straight forward. Copy over each property, then add it to the list. When I'm in the loop, temp's values copy over well. The values are exactly the same as the item in TemplateList. When I step through the loop, tempList is exactly what I expect it to be. Three distinct structures. But after wards I get the exact same number of items, but copies of one of them in my list.
However, the line right after the next loop, the tempList instead is the exact same count as templateList, but each value is exactly the same. So every item has the same name, MD, encoder, etc value.
What I've tried: I've tried changing the line after the next to
Dim x As New XmlSerializer((GetType(List(Of CameraTemplateProduct))))
but it gives the same result.
What am I doing wrong? Is there anything the "templist.gettype" is doing to cause this?
EDIT:
I have found that the temp is not changing property values when it loops, so it stays stuck at the first loop values. Is there a better way to clear or set it? I tried setting it to Nothing, but it gave me NULL assignment error.
EDIT2: So following the comments,
I checked to see if the templatelist items were changing. I added a
Dim test = EditCamerasNEW.templateList(j).mac
for each loop to see that it changed. The value did change. I set the rest of the "templatelist.item(j).x" to just "templatelist(j)" as above, but it didn't stop it from creating a list of repeated values.
EDIT3 Tried the below method to no avail. I'm thinking it is possibly when I create the templist of my class. It may not know how to create a list of the product? I will take any help on that.
tempList.Add(New CameraTemplateProduct With {.Name = EditCamerasNEW.templateList(j).mac, _
.Bitrate = EditCamerasNEW.templateList(j).bitrate, _
.CamDate = EditCamerasNEW.templateList(j).camdate, _
.CamTime = EditCamerasNEW.templateList(j).camtime, _
.Encoder = EditCamerasNEW.templateList(j).encoder, _
.FPS = EditCamerasNEW.templateList(j).fps, _
.Hostname = EditCamerasNEW.templateList(j).hostname, _
.MD = EditCamerasNEW.templateList(j).MDen, _
.OSD = EditCamerasNEW.templateList(j).OSD, _
.Resolution = EditCamerasNEW.templateList(j).res})
Here's a portion of the CameraTemplateProduct definition. It's pretty normal:
Public Class CameraTemplateProduct
Public Shared strhostname As String
Public Shared bOSD As Boolean
Public Shared strbitrate As String
Public Shared strencoder As String
Public Shared bMDen As Boolean 'motion detection enabled
Public Shared strres As String
Public Shared intfps As Integer
Public Shared strcamtime As String
Public Shared strcamdate As String
Public Shared strTemplateName As String
'grab properties
Public Property Name() As String
Get
Name = strTemplateName
End Get
Set(ByVal Value As String)
strTemplateName = Value
End Set
End Property
Public Property Hostname() As String
Get
Hostname = strhostname
End Get
Set(ByVal Value As String)
strhostname = Value
End Set
End Property
Public Property OSD() As Boolean
Get
OSD = bOSD
End Get
Set(ByVal Value As Boolean)
bOSD = Value
End Set
End Property
' code continues

request.querystring in vb.net

I have this url that i need to decode:
http://gistest:54321/default.aspx?data=%7B%22id%22:%2269403%22,%22longitude%22:%22-143.406417%22,%22latitude%22:%2232.785834%22,%22timestamp%22:%2223-10%2010:12%22%7D
This code changes every time
I use this code:
<%Response.Write(Request.QueryString.Item("data") )%><br/>
<%Response.Write(Request.QueryString.Item("id") )%><br/>
<%Response.Write(Request.QueryString.Item("longitude") )%><br/>
<%Response.Write(Request.QueryString.Item("latitude") )%><br/>
<%Response.Write(Request.QueryString.Item("timestamp") )%><br/>
But i only get this as output, maybe there is an option where to check if data is not null, and then i request.querystring the other parts in data:
{"id"="69403","longitude"="-143.406417","latitude"="32.785834","timestamp"="23-10 10:12"}
This is from
<%Response.Write(Request.QueryString.Item("data") )%>
I really hope I understood the problem correctly. I am assuming you require the values of each key within the query string key called Data? To do so I used the code below:
Dim values() As String = Server.UrlDecode(Request.QueryString("data")).Replace("{", "").Replace("}", "").Split(New Char() {","}, StringSplitOptions.RemoveEmptyEntries)
For Each value As String In values
Dim keyValue() As String = value.Split(New Char() {":"}, StringSplitOptions.RemoveEmptyEntries)
Response.Write(keyValue(0).Replace("""", "") & " : " & keyValue(1).Replace("""", "") & "<br/>")
Next
In a nutshell, I decode the QueryString("data"), replace the braces and split the string into an array by using the comma as the first split character. We then end up with an array containing values in the following format "id":"649403".
Thereafter I iterate through the values and split one final time for each value based on the semi-colon (:) character.
With this method you can build and manipulate the data dynamically.
Code Edit
I replaced all references of ":" with "=" to ensure that the time stamp will be correctly retrieved and then split the key values based on =. You can use a select case to assign variables to values if necessary. (Obviously make sure your variable is not declared within the select as it will not be in the right scope for later use!)
If Request.QueryString("data") IsNot Nothing Then
Dim values() As String = Request.QueryString("data").Replace("{", "").Replace("}", "").Replace(""":""", """=""").Split(New Char() {","}, StringSplitOptions.RemoveEmptyEntries)
For Each value As String In values
Dim keyValue() As String = value.Split(New Char() {"="}, StringSplitOptions.RemoveEmptyEntries)
Response.Write(keyValue(0).Replace("""", "") & " : " & keyValue(1).Replace("""", "") & "<br/>")
Select Case keyValue(0).ToLower()
Case "id"
Dim id As String = keyValue(1)
End Select
Next
End If
Reflection Edit
Create an instance of your object then retrieve all its properties (Dim properties() As PropertyInfo = myObj.GetType().GetProperties()). Iterate through the properties and set the value where the name is equal to the key. Don't forget to import the System.Reflection library.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim data As String = "%7B%22id%22:%2269403%22,%22longitude%22:%22-143.406417%22,%22latitude%22:%2232.785834%22,%22timestamp%22:%2223-10%2010:12%22%7D"
If data IsNot Nothing Then
Dim myObj As New MyObject
Dim properties() As PropertyInfo = myObj.GetType().GetProperties()
Dim values() As String = Server.UrlDecode(data).Replace("{", "").Replace("}", "").Replace(""":""", """=""").Split(New Char() {","}, StringSplitOptions.RemoveEmptyEntries)
For Each value As String In values
Dim keyValue() As String = value.Split(New Char() {"="}, StringSplitOptions.RemoveEmptyEntries)
For Each prop As PropertyInfo In properties
If prop.Name.ToLower = keyValue(0).ToLower.Replace("""", "") Then
prop.SetValue(myObj, keyValue(1), Nothing)
End If
Next
Next
myObj.Save()
End If
End Sub
Public Class MyObject
Private _ID As String
Private _Longitude As String
Private _Latitude As String
Private _Timestamp As String
Public Property ID As String
Get
Return _ID
End Get
Set(value As String)
_ID = value
End Set
End Property
Public Property Longitude As String
Get
Return _Longitude
End Get
Set(value As String)
_Longitude = value
End Set
End Property
Public Property Latitude As String
Get
Return _Latitude
End Get
Set(value As String)
_Latitude = value
End Set
End Property
Public Property Timestamp As String
Get
Return _Timestamp
End Get
Set(value As String)
_Timestamp = value
End Set
End Property
Public Sub Save()
'Save logic here
End Sub
End Class
I think the problem you are running into is that there only is one querystring parameter in the URL you posted, and that is data. The rest of the information is encoded in the data querystring value. The value stored in data almost looks like a JSON/Javascript object, except with an = in between the property names and values instead of a :.
So, basically you won't be able to use Request.QueryString to get the values of id, longitude, latitude, etc. I think your options are to either write some code to parse the value of data yourself or replace the = with : and use a JSON parser for .NET (i.e., the JavascriptSerializer class or JSON.net).
Personally, I would write a method in the codebehind that would return a Dictionary(Of String, Object). In that method just I would just change every "=" to a ":" and then use the JavaScriptSerializer provided with .NET to parse the string. I don't have an ASP.NET instance handy right now, but the following sample I threw together in LinqPad should illustrate the idea:
Sub Main
Dim url = "http://gistest:54321/default.aspx?data=%7B%22id%22=%2269403%22,%22longitude%22=%22-143.406417%22,%22latitude%22=%2232.785834%22,%22timestamp%22=%2223-10%2010:12%22%7D"
Dim uri = New Uri(url)
Dim data = System.Web.HttpUtility.ParseQueryString(uri.Query)("data")
Dim o = ParseData(data)
Console.WriteLine(o("id"))
Console.WriteLine(o("longitude"))
Console.WriteLine(o("latitude"))
Console.WriteLine(o("timestamp"))
End Sub
Function ParseData(data As String) As Dictionary(Of String, Object)
Dim js = new System.Web.Script.Serialization.JavaScriptSerializer()
Dim o = js.DeserializeObject(data.Replace("""=""", """:"""))
ParseData = DirectCast(o, Dictionary(Of String, Object))
End Function
One thing to note about this approach is that I am expecting the url to be in the same format as what you posted. You may need to modify this method to make it more robust to handle different inputs.
If you drop the ParseData function into your codebehind, then something like the following code in your front page should give you the output you are looking for (again, sorry I don't have an ASP.NET instance to test with right now):
<%
Dim o = ParseData(Request.QueryString.Item("data"))
Response.Write(o("id"))
Response.Write("<br />")
Response.Write(o("longitude"))
Response.Write("<br />")
Response.Write(o("latitude"))
Response.Write("<br />")
Response.Write(o("timestamp"))
Response.Write("<br />")
%>

Find Consecutive numbers in an Array

I need to find consecutive numbers in an array and return a string which tells the range and numbers that don't form a range.
I found some of the already asked questions but none of them is in VB.Net:
Add to array consecutive numbers
If the array of numbers looks like {11,12,67,68,69,70,92,97} then returned string should be of the form 11,12, 67 through 70, 92 and 97.
This is not homework; I need this function for a word document containing statistical data.
Entered directly into the reply window, so there's almost certainly a bug or three:
Public Class Range
Public Shared Function PrintRanges(ByVal numbers() As Integer) As String
Dim buffer As New List(Of Range)()
Dim CurrentRange As Range = Nothing
For Each i As Integer in numbers ' you may want to add a .OrderBy() here
If CurrentRange IsNot Nothing AndAlso i - 1 = CurrentRange.EndValue Then
CurrentRange.Increase()
Else
CurrentRange = New Range(i)
buffer.Add(CurrentRange)
End If
Next i
'Got a little lazy for this line - it still does a ", " rather than " and " for the final delimiter. Simple code to fix it, just tedious.
Return String.Join(", ", buffer.Select(Function(r) r.ToString()).ToArray())
End Function
Private Sub New(ByVal InitialValue As Integer)
EndValue = IntialValue
Length = 1
End Sub
'For completeness, these two properties should be made read only outside the class, but the private constructor makes that largely moot
Public Property EndValue As Integer
Public Property Length As Integer
Public Sub Increase()
Length += 1
EndValue += 1
End Sub
Public Overrides Function ToString() As String
If Length == 1 Then Return EndValue.ToString()
If Length == 2 Then Return (EndValue -1).ToString() & "," & LastValue.ToString()
Return (EndValue - Length).ToString() & " through " & EndValue.ToString()
End Function
End Class