Ignoring specific query string parameters in custom sitemapprovider - asp.net

I’ve written my own staticsitemapprovider which builds a dynamic site map. The problem I have is that sometimes pages will have additional parameters in the query string which I need to ignore.
Public Overrides Function FindSiteMapNode(ByVal rawUrl As String) As SiteMapNode
Dim startpos As Integer = 0
Dim endpos As Integer = 0
If rawUrl.Contains("pagetype=") Then
startpos = rawUrl.IndexOf("pagetype=")
endpos = rawUrl.IndexOf("&", startpos) + 1
If endpos >= startpos Then
'not the last param
rawUrl = rawUrl.Remove(startpos, endpos - startpos)
Else
'must be the last param
rawUrl = rawUrl.Remove(startpos)
End If
End If
Return MyBase.FindSiteMapNode(rawUrl)
End Function
I've also overridden the FindSiteMapNode function that takes in a HttpContect object. With this I simple find the URL of that request and run it though the same function above.
However with this my sitemappath (which is bound to the site map) returns nothing on every page.

In the end this turned out to be a very simple fix. All i needed to do was check to see if the the parameter was the first in the url. If it wasn't, I aslo needed to remove the ampersand - so it would be startpos - 1
Cheers

Related

Why i am getting the error that object has been used before a vaule is assigned?

Dim EAM017 As EAM017_LNG_SI_GetDetails_Out_SyncService.SI_GetDetails_Out_SyncSoapClient
If URL.Contains("http") Then
Dim endPointHttp = New System.ServiceModel.EndpointAddress(URL)
binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly
binding.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Basic
EAM017 = New EAM017_LNG_SI_GetDetails_Out_SyncService.SI_GetDetails_Out_SyncSoapClient(binding, endPointHttp)
EAM017.ClientCredentials.UserName.UserName = UserName
EAM017.ClientCredentials.UserName.Password = Password
End If
EAM017.FunctionalLocation(MyMTFuncLocRequest)
Now error is EAM017 has been used before a value is assigned.
The solution is to put it inside the if block but I don't want to do that and should be outside becuase more code is going to be there in future in the same way.
What should I do?
Consider the following
' EAM017 is declared, but not assigned to anything, thus is Nothing / null
Dim EAM017 As EAM017_LNG_SI_GetDetails_Out_SyncService.SI_GetDetails_Out_SyncSoapClient
' your URL doesn't contain http
URL = "ftp://123.456.789.001"
' this condition is false ...
If URL.Contains("http") Then
' ... so this line doesn't happen
EAM017 = New EAM017_LNG_SI_GetDetails_Out_SyncService.SI_GetDetails_Out_SyncSoapClient(binding, endPointHttp)
End If
' EAM017 was never assigned, and is null. A null object exception will happen at runtime
EAM017.FunctionalLocation(MyMTFuncLocRequest)
Now you might say that your URL will always contain "http", then you don't need the If.
But if it's possible it won't contain "http" then you shouldn't be doing anything with a null object. You should either
Add another case (where URL contains "ftp" for example) and assign the object in there accordingly
Move the line EAM017.FunctionalLocation(MyMTFuncLocRequest) inside the If
Move the line EAM017 = New EAM017_LNG_SI_GetDetails_Out_SyncService.SI_GetDetails_Out_SyncSoapClient(binding, endPointHttp) outside the If
You can add a Not to the if statement and exit the sub if the requirements are not met. If they are met then just continue with the rest of he code.
To answer your question in the title. Not all code paths include the initialization of EAM017.
Private Sub OPCode(URL As String)
Dim EAM017 As EAM017_LNG_SI_GetDetails_Out_SyncService.SI_GetDetails_Out_SyncSoapClient
If Not URL.Contains("http") Then
'Notify the user and exit the sub
Return
End If
Dim endPointHttp = New System.ServiceModel.EndpointAddress(URL)
Binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly
Binding.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Basic
EAM017 = New EAM017_LNG_SI_GetDetails_Out_SyncService.SI_GetDetails_Out_SyncSoapClient(Binding, endPointHttp)
EAM017.ClientCredentials.UserName.UserName = UserName
EAM017.ClientCredentials.UserName.Password = Password
EAM017.FunctionalLocation(MyMTFuncLocRequest)
End Sub

How to get my params value with a & in the URL?

www.myurl.com?param1=123&param2=456 OK
www.myurl.com?param1=123&param2=456 NOT OK
In my vb code behind, with the second URL, I get the value of param1 only.
Me.Page.Request("param1") : value OK
Me.Page.Request("param2") : value 0
Firstly, I would advise rethinking how your URL is built with a view to removing the need for an & it will be far easier for you.
If this is not possible for whatever reason, you will need to extract the parameter values from the querystring yourself.
One possible solution:
Dim url As String = Request.RawUrl
Dim urlParams As String() = url.Split("?"C)
If urlParams.Length > 1 Then
Dim parameters As String() = urlParams(1).Split(New String() {"&"}, StringSplitOptions.None)
For Each param As var In parameters
' will give you the paramater value
Dim value As String = param.Split("="C)(1)
Next
End If

