93

I am hosting a web service in ASP.Net MVC3 which returns a Json string. What is the best way to call the webservice from a c# console application, and parse the return into a .NET object?

Should I reference MVC3 in my console app?

Json.Net has some nice methods for serializing and deserializing .NET objects, but I don't see that it has ways for POSTing and GETing values from a webservice.

Or should I just create my own helper method for POSTing and GETing to the web service? How would I serialize my .net object to key value pairs?

BrokeMyLegBiking
  • 5,898
  • 14
  • 51
  • 66

3 Answers3

146

I use HttpWebRequest to GET from the web service, which returns me a JSON string. It looks something like this for a GET:

// Returns JSON string
string GET(string url) 
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    try {
        WebResponse response = request.GetResponse();
        using (Stream responseStream = response.GetResponseStream()) {
            StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8);
            return reader.ReadToEnd();
        }
    }
    catch (WebException ex) {
        WebResponse errorResponse = ex.Response;
        using (Stream responseStream = errorResponse.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.GetEncoding("utf-8"));
            String errorText = reader.ReadToEnd();
            // log errorText
        }
        throw;
    }
}

I then use JSON.Net to dynamically parse the string. Alternatively, you can generate the C# class statically from sample JSON output using this codeplex tool: http://jsonclassgenerator.codeplex.com/

POST looks like this:

// POST a JSON string
void POST(string url, string jsonContent) 
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "POST";

    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    Byte[] byteArray = encoding.GetBytes(jsonContent);

    request.ContentLength = byteArray.Length;
    request.ContentType = @"application/json";

    using (Stream dataStream = request.GetRequestStream()) {
        dataStream.Write(byteArray, 0, byteArray.Length);
    }
    long length = 0;
    try {
        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
            length = response.ContentLength;
        }
    }
    catch (WebException ex) {
        // Log exception and throw as for GET example above
    }
}

I use code like this in automated tests of our web service.

Mahmoud Moravej
  • 8,705
  • 6
  • 46
  • 65
GarethOwen
  • 6,075
  • 5
  • 39
  • 56
  • JsonClassGenerator is awesome. Deserialization is easy as you just construct the strongly typed object by passing the json string. – AaronLS Jul 11 '12 at 22:52
  • If you have characters in the non-ascii set, the code you have needs to be altered a bit. ContentLength represents the number of bytes in the posted contents, so technically request.ContentLength should be set to byteArray.Length, not jsonContent.Length. – Grady Werner Sep 28 '13 at 03:23
  • `Encoding.GetEncoding("utf-8")` can be replaced by `Encoding.UTF8` – JoelFan Jan 02 '18 at 21:33
  • Thanks,This is very helpful – shweta Jan 25 '18 at 12:30
  • As part of Authorization token will be set but We may have to pass headers also if required to test. Like this request.Method = "GET"; request.Timeout = 20000; request.ContentType = "application/json"; request.Headers.Add("Authorization", "Bearer your token: – Kurkula Mar 07 '19 at 03:36
  • Add this attribute if you want to use it as api. [HttpGet("[action]")] – Kurkula Mar 07 '19 at 03:39
50

WebClient to fetch the contents from the remote url and JavaScriptSerializer or Json.NET to deserialize the JSON into a .NET object. For example you define a model class which will reflect the JSON structure and then:

using (var client = new WebClient())
{
    var json = client.DownloadString("http://example.com/json");
    var serializer = new JavaScriptSerializer();
    SomeModel model = serializer.Deserialize<SomeModel>(json);
    // TODO: do something with the model
}

There are also some REST client frameworks you may checkout such as RestSharp.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • @BrokeMyLegBiking, which one? It has nothing to do with ASPAjax. If you are talking about the JavaScriptSerializer class it is built in .NET in the System.Web.Extensions assembly so you don't have to download or install anything. – Darin Dimitrov Nov 25 '11 at 14:35
  • Is there a way to turn all the propertynames/property values of a c# object into POST key-value pairs (or GET key-value pairs)? so that I can effectively use the c# object as an input value to my webservice method? – BrokeMyLegBiking Nov 25 '11 at 14:37
  • @BrokeMyLegBiking, that will depend on what object you have and how does the web service expects the input. – Darin Dimitrov Nov 25 '11 at 14:38
  • 3
    I've really enjoyed the RestSharp library. Thanks for mentioning that. – Bryan Ray Sep 06 '12 at 14:17
  • 1
    Daren can you update this, the client.downloadstring() is no longer viable. – JReam Aug 04 '16 at 22:25
9

Although the existing answers are valid approaches , they are antiquated . HttpClient is a modern interface for working with RESTful web services . Check the examples section of the page in the link , it has a very straightforward use case for an asynchronous HTTP GET .

using (var client = new System.Net.Http.HttpClient())
{
    return await client.GetStringAsync("https://reqres.in/api/users/3"); //uri
}
S.Serpooshan
  • 7,608
  • 4
  • 33
  • 61
LostNomad311
  • 1,975
  • 2
  • 23
  • 31