Move string into a Collection - vb.net

I'm receiving post data on the server-side which resembles a querystring:
type=subscribe&fired_at=2021-07-16 07:51:09&data[id]=ebdc32dce6&data[email]=xyz#fakeemail.com&data[email_type]=html&data[ip_opt]=110.20.71.126&data[ip_signup]=110.100.22.217&data[web_id]=566760869&data[merges][EMAIL]=xyz#fakeemail.com.com&data[merges][FNAME]=&data[merges][LNAME]=&data[merges][ADDRESS]=&data[merges][PHONE]=&data[merges][BIRTHDAY]=&data[list_id]=e971d14
The parameters are unknown so I'm looking for a dynamic solution. Note, the "data" parameter is actually an array of sorts.
I'd love to be able to retrieve key fields like:
Dim id as String = ParamList( "id" )
Dim email as String = ParamList( "email" )
What's the best way to achieve this?

As Andrew has indicated:
Dim s = "type=subscribe&fired_at=2021-07-16 07:51:09&data[id]=ebdc32dce6&data[email]=xyz#fakeemail.com&data[email_type]=html&data[ip_opt]=110.20.71.126&data[ip_signup]=110.100.22.217&data[web_id]=566760869&data[merges][EMAIL]=xyz#fakeemail.com.com&data[merges][FNAME]=&data[merges][LNAME]=&data[merges][ADDRESS]=&data[merges][PHONE]=&data[merges][BIRTHDAY]=&data[list_id]=e971d14"
Dim c = HttpUtility.ParseQueryString(s); 'need to Imports System.Web
Note that the parser doesn't care about the data[...] as being "a dictionary" etc - you say you just want to write the ... but the whole key includes the data[ and ] too.. This means you either :
Dim id = c( "data[id]" )
Dim email = c( "data[email]" )
Or you could generate a new collection, such as a dictionary, with altered keys:
Dim d = c.Keys.Cast<string>().ToDictionary( _
Function(k) k.Split("[]".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Last(), _
Function(k) c(k) _
)
This can be indexed like
Dim id = d("id")
Dim bd = d("BIRTHDAY")
But be careful with ToDictionary: the keys need to be unique. If they aren't, you cna use ToLookup but note that the entries in the "dictionary" will then be enumerables (lists of values) not single values

Related

How to sort list of directories in custom order that follows the calendar month name

I have this list of directories:
JAN_20
FEB_20
MAR_20
.....
DEC_20
I am reading it using the following VB.Net code:
Private Const MY_PATH As String = "\\120.199.10.39\departments\2020\"
Dim Z_directories = Directory.GetDirectories(MY_PATH, "*", SearchOption.AllDirectories).ToList()
For Each dir1 In Z_directories
'do something
Next
The issue is that I would like to "OrderBy" it in a custom way that follows the month order (Jan, Feb, Mar,... etc), not alphabetically or by creation time, etc.
How can I achieve this?
Basically, the thing you need to know here is that you can turn those folder names into Date values like this:
Dim d = Date.ParseExact(s, "MMM_yy", Nothing, DateTimeStyles.None)
That means that you can convert all your folder names to Dates and then sort by those Dates. There are a number of specific ways you can do the actual sort.
Here's an example that uses the array returned by GetDirectories and sorts it in place:
Dim rootFolderPath = "folder path here"
Dim subFolderPaths = Directory.GetDirectories(rootFolderPath)
Array.Sort(subFolderPaths,
Function(sfp1, sfp2)
Dim folderName1 = Path.GetFileName(sfp1)
Dim folderName2 = Path.GetFileName(sfp2)
Dim folderDate1 = Date.ParseExact(folderName1, "MMM_yy", Nothing, DateTimeStyles.None)
Dim folderDate2 = Date.ParseExact(folderName2, "MMM_yy", Nothing, DateTimeStyles.None)
Return folderDate1.CompareTo(folderDate2)
End Function)
Here's a further example that uses a LINQ query to sort before creating a final array:
Dim rootFolderPath = "folder path here"
Dim subFolderPaths = Directory.EnumerateDirectories(rootFolderPath).
OrderBy(Function(sfp) Date.ParseExact(sfp, "MMM_yy", Nothing, DateTimeStyles.None)).
ToArray()
Note that the second example calls EnumerateDirectories rather than GetDirectories, so as to not create two different arrays. Note that you can also call ToList if you prefer a List(Of String) to a String array but I tend to advise using arrays unless you specifically need to add and/or remove items.
I found the solution:
Z_directories .Sort(Function(valueB, valueA) CDate(Right(valueB, 2) & "00-" & Mid(valueB, Len(valueB) - 5, 3) & "-" & "01").CompareTo(CDate(Right(valueA, 2) & "00-" & Mid(valueA, Len(valueA) - 5, 3) & "-" & "01")))

How to delete a specific and not constant part of a string

I would like to cut this string
Dim str = "BMW{1}/X5{5}/image"
like this
Dim Brand = "BMW"
Dim idBrand= 1
Dim Model = "X5"
Dim Resource = "image"
for the / part I can easily do str.Split("/") but for the {1} I don't know if there is a special function or not.
This is a good place to use regular expressions:
Dim str = "BMW{1}/X5{5}/image"
Dim regex as new RegEx("(?<brand>[^{]+){(?<idbrand>\d+)}\/(?<model>[^{]+){[^}]+}\/(?<resource>.*)")
Dim match = regex.Match(str)
match is now an object containing various bits of information about what it's found. Since I added named capturing groups into the regex (brand, idbrand, model and resource), you can now access those within the match object:
Dim Brand = match.Groups("brand").Value
Dim idBrand= match.Groups("idbrand").Value
Dim Model = match.Groups("model").Value
Dim Resource = match.Groups("resource").Value
There is lots of information on regex available on the internet, one resource I find useful is regex101.com, which will give you an explanation of what the regex is doing on the right hand side.

Grouping by multiple columns

I am not sure if the title is misleading but I wasn't sure how to summarise this one.
I have a table in an SQL DB where a record exists as below:
I would like to display the measurement values of this item in a gridview as below:
I thought about selecting the target values to a list (and the same for the actual values) as below:
Dim cdc As New InternalCalibrationDataContext
Dim allTargetvalues = (From i In cdc.int_calibration_records
Where i.calibration_no = Request.QueryString(0) And
i.calibration_date = Request.QueryString(1)
Select i.measure1_target, i.measure2_target, i.measure3_target).ToList()
Then joining the lists together in some way although I am unsure of how I could join the lists or even if this is the correct approach to be taking?
Well, let me first say that measure1_target, measure2_target, etc. is almost always indicative of bad database design. These should probably be in another table as the "many" end of a 1-to-many relationship with the table you posted. So to answer one of your questions: No, this is not the correct approach to be taking.
With the structure of your table in its current state, your best option is probably something like this:
Dim cdc As New InternalCalibrationDataContext
Dim allTargetValues As New List(Of Whatever)
For Each targetValue In (From i In cdc.int_calibration_records
Where i.calibration_no = Request.QueryString(0) AndAlso
i.calibration_date = Request.QueryString(1)
Select i)
allTargetValues.Add(New Whatever With {.MeasureNumber = 1,
.Target = targetValue.measure1_target,
.Actual = targetValue.measure1_actual })
allTargetValues.Add(New Whatever With {.MeasureNumber = 2,
.Target = targetValue.measure2_target,
.Actual = targetValue.measure2_actual })
allTargetValues.Add(New Whatever With {.MeasureNumber = 3,
.Target = targetValue.measure3_target,
.Actual = targetValue.measure3_actual })
Next
The Whatever class would look like this:
Public Class Whatever
Public Property MeasureNumber As Integer
Public Property Target As Integer
Public Property Actual As Integer
End Class

VB.NET Array/Hashtable Issue

I am trying to make an array of hashtables. I don't know if this is the best solution, in PHP I would just do a multi-dim array, but it's not so easy in .NET. I am pretty new o VB, so if there is a better solution for this please explain.
I have 2 emails fields for a contact, and a contact can have many. I just want to load in the first two on the edit page for editing, whatever they may be.
Private Sub loadPrimaryContactEmails(ByVal db As CRMDataDataContext, ByVal contactID As Guid)
Dim q = (From ce In db.ContactEmails Where ce.ContactID = contactID Select ce).Take(2)
Dim Emails As Array
Dim count = 0
For Each email In q
Emails(count) = New Hashtable
Emails(count).Add("email", email.Email)
Emails(count).Add("label", email.Label)
Emails(count).Add("id", email.ContactEmailID)
count = count + 1
Next
txtPCEmail1.Text = Emails(0).Item("email")
txtPCEmail1Label.Text = Emails(0).Item("label")
lblEmail1ID.Text = Emails(0).Item("id")
txtPCEmail2.Text = Emails(1).Item("email")
txtPCEmail2Label.Text = Emails(1).Item("label")
lblEmail2ID.Text = Emails(1).Item("id")
End Sub
I get the error the first time I try to reference my array:
txtPCEmail1.Text = Emails(0).Item("email")
The error is:
Object variable or With block variable not set.
It builds, so I thought it might work. I can't just loop through my datasource because I have to explicitly set textbox fields. Is there a better way to go about doing this? Or is there a way to make an array of hashtables work?
EDIT - here is the good code:
So I went w/ the HybridDictionary...
Private Sub loadPrimaryContactEmails(ByVal db As CRMDataDataContext, ByVal contactID As Guid)
Dim q = (From ce In db.ContactEmails Where ce.ContactID = contactID Select ce).Take(2)
Dim Emails As New HybridDictionary()
Dim count = 1
For Each email In q
Emails.Add("email" + NCStr(count), email.Email)
Emails.Add("label" + NCStr(count), email.Label)
Emails.Add("id" + NCStr(count), email.ContactEmailID)
count = count + 1
Next
txtPCEmail1.Text = Emails("email1")
txtPCEmail1Label.Text = Emails("label1")
lblEmail1ID.Text = Emails("id1")
txtPCEmail2.Text = Emails("email2")
txtPCEmail2Label.Text = Emails("label2")
lblEmail2ID.Text = Emails("id2")
End Sub
SO yeah, kind of a hack, but I don't feel like I should have to making special methods just to load some data into a dictionary or array or whatever.
Arrays in VB.NET are different than in PHP. You will need to define the size of your array before attempting to set elements of the array.
Better yet, consider using the generic List<T> collection.
Yes Phil is right you haven't specified the Initial Size of the Array.
And as suggested by him Use generic list or I would recommend
"System.Collections.Specialized.StringCollection" Class or "System.Collections.Specialized.HybridDictionary" class
Build the hashtable first and then build the array.
Dim hash As New Hashtable()
hash.Add("Header", shortModel)
hash.Add("SpecInfo", specinfo)
hash.Add("SerialNumber", serie & "-L")
hash.Add("SerialNumber2", serie)
hash.Add("seriel", serie & "-L")
hash.Add("serie", serie)
hash.Add("Product", modelBase)
hash.Add("varBC", bc)
hash.Add("box_id", boxId.Substring(4).ToString)
Dim dt As DataTable = DbUtil.GetCursor("SFISM4.PKG_AGENCY.sp_get_print_param", {New OracleParameter("in_serie", "3CE5151ZW4")})
For Each row As DataRow In dt.Rows
hash.Add(row("NAME"), row("VALUE"))
Next
Dim mArray(hash.Count() - 1, 1) As String
Dim i As Integer = 0
For Each row As DictionaryEntry In hash
mArray(i, 0) = row.Key.ToString()
mArray(i, 1) = row.Value.ToString()
i = i + 1
Next

How can I get the URL and Querystring? vb.net

I am refactoring some legacy code. The app was not using querystrings. The previous developer was hard coding some variables that the app uses in other places.
Like this using VB.NET
so.Cpage = "ContractChange.aspx"
My question is can I programatically set this value and include the current querystring?
I want so.Cpage to be something like ContractChange.aspx?d=1&b=2
Can I do this with the request object or something? Note, I don't need the domain.
To get the current query string you would simply do something like the following:
Dim query as String = Request.QueryString("d")
This will assign the value of the "d" querystring to the string variable "query". Note that all query string values are strings, so if you're passing numbers around, you'll need to "cast" or convert those string values to numerics (be careful of exceptions when casting, though). For example:
Dim query as String = Request.QueryString("d")
Dim iquery as Integer = CType(query, Integer)
The QueryString property of the Request object is a collection of name/value key pairs. Specifically, it's of type System.Collections.Specialized.NameValueCollection, and you can iterate through each of the name/value pairs as so:
Dim coll As System.Collections.Specialized.NameValueCollection = Request.QueryString
Dim value As String
For Each key As String In coll.AllKeys
value = coll(key)
Next
Using either of these mechanisms (or something very similar) should enable you to construct a string variable which contains the full url (page and querystrings) that you wish to navigate to.
Try this:
so.Cpage = "ContractChange.aspx?" & Request.RawUrl.Split("?")(1)
In VB.Net you can do it with the following.
Dim id As String = Request.Params("RequestId")
If you want to process this in as an integer, you can do the following:
Dim id As Integer
If Integer.TryParse(Request.Params("RequestId"), id) Then
DoProcessingStuff()
End If
try this
Dim name As String = System.IO.Path.GetFileName(Request.ServerVariables("SCRIPT_NAME"))
Dim qrystring As String = Request.ServerVariables("QUERY_STRING")
Dim fullname As String = name & "/" & qrystring
Not sure about the syntax in VB.NET but in C# you would just need to do
StringId = Request.QueryString.Get("d");
Hope this helps.