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

  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 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小节 — 译者注)。

看完此文如果觉得有所收获,恳请给个推荐

时间: 2024-10-30 05:30:22

【ASP.NET Web API教程】3.2 通过.NET客户端调用Web API(C#)的相关文章

开发自己的Web服务处理程序(以支持Ajax框架异步调用Web服务方法)

当你添加Asp.net AJAX功能到你的Web程序的时候,你需要在Web.config中做一些改变,需要你显式地移除默认的ASMX处理程序并且添加asp.net ajax框架自己的脚本处理器来作为ASMX处理程序.在上一篇异步调用Web服务方法中,我们谈论过,ajax框架的asmx(ScriptHandler)是不支持异步调用Web服务方法的,所以为了让asp.netajax支持异步Web方法调用,我们需要避开该处理器,以提供自定义的处理器来取代它. Asp.netAJAX框架的ASMX处理器

客户端调用Web server 总是不行,怪呀,照着下例子做的

问题描述 <htmlxmlns="http://www.w3.org/1999/xhtml"><headrunat="server"><title>UntitledPage</title><scriptlanguage="javascript">functiontest(){WebService.lymantest("lyman",backMeg);returnfal

【ASP.NET Web API教程】6.3 内容协商

原文:[ASP.NET Web API教程]6.3 内容协商 本文是Web API系列教程的第6.3小节 6.3 Content Negotiation 6.3 内容协商 摘自:http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation By Mike Wasson|May 20, 2012 作者:Mike Wasson | 日期:2012-3-20 This article describe

【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/web-api/overview/web-api-clients In this chapter, you'll learn: 本章你将学习: How to create client applications that call your web API. 如何创建调用Web API的客户端应用

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

原文:[ASP.NET Web API教程]3.3 通过WPF应用程序调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 3.3 Calling a Web API From a WPF Application (C#) 3.3 通过WPF应用程序调用Web API(C#) 本文引自:http://www.asp.net/web-api/overview/web-api-clients/calling-a-we

使用AJAX Extensions客户端进行Web服务调用

从根本上讲,ASP.NET 自始至终都是一项服务器端技术.当然,在某些情况下 ASP.NET 会生成客户端 JavaScript,特别是在验证控件中以及在新推出的 Web 部件基础结构中,但它通常只是简单地将客户端 属性转换成客户端行为.作为开发人员,在收到下一个 POST 请求之前不必考虑与客户端进行交互.对于 需要使用客户端 JavaScript 和 DHTML 构建更具交互性的页面的开发人员而言,则需要在 ASP.NET 2.0 脚本回调功能提供的一些帮助下自己编写代码.这一情况在去年得到

安卓调用WEb service实现增删改查功能

问题描述 安卓调用WEb service实现增删改查功能 安卓调用WEb service的String ServerUrl=""http://10.0.2.2:4124/Service1.asmx"",输入这个地址ServerUrl为什么不能实现功能,请问要输入什么地址啊

webservice exception-客户端调用web service服务异常

问题描述 客户端调用web service服务异常 我是一个菜鸟,现在正在学着用wsdl.stub.连接webservice 现在出现的问题是: org.apache.axis2.AxisFault: Exception occurred while trying to invoke service method ReadClientDBByStrings at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils

用javascript在客户端调用CRM Web Service

在CRM中,更多的时候我们为了便于部署和提高用户体验都会选择用Javascript在客户端调用Web Service.其实在服务器端开发plugin我们仍然可以达到类似的效果,并且我们可以很方便的处理通过Web Service返回的结果,但用Javascript最主要的好处是很容易部署.众所周知,在CRM里的二次开发大多集中于定制,我们将写的Javascript及在其客户端事件中调用的Javascript方法都可以方便的Export到Customization文件中,这样在部署到生产机器上时我们