VB.net web api How to get json variable as a parameter? - vb.net

I have a web api built visual basic. i need to send json data from ios device with post method but how can i get one json object as a parameter. Send json and parse it from web api and insert to database. i want to do this way. the function that i wanna help is PostValue()
Imports System.Net
Imports System.Web.Http
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Namespace Controllers
Public Class TestController
Inherits ApiController
Dim Jobject As JObject
Dim Jarray As New JArray
' GET: api/Test
Public Function GetValues() As IEnumerable(Of String)
Return New String() {"value1", "value2"}
End Function
' GET: api/Test/5
Public Function GetValue(ByVal id As Integer) As String
Return "value"
End Function
'i need help in this point------------------------------------
' POST: api/Test
Public Function PostValue(<FromBody()> ByVal value As String) As JArray
Jobject = New JObject
Jobject.Add("a_id", "test")
Jobject.Add("a_kod", "serkan")
Jobject.Add("a_adi", "asdasdas")
Jarray.Add(Jobject)
Return Jarray
End Function
' PUT: api/Test/5
Public Sub PutValue(ByVal id As Integer, <FromBody()> ByVal value As JObject)
End Sub
' DELETE: api/Test/5
Public Sub DeleteValue(ByVal id As Integer)
End Sub
End Class
End Namespace

<AcceptVerbs, HttpPost, HttpPut>
Public Function FuncUser(<FromBody()> ByVal jsonParam As Object) As Object
SyncLock kilit
Dim Jobject As JObject
Dim e = Request.Method
' THİS İS HOW TO PARSE BODY FROM JSON PARAMETER.
'----------------------------------
Dim nesne As JObject = JObject.FromObject(jsonParam)
End SyncLock
End Function
If u wanna post a json data to a VB.net api and if u dont know how to take many parameters with one parameter you should use this.

Related

How to route two get methods with same params in WebApi?

In my ApiController i had one GET method which was returning some data from DB.
Now i have to enlarge that controller by adding one more GET method which will return data from same database but formatted in another way so the parameters i'd pass to that method will be the same as from the 1st one.
I was trying to do the following:
Public Class CshController
Inherits ApiController
Public Function GetValoriCsh(ByVal npv As String, ByVal nc As String) As IEnumerable(Of Cshlvl)
Dim csh As Cshlvl = New Cshlvl
Return csh.ValoreCsh(npv, nc)
End Function
Public Function GetOperazioni(ByVal npv As String, ByVal nc As String) As IEnumerable(Of OperazioniCsh)
Dim operazioni As OperazioniCsh = New OperazioniCsh
Return operazioni.OperazioniCsh(npv, nc)
End Function
End Class
So here come the issue, the api fails as there are two method which require same parameters so it doesn't know how to chose which i would to use.
actually i'm calling the following api by the following url api/csh/ is it possible in some way by calling api/csh/ to get data from GetValoriCsh and like by calling something like api/csh/operazioni/ to get data from GetOperazioni?
My WebApiConfig
Public Module WebApiConfig
Public Sub Register(ByVal config As HttpConfiguration)
' Servizi e configurazione dell'API Web
' Route dell'API Web
config.MapHttpAttributeRoutes()
config.Routes.MapHttpRoute(
name:="DefaultApi",
routeTemplate:="api/{controller}/{id}",
defaults:=New With {.id = RouteParameter.Optional}
)
End Sub
End Module
I've tryed to add <Route("api/csh/op")> above GetOperazioni but it had no effect.
If using attribute routing it is all or nothing.
<RoutePrefix("api/csh")>
Public Class CshController
Inherits ApiController
'GET api/csh
<HttpGet()>
<Route("")>
Public Function GetValoriCsh(ByVal npv As String, ByVal nc As String) As IEnumerable(Of Cshlvl)
Dim csh As Cshlvl = New Cshlvl
Return csh.ValoreCsh(npv, nc)
End Function
'GET api/csh/op
<HttpGet()>
<Route("op")>
Public Function GetOperazioni(ByVal npv As String, ByVal nc As String) As IEnumerable(Of OperazioniCsh)
Dim operazioni As OperazioniCsh = New OperazioniCsh
Return operazioni.OperazioniCsh(npv, nc)
End Function
End Class
Reference Attribute Routing in ASP.NET Web API 2

Deserialize to class

