Page 1 of 2

c# example res/json web API ?

Posted: Tue Dec 05, 2017 3:17 pm
by Clement.Sorriaux
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

Re: c# example res/json web API ?

Posted: Tue Dec 05, 2017 6:00 pm
by Bernd Welter
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

Re: c# example res/json web API ?

Posted: Wed Dec 06, 2017 11:29 am
by Oliver Heilig
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:

Code: Select all

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();
        }
    }
}

Re: c# example res/json web API ?

Posted: Fri Nov 30, 2018 1:34 pm
by Oliver Heilig
Addendum: i'd rather use the async version (using HttpClient) these days:

Code: Select all

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());
        }
    }
}

Re: c# example res/json web API ?

Posted: Sun Dec 16, 2018 8:54 pm
by Oliver Heilig
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/xserve ... #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.

Code: Select all

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}");
    }
}

Re: c# example res/json web API ?

Posted: Tue Jan 14, 2020 4:48 pm
by Oliver Heilig
Hello,

xServer-2 now supports OpenAPI specification (as draft).

This means you can now create your C# classes using autorest:

Code: Select all

npm install -g autorest

autorest --input-file=https://xserver2-europe-eu-test.cloud.ptvgroup.com/services/openapi/2.17/swagger.json --csharp --namespace=XServerClient --generate-empty-classes
generates the client methods (sync and async) for xServer with truely typed classes, which dramatically simplifies the workflow (see attachment).

Re: c# example res/json web API ?

Posted: Wed May 13, 2020 1:08 pm
by Oliver Heilig
Hello, it's me again,

the xServer-2 OpenAPI specification is now final. To create a C# client via autorest:

Code: Select all

npm install -g autorest

autorest --input-file=https://xserver2-europe-eu.cloud.ptvgroup.com/services/openapi/2.19/swagger.json --csharp --namespace=XServerClient --generate-empty-classes
I have attached a sample using the xTour jobs api. As you can see, this creates quite nice client methods. Read here for more details.

Re: c# example res/json web API ?

Posted: Sat Mar 13, 2021 2:51 pm
by stefan.rotaru
Hi,

I have tried to autorest the
https://xserver2-europe-eu-test.cloud.p ... agger.json
but it gives me an error
System.InvalidOperationException: Sequence contains more than one matching element

Can you please tell me if it works on your side or maybe attach the generated files for the XLocate and XRoute services (c#)?

Thank you.

Re: c# example res/json web API ?

Posted: Sat Mar 13, 2021 3:12 pm
by Bernd Welter
Hello Stefan,

how about the clients here?

https://xserver2-europe-eu-test.cloud.p ... 3%7C_____0

Bernd

Re: c# example res/json web API ?

Posted: Sat Mar 13, 2021 3:54 pm
by stefan.rotaru
Hello,

In the link that you gave me, there is this sentence:
If you like to use the JSON API, there is also the possibility to generate clients from OpenAPI Documents.

Generating client (from VS or command prompt) with this command:
autorest --input-file=https://xserver2-europe-eu-test.cloud.p ... agger.json --csharp --namespace=XServerClient --generate-empty-classes
(like shown in the example from Oliver) I received the error I posted.

I have downloaded the example generated by Oliver for the XTourOpenAPI (the post from May 13 2020) and that is how I want to use it for other services (XLocate, XRoute). Can you please tell me how can I do that?

Thank you!