【ASP.NET Web API教程】3.2 通过.NET客户端调用Web API(C#)
原文:【ASP.NET Web API教程】3.2 通过.NET客户端调用Web API(C#)
注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本博客文章,请先看前面的内容。
3.2 Calling a Web API From a .NET Client (C#)
3.2 通过.NET客户端调用Web API(C#)
本文引自:http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client
By Mike Wasson | July 18, 2012
作者:Mike Wasson | 日期:2012-7-18
This tutorial shows how to call a web API from a console application, using HttpClient.
本教程展示如何在一个控制台应用程序中使用HttpClient调用Web API。
In this tutorial, we will consume the "ProductStore" API, described in Creating a Web API that Supports CRUD Operations.
在本教程中,我们将使用在“创建支持CRUD操作的Web API(本系列教程的第2.1小节 — 译者注)”小节中描述的“ProductStore”API。
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.
启动Visual studio,并从“开始”页面选择“新项目”。或者从“文件”菜单选择“新建”,然后选择“项目”。
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.
在“模板”面板中,选择“已安装模板”,并展开“Visual C#”节点。在“Visual C#”下选择“Windows”。在项目模板列表中选择“控制台应用程序”。命名此项目并点击“OK”(见图3-1)。
图3-1. 创建控制台项目
Install NuGet Package Manager
安装NuGet包管理器
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.
“NuGet包管理器(NuGet Package Manager)”是把Web API客户端库添加到项目的一种最容易的方法。如果尚未安装NuGet包管理器,按如下步骤安装。
- Start Visual Studio.
启动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.
如果未看到“NuGet包管理器”,在搜索框中输入“nuget package manager”。 - Select the NuGet Package Manager and click Download.
选择“NuGet包管理器”,并点击“下载”。 - After the download completes, you will be prompted to install.
下载完成后,会提示你安装。 - After the installation completes, you might be prompted to restart Visual Studio.
安装完成后,可能会提示重启Visual Studio。
上述安装过程如图3-2所示。
图3-2. 安装NuGet包管理器
Install the Web API Client Libraries
安装Web API客户端库
After NuGet Package Manager is installed, add the Web API Client Libraries package to your project.
安装NuGet包管理器后,把Web API客户端库包添加到你的项目。步骤如下:
- 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.
从“工具”菜单选择“库包管理器”。注:如果看不到这个菜单项,请确保已正确安装了NuGet包管理器。 - Select Manage NuGet Packages for Solution...
选择“管理解决方案的NuGet包…” - In the Manage Nu
gGet Packages dialog, select Online.
在“管理NuGet包”对话框中,选择“在线”。 - In the search box, type "Microsoft.AspNet.WebApi.Client".
在搜索框中输入“Microsoft.AspNet.WebApi.Client”。 - Select the ASP.NET Web API Self Host package and click Install.
选择“ASP.NET Web API自托管包”,并点击“安装”。 - After the package installs, click Close to close the dialog.
这个包安装后,点击“关闭”,关闭此对话框。
上述安装步骤如图3-3所示。
图3-3. 安装Web API客户端库
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.
这个类创建一个数据对象,HttpClient将把它写入HTTP请求体中,也从HTTP响应体中读取它。
Initialize HttpClient
初始化HttpClient
Create a new instance of HttpClient and initialize it as follows:
创建一个新的HttpClient实例,并像下面这样初始化它:
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.
// 为JSON格式添加一个Accept报头
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.
这段代码把基URI设置为“http://localhost:9000/”,并将Accept报头设置为“application/json”,这是告诉服务器,以JSON格式发送数据。
Getting a Resource (HTTP GET)
获取资源(HTTP GET)
The following code shows how to query the API for a list of products:
以下代码展示如何对产品列表查询API:
// 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.
GetAsync方法发送HTTP GET请求。正如其名称所暗示的,GetAsync是异步的。它立即返回,不会等待服务器的响应。返回值是一个表示异步操作的Task对象。当该操作完成时,Task.Result属性包含HTTP响应。
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.
重要的是理解,直到请求完成(或超时),采用Result属性的过程是应用程序线程阻塞的。控制台应用程序的阻塞没问题,但是,你决不应该在一个Windows应用程序的UI上做这种事,因为这会阻塞UI去响应用户的输入。在本教程的下一部分中,我们将看到如何编写非阻塞调用。
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.
如果HTTP响应指示成功,响应体便含有一个JSON格式的产品列表。要解析这个列表,需调用ReadAsAsync。该方法读取响应体,并试图把它解序列化成一个具体的CLR(公共语言运行时)类型。这个方法也是异步的,因为体可能有任意大小。再次强调,采用Result属性的过程是线程阻塞的。
Example HTTP session:
HTTP会话示例:
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:
通过ID获取产品是类似的:
// Get a product by ID
// 通过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.)
ReadAsAsync是在System.Net.Http.HttpContentExtensions类中定义的一个扩展方法。不带参数,它会使用媒体类型格式化器的默认设置,以试图解析响应体。默认格式化器支持JSON、XML和经过url编码的表单数据(Form-url-encoded data)。(关于媒体类型格式化器的更多信息,参阅“格式化与模型绑定(本教程系列的第6章 — 译者注)”)
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)
创建一个资源(HTTP POST)
The following code sends a POST request that contains a Product instance in JSON format:
以下代码发送一个POST请求,它含有一个JSON格式的Product实例:
// 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:
PostAsJsonAsync是在System.Net.Http.HttpClientExtensions中定义的一个扩展方法。上述代码与以下代码等效:
var product = new Product() { Name = "Gizmo", Price = 100, Category = "Widget" };
// Create the JSON formatter.
// 创建JSON格式化器。
MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
// Use the JSON formatter to create the content of the request body.
// 使用JSON格式化器创建请求体内容。
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.
对于XML格式,使用PostAsXmlAsync方法。
Example HTTP session:
HTTP会话示例:
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:
默认地,JSON格式化器将content-type(内容类型)设置为“application/json”。你也可以明确地指定媒体类型。例如,假设“application/vnd.example.product”是你用于Product实例的媒体类型。可以像下面这样来设置这种媒体:
HttpContent content = new ObjectContent<Product>(product, jsonFormatter,
"application/vnd.example.product+json");
Updating a Resource (HTTP PUT)
更新一个资源(HTTP PUT)
The following code sends a PUT request.
以下代码发送一个PUT请求:
// 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.
PutAsJsonAsync方法与PostAsJsonAsync类似,只是它发送的是一个PUT请求,而不是POST。
Deleting a Resource (HTTP DELETE)
删除一个资源(HTTP DELETE)
By now, you can probably predict how to send a DELETE request:
现在,你可能已经能预测到如何发送一个DELETE请求了:
// 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.
与GET一样,DELETE请求没有请求体,因此你不必指定JSON或XML格式。
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).
HttpClient在它接收到一个带有错误代码的HTTP响应时,不会抛出异常。但是,该响应的StatusCode属性含有状态码。而且,如果其状态是一个成功的状态码(状态码在200-299之间)时,IsSuccessStatusCode属性为true。
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.
如果你喜欢把错误代码处理成异常,可以调用EnsureSuccessStatusCode方法。这个方法在响应状态不是一个成功的代码时,会抛出一个异常。
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.
当然,由于其它原因,HttpClient也可能抛出异常 — 例如,请求超时的时候。
Configuring HttpClient
配置HttpClient
To configure HttpClient, create a WebRequestHandler instance, set properties on it, and pass it to the HttpClient constructor:
为了配置HttpClient,可以创建一个WebRequestHandler实例,设置其属性,并把它传递给HttpClient构造器:
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.
WebRequestHandler派生于HttpMessageHandler。通过从HttpMessageHandler派生,你也可以插入自定义消息处理程序。更多信息参阅“HTTP消息处理器(本系列教程的第5.1小节 — 译者注)”。
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
控制台应用程序使我们很容易看到代码流程。然而,阻塞调用对于图形UI的应用程序并不是一种好的做法。要了解如何处理非阻塞HttpClient中的异步操作,参阅“通过WPF应用程序调用Web API”(本系列教程的第3.3小节 — 译者注)。
看完此文如果觉得有所收获,恳请给个推荐
【ASP.NET Web API教程】3.2 通过.NET客户端调用Web API(C#)的更多相关文章
- Asp.Net Web API 2第三课——.NET客户端调用Web API
详情请查看http://aehyok.com/Blog/Detail/70.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...
- 通过.NET客户端调用Web API(C#)
3.2 Calling a Web API From a .NET Client (C#) 3.2 通过.NET客户端调用Web API(C#) 本文引自:http://www.asp.net/web ...
- Scrapyd 改进第二步: Web Interface 添加 STOP 和 START 超链接, 一键调用 Scrapyd API
0.提出问题 Scrapyd 提供的开始和结束项目的API如下,参考 Scrapyd 改进第一步: Web Interface 添加 charset=UTF-8, 避免查看 log 出现中文乱码,准备 ...
- ASP.NET MVC轻教程 Step By Step 12——客户端验证
前面两节使用的两种数据验证方法都是在服务器端进行的,也就是提交了表单,数据回传给服务器才能验证.这样会带来两个问题,一是用户体验不好,用户提交了表单之后才知道存在问题:二是会给服务器带来额外的压力.我 ...
- 客户端调用web中js方法(C调B)跨域问题
这几天遇到了个棘手问题(c调b),经过排错查出了问题. 一,问题描述如下: 1.客户端需要调用father.html中一个js方法,特殊之处在于 这个father.html中有个iframe嵌套了一个 ...
- 在使用HttpClient做客户端调用一个API时 模拟并发调用时发生“死锁"?
平时还是比较喜欢看书的..但有时候遇到问题还是经常感到脑袋一蒙..智商果然是硬伤.. 同事发现了个问题,代码如下: class Program { static void Main(string[] ...
- 【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系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API. 使用IdentityServer4 来实现使用客户端凭据保护ASP.N ...
随机推荐
- eclipse the user operation is waiting for building workspace" to complete
"the user operation is waiting for building workspace" to complete", 解决办法: 1.选择菜单栏的“P ...
- HDU 4121
http://www.bnuoj.com/v3/problem_show.php?pid=10277 //#pragma comment(linker, "/STACK:16777216&q ...
- Chapter 6 装饰模式
修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式.就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能. 例如:DataOutputStrea ...
- Hibernate执行sql语句
Hibernate执行sql语句:BasicServiceImpl basicServiceImpl = new BasicServiceImpl();String hql = "selec ...
- Qt5程序开机自启动(windows)
简介 window下开机启动最简单的实现方式就是在注册表中添加启动项目 添加位置有两个 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVer ...
- docker 学习笔记21:docker连接网络的设置
1.如果docker主机不需要通过代理连接外网 则docker的相关命令(如docker search)或docker容器与网络相关的操作都可以正常进行,不需要特殊设置. 2.当docker主机 是通 ...
- 【CSDN博客之星评选】我为什么坚持写博客
今天无意中在CSDN的博客之星评选活动看到自己竟然是候选人之一,真的是十分的惊讶也十分的高兴.对于喜欢写东西.喜欢分享的我来说,已经忍不住用文字来记录一下今天的美好心情,同时也让我回想起我是如何开始在 ...
- sencha touch笔记(6)——路由控制(1)
做项目的时候在界面的跳转上遇到了挺大的问题,本来跳转不想通过路由来控制的,没办法,只能再去看一下路由的跳转方式了. 应用程序的界面发生改变后,可以通过路由让应用程序的界面返回到改变之前的状态,例如浏览 ...
- pyfits例子
下面是一个读入fits文件,画积分强度图,再把某个星表里的天体画到图上的python程序. ====================================================== ...
- 读取sd卡下图片,由图片路径转换为bitmap
public Bitmap convertToBitmap(String path, int w, int h) { BitmapFactory.Options opts = ...