Returning multiple values from a function in an parcial class in VB - asp.net

Hi Please can someone show me how to return multiple values from a function? I have my function in a seperate file within App_Code and here it is:
Public Function GetQuoteStatus(ByVal QuoteID As String) As String
Dim quoteStatus As String
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Try
con.ConnectionString = ConfigurationManager.AppSettings("quotingSystemConnectionString")
con.Open()
cmd.Connection = con
cmd.CommandText = "SELECT Status FROM Quote WHERE QuoteID =" & QuoteID & ";"
Dim lrd As SqlDataReader = cmd.ExecuteReader()
While lrd.Read()
quoteStatus = lrd("Status")
End While
Catch ex As Exception
Finally
con.Close()
End Try
Return quoteStatus
End Function
To get the returned quoteStatus from within another vb file in my site I would normally use:
Dim statusHelper As New quoteStatusHelper()
Dim quoteStatus As String = statusHelper.GetQuoteStatus("QuoteID")
However this is all good and well for one returned value but what If I wanted to return multiple values... How do I access them?
Many thanks!

You could use
Public Function GetQuoteStatus(ByVal QuoteID As String) As String()
This let you return a string array, so there is no limit to data you can have.
The cons is you have to parse the array.
You could even use
Public Function GetQuoteStatus(ByVal QuoteID As String,
Byref Second As String) As String
This let you return a string as result and set the value of another var (Second); you can use more than one Byref variables to return multiple values...
The cons is that you have to statically declare your function and modifiy all previous calls. In this case the use of refactoring is reccomended!
EDITED:
You could even return a class for example.
Declare a class that fits your needs (with all the fields, getters, setters and constructors) and inside your function you could create an instance of that class, fill every field and return this class.
Easy to implement, easy to use.
EDITED AGAIN:
Public Class MyClass
Public Property Val1 As String
Public Property Val2 As String
Public Property Val3 As String
Public Sub New(ByVal newVal1 As String, ByVal newVal2 As String, ByVal newVal3 As String)
Val1 = newVal1
Val2 = newVal2
Val3 = newVal3
End Sub
End Class
Public Function GetInfo() As MyClass
Dim mc As New MyClass("test1", "test2", "test3")
Return mc
End Function

You may return multiple values using ByRef and arrays (see #Marco post). You may also return/pass an object for your purpose.
For instance,
Public Class Info
Public Property No As Integer
Public Property Name As String
End Class
....
Public Function GetInfo() As Info
Dim inf As New Info
inf.No = 10
inf.Name = "A"
Return inf
End Function
....

I believe that the "correct/best" way to deal with a single function that needs to return a couple of discrete (typically primitive) types is a Tuple(Of T1, T2, T3, T4, T5, T6, T7, TRest).
Something like this
Public Function MyExampleMethod() As Tuple(Of String, Integer, Guid)
Return New Tuple(Of String, Integer, Guid)("Value1", 2, Guid.NewGuid)
End Function

Related

Function result in an array of own structure

In the Gen class file I have got this structure:
Public Structure StructElements
Public ID As Integer
Public Name As String
End Structure
An then this function:
Public Function FillElements(_param As String, count As Integer) As StructElements
Dim i As Integer = 0
Dim myConn As SqlConnection = New SqlConnection
Dim myCmd As SqlCommand
Dim myReader As SqlDataReader
myConn.ConnectionString = sc.ConfigurationManager.ConnectionStrings("sidConnectionString").ConnectionString
myCmd = myConn.CreateCommand
myCmd.CommandText = "SELECT * FROM " & _param
Select Case _param
Case = "Scopes"
Dim Scope(count) As StructElements
myConn.Open()
myReader = myCmd.ExecuteReader()
While myReader.Read
Scope(i).ID = myReader.Item(0)
Scope(i).Name = myReader.Item(1).ToString
i += 1
End While
myReader.Close()
myCmd.Dispose()
myConn.Close()
myConn.Dispose()
Return Scope
...
End Function
Then in the edit.aspx codebehind I have:
Public Class edit
...
Public istGen = New Gen()
...
Public iScopes As Integer
Public Scope(iScopes) As StructElements
...
Private Sub edit_Init(sender As Object, e As EventArgs) Handles Me.Init
...
iScopes = istGen.CountElements("Scopes") - 1
ReDim Scope(iScopes)
Scope = istGen.FillElements("Scopes", iScopes)
...
End Sub
End Class
This is the error I get:
Value of type 'Gen.StructElements()' cannot be converted to 'Gen.StructElements'.
I have figured out the problem is with the "Return Scope" of the FillElements function since it's expecting as an output a StructElements and not an array of StructElements (that's what the Scope variable is). How should I change my code in order for the function output to be an array of StructElements?
I have tried to look for an answer on the web but didn't find much. Someone was suggesting to use lists instead of arrays, but that would request to heavily refurbish my code and project, so if there is an easy way to do it I would strongly prefer it.
Thanks in advance for your support.
Regards.