I have a class Person which I can serialize with the following code, but I can’t figure out how to deserialize the file back to the class.
I would be grateful for help on this. Thank you.
Imports Newtonsoft.Json
Imports Windows.Storage
Imports Windows.Storage.Streams
Public Class Person
Public Property Name As String
Public Property Age As Integer
Public Property Gender As String
End Class
Public NotInheritable Class MainPage
Inherits Page
Private p As Person
Private pList As New List(Of Person)
Private Async Sub Save()
Dim jsonContents As String = JsonConvert.SerializeObject(pList)
Dim localFolder As StorageFolder = ApplicationData.Current.LocalFolder
Dim textFile As StorageFile = Await localFolder.CreateFileAsync("a.txt", CreationCollisionOption.ReplaceExisting)
Using textStream As IRandomAccessStream = Await textFile.OpenAsync(FileAccessMode.ReadWrite)
Using textWriter As New DataWriter(textStream)
textWriter.WriteString(jsonContents)
Await textWriter.StoreAsync()
End Using
End Using
End Sub
End Class
I tried the following but it doesn’t work.
Private Async Sub GetData()
Dim localFolder As StorageFolder = ApplicationData.Current.LocalFolder
Dim textFile = Await localFolder.GetFileAsync("a.txt")
Dim readFile = Await FileIO.ReadTextAsync(textFile)
Dim obj As RootObject = JsonConvert.DeserializeObject(Of RootObject)(readFile)
End Sub
Public Class RootObject
'Public Property pList1() As List(Of Person)
Public Property Name() As String
Public Property Age() As Integer
Public Property Gender() As String
End Class
You should make sure your VB class object's property in accordance with the JSON key or JSON name.
For example using your sample JSON data in your comment:
Since your JSON data is not complete, I modify it as the following:
{"pList1":[{"Name":"Henrik","Age":54,"Gender":"Mand"},{"Name":"Lone","Age":50,"Gender":"Kvinde"},{"Name":"Niels","Age":24,"Gender":"Mand"},{"Name":"Pernille","Age":26,"Gender":"Kvinde"}]}
You can keep the above Json data in a file named my.txt, if you want to deserialize the Json data to VB object, your VB objects classes should be as the following two classes:
Public Class Person
Public Property Name As String
Public Property Age As Integer
Public Property Gender As String
End Class
Public Class RootObject
Public Property pList1() As List(Of Person)
End Class
Please pay attention to that: the pList1 property of RootObject class is corresponding to the pList1 key or name in the JSON data.
Then you should be able to use the JsonConvert class to deserialize to RootObject.
Private Async Sub GetData()
Dim localFolder As StorageFolder = ApplicationData.Current.LocalFolder
Dim textFile = Await localFolder.GetFileAsync("my.txt")
Dim readFile = Await FileIO.ReadTextAsync(textFile)
Dim obj As RootObject = JsonConvert.DeserializeObject(Of RootObject)(readFile)
End Sub

Is it possible to make a shared function generic?

I can create classes that use generics, however I was wondering if it is possible to apply this to a shared method rather than rely on the caller casting to the correct type.
This is the method:
Public Shared Function DeserializeObject(ByVal serializedXml As String, ByVal givenType As System.Type) As Object
Dim serializer As New XmlSerializer(givenType)
Return serializer.Deserialize(New IO.StringReader(serializedXml))
End Function
I'm pretty sure this can't be done, but thought I'd check (if so Extra points will be awarded if someone can technically explain why the compiler can't do this).. Alternative suggestions would also be appreciated.
Public Shared Function StronglyTypedDeserializeObject(Of T)
(ByVal serializedXml As String) As T
Dim serializer As New XmlSerializer(GetType(T))
Return DirectCast(
serializer.Deserialize(New IO.StringReader(serializedXml))
, T)
End Function
Note that invocations will have to supply the type expected:
Dim foo As MyType
= Utility.StronglyTypedDeserializeObject(Of MyType)(sourceXml)
There's no reason you couldn't create a generic version of the function. e.g.:
Public Shared Function Deserialize(Of T)(ByVal serializedXml As String) As T
Dim serializer As New XmlSerializer(GetType(T))
Return DirectCast(serializer.Deserialize(New StringReader(serializedXml)), T)
End Function
The Following Example shows how you can do this. The esstential trick is remember that can you can use the GetType function a defined Generic for example GetType(MyObject(Of T))
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Test1 As New MyObject(Of String)
Dim Test2 As New MyObject(Of Integer)
Dim Data As String = ""
Test1.Data = "Hello World"
Test2.Data = 1010101
Data = Test1.SerializeObject
Test1 = MyObject(Of String).DeserializeObject(Data)
Debug.Print(Test1.Data)
Data = Test2.SerializeObject
Test2 = MyObject(Of Integer).DeserializeObject(Data)
Debug.Print(Test2.Data)
End Sub
End Class
Public Class MyObject(Of T)
Public Data As T
Public Sub New()
End Sub
Public Shared Function DeserializeObject(ByVal serializedXml As String) As MyObject(Of T)
Dim serializer As New XmlSerializer(GetType(MyObject(Of T)))
Return serializer.Deserialize(New IO.StringReader(serializedXml))
End Function
Public Function SerializeObject() As String
Dim serializer As New XmlSerializer(GetType(MyObject(Of T)))
Dim Result As New IO.StringWriter()
serializer.Serialize(Result, Me)
Return Result.ToString
End Function
End Class
If you don't like fully qualifying the type to get at the shared member then you can do something like this.
Public Class MyObjectString
Inherits MyObject(Of String)
End Class
Then you can call MyObjectString.Deserialize

