Getting Values of a JSON Object using webmeothd in vb.net - json

I got stuck while getting value of a JSON object in vb.net. My JSON request posts data like given below:
function submitEmail() {
var ClientsPersonalInfo = {
FullName: $("#FullName").val(),
PhoneNumber: $("#PhoneNumber").val(),
EmailAddress: $("#EmailAddress").val(),
DOB: $("#DOB").val(),
Occupation: $("#Occupation").val(),
NINumber: $("#NINumber").val(),
FullAddress: $("#FullAddress").val()
}
var ClientsData = {};
ClientsData.ClientsPersonalInfo = ClientsPersonalInfo;
var d = '{"ClientsData":' + JSON.stringify(ClientsData) + '}'
$.ajax({
type: "POST",
url: "add-new-client.aspx/SubmitEmail", // WebMethod Call
data: d,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
alert(response)
},
failure: function (msg) {
alert(msg);
}
});
}
JSON Object Looks Like
{
"ClientsPersonalInfo": {
"FullName": "",
"PhoneNumber": "",
"EmailAddress": "",
"DOB": "",
"Occupation": "",
"NINumber": "",
"FullAddress": ""
}
}
The above request returns an object in vb.net
VB Code:
<WebMethod()> _
Public Shared Function SubmitEmail(ByVal ClientsPersonalInfo As Object) As String
'What to do next to get object "ClientsPersonalInfo"
'I want to access properties of the object like
'Dim name As String = ClientsPersonalInfo.FullName
Return "Successfully Converted."
End Function
No I want to get values of this object and needs to append in a table. Please guide me how to get values of the above object? I am new in vb.net. Please guide. Thanks!

First, you need to add the ClientsData and ClientsPersonalInfo classes to your web service:
Public Class ClientsPersonalInfo
Public Property FullName As String
Public Property PhoneNumber As String
Public Property EmailAddress As String
Public Property DOB As String
Public Property Occupation As String
Public Property NINumber As String
Public Property FullAddress As String
End Class
Public Class RootObject
Public Property ClientsPersonalInfo As ClientsPersonalInfo
End Class
Now, you can simply change the parameter type in your web service method and .Net engine will do the parsing for you:
<WebMethod()> _
Public Shared Function SubmitEmail(ByVal MyClientsPersonalInfo As ClientsPersonalInfo) As String
'You can access properties of the object like
Dim name As String = MyClientsPersonalInfo.FullName
Return "Successfully Converted."
End Function

Related

How to deserialize a more complex Json Doc in Vb.net with Newtonsoft

