Xamarin JSON Deserialize - json

I created a HTTPWebRequest to check if the username and password of the user is correct. If the username and password of the user is correct it will return a JSON Array with the ContactID of the user. I tried to deserialize the JSON but I failed to get the actual data. I want to get the Contact id and send the data to a variable of the next page.
The output of the JSON when the username and password is correct:
[{"ContactID":"1"}]
My code:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Input;
using TBSMobileApplication.Data;
using TBSMobileApplication.View;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace TBSMobileApplication.ViewModel
{
public class LoginPageViewModel : INotifyPropertyChanged
{
void OnProperyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public string username;
public string password;
public string Username
{
get { return username; }
set
{
username = value;
OnProperyChanged(nameof(Username));
}
}
public string Password
{
get { return password; }
set
{
password = value;
OnProperyChanged(nameof(Password));
}
}
public ICommand LoginCommand { get; set; }
public LoginPageViewModel()
{
LoginCommand = new Command(OnLogin);
}
public void OnLogin()
{
if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password))
{
MessagingCenter.Send(this, "Login Alert", Username);
}
else
{
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)
{
var link = "http://192.168.1.25:7777/TBS/test.php?User=" + Username + "&Password=" + Password;
var request = HttpWebRequest.Create(string.Format(#link));
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
{
Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
}
else
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if (content.Equals("[]") || string.IsNullOrWhiteSpace(content) || string.IsNullOrEmpty(content))
{
MessagingCenter.Send(this, "Http", Username);
}
else
{
var usr = JsonConvert.DeserializeObject(content);
App.Current.MainPage.Navigation.PushAsync(new DatabaseSyncPage(), true);
}
}
}
}
}
else
{
MessagingCenter.Send(this, "Not Connected", Username);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}

Modify your code else block like below
if (content.Equals("[]") || string.IsNullOrWhiteSpace(content) || string.IsNullOrEmpty(content))
{
MessagingCenter.Send(this, "Http", Username);
}
else
{
var response = JsonConvert.DeserializeObject<List<LoggedInUser>>(content);
var contactId=response[0].ContactID;
//response have your ContactID value. Try to debug & see.
App.Current.MainPage.Navigation.PushAsync(new DatabaseSyncPage(), true);
}
Create one another public class to deserialize your response
public class LoggedInUser
{
public string ContactID { get; set; }
}
If you have more than 1 record in result(as you asked this in comment below)
you can get them using loops
for (int i = 0; i < response.Count; i++)
{
var item = response[i];
var contactId = item.ContactId;
}
Hope it help you.