Convert string to list of custom objects

Say I have an object Fish with properties like
Public Property ID As Integer
Public Property Name As String
Public Property Type As Integer
Public Property Age As Integer
And I have a string that looks like this:
"Fishes[0].ID=1&Fishes[0].Name=Fred&Fishes[0].Type=1&Fishes[0].Age=3&Fishes[1].ID=2&Fishes[1].Name=George&Fishes[1].Type=2&Fishes[1].Age=5&..."
Is there any way of converting/casting/whatever my string into a list of Fish objects? I can't seem to find anything to help. I do have some control over the format of the string if that would make things easier.
Many thanks
What you need to do is to parse the input string to look for Fishes[X].PROPNAME=VALUE pattern. Loop through all matches found in the string and add into or set the existing object in Dictionary. Use X as each object key in the Dictionary.
Create Fish structure:
Structure Fish
Public ID As String
Public Name As String
Public Type As Integer
Public Age As Integer
End Structure
Codes to process the input string:
Dim Fishes As New Dictionary(Of String, Fish)
Dim m As Match = Regex.Match(str, "Fishes\[(?<key>\d+)]\.(?<prop>.+?)=(?<value>[^&]+)", RegexOptions.IgnoreCase)
Do While m.Success
Dim key As String = m.Groups("key").Value.Trim.ToUpper
Dim prop As String = m.Groups("prop").Value.Trim.ToUpper
Dim value As String = m.Groups("value").Value
' if the key not yet exist in the Dictionary, create and add into it.
If Not Fishes.ContainsKey(key) Then
Fishes.Add(key, New Fish)
End If
Dim thisFish As Fish = Fishes(key) ' get the Fish object for this key
' determine the object property to set
Select Case prop
Case "ID" : thisFish.ID = value
Case "NAME" : thisFish.Name = value
Case "TYPE" : thisFish.Type = CInt(value)
Case "AGE" : thisFish.Age = CInt(value)
End Select
Fishes(key) = thisFish ' since the Fish object is declared as Structure,
' update the Dictionary item of key with the modified object.
' If Fish is declared as Class, then this line is useless
m = m.NextMatch()
Loop
Try this ..
Structure Test
Dim ID As String
Dim Name As String
Dim Type As Integer
Dim Age As Integer
End Structure
In your Button click event ..
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Fishes As New List(Of Test)
Dim Fish As New Test
Fish.ID = "GF"
Fish.Name = "Gold Fish"
Fish.Age = 1
Fish.Type = 1
Fishes.Add(Fish)
MsgBox(Fishes(0).Name)
End Sub
this is vb.net converted
Public Partial Class test
Inherits System.Web.UI.Page
Protected Sub Page_Load(sender As Object, e As EventArgs)
If Not IsPostBack Then
End If
End Sub
Public Sub MYtest()
Dim ls As New List(Of Fish)()
Dim f As New Fish()
f.ID = 1
f.Name = "My name"
f.Type = "My type"
f.Age = 20
ls.Add(f)
End Sub
End Class
Public Class Fish
Public Property ID() As Integer
Get
Return m_ID
End Get
Set
m_ID = Value
End Set
End Property
Private m_ID As Integer
Public Property Name() As String
Get
Return m_Name
End Get
Set
m_Name = Value
End Set
End Property
Private m_Name As String
Public Property Type() As String
Get
Return m_Type
End Get
Set
m_Type = Value
End Set
End Property
Private m_Type As String
Public Property Age() As Integer
Get
Return m_Age
End Get
Set
m_Age = Value
End Set
End Property
Private m_Age As Integer
End Class
In the comments you mentioned that this is via ASP.Net MVC. The ModelBinder will do everything for you.
public ActionResult UpdateFish(IList<Fish> listOfFish)
{
//the ModelBinder will figure out that the user has posted a list of Fish instances.
//do something with listOfFish
return View(listOfFish);
}

SQL Dataset to JSON

