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, selectConsole 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包管理器,按如下步骤安装。

  1. Start Visual Studio.

    启动Visual Studio.
  2. From the Tools menu, select Extensions and Updates.

    从“工具”菜单选择“扩展与更新”
  3. In the Extensions and Updates dialog, select Online.

    在“扩展与更新”对话框中,选择“在线”
  4. If you don't see "NuGet Package Manager", type "nuget package manager" in the search box.

    如果未看到“NuGet包管理器”,在搜索框中输入“nuget package manager”。
  5. Select the NuGet Package Manager and click Download.

    选择“NuGet包管理器”,并点击“下载”。
  6. After the download completes, you will be prompted to install.

    下载完成后,会提示你安装。
  7. 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客户端库包添加到你的项目。步骤如下:

  1. 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包管理器。
  2. Select Manage NuGet Packages for Solution...

    选择“管理解决方案的NuGet包…”
  3. In the Manage NugGet Packages dialog, select Online.

    在“管理NuGet包”对话框中,选择“在线”。
  4. In the search box, type "Microsoft.AspNet.WebApi.Client".

    在搜索框中输入“Microsoft.AspNet.WebApi.Client”。
  5. Select the ASP.NET Web API Self Host package and click Install.

    选择“ASP.NET Web API自托管包”,并点击“安装”。
  6. 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 Resultproperty 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小节 — 译者注)。

来源于http://www.cnblogs.com/r01cn/archive/2012/11/20/2779011.html

通过.NET客户端调用Web API(C#)的更多相关文章

  1. 【ASP.NET Web API教程】3.2 通过.NET客户端调用Web API(C#)

    原文:[ASP.NET Web API教程]3.2 通过.NET客户端调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...

  2. Asp.Net Web API 2第三课——.NET客户端调用Web API

    详情请查看http://aehyok.com/Blog/Detail/70.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...

  3. 通过.NET客户端异步调用Web API(C#)

    在学习Web API的基础课程 Calling a Web API From a .NET Client (C#) 中,作者介绍了如何客户端调用WEB API,并给了示例代码. 但是,那些代码并不是非 ...

  4. 【ASP.NET Web API教程】3.3 通过WPF应用程序调用Web API(C#)

    原文:[ASP.NET Web API教程]3.3 通过WPF应用程序调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...

  5. WebApi系列~通过HttpClient来调用Web Api接口

    回到目录 HttpClient是一个被封装好的类,主要用于Http的通讯,它在.net,java,oc中都有被实现,当然,我只会.net,所以,只讲.net中的HttpClient去调用Web Api ...

  6. ASP.NET MVC4中调用WEB API的四个方法

    http://tech.it168.com/a2012/0606/1357/000001357231_all.shtml [IT168技术]当今的软件开发中,设计软件的服务并将其通过网络对外发布,让各 ...

  7. 通过HttpClient来调用Web Api接口

    回到目录 HttpClient是一个被封装好的类,主要用于Http的通讯,它在.net,java,oc中都有被实现,当然,我只会.net,所以,只讲.net中的HttpClient去调用Web Api ...

  8. Http下的各种操作类.WebApi系列~通过HttpClient来调用Web Api接口

    1.WebApi系列~通过HttpClient来调用Web Api接口 http://www.cnblogs.com/lori/p/4045413.html HttpClient使用详解(java版本 ...

  9. [置顶] Xamarin android 调用Web Api(ListView使用远程数据)

    xamarin android如何调用sqlserver 数据库呢(或者其他的),很多新手都会有这个疑问.xamarin android调用远程数据主要有两种方式: 在Android中保存数据或调用数 ...

随机推荐

  1. 小梦词典WP8.1应用发布

    这几天一直在做这款应用,今天终于发布了! 小梦词典简介: 小梦词典是一款永久免费无广告的网络词典. 支持英汉单词查询: 支持中,英,法,韩,德,俄,日七国语言翻译,多语言极致体验: 支持生词本记忆,查 ...

  2. 微信小程序初步运营方案

    小程序的运营方案有很多种,目前我们遇到两个事情需要解决:1.问答的内容,这块也是大家比较关心的话题.内容的定位和细节. 2.预热与推广,就这两个问题,我列出了一些自己的想法和小程序初步运营方案,有不足 ...

  3. 微信小程序从零开始开发步骤(三)

    上一章节,我们分享了如何创建一个新的页面和设置页面的标题,这一章我们来聊聊底部导航栏是如何实现的.即点击底部的导航,会实现不同对应页面之间的切换. 我们先来看个我们要实现的底部导航栏的效果图:(三个导 ...

  4. [Redux] Avoid action type naming conflicts

    In redux, the action type is just a normal string type, it is easy to get naming conflicts in large ...

  5. 机器学习 Softmax classifier (一个隐含层)

    程序实现 softmax classifier, 含有一个隐含层的情况.activation function 是 ReLU : f(x)=max(0,x) f1=w1x+b1 h1=max(0,f1 ...

  6. Redis管理及监控工具

    Redis管理及监控工具 Redis做为现在web应用开发的黄金搭担组合,大量的被应用,广泛用于存储session信息,权限信息,交易作业等热数据.做为一名有10年以上JAVA开发经验的程序员,工作中 ...

  7. Expression Blend 的点滴(4)--创建类似iPhone屏幕锁控件(上)

    原文:Expression Blend 的点滴(4)--创建类似iPhone屏幕锁控件(上) 本篇文章,最终效果图:  当然,不只是一个UI而已,如果只是一张图片,那专业的设计师能做出更出色的效果.在 ...

  8. 面试无忧之Zookeeper总结心得

    为什么需要分布式系统 l 单机系统已经无法满足业务需要 l 高性能硬件价格昂贵 分布式系统带来哪些问题 l 集群中节点数据一致性问题 l 集群产生分区 l 负载问题 l 幂等性问题 l 可用性问题 l ...

  9. Oracle数据库表空间 数据文件 用户 以及表创建的SQL代码

    --create the tablespace CREATE SMALLFILE TABLESPACE "TABLE_CONTAINER" --创建表空间 DATAFILE 'E: ...

  10. 【BZOJ 1032】 [JSOI2007]祖码Zuma

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1032 [题意] [题解] /* 设f[i][j]表示从第i个珠子开始的j个珠子被消除; ...