JSON Response object is not looking standard format for output result. Whatever for JSON deserialization you should create separate class as per below code.
public class RootObject
{
public string ContactID { get; set; }
}
Public Void ServiceRequest()
{
var content = reader.ReadToEnd();
if(!String.IsNullOrEmpty(content)
{
var response = JsonConvert.DeserializeObject<RootObject>(content);
}
}
I hope it will be useful.

Related

Deserialize json shows null in xamarin forms

Hi I have a Login API which I am using to login though my xamarin.forms app.
I will post my username and password and in return I am getting some data.Now Iam facing some issues at deserialization of json. Iam getting data at my resultJson but I cant deserialize it. Help me.
My Json :
[
{
"Result":true,
"ID":"fc938df0",
"LoginName":"test",
"UserName":"test",
"ConnectionString":"MSSQLSERVER;Initial Catalog=Test1;User ID=db;Password=db#2018",
"UserProfileID":"fc938df0"
}
]
My API Call class which have deserialization of Json.
public T APICallResult<T>()
{
try
{
Device.BeginInvokeOnMainThread(() =>
{
if (loadingIndicator != null)
{
loadingIndicator.IsRunning = true;
loadingIndicator.IsVisible = true;
}
});
var client = new HttpClient { BaseAddress = baseAddress };
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var req = new HttpRequestMessage(HttpMethod.Post, apiurl);
req.Content = new StringContent(postdata, Encoding.UTF8, "application/json");
string stringObtained = "";
Task<string> task = Task.Run(async () => await Threading(client, req));
task.Wait();
stringObtained = task.Result;
var jsonObtained = Regex.Unescape(stringObtained);
int startIndex = jsonObtained.IndexOf('[');
int endIndex = jsonObtained.LastIndexOf(']');
int length = endIndex - startIndex + 1;
var resultJSON = jsonObtained.Substring(startIndex, length);
T resultObject;//Generic type object
try
{
//**Deserializing**
resultObject = JsonConvert.DeserializeObject<T>(resultJSON);//, settings);
removeLoadingAnimation();
return resultObject;
}
catch (Exception e)
{
List<ErrorMessageData> errorMessages = JsonConvert.DeserializeObject<List<ErrorMessageData>>(resultJSON);
errorMessage = errorMessages[0];
removeLoadingAnimation();
return default(T);
}
}
catch (Exception e)
{
errorMessage = new ErrorMessageData();
errorMessage.Flag = false;
errorMessage.Message = e.Message;
removeLoadingAnimation();
return default(T);
}
}
My API call at login class
string postdataForLogin = "{\"userName\":\"" + userName.Text + "\",\"password\":\"" + password.Text + "\",\"RequestURL\":\"" + CommonValues.RequestURL + "\"}";
APICall callForLogin = new APICall("/API/LoginMobile/HomeLogin", postdataForLogin, loadingIndicator);
try
{
List<LoginData> resultObjForLogin = callForLogin.APICallResult <List<LoginData>>();
if (resultObjForLogin != null)
{
LoginData loginData = new LoginData();
loginData = resultObjForLogin[0];
Settings.userID = loginData.UserProfileID;
Settings.connectionString = loginData.ConnectionString;
if (loginData.Result)
{
Device.BeginInvokeOnMainThread(async () =>
{
Navigation.InsertPageBefore(new MainPage(), this);
await Navigation.PopAsync();
});
}
My DataModel
public class LoginData
{
public bool Result { get; set; }
public string ID { get; set; }
public string UserProfileID { get; set; }
public string LoginName { get; set; }
public string UserName { get; set; }
public string ConnectionString { get; set; }
}
Its seems strange, My problem solved after downgrading my xamarin.forms from latest version to pre release 4.0.0.169046- pre5. I think its a xamarin forms bug

Xamarin Forms reading JSON

So I am retrieving JSON data from my site and this is my code:
The model:
class Reservations
{
public string id_reservation { get; set; }
public string spz { get; set; }
public string reservation_day { get; set; }
public string reservation_time { get; set; }
public string ip_address { get; set; }
}
The connection and parsing:
protected async void CheckReservations(string day)
{
if (CrossConnectivity.Current.IsConnected)
{
try
{
private const string Url = "Urltomysite";
private HttpClient _client = new HttpClient();
var content = await _client.GetStringAsync(Url);
List<Reservations> myData = JsonConvert.DeserializeObject<List<Reservations>>(content);
foreach (Reservations res in myData)
{
System.Console.WriteLine("Time:" + res.reservation_time);
}
}
catch (Exception e)
{
Debug.WriteLine("" + e);
}
}
}
And the JSON response from my site:
[
{
id_reservation: "39",
spz: "NRGH67L",
reservation_day: "2019-01-26",
reservation_time: "14:00",
ip_address: "192.168.137.5"
}
]
But when I try to print the reservation_time from List of the Object in the foreach I dont get any results. I am still pretty new to this and got this far from tutorials, so dont know what I am missing.
Thanx for any replies.
I suggest using a crash prone way of this
var response = await client.GetAsync(uri);
if(response.IsSuccessStatusCode)
{
var json = await responseMessage.Content.ReadAsStringAsync(); //using ReadAsStreamAsync() gives you better performance
List<Reservations> myData = JsonConvert.DeserializeObject<List<Reservations>>(json);
//do the rest jobs
}
else
{
//alert the api call failed
}

Multipart/form-data images upload with JSON asp.net core api

How to POST both images and JSON at the same time in a single POST ? (using multipart)
I have a form with some data that i put into JSON and the users can add 0 to 6 photos and submit it to the API.
Can someone explain me how to do it ?
Edit :
Here is my code thanks to your help :
// POST api/<controller>
[HttpPost, Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IActionResult Post(ViewModel vm)
{
IActionResult response = Unauthorized();
var data = vm.FamilleProduit;
var reforigine = vm.RefOrigine;
if (vm.Images != null)
{
foreach (var image in vm.Images)
{
byte[] fileData = null;
// read file to byte array
using (var binaryReader = new BinaryReader(image.OpenReadStream()))
{
fileData = binaryReader.ReadBytes((int)image.Length);
}
}
}
return response;
}
public class ViewModel
{
public string FamilleProduit { get; set; }
public string RefOrigine { get; set; }
public List<IFormFile> Images { get; set; }
}
I'm testing with Postman and i POST 2 text (FamilleProduit & RefOrigine) and 2 files (2 images) with "multipart/form-data".
I get the 2 texts perfectly but Images field is null everytime.
Thanks,
Tristan.
You can use built-in class IFormFile to easily work with file upload. To use it together with JSON you may create custom model binder and combine it together in DTO object:
public class ViewModel
{
[ModelBinder(BinderType = typeof(FormDataJsonBinder))]
public DataModel Data { get;set; }
public List<IFormFile> Images { get; set; }
}
public class FormDataJsonBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if(bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
string fieldName = bindingContext.FieldName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(fieldName);
if(valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
else
{
bindingContext.ModelState.SetModelValue(fieldName, valueProviderResult);
}
string value = valueProviderResult.FirstValue;
if(string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
try
{
object result = JsonConvert.DeserializeObject(value, bindingContext.ModelType);
bindingContext.Result = ModelBindingResult.Success(result);
}
catch(JsonException)
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
Then you can work with it in your controller:
[HttpPost]
public IActionResult Create(ViewModel vm)
{
var data = vm.Data;
if (vm.Images != null)
{
foreach(var image in vm.Images)
{
byte[] fileData = null;
// read file to byte array
using (var binaryReader = new BinaryReader(image.OpenReadStream()))
{
fileData = binaryReader.ReadBytes((int)image.Length);
}
}
}
}

Unable to deserialize json array using wcf service

I'm trying to DeSerialize data in json array using wcf service in the project.
The data is fetched and can be noticed in the debugging but i'm unable to deserialize, or something else that I'm mistaken. Below is the code that I've tried to deserialize.
Note:- I've separately run the wcf application and its returning json array in correct format with the actual result.
HotelServiceClient.cs
public class HotelServiceClient
{
private string BASE_URL = "http://localhost:50540/ServiceHotel.svc/";
public List<HotelInfo> findall()
{
try
{
var webClient = new WebClient();
var json = webClient.DownloadString(BASE_URL + "findall");
var javaScriptJson = new JavaScriptSerializer();
return javaScriptJson.Deserialize<List<HotelInfo>>(json);
}
catch
{
return null;
}
}
HotelInfo.cs
public class HotelInfo
{
private int _hotelid;
private string _hotelname;
private string _hoteldesc;
private string _hotelprice;
private byte[] _hotelpicture;
[Key]
[Display(Name = "Id")]
public int Hotelid
{
get
{
return _hotelid;
}
set
{
_hotelid = value;
}
}
[Display(Name = "Name")]
public string Hotelname
{
get
{
return _hotelname;
}
set
{
_hotelname = value;
}
}
[Display(Name = "description")]
public string Hoteldesc
{
get
{
return _hoteldesc;
}
set
{
_hoteldesc = value;
}
}
[Display(Name = "price")]
public string Hotelprice
{
get
{
return _hotelprice;
}
set
{
_hotelprice = value;
}
}
[Display(Name = "picture")]
public byte[] Hotelpicture
{
get
{
return _hotelpicture;
}
set
{
_hotelpicture = value;
}
}
}
WebService
Hotel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CRUDwithHotels
{
public class Hotel
{
public int Id { get; set; }
public string Name { get; set; }
public string description { get; set; }
public string price { get; set; }
public byte[] picture { get; set; }
}
}
IServiceHotel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace CRUDwithHotels
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IServiceHotel" in both code and config file together.
[ServiceContract]
public interface IServiceHotel
{
[OperationContract]
[WebInvoke(Method ="GET", UriTemplate ="findall", ResponseFormat =WebMessageFormat.Json)]
List<Hotel> findall();
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "find/{id}", ResponseFormat = WebMessageFormat.Json)]
Hotel find(string id);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "create", ResponseFormat = WebMessageFormat.Json, RequestFormat =WebMessageFormat.Json)]
bool create(Hotel hotel);
[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "edit", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
bool edit(Hotel hotel);
[OperationContract]
[WebInvoke(Method = "DELETE", UriTemplate = "delete", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
bool delete(Hotel hotel);
}
}
ServiceHotel.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace CRUDwithHotels
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ServiceHotel" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select ServiceHotel.svc or ServiceHotel.svc.cs at the Solution Explorer and start debugging.
public class ServiceHotel : IServiceHotel
{
public bool create(Hotel hotel)
{
using (ModelMyDemo hie = new ModelMyDemo())
{
try
{
HotelInfoEntities info = new HotelInfoEntities();
info.Hotelname = hotel.Name;
info.Hoteldesc = hotel.description;
info.Hotelprice = hotel.price;
info.Hotelpicture = hotel.picture;
hie.HotelInfoEntities.Add(info);
hie.SaveChanges();
return true;
}
catch
{
return false;
}
};
}
public bool delete(Hotel hotel)
{
using (ModelMyDemo hie = new ModelMyDemo())
{
try
{
int id = Convert.ToInt16(hotel.Id);
HotelInfoEntities info = hie.HotelInfoEntities.Single(p => p.Hotelid == id);
hie.HotelInfoEntities.Remove(info);
hie.SaveChanges();
return true;
}
catch
{
return false;
}
};
}
public bool edit(Hotel hotel)
{
using (ModelMyDemo hie = new ModelMyDemo())
{
try
{
int id = Convert.ToInt16(hotel.Id);
HotelInfoEntities info = hie.HotelInfoEntities.Single(p => p.Hotelid == id);
info.Hotelname = hotel.Name;
info.Hoteldesc = hotel.description;
info.Hotelprice = hotel.price;
info.Hotelpicture = hotel.picture;
hie.SaveChanges();
return true;
}
catch
{
return false;
}
};
}
public Hotel find(string id)
{
int hid = Convert.ToInt16(id);
using (ModelMyDemo hie = new ModelMyDemo())
{
return hie.HotelInfoEntities.Where(pe => pe.Hotelid == hid).Select(pe => new Hotel
{
Id = pe.Hotelid,
Name = pe.Hotelname,
description = pe.Hoteldesc,
price = pe.Hotelprice,
picture = pe.Hotelpicture
}).First();
};
}
public List<Hotel> findall()
{
//var imagesrc = string.Format("data:image/jpeg;base64,{0}", base64);
using (ModelMyDemo hie = new ModelMyDemo())
{
return hie.HotelInfoEntities.Select(pe => new Hotel
{
Id = pe.Hotelid,
Name = pe.Hotelname,
description = pe.Hoteldesc,
price = pe.Hotelprice,
picture = pe.Hotelpicture
// picture = pe.Hotelpicture
}).ToList();
};
}
}
}
at first we need an object in order to deserilize the the result in it.
public class RootObject
{
public int Id { get; set; }
public string Name { get; set; }
public string description { get; set; }
public List<byte> picture { get; set; }
}
now all we need is to deserilize the json result in to the object. but your json is twice serilized so you need to deserilized it twice like this:
public RootObject findall()
{
try
{
var webClient = new WebClient();
var json = webClient.DownloadString(BASE_URL + "findall");
return JsonConvert.DeserializeObject<RootObject[]>(json);
}
catch
{
return null;
}
}

WebInvoke Parameter is NULL

I have a service where the operation contract looks like the following. I have a WebInvoke attribute and the method is set to POST. I do have a UriTemplate. The actual service method name is SaveUser. I am trying to pass in a User object (a data contract with properties annotated as data member attributes).
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "SaveUser", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json)]
User SaveUser(User user);
The client looks like the following. For simplicity I have excluded the token and authorization etc.:
using (WebClient webClient = new WebClient())
{
try
{
Random r = new Random();
var partitionKey = Guid.NewGuid().ToString();
var rowKey = r.Next(999900, 999999).ToString();
User u = new User()
{
UserId = partitionKey,
FirstName = "First-" + DateTime.Now.Ticks.ToString(),
LastName = "Last-" + DateTime.Now.Ticks.ToString(),
LoginName = rowKey,
Password = "password1",
PayPalEmailAddress = "First" + DateTime.Now.Ticks.ToString() + "#verascend.com",
PhoneNumber = "+1206" + r.Next(1234567, 9999999).ToString()
};
string url = serviceBaseUrl + "/SaveUser";
webClient.Headers["Content-type"] = "application/json; charset=utf-8";
// webClient.Headers[HttpRequestHeader.Authorization] = authToken;
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(User));
using (var memStream = new MemoryStream())
{
ser.WriteObject(memStream, u);
Debug.WriteLine("-------------> "+ByteArrayToString(memStream.ToArray()));
webClient.UploadData(url, "POST", memStream.ToArray());
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
string responseText = string.Empty;
using (Stream responseStream = ((HttpWebResponse)ex.Response).GetResponseStream())
{
using (StreamReader streamReader = new StreamReader(responseStream))
{
responseText = streamReader.ReadToEnd();
}
}
throw new Exception(responseText);
}
else
{
throw new Exception(ex.Message.ToString());
}
}
}
Problem: The service method (actual service) is receiving the param (User) as NULL. What am I doing wrong? I tried adding the known type in the service contract but no luck.
Your problem is that you define your operation to have a wrapped request. That means that the parameter, instead of being sent as a "plain" JSON object, must be wrapped in a JSON object, and the member name must correspond to the parameter name (in your case, user). The code below does the wrapping; you can see that with that the parameter now is properly received by the server. Another option would be to change the BodyStyle property to Bare instead of WrappedRequest as you have (in which case you'd need to send the plain object to the service operation).
public class StackOverflow_12452466
{
[ServiceContract]
public interface ITest
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "SaveUser", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json)]
User SaveUser(User user);
}
public class Service : ITest
{
public User SaveUser(User user)
{
Console.WriteLine("User: {0}", user);
return user;
}
}
public class User
{
public string UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string LoginName { get; set; }
public string Password { get; set; }
public string PayPalEmailAddress { get; set; }
public string PhoneNumber { get; set; }
public override string ToString()
{
return string.Format("Id={0},First={1},Last={2},Login={3},Pwd={4},PayPal={5},Phone={6}",
UserId, FirstName, LastName, LoginName, Password, PayPalEmailAddress, PhoneNumber);
}
}
public static void Test()
{
string serviceBaseUrl = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(serviceBaseUrl));
host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
host.Open();
Random r = new Random();
User u = new User()
{
UserId = "partitionKey",
FirstName = "First-" + DateTime.Now.Ticks.ToString(),
LastName = "Last-" + DateTime.Now.Ticks.ToString(),
LoginName = "rowKey",
Password = "password1",
PayPalEmailAddress = "First" + DateTime.Now.Ticks.ToString() + "#verascend.com",
PhoneNumber = "+1206" + r.Next(1234567, 9999999).ToString()
};
string url = serviceBaseUrl + "/SaveUser";
WebClient webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json; charset=utf-8";
Func<byte[], string> ByteArrayToString = (b) => Encoding.UTF8.GetString(b);
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(User));
try
{
using (var memStream = new MemoryStream())
{
byte[] wrappingStart = Encoding.UTF8.GetBytes("{\"user\":");
memStream.Write(wrappingStart, 0, wrappingStart.Length);
ser.WriteObject(memStream, u);
byte[] wrappingEnd = Encoding.UTF8.GetBytes("}");
memStream.Write(wrappingEnd, 0, wrappingEnd.Length);
Debug.WriteLine("-------------> " + ByteArrayToString(memStream.ToArray()));
webClient.UploadData(url, "POST", memStream.ToArray());
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
string responseText = string.Empty;
using (Stream responseStream = ((HttpWebResponse)ex.Response).GetResponseStream())
{
using (StreamReader streamReader = new StreamReader(responseStream))
{
responseText = streamReader.ReadToEnd();
}
}
throw new Exception(responseText);
}
else
{
throw new Exception(ex.Message.ToString());
}
}
}
}