Calling a Web API From a .NET Client (C#)
This tutorial shows how to call a web API from a .NET application, using System.Net.Http.HttpClient.
In this tutorial, we will write an client application that consumes the following web API.
Action | HTTP method | Relative URI |
---|---|---|
Get a product by ID | GET | /api/products/id |
Create a new product | POST | /api/products |
Update a product | PUT | /api/products/id |
Delete a product | DELETE | /api/products/id |
To learn how to implement this API on the server, using ASP.NET Web API, see Creating a Web API that Supports CRUD Operations.
For simplicity, the client application in this tutorial is a Windows console application. HttpClient is also supported for Windows Phone and Windows Store apps. For more information, see Writing Web API Client Code for Multiple Platforms Using Portable Libraries
Create the Console Application
In Visual Studio, create a new Windows console application and paste in the following code.
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks; namespace HttpClientSample
{
class Program
{ static void Main()
{
RunAsync().Wait();
} static async Task RunAsync()
{
Console.ReadLine();
}
}
}
This code provides the skeleton for the application. The Main
RunAsync method and blocks until it completes. The reason for this approach is that most HttpClient methods are async, because they perform network I/O. All of the async tasks will be done inside RunAsync
. In a console application, it's OK to block the main thread inside of Main
. In a GUI application, you should never block the UI thread.
Install the Web API Client Libraries
Use NuGet Package Manager to install the Web API Client Libraries package.
From the Tools menu, select Library Package Manager, then select Package Manager Console. In the Package Manager Console window, type the following command:
Install-Package Microsoft.AspNet.WebApi.Client
Add a Model Class
Add the following class to the application:
namespace HttpClientSample
{
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
}
This class matches the data model used by the web API. We can use HttpClient to read a Product
instance from an HTTP response, without having to write a lot of deserialization code.
Create and Initialize HttpClient
Add a static HttpClient property to the Program
class.
class Program
{
// New code:
static HttpClient client = new HttpClient(); }
HttpClient is intended to be instantiated once and re-used throughout the life of an application. Especially in server applications, creating a new HttpClient instance for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.
To initialize the HttpClient instance, add the following code to the RunAsync
method:
static async Task RunAsync()
{
// New code:
client.BaseAddress = new Uri("http://localhost:55268/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); Console.ReadLine();
}
This code sets the base URI for HTTP requests, and sets the Accept header to "application/json", which tells the server to send data in JSON format.
Sending a GET request to retrieve a resource
The following code sends a GET request for a product:
static async Task<Product> GetProductAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product;
}
The GetAsync method sends the HTTP GET request. The method is asynchronous, because it performs network I/O. When the method completes, it returns an HttpResponseMessage that contains the HTTP response. If the status code in the response is a success code, the response body contains the JSON representation of a product. Call ReadAsAsync to deserialize the JSON payload to a Product
instance. TheReadAsync method is asynchronous because the response body can be arbitrarily large.
HttpClient does not throw an exception when the HTTP response contains an error code. Instead, the IsSuccessStatusCode property is false if the status is an error code. If you prefer to treat HTTP error codes as exceptions, call HttpResponseMessage.EnsureSuccessStatusCode on the response object. This method throws an exception if the status code falls outside the range 200–299. Note that HttpClient can throw exceptions for other reasons — for example, if the request times out.
Using Media-Type Formatters to Deserialize
When ReadAsAsync is called with no parameters, it uses a default set of media formatters to read the response body. The default formatters support JSON, XML, and Form-url-encoded data.
Instead of using the default formatters, you can provide a list of formatters to the ReadAsync method, which 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);
For more information, see Media Formatters in ASP.NET Web API 2
Sending a POST Request to Create a Resource
The following code sends a POST request that contains a Product
instance in JSON format:
static async Task<Uri> CreateProductAsync(Product product)
{
HttpResponseMessage response = await client.PostAsJsonAsync("api/products", product);
response.EnsureSuccessStatusCode(); // Return the URI of the created resource.
return response.Headers.Location;
}
The PostAsJsonAsync method serializes an object to JSON and then sends the JSON payload in a POST request. If the request succeeds, it should return a 201 (Created) response, with the URL of the created resources in the Location header.
Sending a PUT Request to Update a Resource
The following code sends a PUT request to update a product.
static async Task UpdateProductAsync(Product product)
{
HttpResponseMessage response = await client.PutAsJsonAsync($"api/products/{product.Id}", product);
response.EnsureSuccessStatusCode(); // Deserialize the updated product from the response body.
product = await response.Content.ReadAsAsync<Product>();
return product;
}
The PutAsJsonAsync method works like PostAsJsonAsync, except that it sends a PUT request instead of POST.
Sending a DELETE Request to Delete a Resource
The following code sends a DELETE request to delete a product.
static async Task DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync($"api/products/{id}");
return response.StatusCode;
}
Like GET, a DELETE request does not have a request body, so you don't need to specify JSON or XML format.
Complete Code Example
Here is the complete code for this tutorial. The code is very simple and doesn't include much error handling, but it shows the basic CRUD operations using HttpClient.
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks; namespace HttpClientSample
{
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
} class Program
{
static HttpClient client = new HttpClient(); static void ShowProduct(Product product)
{
Console.WriteLine($"Name: {product.Name}\tPrice: {product.Price}\tCategory: {product.Category}");
} static async Task<Uri> CreateProductAsync(Product product)
{
HttpResponseMessage response = await client.PostAsJsonAsync("api/products", product);
response.EnsureSuccessStatusCode(); // return URI of the created resource.
return response.Headers.Location;
} static async Task<Product> GetProductAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product;
} static async Task<Product> UpdateProductAsync(Product product)
{
HttpResponseMessage response = await client.PutAsJsonAsync($"api/products/{product.Id}", product);
response.EnsureSuccessStatusCode(); // Deserialize the updated product from the response body.
product = await response.Content.ReadAsAsync<Product>();
return product;
} static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync($"api/products/{id}");
return response.StatusCode;
} static void Main()
{
RunAsync().Wait();
} static async Task RunAsync()
{
client.BaseAddress = new Uri("http://localhost:55268/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); try
{
// Create a new product
Product product = new Product { Name = "Gizmo", Price = 100, Category = "Widgets" }; var url = await CreateProductAsync(product);
Console.WriteLine($"Created at {url}"); // Get the product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product); // Update the product
Console.WriteLine("Updating price...");
product.Price = 80;
await UpdateProductAsync(product); // Get the updated product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);// Delete the productvar statusCode = await DeleteProductAsync(product.Id);Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");}catch(Exception e){Console.WriteLine(e.Message);}Console.ReadLine();}}}
This article was originally created on January 20, 2014
Author Information

Mike Wasson – Mike Wasson is a programmer-writer at Microsoft.
Calling a Web API From a .NET Client (C#)的更多相关文章
- Web API: Client: Call a Web API from a .net client
原文地址: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client 翻译地址:h ...
- ASP.NET Web API系列教程目录
ASP.NET Web API系列教程目录 Introduction:What's This New Web API?引子:新的Web API是什么? Chapter 1: Getting Start ...
- 【ASP.NET Web API教程】3.2 通过.NET客户端调用Web API(C#)
原文:[ASP.NET Web API教程]3.2 通过.NET客户端调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...
- 【ASP.NET Web API教程】3 Web API客户端
原文:[ASP.NET Web API教程]3 Web API客户端 Chapter 3: Web API Clients 第3章 Web API客户端 本文引自:http://www.asp.net ...
- 【ASP.NET Web API教程】3.3 通过WPF应用程序调用Web API(C#)
原文:[ASP.NET Web API教程]3.3 通过WPF应用程序调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...
- Web API 2
Asp.Net Web API 2 官网菜鸟学习系列导航[持续更新中] 前言 本来一直参见于微软官网进行学习的, 官网网址http://www.asp.net/web-api.出于自己想锻炼一下学 ...
- ASP.NET Web API系列教程(目录)(转)
注:微软随ASP.NET MVC 4一起还发布了一个框架,叫做ASP.NET Web API.这是一个用来在.NET平台上建立HTTP服务的Web API框架,是微软的又一项令人振奋的技术.目前,国内 ...
- 通过.NET客户端异步调用Web API(C#)
在学习Web API的基础课程 Calling a Web API From a .NET Client (C#) 中,作者介绍了如何客户端调用WEB API,并给了示例代码. 但是,那些代码并不是非 ...
- [转]ASP.NET Web API系列教程(目录)
本文转自:http://www.cnblogs.com/r01cn/archive/2012/11/11/2765432.html 注:微软随ASP.NET MVC 4一起还发布了一个框架,叫做ASP ...
随机推荐
- windows 编程 之 问题解决笔记
问题目录: 1.如何隐藏和显示窗口 2.InvalidateRect在连续使用鼠标或光标时暂时不起作用 3.在VC项目里自己添加头文件和cpp文件在编译阶段报错 4.在static 控件里添加子控件或 ...
- MySQL行列转换
分类: Mysql/postgreSQL 在某些数据库中有交叉表,但在MySQL中却没有这个功能,但网上看到有不少朋友想找出一个解决方法,特发贴集思广义.http://topic.csdn.net/u ...
- ContentProvider简单介绍
1.什么是ContentProvider 数据库在Android其中是私有的,当然这些数据包含文件数据和数据库数据以及一些其它类型的数据. 不能将数据库设为WORLD_READABLE,每一个数据 ...
- C#3.0 语言基础扩充
隐含类型局部变量 var i = 5; var h = 13.4; var s = "C Sharp"; var intArr = new[] {1,2,3 }; var a = ...
- android studio 的部分设置
1.android studio 如何提示方法的用法 在 Eclipse中鼠标放上去就可以提示方法的用法,实际上Android Studio也可以设置的.如图 Preferences > Edi ...
- MM32Flash读写操作(兼容STM32)
MM32Flash读写操作(兼容STM32) Flash基础描述 思维导图 编程实现读写操作 主函数结构 #include "delay.h" #include "sys ...
- SQL 去除小数点后无效 0 的方法
select convert(float,10.0000) 就是这么简单
- HTML基础总结<段落>
HTML 段落 段落是通过 <p> 标签定义的. 实例 <p>This is a paragraph </p><p>This is another pa ...
- sping注解原理
持续更新中.. spring注解用的是java注解,用到的是java反射机制. 参考文档如下: http://zxf-noimp.iteye.com/blog/1071765 对应spring源码如下 ...
- 一条insert语句批量插入多条记录
一条insert语句批量插入多条记录 常见的insert语句,向数据库中,一条语句只能插入一条数据: insert into persons (id_p, lastname , firstName, ...