I am currently trying to implement MessagePack in a solution which contains 2 projects : AspNet Core WebAPI and a simple console app. The following package was added :
How fo I Deserialize the object back on the client, here is the code snippets, also when Posting back an object from the client to the api, do I just Serialize on the client and send it to the Post method in the api, which will take a string, take the string and Deserialize it again, I will need to pass the type somehow to the controller also.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MessagePack;
using Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpGet]
public IActionResult Get()
{
var results = new List<Superhero>();
results.Add(new Superhero { HeroID = 1, HeroName = "Bruce Wayne" });
results.Add(new Superhero { HeroID = 2, HeroName = "Selina Kyle" });
results.Add(new Superhero { HeroID = 3, HeroName = "Clark Kent" });
var bytes = MessagePackSerializer.Serialize(results);
return Ok(bytes);
}
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
[HttpPost]
public void Post([FromBody]string value)
{
// how to I Deserialize here ? what do I just post from client to
// with the Serialized object and pass the type also ???
}
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
[MessagePackObject]
public class Superhero
{
[Key(0)]
public int HeroID { get; set; }
[Key(1)]
public string HeroName { get; set; }
}
}
using MessagePack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace MessagePackExampleOne
{
class Program
{
static HttpClient client = new HttpClient();
static void Main(string[] args)
{
client.BaseAddress = new Uri("http://localhost:57752");
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = client.GetAsync("/api/values").Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
//how to Deserialize this objec ??
// Console.WriteLine(MessagePackSerializer.ToJson(result));
// var mc2 = MessagePackSerializer.Deserialize<List<Superhero>>(result);
}
Console.Read();
}
}
[MessagePackObject]
public class Superhero
{
[Key(0)]
public int HeroID { get; set; }
[Key(1)]
public string HeroName { get; set; }
}
}
to send something in post method from client use TryAddWithoutValidation:
var x = MessagePackSerializer.Serialize(MyCLassObj to send);
var content = new ByteArrayContent(x);
content.Headers.TryAddWithoutValidation("Content-Type", "application/x-msgpack");
httpResponse = await httpClient.PostAsync("/api...", content,token);
Related
How can I format a collection of a custom class in the expected format for an API query string using Refit?
I've tried using various combinations of the Query / CollectionType / Format attributes.
Expected query string: http://someurl.com/api?Data[0].A=6&Data[0].B=7&Data[1].A=8&Data[1].B=9
Actual query string: http://someurl.com/api?Data=SomeClass%2CSomeClass
Full code using Refit.Newtonsoft.Json version 6.3.2 on .NET 4.6.1 (including outputting the request for debugging purposes):
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Refit;
public class SomeClass
{
public int A { get; set; }
public int B { get; set; }
}
public class Parameters
{
public IReadOnlyCollection<SomeClass> Data { get; set; }
}
public interface IClient
{
[Get("/api")]
Task<int> GetResult(Parameters parameters);
}
public class LoggingMessageHandler : DelegatingHandler
{
public LoggingMessageHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Debug.WriteLine("Request:");
Debug.WriteLine(request.ToString());
if (request.Content != null)
{
Debug.WriteLine(await request.Content.ReadAsStringAsync());
}
return await base.SendAsync(request, cancellationToken);
}
}
public class Test
{
static void Main(string[] args)
{
var service = RestService.For<IClient>(
"http://someurl.com",
new RefitSettings
{
HttpMessageHandlerFactory = () => new LoggingMessageHandler(new HttpClientHandler())
}
);
var parameters = new Parameters()
{
Data = new SomeClass[] { new SomeClass() { A = 6, B = 7 }, new SomeClass() { A = 8, B = 9} }
};
var result = service.GetResult(parameters);
}
}
I am trying to stream a large JSON file and deserialize item by item during the streaming.
I am using for this test https://github.com/ysharplanguage/FastJsonParser/blob/master/JsonTest/TestData/fathers.json.txt.
This is my code:
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
namespace AMServices.Controllers
{
public class FathersData
{
public Father[] fathers { get; set; }
}
public class Someone
{
public string name { get; set; }
}
public class Father : Someone
{
public int id { get; set; }
public bool married { get; set; }
// Lists...
public List<Son> sons { get; set; }
// ... or arrays for collections, that's fine:
public Daughter[] daughters { get; set; }
}
public class Child : Someone
{
public int age { get; set; }
}
public class Son : Child
{
}
public class Daughter : Child
{
public string maidenName { get; set; }
}
public class StreamerController : ApiController
{
static readonly JsonSerializer _serializer = new JsonSerializer();
static readonly HttpClient _client = new HttpClient();
[HttpPost]
[Route("streamer/stream")]
public async Task<IHttpActionResult> stream()
{
string apiUrl = "https://github.com/ysharplanguage/FastJsonParser/blob/master/JsonTest/TestData/fathers.json.txt";
using (var stream = await _client.GetStreamAsync(apiUrl).ConfigureAwait(false))
using (var reader = new StreamReader(stream))
using (var json = new JsonTextReader(reader))
{
if (json == null)
StatusCode(HttpStatusCode.InternalServerError);
JsonSerializer serializer = new JsonSerializer();
JObject obj = JObject.Load(json);
// Father f = serializer.Deserialize<Father>(json);
}
return StatusCode(HttpStatusCode.OK);
}
}
}
When i call this WebAPI Controller Method from Postman i get the following error
"ExceptionMessage": "Unexpected character encountered while parsing value: <. Path '', line 0, position 0.",
"ExceptionType": "Newtonsoft.Json.JsonReaderException",
What is wrong with this code?
You are trying to parse an html page.
Try with the raw version :
https://raw.githubusercontent.com/ysharplanguage/FastJsonParser/master/JsonTest/TestData/fathers.json.txt
My model is GasStation.
using Newtonsoft.Json;
using SQLite;
using System;
using System.Collections.Generic;
using System.Text;
namespace TDEv2.Models
{
public class GasStation
{
[JsonProperty("costcentre")][PrimaryKey]
public string CostCentre { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
}
}
My GasStationQuery contains this:
namespace TDEv2.Models
{
public class GasStationQuery
{
public GasStation[] GasStations { get; set; }
}
}
My JSON Array looks like this:
gasstations: [
{
"id": 01,
"name": "GasStation1",
"costcentre": 123
},
{
"id": 02,
"name": "GasStation2",
"costcentre": 456
}
]
Now I want to deserialize this into my SQLite database:
using SQLite;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using TDEv2.Models;
namespace TDEv2.Data
{
public class GasStationDatabase
{
readonly SQLiteAsyncConnection database;
public GasStationDatabase(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<GasStation>().Wait();
}
public Task<List<GasStation>> GetItemsAsync()
{
return database.Table<GasStation>().ToListAsync();
}
public Task<GasStation> GetItemAsync(string costCentre)
{
return database.Table<GasStation>().Where(i => i.CostCentre == costCentre).FirstOrDefaultAsync();
}
public Task<int> SaveItemAsync(GasStation gasStation)
{
if (gasStation.CostCentre != null)
{
return database.UpdateAsync(gasStation);
}
else
{
return database.InsertAsync(gasStation);
}
}
}
}
Now I want to do an initial sync to fill my database to work with offline on the devices, but I don't know further steps since I am programming for not that long.
Here's my try to fill the database:
using System.Net;
using TDEv2.Data;
using TDEv2.Models;
namespace TDEv2.Services
{
public class InitialAsyncGasStationDatabase
{
private GasStationDatabase db;
public GasStationQuery InitialAsyncGasStationsToDatabase()
{
string json;
using (WebClient client = new WebClient())
{
json = client.DownloadString($"http://xxx/gasstations.json");
}
foreach (GasStation gasStation in json)
{
db.SaveItemAsync(gasStation);
}
return;
}
}
}
The code doesn't work. I am getting an error in the foreach section with Cannot convert type "char" to "TDEv2.Models.GasStation"
you need to deserialize your json into an object before you can save it to the db
using (WebClient client = new WebClient())
{
json = client.DownloadString($"http://xxx/gasstations.json");
}
// using newtonsoft json.net - use http://json2csharp.com/ to verfiy
// that your C# model class actually matches your json
var data = JsonConvert.DeserializeObject<GasStationQuery>(json);
foreach (GasStation gasStation in data.GasStations)
{
db.SaveItemAsync(gasStation);
}
Probably your source has a list of GasStations, so you can Deserialize your json object into a List of GasStation,
private GasStationDatabase db;
public GasStationQuery InitialAsyncGasStationsToDatabase()
{
string json;
using (WebClient client = new WebClient())
{
json = client.DownloadString($"http://xxx/gasstations.json");
}
var gasStationList = JsonConvert.DeserializeObject<List<GasStation>>(json);
foreach (GasStation gasStation in gasStationList )
{
db.SaveItemAsync(gasStation);
}
return;
}
I'm trying to do qualification job for a work and have some problems with realization of code on Xamarin.
I have such classes and functions. They're working on console of c# but not in xamarin. I don't know what to do. They give only freeze on Xamarin.
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace radacode.ActionForm
{
class ListMaker
{
public static List<Country> GetCountryList()
{
List<Country> result=new List<Country>();
Task<string> task =GetRequestAsync(#"http://api.vk.com/method/database.getCountries?need_all=1&v=5.60");
JObject vk = JObject.Parse(task.GetAwaiter().GetResult());
foreach (JObject jsonCountry in vk["response"]["items"])
result.Add(JsonConvert.DeserializeObject<Country>(jsonCountry.ToString()));
return result;
}
public static async Task<string> GetRequestAsync(string url)
{
using (var httpClient = new HttpClient())
return await httpClient.GetStringAsync(url);
}
public class Country
{
public int Cid { get; set; }
public string Title { get; set; }
override public string ToString()
{
return Title;
}
}
}
}
When using Xamarin Forms, it's best to use Portable Class Projects rather than Shared. In my opinion.
Also it's important that Statics are not used especially for calls that are async. Think of Async as to being similar to AsyncTask in JAVA. They're none blocking.
public class ListMaker
{
public List<Country> GetCountyList()
{
return GetCountryListAsync().Result;
}
private async Task<List<Country>> GetCountryListAsync()
{
var result = new List<Country>();
var task =
await GetRequestAsync(#"http://api.vk.com/method/database.getCountries?need_all=1&v=5.60");
var vk = JObject.Parse(task);
foreach (var jsonCountry in vk["response"]["items"])
result.Add(JsonConvert.DeserializeObject<Country>(jsonCountry.ToString()));
return result;
}
private async Task<string> GetRequestAsync(string url)
{
using (var httpClient = new HttpClient())
return await httpClient.GetStringAsync(url);
}
public class Country
{
public int Cid { get; set; }
public string Title { get; set; }
public new string ToString()
{
return Title;
}
}
}
Now that you have your class, you can then create an instance of it and execute it.
NOTE:- the Async and Await in my example, or this one, is incorrect.
It should really bubble up to a parent class that has a property and a void in the class statement.
public async void TheLister()
{
var listMaker = new ListMaker();
var countryList = await listmaker.GetCountryListAsync();
// Do something with countryList
}
I am building an app in Xamarin.Android ! which determines my Address using google Maps API when given a latitude and longitude. However my App fails to deliver an HTTP response. I don't receive any runtime errors and VS debugger behaves as if my App has hanged.
1> I don't know whether this is an issue of Xamarin.Android
2> As i read somehwere it could be an issue of blocking,asynchronous codes but then I use the same piece of code for my Windows App and it never gave me trouble
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
namespace App_Code
{
public class myLocationProxy
{
public static async Task<RootObject_AutoLocationAddress> getmyLocation(string lat, string lng)
{
var http = new HttpClient();
/*CODE STOPS HERE*/var response = await http.GetAsync(String.Format("http://maps.google.com/maps/api/geocode/json?latlng={0},{1}&sensor=false", Uri.EscapeDataString(lat), Uri.EscapeDataString(lng)));
var result = await response.Content.ReadAsStringAsync();
var serializer = new DataContractJsonSerializer(typeof(RootObject_AutoLocationAddress));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject_AutoLocationAddress)serializer.ReadObject(ms);
return data;
}
}
[DataContract]
public class AddressComponent_AutoLocationAddress
{
[DataMember]
public string long_name { get; set; }
[DataMember]
public List<string> types { get; set; }
}
[DataContract]
public class Result_AutoLocationAddress
{
[DataMember]
public List<AddressComponent_AutoLocationAddress> address_components { get; set; }
[DataMember]
public string formatted_address { get; set; }
}
[DataContract]
public class RootObject_AutoLocationAddress
{
[DataMember]
public List<Result_AutoLocationAddress> results { get; set; }
[DataMember]
public string status { get; set; }
}
}
Try below code snippet just added TimeOut value.
public static async Task<RootObject_AutoLocationAddress> getmyLocation(string lat, string lng)
{
var client = new HttpClient()
{
Timeout = TimeSpan.FromMilliseconds(10000) //10 second, This line might help you
};
var response = await client.GetAsync(String.Format("http://maps.google.com/maps/api/geocode/json?latlng={0},{1}&sensor=false", Uri.EscapeDataString(lat), Uri.EscapeDataString(lng)));
var result = await response.Content.ReadAsStringAsync();
var serializer = new DataContractJsonSerializer(typeof(RootObject_AutoLocationAddress));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject_AutoLocationAddress)serializer.ReadObject(ms);
return data;
}
Cheers!!