VB.NET CType: How do I use CType to change an object variable "obj" to my custom class that I reference using a string variable like obj.GetType.Name?

The code below works for the class that I hard coded "XCCustomers" in my RetrieveIDandName method where I use CType. However, I would like to be able to pass in various classes and property names to get the integer and string LIST returned. For example, in my code below, I would like to also pass in "XCEmployees" to my RetrieveIDandName method. I feel so close... I was hoping someone knew how to use CType where I can pass in the class name as a string variable.
Note, all the other examples I have seen and tried fail because we are using Option Strict On which disallows late binding. That is why I need to use CType.
I also studied the "Activator.CreateInstance" code examples to try to get the class reference instance by string name but I was unable to get CType to work with that.
When I use obj.GetType.Name or obj.GetType.FullName in place of the "XCCustomers" in CType(obj, XCCustomers)(i)
I get the error "Type 'obj.GetType.Name' is not defined" or "Type 'obj.GetType.FullName' is not defined"
Thanks for your help.
Rick
'+++++++++++++++++++++++++++++++
Imports DataLaasXC.Business
Imports DataLaasXC.Utilities
Public Class ucCustomerList
'Here is the calling method:
Public Sub CallingSub()
Dim customerList As New XCCustomers()
Dim customerIdAndName As New List(Of XCCustomer) = RetrieveIDandName(customerList, "CustomerId", " CustomerName")
'This code below fails because I had to hard code “XCCustomer” in the “Dim item...” section of my RetrieveEmployeesIDandName method.
Dim employeeList As New XCEmployees()
Dim employeeIdAndName As New List(Of XCEmployee) = RetrieveIDandName(employeeList, "EmployeeId", " EmployeeName")
'doing stuff here...
End Sub
'Here is the method where I would like to use the class name string when I use CType:
Private Function RetrieveIDandName(ByVal obj As Object, ByVal idPropName As String, ByVal namePropName As String) As List(Of IntStringPair)
Dim selectedItems As List(Of IntStringPair) = New List(Of IntStringPair)
Dim fullyQualifiedClassName As String = obj.GetType.FullName
Dim count As Integer = CInt(obj.GetType().GetProperty("Count").GetValue(obj, Nothing))
If (count > 0) Then
For i As Integer = 0 To count - 1
'Rather than hard coding “XCCustomer” below, I want to use something like “obj.GetType.Name”???
Dim Item As IntStringPair = New IntStringPair(CInt(CType(obj, XCCustomers)(i).GetType().GetProperty("CustomerId").GetValue(CType(obj, XCCustomers)(i), Nothing)), _
CStr(CType(obj, XCCustomers)(i).GetType().GetProperty("CustomerName").GetValue(CType(obj, XCCustomers)(i), Nothing)))
selectedItems.Add(Item)
Next
End If
Return selectedItems
End Function
End Class
'+++++++++++++++++++++++++++++++
' Below are the supporting classes if you need to see what else is happening:
Namespace DataLaasXC.Utilities
Public Class IntStringPair
Public Sub New(ByVal _Key As Integer, ByVal _Value As String)
Value = _Value
Key = _Key
End Sub
Public Property Value As String
Public Property Key As Integer
End Class
End Namespace
'+++++++++++++++++++++++++++++++
Namespace DataLaasXC.Business
Public Class XCCustomer
Public Property CustomerId As Integer
Public Property CustomerName As String
End Class
End Namespace
'+++++++++++++++++++++++++++++++
Namespace DataLaasXC.Business
Public Class XCCustomers
Inherits List(Of XCCustomer)
Public Sub New()
PopulateCustomersFromDatabase()
End Sub
Public Sub New(ByVal GetEmpty As Boolean)
End Sub
End Class
End Namespace
'+++++++++++++++++++++++++++++++
Namespace DataLaasXC.Business
Public Class XCEmployee
Public Property EmployeeId As Integer
Public Property EmployeeName As String
End Class
End Namespace
'+++++++++++++++++++++++++++++++
Namespace DataLaasXC.Business
Public Class XCEmployees
Inherits List(Of XCEmployee)
Public Sub New()
PopulateEmployeesFromDatabase()
End Sub
Public Sub New(ByVal GetEmpty As Boolean)
End Sub
End Class
End Namespace
From MSDN
CType(expression, typename)
. . .
typename : Any expression that is legal
within an As clause in a Dim
statement, that is, the name of any
data type, object, structure, class,
or interface.
This is basically saying you can't use CType dynamically, just statically. i.e. At the point where the code is compiled the compiler needs to know what typename is going to be.
You can't change this at runtime.
Hope this helps.
Since List(Of T) implements the non-generic IList interface, you could change your function declaration to:
Private Function RetrieveIDandName(ByVal obj As System.Collections.IList, ByVal idPropName As String, ByVal namePropName As String) As List(Of IntStringPair)
And then your troublesome line would become (with also using the property name parameters):
Dim Item As IntStringPair = New IntStringPair(CInt(obj(i).GetType().GetProperty(idPropName).GetValue(obj(i), Nothing)), _
CStr(obj(i).GetType().GetProperty(namePropName).GetValue(obj(i), Nothing)))
Of course, you could still have the first parameter by Object, and then attempt to cast to IList, but that's up to you.
ctype is used to convert in object type.