I have a rest API which returns me a json response which is an array of docs which in turn has multiple arrays it self. Below is a sample of a doc i like to deserialize
{
"DocId": "contact::6f128681-218d-409d-b71d-31031852057d",
"Name": "Joe F Miller",
"buckets": [
{
"DocId": "leadbucket::5652A756-5B58-45A5-9566-9C85E8783440",
"text": "Dead Leads"
},
{
"DocId": "leadbucket::8A234FC1-6389-485D-8BDE-7FCB1E7639E0",
"text": "No Follow-Up Needed"
},
{
"DocId": "leadbucket::C97632BE-5A24-4AE7-8D18-4DFE174F0D0F",
"text": "Long-Term Buyers"
},
{
"DocId": "leadbucket::D6802064-8AC5-4E5A-855E-B59C32859C81",
"text": "New Lead"
}
],
"emails": [
{
"other": "demo#test.com"
},
{
"work": "work#demo.com"
},
{
"work": "work2#demo.com"
}
],
"followup": {
"date": "05/01/2019",
"type": "phone"
},
"lastactivity": "04/05/2019",
"phones": [
{
"home": "(213) 444-2222"
},
{
"work": "(949) 555-1212"
}
],
"tags": [
{
"DocId": "tag::FC276FBD-DC3A-4E18-8244-E89EF24E022E",
"text": "Buyer"
},
{
"DocId": "tag::EA5DE0FB-34B0-4F7C-B631-177D6BD2F65E",
"text": "Investor"
}
]
}
After i get the response from my API i use the below code to try to convert the data.
ContactList = JsonConvert.DeserializeObject(Of List(Of Contact.ContactList))(read.Item("Data").ToString)
So i hope someone can point me in the right direction on how to create a class to store this type of doc and how to Deserialize it. Do i have to do this in my class or do i have to call a Deserialize for each array in the Json ?
Another issue i have is the emails and phones section, as the key value is not unique and i dont always know what will get returned. how would i build a class to store this as the key field can change.
An example, using an IEnumerable(Of Dictionary(Of String, String)) to deserialize JSON Objects that have an undefined number of elements, with an undefined combination of (Key, Value) pairs per object.
The Key part may also repeat, as shown in the exmple:
"emails": [
{"other": "demo#test.com"},
{"work": "work#demo.com"},
{"work": "work2#demo.com"}
The other, work keys may be different each time and may repeat.
Deserializing/Serializing this property with a IEnumerable(Of Dictionary(Of String, String)), allows to
The sample class object, Contacts, contains the methods (simplified, here) that perform the deserialization of the JSON Object and the seriaization of the Object Root, reproducing the original JSON Object.
These methods are static (Shared), you just need to call the method, no need to create an instance of the Contacts class.
For example, deserialize a JSON Object (a string received from a service):
Dim myContacts As Contacts.RootObject = Contacts.DeserializeJSON(JSONObject)
Serialize the class object back to the original string:
Dim myJsonContacts = Contacts.SerializeJSON(myContacts)
Compare the JSON just serialized to the original and to see whether they match.
List all the Emails and Phone Numbers in the deserialized class object:
(just an example: converting to List is not necessary)
myContacts.Emails.ToList().ForEach(
Sub(em) Console.WriteLine($"from: {em.Keys(0)}, Email: {em.Values(0)}"))
myContacts.Phones.ToList().ForEach(
Sub(ph) Console.WriteLine($"place: {ph.Keys(0)}, Phone Number: {ph.Values(0)}"))
Access a single Email (or Phone Number):
(any other method to extract the (Key, Value) pair from a Dictionary can of course be used)
Dim eMailFrom = myContacts.Emails(0).Keys(0)
Dim eMailValue = myContacts.Emails(0).Values(0)
Get all the Emails from a specific location (work, here):
Dim emailFromWork = myContacts.Emails.Where(Function(em) em.Keys.Contains("work"))
The Contacts class:
Some properties are decorated with a <JsonProperty()>. The property name is changed because the original JSON uses names that are reserved keywords in the language.
For example:
<JsonProperty("text")>
Public Property BucketText As String
Imports Newtonsoft.Json
Public Class Contacts
Public Shared Function DeserializeJSON(JsonObject As String) As RootObject
Return JsonConvert.DeserializeObject(Of RootObject)(JsonObject)
End Function
Public Shared Function SerializeJSON(classObject As RootObject) As String
Return JsonConvert.SerializeObject(classObject)
End Function
Partial Public Class RootObject
Public Property DocId As String
Public Property Name As String
Public Property Buckets As List(Of Bucket)
Public Property Emails As Dictionary(Of String, String)()
Public Property Followup As Followup
Public Property Lastactivity As String
Public Property Phones As IEnumerable(Of Dictionary(Of String, String))
Public Property Tags As List(Of Tag)
End Class
Partial Public Class Bucket
Public Property DocId As String
<JsonProperty("text")>
Public Property BucketText As String
End Class
Partial Public Class Tag
Public Property DocId As String
<JsonProperty("text")>
Public Property TagText As String
End Class
Partial Public Class Followup
<JsonProperty("date")>
Public Property FollowupDate As String
<JsonProperty("type")>
Public Property FollowupType As String
End Class
End Class

How to parse the JSON returned by a REST API call into a collection of objects in JAX-RS?

I am fairly new to JAX-RS so bear with me on this question. I'm trying to consume a REST API using JAX-RS framework. In particular I am trying to invoke a HTTP GET method on a resource where the response entity will be in JSON format. Up until now I can parse the returned JSON into a customized class with the following code snippet;
WebTarget target = client.target(url);
Builder builder = target.request(MediaType.APPLICATION_JSON);
myClass obj = builder.get(myClass.class);
However, in my latest GET request the JSON return will be best abstracted as a collection of objects. I know in .NET this can be done fairly easily with
JsonConvert.DeserializeObject<List<myClass>>
but how could I do that in JAX-RS? Thanks in advance.
EDIT:
I model my code after the solution in How to get list<String> as response from jersey2 client
WebTarget target = client.target(url);
Builder builder = target.request(MediaType.APPLICATION_JSON);
builder.header(X_OCTOPUS_APIKEY_NAME, apiKey);
Response serviceResponse = builder.get(Response.class);
List<myType> objects = serviceResponse.readEntity(new GenericType<List<myType>>() {});
However the objects returned is always null. To verify the REST API call actually return a valid JSON value I replace the last line with:
String strDate = serviceResponse.readEntity(String.class);
It is confirmed with the following JSON return:
[
{
"Id": "Users-267",
"Username": "mdamon#mydomain.com",
"DisplayName": "Damon, Matt",
"IsActive": true,
"IsService": false,
"EmailAddress": "mdamon#mydomain.com",
"IsRequestor": false,
"Links": {
"Self": "/api/users/Users-267",
"Permissions": "/api/users/Users-267/permissions",
"ApiKeys": "/api/users/Users-267/apikeys{/id}{?skip}",
"Avatar": "https://www.gravatar.com/avatar/94324e7c54a9a5f9d103b2a709863fc3?d=blank"
}
},
{
"Id": "Users-2101",
"Username": "baffleck#mydomain.com",
"DisplayName": "Affleck, Ben",
"IsActive": true,
"IsService": false,
"EmailAddress": "baffleck#mydomain.com",
"IsRequestor": false,
"Links": {
"Self": "/api/users/Users-2101",
"Permissions": "/api/users/Users-2101/permissions",
"ApiKeys": "/api/users/Users-2101/apikeys{/id}{?skip}",
"Avatar": "https://www.gravatar.com/avatar/11edd32712facde9a7d3dd4445a4abe9?d=blank"
}
},
...
]
So for reason the JSON is not being parsed at a collection of my custom type. One extra piece of information is my custom is defined as follows:
#XmlRootElement
public class myType {
String DisplayName;
String EmailAddress;
public myType() {
super();
}
public void setDisplayName(String displayName) {
DisplayName = displayName;
}
public String getDisplayName() {
return DisplayName;
}
public void setEmailAddress(String emailAddress) {
EmailAddress = emailAddress;
}
public String getEmailAddress() {
return EmailAddress;
}
}
I only include the DisplayName and EmailAddress field of the JSON in my custom type because I don't need all the other data, in case that matters. Can anyone tell me why it is not being parsed? Thanks

Getting Values of a JSON Object in vb.net

EDITED:
I got stuck while getting value of a JSON object in vb.net. My JSON request posts data like given below:
function submitEmail() {
var ClientsPersonalInfo = {
FullName: $("#FullName").val(),
PhoneNumber: $("#PhoneNumber").val(),
EmailAddress: $("#EmailAddress").val(),
DOB: $("#DOB").val(),
Occupation: $("#Occupation").val(),
NINumber: $("#NINumber").val(),
FullAddress: $("#FullAddress").val()
}
var ClientsData = {};
ClientsData.ClientsPersonalInfo = ClientsPersonalInfo;
var d = '{"ClientsData":' + JSON.stringify(ClientsData) + '}'
$.ajax({
type: "POST",
url: "add-new-client.aspx/SubmitEmail",
data: d,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
alert(response)
},
failure: function (msg) {
alert(msg);
}
});
}
JSON Object Looks Like
{
"ClientsPersonalInfo": {
"FullName": "",
"PhoneNumber": "",
"EmailAddress": "",
"DOB": "",
"Occupation": "",
"NINumber": "",
"FullAddress": ""
}
}
The above request returns an object in vb.net
VB Code:
<WebMethod()> _
Public Shared Function SubmitEmail(ByVal ClientsPersonalInfo As Object) As String
// What to do next to get object "ClientsPersonalInfo"
// I want to access properties of the object like
//Dim name As String = ClientsPersonalInfo.FullName
Return "Successfully Converted."
End Function
No I want to get values of this object and needs to append in a table. Please guide me how to get values of the above object?
First make sure your Json is in valid format using jsonlint
Then generate class base on it using jsonutils
Public Class ClientsPersonalInfo
Public Property FullName As String
Public Property PhoneNumber As String
Public Property EmailAddress As String
Public Property DOB As String
Public Property Occupation As String
Public Property NINumber As String
Public Property FullAddress As String
End Class
Public Class ClientsVehicleInfo
Public Property DrivingLicense As String
Public Property VehicleMakeModel As String
Public Property VehicleColour As String
Public Property PolicyNumber As String
Public Property TypeOfCover As String
Public Property VehicleStoredIn As String
End Class
Public Class ClientsData
Public Property ClientsPersonalInfo As ClientsPersonalInfo
Public Property ClientsVehicleInfo As ClientsVehicleInfo
End Class
Public Class ClientData
Public Property ClientsData As ClientsData
End Class
Use Newtonsoft JSON to deserialize your Json into object(s) then you may simply access its properties value. (remember to add Json.net to your project using Manage NuGet Packages)
Imports Newtonsoft.Json
Dim obj = JsonConvert.DeserializeObject(Of Dictionary(Of String, ClientsData))(yourJsonString)
At least one problem is not using Option Strict On. The code at fault:
Shared Function SubmitEmail(ByVal ClientData As Object) As String
Dim obj = JsonConvert.DeserializeObject(Of NewClientData)(ClientData)
If you turn on Option Strict that will not compile because JsonConvert.DeserializeObject takes a string argument. I am not sure why the exception (image now removed) seems to come from VB rather than Newtonsoft, but that isnt helping.
Your deserialized object will also just disappear when it goes out of scope when the method ends.
Applicable to Edit #9
The error mentioning a Dictionary seems misleading and probably something internal relating to how the properties are collected (many times json can be deserialized to a Dictionary(Of String, String). Given the json posted (with data):
{
"ClientsData": {
"ClientsPersonalInfo": {
"FullName": "Ziggy Le Strange",
"PhoneNumber": "505050",
"EmailAddress": "ziggy#foobar.com",
"DOB": "",
"Occupation": "Freelancer",
"NINumber": "7",
"FullAddress": "123 Easy street"
}
}
}
There are actually 3 classes: ClientsPersonalInfo with the data, ClientsData which is a class containing that one and in previous edits also included a ClientsVehicleInfo class.
But there is yet another class represented by the enclosing {...}. The robots who can create the classes for you name it Example or RootObject. In this case, I would call it ClientContainer.
This works:
' the outermost {}
Public Class ClientContainer
Public Property ClientsData As ClientsData
End Class
Public Class ClientsPersonalInfo
Public Property FullName As String
Public Property PhoneNumber As String
Public Property EmailAddress As String
Public Property DOB As String
Public Property Occupation As String
Public Property NINumber As String
Public Property FullAddress As String
End Class
Public Class ClientsData
Public Property ClientsPersonalInfo As ClientsPersonalInfo
Public Property ClientsVehicleInfo As ClientsVehicleInfo
End Class
Public Class ClientsVehicleInfo
' whatever it is supposed to hold
End Class
To deserialize the data (you may have to adapt it for web use, Shared seems incorrect to me):
' pass in the json AS STRING
' returns JUST the ClientsPersonalInfo
Public Function GetClientData(jsonData As String) As ClientsPersonalInfo
' you must use the container class
Dim client = JsonConvert.DeserializeObject(Of ClientContainer)(jsonData )
' TEST:
Console.WriteLine(client.ClientsData.ClientsPersonalInfo.FullName)
Return client.ClientsData.ClientsPersonalInfo
End Function
ClientsData seems to be an unneeded layer. The container could hold both of the other objects directly. If this is meant to hold info for more than one client, you would have keys in place of "ClientsData": in the json (e.g. "ziggy":{}, "zacky":{}, "zoey":{}.
Output:
Ziggy Le Strange
Since, as per comment, that vehicle info is part of the deal, you can change it to return ClientsData which holds both the Personal and Vehicle info:
Public Function GetClientData(jsonData As String) As ClientsData
' you must use the container class
Dim client = JsonConvert.DeserializeObject(Of ClientContainer)(jsonData )
Return client.ClientsData
Turn on Option Strict
Dont box parameters or returns As Object, they loose some of their meaning.
Keep in mind that the outermost braces in json represent a container object
Also, storing a Date as string looks bad too.

ASP.NET MVC 4 JSON Binding to the View Model - Nested object error

I have got the problem with json binding to the view model. Here is my code:
part of my ViewModels (AddressViewModel has more properties):
public class AddressViewModel
{
[Display(Name = "Address_Town", ResourceType = typeof(Resources.PartyDetails))]
public string Town { get; set; }
[Display(Name = "Address_Country", ResourceType = typeof(Resources.PartyDetails))]
public Country Country { get; set; }
}
public class Country : EntityBase<string>
{
public string Name { get; set; }
protected override void Validate()
{
if (string.IsNullOrEmpty(Name))
{
base.AddBrokenRule(new BusinessRule("CountryName", "Required"));
}
}
}
Javascript:
$(document).on("click", "#addAddress", function () {
var jsonData = {
"Town": $('#txt-Town').val(),
"District": $('#txt-District').val(),
"Street": $('#txt-Street').val(),
"PostCode": $('#txt-PostCode').val(),
"FlatNumber": $('#txt-FlatNumber').val(),
"PremiseName": $('#txt-PremiseName').val(),
"PremiseNumber": $('#txt-Premisenumber').val(),
"Country": {
"Name": $('#txt-Country').val(),
}
};
var addressData = JSON.stringify(jsonData);
$.ajax({
url: '/Customer/SaveAddress',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: addressData,
success: function (result) {
$("#addIndividualAddressDialog").data("kendoWindow").close();
},
error: function (result) {
alert("Failed");
}
});
});
Header of controller:
[HttpPost]
public ActionResult SaveAddress(AddressViewModel addressViewModel)
This is what I see with firebug:
And this is what I see in VS:
As you can see Plain properties are binded correct but my nested object (Country) is null. I read a lot of different articles and I still don't know what I'm doing wrong. Help me please!
You can keep your existing ActionMethod untouched without the need of json serializing:
In the client side create an object from your json:
JSON.parse(jsonData)
and send that in the $.ajax data property.
Or, instead of creating json, create an object:
var dataObject = new Object();
dataObject.Town = $('#txt-Town').val();
dataObject.District = $('#txt-District').val();
...
And again, send that object in the $.ajax data property.
The problem is from your action method parameter:
[HttpPost]
public ActionResult SaveAddress(AddressViewModel addressViewModel)
As you use JSON.stringify(), you send a string to your controller, not an object! So, you need to do some works to achive your goal:
1) Change your action method parametter:
[HttpPost]
public ActionResult SaveAddress(string addressViewModel)
2) Deserialize that string to an object - that is AddressViewModel:
IList<AddressViewModel> modelObj = new
JavaScriptSerializer().Deserialize<IList<AddressViewModel>>(addressViewModel);
So, your final action method should be like the following:
[HttpPost]
public ActionResult SaveAddress(string addressViewModel)
{
IList<AddressViewModel> modelObj = new
JavaScriptSerializer().Deserialize<IList<AddressViewModel>>(addressViewModel);
// do what you want with your model object ...
}
Actually the best option is just to remove the
var addressData = JSON.stringify(jsonData);
line and send jsonData itself. ASP.NET MVC will auto-bind it if it is an actual object and not just a string.
Occam's Razor
Sorry to answer for old thread.here you could work with JsonResult instead of ActionResult
this is your signature
[HttpPost]
public ActionResult SaveAddress(AddressViewModel addressViewModel)
it should look like
[HttpPost]
public JsonResult SaveAddress(AddressViewModel addressViewModel)
{
return Json(status);
}
the advantage would be if you use JsonResult instead of ActionResult that u do not need to Deserialize
here is the link http://codeforcoffee.org/asp-net-mvc-intro-to-mvc-using-binding-json-objects-to-models/ from this link you can get the idea.
OR you can use JsonConvert.DeserializeObject<>();
following is the code to deserialize the JSON.stringify() result
IList<AddressViewModel> modelObj = JsonConvert.DeserializeObject<IList<AddressViewModel>>(addressViewModel);
instead of
JavaScriptSerializer().Deserialize<IList<AddressViewModel>>(addressViewModel);
You must reference to Country object inside jsonData variable. The JSON POST binding will work correctly.
Old code:
var jsonData = {
"Town": $('#txt-Town').val(),
"District": $('#txt-District').val(),
"Street": $('#txt-Street').val(),
"PostCode": $('#txt-PostCode').val(),
"FlatNumber": $('#txt-FlatNumber').val(),
"PremiseName": $('#txt-PremiseName').val(),
"PremiseNumber": $('#txt-Premisenumber').val(),
"Country": {
"Name": $('#txt-Country').val(),
}
New code:
var jsonData = {
"Town": $('#txt-Town').val(),
"District": $('#txt-District').val(),
"Street": $('#txt-Street').val(),
"PostCode": $('#txt-PostCode').val(),
"FlatNumber": $('#txt-FlatNumber').val(),
"PremiseName": $('#txt-PremiseName').val(),
"PremiseNumber": $('#txt-Premisenumber').val(),
"Country.Name": $('#txt-Country').val(),
}

Deserializing JSON to object with no default constructor in ASP.NET MVC 3

There are quite a few questions around JSON deserialization but a lot of them seem to be for MVC 1 or MVC 2. I don't seem to have found a satisfactory answer to this specifically for MVC 3.
I have an object with immutable properties and no default constructor, which I want to deserialize to in an ASP.NET MVC 3 application. Here is a simplified version:
public class EmailAddress
{
public EmailAddress(string nameAndEmailAddress)
{
Name = parseNameFromNameAndAddress(nameAndEmailAddress);
Address = parseAddressFromNameAndAddress(nameAndEmailAddress);
}
public EmailAddress(string name, string address)
{
Guard.Against<FormatException>(!isNameValid(name), "Value is invalid for EmailAddress.Name: [{0}]", name);
Guard.Against<FormatException>(!isAddressValid(address), "Value is invalid for EmailAddress.Address: [{0}]", address);
Name = name;
Address = address;
}
public string Address { get; private set; }
public string Name { get; private set; }
// Other stuff
}
An example controller action might be:
[HttpPost]
public ActionResult ShowSomething(EmailAddress emailAddress)
{
return View(emailAddress)
}
The JSON coming in is:
{"Address":"joe#bloggs.com","Name":"Joe Bloggs"}
What is the best way to get this to deserialize in MVC3? Is there some way of implementing a custom model binder or deserializer class that can handle this?
A solution that doesn't interfere with the object itself would be preferable (ie. a separate deserializer class, rather than adding attributes to properties, etc), although open to any good suggestions.
I found a similar question (with no answer) here: Can I deserialize to an immutable object using JavascriptSerializer?
Is there some way of implementing a custom model binder or
deserializer class that can handle this?
Yes, you could write a custom model binder:
public class EmailAddressModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var addressKey = "Address";
var nameKey = "Name";
if (!string.IsNullOrEmpty(bindingContext.ModelName))
{
addressKey = bindingContext.ModelName + "." + addressKey;
nameKey = bindingContext.ModelName + "." + nameKey;
}
var addressValue = bindingContext.ValueProvider.GetValue(addressKey);
var nameValue = bindingContext.ValueProvider.GetValue(nameKey);
if (addressValue == null || nameValue == null)
{
throw new Exception("You must supply an address and name");
}
return new EmailAddress(nameValue.AttemptedValue, addressValue.AttemptedValue);
}
}
which will be registered in Application_Start:
ModelBinders.Binders.Add(typeof(EmailAddress), new EmailAddressModelBinder());
and finally all that's left is to invoke the action:
$.ajax({
url: '#Url.Action("ShowSomething")',
type: 'POST',
data: JSON.stringify({ "Address": "joe#bloggs.com", "Name": "Joe Bloggs" }),
contentType: 'application/json',
succes: function (result) {
alert('success');
}
});
EDITED ANSWER:
I misread the code, looked at the constructor parameters, instead of the properties.
The cause of your problem is the private set of the properties.
Ie, it should be:
public string Address { get; set; }
public string Name { get; set; }
If you make that change, it should all work.
Just remember:
The model binder looks for PROPERTIES, not the constructor!