c# example res/json web API ?

Within this forum we want to offer discussions all around our .NET based Map control including all .Net-language specific questions concerning calls of the xServer-API. Attention: xServer-relevant concepts can be found in further forums such as xRoute or xTour.

c# example res/json web API ?

Postby Clement.Sorriaux » Tue Dec 05, 2017 3:17 pm

Hello,

I just recieved a demand from a customer and I can't find such example so far.

I sent to the customer the democenter in c# with sources and everything.
here is his question :
I've notice that the example of WCF service are all in SOAP/XML, is there any c# sample with REST/JSON webService or webAPI ?

if you need more precision, feel free to ask for some.

have a good day
Best regards
Clément
Clement.Sorriaux
 

Re: c# example res/json web API ?

Postby Bernd Welter » Tue Dec 05, 2017 6:00 pm

Hello Clement,

I spoke to some developers and they recommended to use frameworks such as JSON.NET (or the expensive, high performant alternative https://servicestack.net/text). But I also hope that Oliver can provide a real sample for this.

Best regards,
Bernd
Bernd Welter
Senior Technical Consultant Developer Components
PTV GROUP - Germany

Bernd at Youtube
User avatar
Bernd Welter
Site Admin
 
Posts: 1370
Joined: Mon Apr 14, 2014 10:28 am

Re: c# example res/json web API ?

Postby Oliver Heilig » Wed Dec 06, 2017 11:29 am

My recommendation is JSON.NET (https://www.newtonsoft.com/json). It's some kind of de-facto standard, even Microsoft uses in their projects. But there are many flavors for serializing and deserializing your objects, here are two:

  • The JavaScript way: You can use .NET anonymous / dynamic types. This doesn't require any specific types, but it isn't very convenient at design-time, see code below and attached sample.
  • With typed classes: Find an example JSON, for example from the Raw-Request-Runner, then create your classes by pasting the Request/Response to http://json2csharp.com/. You can (de)serialize them with JSON.NET then.

Oli

Sample with dynamic types:
csharp code
using System;
using Newtonsoft.Json;
using System.IO;
using System.Net;

namespace XServerJson
{
class Program
{
// Make a request on xServer with JSON, using JSON.NET and dynamic/anonymous types.
// This means we don't have any types defined for our requests and responses and do it like JavaScript.
static void Main(string[] args)
{
// for input just use an anonymous type
var gco = new
{
addr = new
{
country = "L",
postCode = "",
city = "Schengen",
city2 = "",
street = "Rue de la Moselle 5",
houseNumber = ""
}
};

// Create the request
// When using using xServer-internet you need a token!
var request = WebRequest.Create("https://xlocate-eu-n-test.cloud.ptvgroup.com/xlocate/rs/XLocate/findAddress");
request.Credentials = new NetworkCredential("xtok", "<your xServer-internet token>");
request.Method = "POST";
request.ContentType = "application/json";

// serialize object to the request stream
// should do some proper error-handly here
using (var s = request.GetRequestStream())
using (var writer = new StreamWriter(s))
using (var jsonWriter = new JsonTextWriter(writer))
{
var ser = new JsonSerializer();
ser.Serialize(jsonWriter, gco);
}

// now just parse it to a dynamic object
dynamic result;
using (var response = request.GetResponse())
using (var rs = response.GetResponseStream())
using (var sr = new StreamReader(rs))
{
result = JsonConvert.DeserializeObject(sr.ReadToEnd());
}

// now work with the object like in JavaScript
// You don't have intellisense, but can view the fields in the watch window of the debugger.
foreach (var ra in result.resultList)
{
Console.WriteLine($"{ra.country} {ra.postCode} {ra.city} {ra.street} {ra.houseNumber}");
}

Console.ReadKey();
}
}
}
Attachments
XServer-Json-Dynamic.zip
(4.22 KiB) Downloaded 88 times
Oliver Heilig
Chief Developer Logistic Services
PTV GROUP - Germany

https://github.com/oliverheilig/
User avatar
Oliver Heilig
 
Posts: 123
Joined: Tue May 13, 2014 12:10 pm
Location: Karlsruhe, Germany

Re: c# example res/json web API ?

Postby Oliver Heilig » Fri Nov 30, 2018 1:34 pm

Addendum: i'd rather use the async version (using HttpClient) these days:

csharp code
using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.Text;
using Newtonsoft.Json;

namespace XServerJson
{
class Program
{
// Make a request on xServer with JSON, using JSON.NET and dynamic/anonymous types.
// This means we don't have any types defined for our requests and responses and do it like JavaScript.
// This is the async version using HttpClient
static void Main(string[] args)
{
ExecAsync().Wait();

Console.ReadKey();
}

static async Task ExecAsync()
{
// input address for geocoding as anonymous type
var result = await GeocodeAsync(new
{
addr = new
{
country = "L",
postCode = "",
city = "Schengen",
city2 = "",
street = "Rue de la Moselle 5",
houseNumber = ""
}
});

// now work with the object like in JavaScript
// You don't have intellisense, but can view the fields in the watch window of the debugger.
foreach (var ra in result.resultList)
{
Console.WriteLine($"{ra.country} {ra.postCode} {ra.city} {ra.street} {ra.houseNumber}");
}
}

static async Task<dynamic> GeocodeAsync(object address)
{
// Create the request Client
var httpClient = new HttpClient();

// When using using xServer-internet you need a token!
httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes("xtok:<your xServer-internet token>")));

// The content (body)
var content = new StringContent(JsonConvert.SerializeObject(address), Encoding.UTF8, "application/json");

// Do the POST
var response = await httpClient.PostAsync("https://xlocate-eu-n-test.cloud.ptvgroup.com/xlocate/rs/XLocate/findAddress", content);

// throws an exception if not status 200
response.EnsureSuccessStatusCode();

// Just return as dynamic object
return JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
}
}
}
Oliver Heilig
Chief Developer Logistic Services
PTV GROUP - Germany

