您的位置:首页 > 编程语言 > C#

Calling a Web API From a .NET Client (C#)

2013-08-09 10:12 357 查看
This tutorial shows how to call a web API from a console application, using
HttpClient
.

In this tutorial, we will consume the
"ProductStore" API, described in
Creating a Web API that Supports CRUD Operations.

Create the Console Application

Start Visual Studio and select New Project from the Start page. Or, from the
File menu, select New and then Project.

In the Templates pane, select Installed Templates and expand the
Visual C# node. Under Visual C#, select
Windows
. In the list of project templates, select Console Application. Name the project and click
OK.



Install NuGet Package Manager

NuGet Package Manager is the easiest way to add the Web API Client library to a project. If you do not have NuGet Package Manager already installed, install it as follows.

Start Visual Studio.
From the Tools menu, select Extensions and Updates.
In the Extensions and Updates dialog, select Online.
If you don't see "NuGet Package Manager", type "nuget package manager" in the search box.
Select the NuGet Package Manager and click Download.
After the download completes, you will be prompted to install.
After the installation completes, you might be prompted to restart Visual Studio.



Install the Web API Client Libraries

After NuGet Package Manager is installed, add the Web API Client Libraries package to your project.

From the Tools menu, select Library Package Manager.
Note: If do you not see this menu item, make sure that NuGet Package Manager installed correctly.
Select Manage NuGet Packages for Solution...
In the Manage NugGet Packages dialog, select Online.
In the search box, type "Microsoft.AspNet.WebApi.Client".
Select the package named "Microsoft ASP.NET Web API Client Libraries".
Click Install.
After the package installs, click Close to close the dialog.



Add the Model Class

Add the following class to the application:

class Product
{
public string Name { get; set; }
public double Price { get; set; }
public string Category { get; set; }
}

This class creates a data object that HttpClient will write into the HTTP request body and read from the HTTP response body.

Initialize HttpClient

Create a new instance of HttpClient and initialize it as follows:

namespace ProductStoreClient
{
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;

class Program
{
static void Main(string[] args)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:9000/");

// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
}
}

This code sets the base URI to "http://localhost:9000/", and sets the Accept header to "application/json", which tells the server to send data in JSON format.

Getting a Resource (HTTP GET)

The following code shows how to query the API for a list of products:

// List all products.
HttpResponseMessage response = client.GetAsync("api/products").Result;  // Blocking call!
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
var products = response.Content.ReadAsAsync<IEnumerable<Product>>().Result;
foreach (var p in products)
{
Console.WriteLine("{0}\t{1};\t{2}", p.Name, p.Price, p.Category);
}
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}

The GetAsync method sends an HTTP GET request. As the name implies,
GetAsyc is asynchronous. It returns immediately, without waiting for a response from the server. The return value is a
Task object that represents the asynchronous operation. When the operation completes, the
Task.Result property contains the HTTP response.

It is important to understand that taking the Result property blocks your application thread until the request completes (or times out). Blocking in a console application is OK, but you should never do this on the UI thread of a Windows
application, because it blocks the UI from responding to user input. In the next part of this tutorial, we'll see how to write non-blocking calls.

If the HTTP response indicates success, the response body contains a list of products in JSON format. To parse the list, call
ReadAsAsync. This method reads the response body and tries to deserialize it to a specified CLR type. This method is also asynchronous, because the body can be arbitrarily large. Again, taking the
Result property blocks the thread.

Example HTTP session:

GET http://localhost:9000/api/products HTTP/1.1
Accept: application/json
Host: localhost:9000
Connection: Keep-Alive

HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Mon, 20 Aug 2012 22:14:59 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 183
Connection: Close

[{"Id":1,"Name":"Tomato soup","Category":"Groceries","Price":1.39},{"Id":2,"Name":"Yo-yo",
"Category":"Toys","Price":3.75},{"Id":3,"Name":"Hammer","Category":"Hardware","Price":16.99}]

Getting a product by ID is similar:

// Get a product by ID
response = client.GetAsync("api/products/1").Result;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
var product = response.Content.ReadAsAsync<Product>().Result;
Console.WriteLine("{0}\t{1};\t{2}", product.Name, product.Price, product.Category);
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}

Media-Type Formatters

ReadAsAsync is an extension method defined in the System.Net.Http.HttpContentExtensions class. With no parameters, it uses the default set of media-type formatters to try to parse the response body. The default formatters
support JSON, XML, and Form-url-encoded data. (For more information about media-type formatters, see

Formats and Model Binding.)