Detect if a names field exists in a record set

Is it possible to check if a named field is within a record set?
EG id, field1, field2, field3 have been selected. Is it possible for VBScript to detect if field2 has been selected. I am also hoping this is possible without looping
Please assume I dont know, nor can see the actual SELECT. I need to detect this after the query has been executed.
This is how its done using a loop, I am also hoping this is possible without looping:
dim rs,field,foundField
sql = "SELECT * from table;"
set rs = conn.execute(sql)
For Each field in rs.Fields
if field.Name = "someFieldName" then
foundField = true
exit for
else
foundField = false
end if
next
TYIA
I use a similar function (in VB6) to the one proposed by bfavaretto... I'm curious why the OP says it doesn't work?
Public Function FieldExists(ByVal rs As Recordset, ByVal fieldName As String) As Boolean
On Error GoTo merr
FieldExists = rs.Fields(fieldName).name <> ""
Exit Function
merr:
FieldExists = False
End Function
This function works for me... and it doesn't return false negatives as far as I know. Also, it appears to be faster than executing a loop for fields that are included in the collection; for fields that are actually missing, the execution times of both methods seems to be equivalent.
EDIT
For VBScript, the above function would look like this:
Function FieldExists(ByVal rs, ByVal fieldName)
On Error Resume Next
FieldExists = rs.Fields(fieldName).name <> ""
If Err <> 0 Then FieldExists = False
Err.Clear
End Function
And the code posted in the question would look like:
dim rs,field,foundField
sql = "SELECT * from table;"
set rs = conn.execute(sql)
foundField = FieldExists(rs, "someFieldName")
I think you need the loop. Found this on MSDN (emphasis mine):
Most of the ASP built-in objects provide collections. Collections are
data structures similar to arrays that store strings, numbers, objects
and other values. Unlike arrays, collections expand and contract
automatically as items are retrieved or stored. The position of an
item will also move as the collection is modified. You can access an
item in a collection by its unique string key, by its index (position)
in the collection, or by iterating through all the items in the
collection.
In any case, you could try this (untested):
dim rs,field,foundField
sql = "SELECT * from table;"
set rs = conn.execute(sql)
if rs.Fields("someFieldName") then
' ... if this doesn't crash, it may return
' false negatives for columns containing null or 0
end if

ASP array element is null and conversion of string to long

I've inherited an ASP project, and I'm a PHP coder with no ASP knowledge. Sorry if this post is lengthy, I just want to give as much informations as possible.
I'm struggling with this one block of code.
Dim resultArray As String()
For Each resultitem In resultArray
' Do something with each element of the array
hash.Add(dllFunctionObj.ReturnTemplateField(i), resultitem)
i = i + 1
Next
Error:
Exception!!: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
The solution seems simple. Check if resultitem is null then either break or skip to the next element.
So I tried this:
If IsNull(resultitem) Then
Break
End If
Error:
BC30451: Name 'IsNull' is not declared.
I tried several other alternatives I found online:
IsEmpty(resultitem) - IsEmpty not declared
String.IsNullOrEmpty(resultitem) - index out of bounds error, seems to have no effect
resultitem Is Nothing - index out of bounds
Not (Len(resultitem) > 0) - index out of bounds
Len(resultitem) = 0 - index of out bounds
The only thing that seems to come close is:
If Not resultitem Then
Break
End If
Error:
Exception!!: Conversion from string "some_string_here" to type 'Long' is not valid.
If I use Next instead of Break I get this error:
If Not resultitem Then
Next
End If
Error:
BC30081: 'If' must end with a matching 'End If'.
Help!
I'm going to include the full block of code in case it is helpful
Dim isResultArray As Boolean
isResultArray = methodInf.ReturnType.IsArray()
If isResultArray Then
Dim resultArray As String()
'*** Invoke the dll function
resultArray = methodInf.Invoke(REMem, args.ToArray)
Dim i As Integer = 0
For Each resultitem In resultArray
If Not resultitem Then
Response.Write("Found null value.")
Exit For
End If
Response.Write("i: " & i & "<br />")
hash.Add(dllFunctionObj.ReturnTemplateField(i), resultitem)
i = i + 1
' i = 6 will cause Get Constituent Name to work
'If i = 6 Then
' Exit For
'End If
Next
outputArray.Add(hash)
Else
'*** could be boolean, string, long etc.
Dim result As String
'*** Invoke the dll function
result = methodInf.Invoke(REMem, args.ToArray)
hash.Add(dllFunctionObj.ReturnTemplateField(0), result)
outputArray.Add(hash)
End If
You need to make sure you're not overflowing the index of the collection you're accessing. Something like this should work:
If i < dllFunctionObj.ReturnTemplateField.Length Then
hash.Add(dllFunctionObj.ReturnTemplateField(i), resultitem)
End If
Basically, you need to wrap your call to "hash.Add" in this if block to protect against accessing a value that doesn't exist.
Granted, I don't understand the purpose of the code, so you might need to handle the "else" case. But this should stop the error.
Looks to me like the array may be defined incorrectly.
Change this:
Dim resultArray As String()
For Each resultitem In resultArray
' Do something with each element of the array
hash.Add(dllFunctionObj.ReturnTemplateField(i), resultitem)
i = i + 1
Next
To this:
Dim resultArray() As String
For Each resultitem In resultArray()
' Do something with each element of the array
hash.Add(dllFunctionObj.ReturnTemplateField(i), resultitem)
i = i + 1
Next
Additionally, you may need to define the length of the array, e.g.:
Dim resultArray(0 to 9) As String
If the length of the array is unknown, you may define it without the minimum and maximum index, but will need to use ReDim to assign the minimum and maximum indexes later. One method would be to create the array without a length, count the items that you know will be added to the array, and then use ReDim with that count as the length of the array. For example:
Dim resultArray() As String
Dim iCount as integer 'Keep track of the count with this variable.
'Enter custom counting script here...Use a loop to count the items that will be used in the array.
ReDim resultArray(0 to iCount - 1) 'Subtract one from the iCount to match the 0-based index.
If you try to call upon a index of an array that has no set length (or use an index greater/less than the size of the array), you will most likely encounter either an "Index out of range" or "Substring out of range" error.

