[Web API] WinForm 使用 HttpClient 调用 Web API

简单介绍 HttpClient 类与该如何于 Windows Form 中使用 HttpClient 类调用 Web API 的服务。


前言


  之前几篇文章已经介绍了 Web 与 Web API 的使用方式,接下来将介绍如何在 Windows Form 调用 Web API 的方法,要在 WinForm 中使用 Web API 的话,除了可以使用旧有的 WebClient、HttpWebRequest 类之外,还可以使用新的 HttpClient 类进行操作,HttpClient 类是包含在 .Net Framework 4.5 中的 System.Net.Http 之命名空间底下,HttpClient 类一般来说需要在 .Net Framework 4.5 上才能够使用,但是如果有装 NuGet 的话,可以使用 NuGet 搜寻 Microsoft.Net.Http,NuGet 有提供 4.0 可以使用的安装包。

HttpClient 简介


  在开始使用 WinForm 操作 Web API 前先来介绍一下 HttpClient 类,HttpClient 类主要使用于发送 HTTP 要求与接收 HTTP 响应内容,其中包含了一个特点,就是使用异步方式发送 GET、POST、PUT、DELETE 要求,在 MSDN HttpClient 类文档中提到,使用 HttpClient 的每个请求都拥有各自的连接集区,每个连接集区并不会互相干扰,意思就是可以使用一个实例化的 HttpClient 对象发送给各个不同的 HTTP 服务而不会相互影响。

  HttpClient 能够自订自己的 HttpClient Handler,需要透过继承 DelegatingHandler 的方式并覆写其 SendAsync 方法,参考此 HttpClient Message Handlers 文章提到,通常一个服务进程接收到了一个请求并处理其相关内容再回复结果,而过程中可能会经过数个 Handler 层层传递,这种处理模式称为 Delegating Handler,如下图:

  在客户端 HttpClient 透过消息处理进程来处理请求时,默认使用的是 HttpClientHandler 发送请求并得到服务响应,所以我们可以在此将自订的 Message Handler 插入到 HttpClient 与服务之间,如下图,但是在这里不特别说明作法,可以参考 [Web API] 自定 HTTP Message Handlers 此篇,另外对于 Web API 也能够自订Http Message Handler。

使用 HttpClient


  经过以上描述应该对于 HttpClient 有了大概的了解,接下来就来在 Windows Form 里使用 HttpClient 类操作调用 Web API 吧,同样使用前几篇建立好的 Web API 做为基底然后再加入一个窗口应用程序,如下图步骤

  再来因为 Web API 使用到 JSON 格式,所以透过 NuGet 安装 Json.Net 帮助我们处理 JSON 格式数据。

  接下来接可以加入一个 Windows Form,简单的把要使用的控制箱加入后切换到程序检视,准备开始撰写相关代码。

  在开始撰写代码之前要先注意一件事,由于先前有提到,HttpClient 类提供的 GET、POST、PUT、DELETE 方法都是异步方法,所以我们在实际上要去执行 HttpClient 操作的方法上必须加入 asyncawait 关键字,详细可以参考 使用 Async 和 Await 设计异步程序 (C# 和 Visual Basic) 文章。

  例如当需要取得 Web API 的所有产品清单时,就可以撰写  GetAllProducts() 方法,如下

private async void GetAllProducts()
{
    HttpClient client = new HttpClient();
    HttpResponseMessage response = await client.GetAsync("http://localhost:49988/api/products");
    response.EnsureSuccessStatusCode();
    string responseBody = await response.Content.ReadAsStringAsync();
    ShowResult(JsonConvert.DeserializeObject>(responseBody));
}

  在以上方法中可以看到于方法声明中加入了 async 声明此方法为异步方法,之后产生了 HttpClient 对象,并透过该对象的 GetAsync(string) 方法使用异步作业要求取得此 URI 资源,GetAsync(string) 方法将发送一个 GET 请求至 Web API 服务并返回结果,这里可以注意到在 client.GetAsync(URL) 前面加了一个 await 关键字,其原因在于 HttpClient 是异步方法,所以必须要求等待到数据处理完成返回后才能继续下面的步骤,如果不加 await 关键字于前方,GetAsync(string) 方法默认是返回一个 Task 的类型。

  而如需要使用 POST 动词的方式调用 Web API,就需要改使用 PostAsync(string, httpContent) 方法,如下

private async void PostProduct()
{
    HttpClient client = new HttpClient();
    HttpResponseMessage response = await client.PostAsync("http://localhost:49988/api/products/ASP.NET/WEB/399/12", null);
    response.EnsureSuccessStatusCode();
    string responseBody = await response.Content.ReadAsStringAsync();
    ShowResult(JsonConvert.DeserializeObject>(responseBody));
}

  在以上方法中使用 PostAsync(string, httpContent) 方法处理 Post 传输,在此 HttpContent 参数为 null 的原因在此 Web API 的服务是使用 URI 资源的形式,会将参数都至于此 URI 位置中,所以当不是使用此方式的情况下,就必须要自行将参数写入 HttpContent。

  而 Put、Delete 就如同上述内容一样做法,如下

private async void PutProduct()
{
    HttpClient client = new HttpClient();
    HttpResponseMessage response = await client.PutAsync("http://localhost:49988/api/products/1/The WebAPI/MVC/450/5", null);
    response.EnsureSuccessStatusCode();
    string responseBody = await response.Content.ReadAsStringAsync();
    ShowResult(JsonConvert.DeserializeObject>(responseBody));
}

private async void DeleteProductById()
{
    HttpClient client = new HttpClient();
    HttpResponseMessage response = await client.DeleteAsync("http://localhost:49988/api/products/2");
    response.EnsureSuccessStatusCode();
    string responseBody = await response.Content.ReadAsStringAsync();
    ShowResult(JsonConvert.DeserializeObject>(responseBody));
}

  参考以上内容完成后,就可以来测试一下,如下

  以上就是一个 Windows Form 使用 HttpClient 调用 Web API 的使用范例,如有任何遗漏或错误,日后将继续修正补充。

范例程序


TWebApi_03.part01.rar

TWebApi_03.part02.rar

TWebApi_03.part03.rar

参考数据


HttpClient 类

HttpMessageHandler 类

使用 Async 和 Await 设计异步程序 (C# 和 Visual Basic)

HttpClient Message Handlers

HTTP Message Handlers

ASP.NET WEB API 心得笔记 (9) 简介 SYSTEM.NET.HTTP.HTTPCLIENT 类




以上文章叙述如有错误及观念不正确,请不吝啬指教
如有侵权内容也请您与我反应~谢谢您 :)