You can also explicitly specify the media-types formatters to use. This is useful if you have a custom media-type formatter.

var formatters = new List<MediaTypeFormatter>() {
new MyCustomFormatter(),
new JsonMediaTypeFormatter(),
new XmlMediaTypeFormatter()
};

resp.Content.ReadAsAsync<IEnumerable<Product>>(formatters);

Creating a Resource (HTTP POST)

The following code sends a POST request that contains a
Product
instance in JSON format:

// Create a new product
var gizmo = new Product() { Name = "Gizmo", Price = 100, Category = "Widget" };
Uri gizmoUri = null;

response = client.PostAsJsonAsync("api/products", gizmo).Result;
if (response.IsSuccessStatusCode)
{
gizmoUri = response.Headers.Location;
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}

PostAsJsonAsync is an extension method defined in System.Net.Http.HttpClientExtensions. It is equivalent to the following:

var product = new Product() { Name = "Gizmo", Price = 100, Category = "Widget" };

// Create the JSON formatter.
MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();

// Use the JSON formatter to create the content of the request body.
HttpContent content = new ObjectContent<Product>(product, jsonFormatter);

// Send the request.
var resp = client.PostAsync("api/products", content).Result;

For XML format, use the PostAsXmlAsync method.

Example HTTP session:

POST http://localhost:9000/api/products HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-8
Host: localhost:9000
Content-Length: 50
Expect: 100-continue

{"Name":"Gizmo","Price":100.0,"Category":"Widget"}

HTTP/1.1 201 Created
Server: ASP.NET Development Server/11.0.0.0
Date: Mon, 20 Aug 2012 22:15:00 GMT
X-AspNet-Version: 4.0.30319
Location: http://localhost:9000/api/products/7 Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/json; charset=utf-8
Content-Length: 57
Connection: Close

{"Id":7,"Name":"Gizmo","Category":"Widget","Price":100.0}

By default, the JSON formatter sets the content-type to "application/json". You can also specify the media type explicitly. For example, suppose that "application/vnd.example.product" is your media type for
Product
instances. You could set this media type as follows:

HttpContent content = new ObjectContent<Product>(product, jsonFormatter,
"application/vnd.example.product+json");

Updating a Resource (HTTP PUT)

The following code sends a PUT request.

// Update a product
gizmo.Price = 99.9;
response = client.PutAsJsonAsync(gizmoUri.PathAndQuery, gizmo).Result;
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);

The PutAsJsonAsync method works like PostAsJsonAsync, except it sends a PUT request instead of POST.

Deleting a Resource (HTTP DELETE)

By now, you can probably predict how to send a DELETE request:

// Delete a product
response = client.DeleteAsync(gizmoUri).Result;
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);

Like GET, a DELETE request does not have a request body, so you don't need to specify JSON or XML format.

Error Handling

HttpClient does not thrown an exception when it receives an HTTP response with an error code. Instead, the
StatusCode property on the response contains the status code. Also, the
IsSuccessStatusCode property is true if the status is a success code (status codes in the range 200-299).

The previous examples used this pattern:

HttpResponseMessage response = client.GetAsync("api/products").Result;
if (response.IsSuccessStatusCode)
{
// ....
}

If you prefer to treat error codes as exceptions, call the EnsureSuccessStatusCode method. This method throws an exception if the response status is not a success code.

try
{
var resp = client.GetAsync("api/products").Result;
resp.EnsureSuccessStatusCode();    // Throw if not a success code.

// ...
}
catch (HttpRequestException e)
{
Console.WriteLine(e.Message);
}

HttpClient can throw exceptions for other reasons, of course — for example, if the request times out.

Configuring HttpClient

To configure HttpClient, create a
WebRequestHandler instance, set properties on it, and pass it to the
HttpClient
constructor:

WebRequestHandler handler = new WebRequestHandler()
{
AllowAutoRedirect = false,
UseProxy = false
};
HttpClient client = new HttpClient(handler);

WebRequestHandler derives from HttpMessageHandler. You can also plug in custom message handlers by deriving from
HttpMessageHandler. For more information, see
HTTP Message Handlers.

Additional Resources

A console application makes it easy to see the code flow. However, the blocking calls are not good practice for applications with a graphical UI. To learn how to handle asynchronous operations in
HttpClient without blocking, see
Calling a Web API From a WPF Application

参考资料
http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