https://github.com/oliverheilig/
User avatar
Oliver Heilig
 
Posts: 123
Joined: Tue May 13, 2014 12:10 pm
Location: Karlsruhe, Germany

Re: c# example res/json web API ?

Postby Oliver Heilig » Sun Dec 16, 2018 8:54 pm

Hello,

this is part three:

... while the sample above also works well with .NET Core, it doesn't use pascal-casing. Pascal-casing is default for .NET fields while camel-casing is default for JSON/JavaScript. Another caveat is that xServer (especially xServer-2) uses polymorphic parameter types. These require a type-inference using a $type attribute which is somehow cumbersome, especially when working with dynamic typing.

I've added a helper class XServerSerializerSettings which handles both pascal-casing and type-inference with $type. You can write the input/output field names pascal-casing, and a field named ObjectType can be used to specify the $type value. See the example below.

A general way to overcome the $type constraint for xServer is to use another moniker and replace it before and after serialization. This is what we do for xServer.NET https://github.com/ptv-logistics/xserver.net/blob/master/Map/Layers/Xmap2/UntiledProvider.cs#L109-L113.

While this may look complex it works well and it's very fast. I would prefer it over SOAP any time. We are looking to make the xServer API definitions more accesible to other languages in future releases.

csharp code
static async Task ExecAsync()
{
// input address for geocoding as anonymous type
var result = await GeocodeAsync(new
{
// required by xLocate2, mapped to $type
ObjectType = "SearchByAddressRequest",
// request and response types are pascal-casing
Address = new {
Country = "L",
PostalCode = "",
City = "Schengen",
Street = "Rue de la Moselle 5",
}
});

// now work with the object like in JavaScript
// You don't have intellisense, but can view the fields in the watch window of the debugger.
Console.WriteLine($"Result is of type: {result.ObjectType}");
foreach (var ra in result.Results)
{
Console.WriteLine($"Match Type: {ra.Type}, Match Quality: {ra.MatchQuality.TotalScore} " +
$"Lat/Lng: {ra.Location.ReferenceCoordinate.Y}/{ra.Location.ReferenceCoordinate.X}");
}
}
Attachments
XServerSerializerSettings.zip
XServer with pascal-casing and $type support
(3.96 KiB) Downloaded 30 times
Oliver Heilig
Chief Developer Logistic Services
PTV GROUP - Germany

https://github.com/oliverheilig/
User avatar
Oliver Heilig
 
Posts: 123
Joined: Tue May 13, 2014 12:10 pm
Location: Karlsruhe, Germany


Return to PTV xServer.NET (Admin=OH)

cron