Getting the Request Variables from an ASP.NET page

I wrote the following function that works about 95% of the time, but I need it to work 100% (obviously):
Public Shared Function getPassedVars() As String
Const keyCount As Integer = 54 ' 54 seems to be the number of parameter keys passed by default (for this web_app).
' there are more if there is a form involved (ie. from search page)
Dim oParams As String = ""
Try
With HttpContext.Current
If .Request.Params.AllKeys.Count > keyCount Then
For i As Integer = 0 To (.Request.Params.AllKeys.Count - (keyCount + 1))
oParams &= String.Format("{0}={1}{2}", .Request.Params.Keys.Item(i), .Request.Params(i), IIf(i < .Request.Params.AllKeys.Count - (keyCount + 1), ";", ""))
Next
End If
End With
Return oParams
Catch ex As Exception
Return Nothing
End Try
End Function
It scrubs the Request.Params object for passed variables, which are in the beginning of the array (the remaining ones are ASP parameters). I am pretty sure I've seen a different way to get these parameters, but I haven't been able to figure it out. Any suggestions?
EDIT
So it looks like I can use the Request.URL.Query to achieve this, I will investigate this and post back.
Here is what I came up with:
Public Shared Function getPassedVars() As String
Dim oParams As String = ""
Dim qString As String = ""
Dim oSplit As New List(Of String)
Try
With HttpContext.Current
qString = .Request.Url.Query
If qString.Length > 0 Then 'do we have any passed variables?
If qString.StartsWith("?") Then qString = qString.Remove(0, 1) 'remove leading ? from querystring if it is there
oSplit.AddRange(qString.Split("&"))
For i As Integer = 0 To oSplit.Count - 1
oParams &= String.Format("{0}{1}", oSplit.Item(i), IIf(i < oSplit.Count - 1, ";", ""))
Next
Return oParams
Else
Return Nothing
End If
End With
Catch ex As Exception
Return Nothing
End Try
End Function
So far so good.
Request.QueryString is a NameValueCollection, so the easiest way to get the "parameters" is to do the following:
foreach (String s in Request.QueryString) {
Response.Write(s + " = " + Request.QueryString[s]);
}
Where is your function located? If it's executing in the page's code behind then you definitely do not need to use the HttpContext variable.
It looks like you are trying to get values from the query string.
For example, for this URL:-
http://www.tempuri.org/mypage.aspx?param1=x&param2=y
I assume you want retreive the values of the query string parameters param1 and param2?
If so, just use:-
Dim param1 as String = Request.QueryString("param1")
Otherwise, if these parameters are contained in a form (an HTTP POST request) then use the method which Mitchel Sellers suggests.
If you know the name you can use the following to get it by key value
Dim myParamValue as String = Request.Form("MyKeyName")
Otherwise, you can loop through the form collection, by key etc, to get the values. The key is, do you really need to be parsing all 54 items? Or are you simply looking for a few specific values?
httpcontext.Current.Request.QueryString("KeyName")
Request.Params will contain the query parameters you're after.
There's no need to parse the info from Request.URL since it's already done for you.

Resources