Alright I have been trying to figure this out and I read the MSDN page on the JavaScriptSerializer. However, I still can't figure out how to get this to work on an asp.net page. I want to convert my dataset into a json string so I can graph it using FLOT(graphing tool)
THIS MADE IT WORK THANKS FOR YOUR HELP GUYS: this is in vb.net for future people
Imports System.Web.Script.Serialization
....
Dim myObject = dataset.GetXml()
Dim jsonString = (New JavaScriptSerializer()).Serialize(myObject)
Reference the assembly System.Web.Extensions.dll and then do this:
using System.Web.Script.Serialization;
....
var myObject = ... your stuff ...
var jsonString = new JavaScriptSerializer().Serialize(myObject);
Check out the MSDN page for more info.
I did the following when I was working on a Project using PlotKit. I create a webservice to return the data and set the response format to Jason...this was while ago...should also work in 3.5
Here is a sample
<WebMethod()> _
<Script.Services.ScriptMethod(UseHttpGet:=True, ResponseFormat:=ResponseFormat.Json)> _
Public Function GetSales(ByVal a As String) As Generic.List(Of Sale)
Dim _conn As SqlConnection = New SqlConnection(connstr)
Dim _dr As SqlDataReader
Try
Dim _cmd As SqlCommand = New SqlCommand("select * from sales", _conn)
_conn.Open()
_dr = _cmd.ExecuteReader(CommandBehavior.CloseConnection)
If _dr.HasRows Then
Dim s As Sale
Dim c As New Generic.List(Of Sale)
While _dr.Read
s = New Sale
With s
.Month = _dr("monthname")
.TheSale = _dr("sale")
End With
c.Add(s)
End While
Return c
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
_conn.Close()
End Try
End Function
End Class
Here is the object class...notice I am serializing the object.
<Serializable()> _
Public Class Sale
Private _month As String
Private _sale As String
Public Property Month() As String
Get
Return _month
End Get
Set(ByVal value As String)
_month = value
End Set
End Property
Public Property TheSale() As String
Get
Return _sale
End Get
Set(ByVal value As String)
_sale = value
End Set
End Property
End Class
Check out the DataContractJsonSerializer, and this article on MSDN
public static string DStoJSON(DataSet ds)
{
StringBuilder json = new StringBuilder();
foreach (DataRow dr in ds.Tables[0].Rows)
{
json.Append("{");
int i = 0;
int colcount = dr.Table.Columns.Count;
foreach (DataColumn dc in dr.Table.Columns)
{
json.Append("\"");
json.Append(dc.ColumnName);
json.Append("\":\"");
json.Append(dr[dc]);
json.Append("\"");
i++;
if (i < colcount) json.Append(",");
}
json.Append("\"}");
json.Append(",");
}
return json.ToString();
}
Probably most useful to you is the dataset loop instead of the stringbuilder. You could loop these into an object, then use the javascript serializer library.
Or even better, if you are using asp.net mvc, you can just do this:
return Json(List<myobject>, JsonRequestBehavior.AllowGet);
but this way is quick & easy! -- I didn't quite test this! the appended comma might be wrong (or code can be improved) and the final row comma needs to be handled
I use the mvc way & never looked back :)

Scrambling URLS for dynamic data