Custom ASP.NET MVC2 HtmlHelper: How to get the instance of the object passed to it?

I am working on a ASP.NET MVC2 website. For learning. I am working with the Visual Basic language.
In a view I would like to do this:
<%: Html.EditorForEnumeracion(Function(v) v.combustible%>
So, I created an HtmlHelper extension method:
Imports System.Runtime.CompilerServices
Imports System.Linq.Expressions
Imports System.Reflection
Public Module HtmlHelpers
<Extension()> _
Public Function EditorForEnumeracion(Of TModel, TValue)(ByVal html As HtmlHelper(Of TModel), ByVal expression As Expression(Of Func(Of TModel, TValue))) As MvcHtmlString
'My stuff goes here
End Function
End Module
The problem is that I do not know how to get the instance of the v.combustible object that I pass to the helper. I do not care about the v object. I need to work with the combustible attribute of the v object.
Here and here seems to be how to do this, but I do not understand. Also, I work with Visual Basic, not C#.
I think that I can get the instance of the Enumeracion object through the expression parameter, but I do not understand how.
More info now.
This is my "Vehiculo" class:
Namespace Models.Automovil
Public Class Vehiculo
Public Property tipo As New Models.Enumeracion("TipoDeVehiculo")
Public Property marca As String
Public Property modelo As String
Public Property numeroDePuertas As Integer
Public Property combustible As New Models.Enumeracion("TipoDeCombustible")
Public Property potencia As Integer
Public Property fechaPrimeraMatriculacion As DateTime
Public Property version As String
Public Property precio As Decimal
Public Property descripcion As String
End Class
End Namespace
And this is my "Enumeracion" class:
Namespace Models
Public Class Enumeracion
Private bd As New tarificadorasegasaEntities
Private diccionario As New Dictionary(Of String, Integer)
Private _nombre As String
Private _clave As String
Private _valor As Integer
Public ReadOnly Property nombre As String
Get
Return _nombre
End Get
End Property
Public ReadOnly Property clave As String
Get
Return _clave
End Get
End Property
Public ReadOnly Property valor As Integer
Get
Return _valor
End Get
End Property
'More stuff here. Methods.
End Class
End Namespace
The model is the Vehiculo class.
Still not resolving this.
Thanks in advance.
You need to compile the expression into a Func(Of TModel, TValue), then call it on the model:
Dim func = expression.Compile()
Dim value = func(html.ViewData.Model)
Try like this:
<Extension()> _
Public Function EditorForMyCustomClassB(Of Vehiculo, Enumeracion)(ByVal html As HtmlHelper(Of TModel), ByVal expression As Expression(Of Func(Of Vehiculo, Enumeracion))) As MvcHtmlString
Dim res = ModelMetadata.FromLambdaExpression(expression, html.ViewData)
Dim e As Enumeracion = DirectCast(res.Model, Enumeracion)
' use e here
End Function