What is the best method to obfuscate the urls created in Dynamic Data?
eg \Products\List.aspx?ProductId=2 could become
\Products\List.aspx?x=UHJvZHVjdElkPTI=
where "ProductId=2" is base 64 encoded to prevent casual snooping on
\Products\List.aspx?ProductId=3
\Products\List.aspx?ProductId=4
etc...?
I will probably have to inherit from an existing object and override some function
The question is which object and what function
GetActionPath of the Metamodel object seems interesting,
but how does the DynamicRoute "{table}/{Action}.aspx" play in into it...
Right now on Asp.net 1.1 site I use an custom implementation of the following code.
http://www.mvps.org/emorcillo/en/code/aspnet/qse.shtml It is HTTPModule that uses regular expression to rewrite all the querystrings and also with reflection changes the Querystring collection with decoded values.
So where is the hook to affect the change.
I have found the solution
With advice, I have implemented a Route that inherits from DynamicDataRoute.
The methods overridden were GetVirtualPath and GetRouteData.
Here is the global.asax page
routes.Add(New EncodedDynamicDataRoute("{table}/{action}.aspx") With { _
.Defaults = New RouteValueDictionary(New With {.Action = PageAction.List}), _
.Constraints = New RouteValueDictionary(New With {.Action "List|Details|Edit|Insert"}), _
.Model = model})
Here is the Encoded DynamicDataRoute.
Imports System.Web.DynamicData
Imports System.Web.Routing
''' <summary>
''' The purpose of this class to base 64 encode the querystring parameters.
''' It converts the keys to base64 encoded and back.
''' </summary>
Public Class EncodedDynamicDataRoute
Inherits DynamicDataRoute
Public Sub New(ByVal url As String)
MyBase.New(url)
End Sub
Public Overloads Overrides Function GetRouteData(ByVal httpContext As HttpContextBase) As RouteData
Dim routeData As RouteData = MyBase.GetRouteData(httpContext)
If Not (routeData Is Nothing) Then
DecodeRouteValues(routeData.Values)
End If
Return routeData
End Function
Private Sub EncodeRouteValues(ByVal routeValues As RouteValueDictionary)
Dim tableName As Object
If Not routeValues.TryGetValue("table", tableName) Then
Return
End If
Dim table As MetaTable
If Not Model.TryGetTable(DirectCast(tableName, String), table) Then
Return
End If
Dim strOutput As New StringBuilder
Dim val As Object
For Each column As MetaColumn In table.PrimaryKeyColumns
If routeValues.TryGetValue(column.Name, val) Then
strOutput.Append(column.Name & Chr(254) & val & Chr(255))
routeValues.Remove(column.Name)
End If
Next
Dim out As String = (Convert.ToBase64String(Encoding.ASCII.GetBytes(strOutput.ToString)))
If routeValues.ContainsKey("x") Then
routeValues.Item("x") = out
Else
routeValues.Add("x", out)
End If
End Sub
Public Overloads Overrides Function GetVirtualPath(ByVal requestContext As RequestContext, ByVal values As RouteValueDictionary) As VirtualPathData
EncodeRouteValues(values)
Return MyBase.GetVirtualPath(requestContext, values)
End Function
Private Sub DecodeRouteValues(ByVal routeValues As RouteValueDictionary)
Dim tableName As Object
If Not routeValues.TryGetValue("table", tableName) Then
Return
End If
Dim table As MetaTable
If Not Model.TryGetTable(DirectCast(tableName, String), table) Then
Return
End If
Dim enc As New System.Text.ASCIIEncoding()
Dim val As Object
If routeValues.TryGetValue("x", val) AndAlso val <> "AAA" Then
Dim strString As String = enc.GetString(Convert.FromBase64String((val)))
Dim nameValuePairs As String() = strString.Split(Chr(255))
Dim col As MetaColumn
For Each str11 In nameValuePairs
Dim vals() As String = str11.Split(Chr(254))
If table.TryGetColumn(vals(0), col) Then
routeValues.Add(val(0), col)
End If
Next
End If
End Sub
End Class
Here is how I did it:
I created 4 functions in a module:
public static string EncryptInt(int val)
public static int DecryptInt(string val)
public static string DecryptStr(string str)
public static string EncryptStr(string source)
When I wanted to create a url I did something like this:
string.Format(#"\path\file.aspx?ID={0}&name={1}",encrypt.EncryptInt(inID),encrypt.EncriptStr(inName));
When I wanted to get the results I would call the Decrypt function on retrieved param.
I used two types because it added a level of type safety to the system, but you could just use one with strings and then call int.Parse() as needed.
Does this answer your question?
For Microsoft's Dynamic Data I believe the hooks would be found in the code behind for the template pages.

How can i convert the C# code listed below into VB

i am using the Json.net to serialize an object. the specific object is eventInstance.Properties which is the properties of a windows event log.
i am getting a
Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property
for C# an example is shown here
string json = JsonConvert.SerializeObject(joe, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
my line of code is below but i am not sure how to make it work in VB or if it is even possible
command.Parameters.AddWithValue("#f18", JsonConvert.SerializeObject(eventInstance.Properties(), New JsonSerializerSettings() {ReferenceLoopHandling = ReferenceLoopHandling.Ignore}))
i get an error that states 'ReferenceLoopHandling' is an enum type and cannot be used as an expression
thanks for the help
You can use below code:
Private Function getJSON(sJSON As String) As String
Dim objNews = New List(Of News)()
Dim news = New News()
news.id = ""
news.title = "blah"
Dim lst = New List(Of Object)()
lst.Add(New With {.video_identifier = "id1"})
lst.Add(New With {.video_identifier = "id2"})
news.video_identifier = lst.ToArray()
objNews.Add(news)
Return Newtonsoft.Json.JsonConvert.SerializeObject(New With {.data = objNews})
End Function
Class News
Public Property title As String
Get
Return _title
End Get
Set
_title = value
End Set
End Property
Private _title As String
Private _sId As String
Public Property id As String
Get
Return _sId
End Get
Set
_sId = value
End Set
End Property
Private _youtube_videos As Object() = New List(Of Object)().ToArray()
Public Property video_identifier As Object()
Get
Return _youtube_videos
End Get
Set
_youtube_videos = value
End Set
End Property
End Class
Public Class YoutubeVideos
Private _video_identifier As String
Public Property video_identifier As String
Get
Return _video_identifier
End Get
Set
_video_identifier = value
End Set
End Property
End Class

Resources