【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-web-api-from-a-wpf-application

By Mike Wasson | August 22, 2012
作者:Mike Wasson | 日期:2012-8-22

This tutorial shows how to call a web API from a Windows Presentation Foundation (WPF) application, using HttpClient.
本教程展示如何用HttpClient通过WPF应用程序(Windows Presentation Foundation — Windows表现基础,WPF应用程序指常规的窗口应用程序 — 译者注)调用Web API。

The main purpose of this tutorial is to see how asynchronous operations are handled in HttpClient. In this tutorial, we will consume the "ProductStore" API, described in "Creating a Web API that Supports CRUD Operations".
本教程的主要目的是考查在HttpClient中如何处理异步操作。在本教程中,我们将使用在“创建支持CRUD操作的Web API”小节中描述的“ProductStore”API。

Before you read this tutorial, you might want to read Calling a Web API From a .NET Client. That article introduces some of the concepts that I use in this tutorial.
在阅读这篇文章之前,你或许想阅读“通过.NET客户端调用Web API”(本系列教程的上一小节 — 译者注)。这篇文章中介绍了本教程使用的一些概念。

Asynchronous Calls
异步调用

HttpClient is designed to be non-blocking. Potentially long-running operations are implemented as asynchonrous methods, such as GetAsync and PostAsync. These methods return without waiting for the operation to complete. The previous tutorial (Calling a Web API From a Console Application) showed only blocking calls:
HttpClient被设计成是非阻塞的。潜在地,长时间运行的操作是作为异步方法实现的,例如,GetAsyncPostAsync。这些方法不会等待操作完成便会返回。上一教程(通过控制台应用程序调用Web API)只展示了阻塞调用:

HttpResponseMessage response = client.GetAsync("api/products").Result;  // Blocking call(阻塞)!

This code blocks the calling thread by taking the Result property. That's OK for a console application, but you should not do it from a UI thread, because it blocks the UI from responding to user input.
这段代码通过采用Result属性,会阻塞调用线程。对于一个控制台应用程序,这没问题,但你不应该在一个UI线程中采用这一做法,因为这会阻止UI去响应用户输入。

The asynchronous methods of HttpClient return Task objects that represent the asynchronous operation.
HttpClient的异步方法会返回表示异步操作的Task对象。

Create the WPF Project
创建WPF项目

Start Visual Studio. From the Start menu, select New Project. In the Templates pane, select Installed Templates and expand the Visual C# node. In the list of project templates, select WPF Application. Name the project and click OK.
启动Visual Studio。从“开始”菜单选择“新项目”。在“模板”面板中,选择“已安装模板”,并展开“Viusal C#”节点。在项目模板列表中,选择“WPF应用程序”。命名此项目并点击“OK”。

Open MainWindow.xaml and add the following XAML markup inside the Grid control:
打开MainWindow.xaml,并在Grid控件中添加以下XAML标记:

<StackPanel Width="250" > <Button Name="btnGetProducts" Click="GetProducts">Get Products</Button> <ListBox Name="ProductsList"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Margin="2"> <TextBlock Text="{Binding Path=Name}" /> <TextBlock >Price: $<Run Text="{Binding Path=Price}" />  (<Run Text="{Binding Path=Category}" />)</TextBlock> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> 
</StackPanel>

This markup defines a ListBox that will be data-bound to the list of products. The DataTemplate defines how each product will be displayed.
这段标记定义了一个将被数据绑定到产品列表的ListBox(列表框)。DataTemplate(数据模板)定义了如何显示每个产品。(其效果如图3-4所示)。

WebAPI3-4

图3-4. WPF界面效果

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 defines a data object that HttpClient will write into the HTTP request body and read from the HTTP response body.
这个类定义了一个数据对象,HttpClient将把它写入HTTP请求体,也从HTTP响应体中读取它。

We'll also add an observable class for data binding:
我们也要添加一个用于数据绑定的可见对象类(observable class):

class ProductsCollection : ObservableCollection<Product> 
{ public void CopyFrom(IEnumerable<Product> products) { this.Items.Clear(); foreach (var p in products) { this.Items.Add(p); } 
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } }

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.
将Web API客户端库添加到项目最容易的办法是安装“NuGet包管理器(NuGet Package Manager)”。如果尚未安装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-5所示。

WebAPI3-5

图3-5. 安装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 NuGet 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-6所示。

WebAPI3-6

图3-6. 安装Web API客户端库

Initialize HttpClient
初始化HttpClient

From Solution Explorer, open the file MainWindow.xaml.cs. Add the following code.
在“解决方案资源管理器”中,打开MainWindow.xaml.cs文件。添加以下代码:

namespace WpfProductClient 
{ using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Windows; 
public partial class MainWindow : Window { HttpClient client = new HttpClient(); ProductsCollection _products = new ProductsCollection();
public MainWindow() { InitializeComponent();
client.BaseAddress = new Uri("http://localhost:9000"); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json"));
this.ProductsList.ItemsSource = _products; } } }

This code creates a new instance of HttpClient. It also 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.
这段代码创建了一个新的HttpClient实例。也把基URI设置为“http://localhost:9000/”,并且把Accept报头设置为“application/json”,这是告诉服务器,以JSON格式发送数据。

Notice that we also created a new ProductsCollection class and set it as the binding for the ListBox.
注意,我们也创建了一个新的ProductsCollection类,并把它设置为对ListBox的绑定。

Getting a Resource (HTTP GET)
获取资源(HTTP GET)

If you are targeting .NET Framework 4.5, the async and await keywords make it much easier to write asynchronous code.
如果你的目标是.NET Framework 4.5(意即,你所开发的应用程序将在.NET 4.5平台上运行 — 译者注),asyncawait关键字会让你很容易编写异步代码。

If you are targeting .NET Framework 4.0 with Visual Studio 2012, you can install the Async Targeting Pack to get async/await support.
如果你的目标是使用Visual Studio 2012的.NET Framework 4.0,可以安装Async Targeting Pack来获得async/await支持。

The following code queries the API for a list of products. Add this code to the MainWindow class:
以下代码查询产品列表API。将此代码添加到MainWindow类:

private async void GetProducts(object sender, RoutedEventArgs e) 
{ try { btnGetProducts.IsEnabled = false; 
var response = await client.GetAsync("api/products"); response.EnsureSuccessStatusCode(); // Throw on error code(有错误码时报出异常).
var products = await response.Content.ReadAsAsync<IEnumerable<Product>>(); _products.CopyFrom(products);
} catch (Newtonsoft.Json.JsonException jEx) { // This exception indicates a problem deserializing the request body.// 这个异常指明了一个解序列化请求体的问题。MessageBox.Show(jEx.Message); } catch (HttpRequestException ex) { MessageBox.Show(ex.Message); } finally { btnGetProducts.IsEnabled = true; } }

The GetAsync method sends an HTTP GET request. 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.
GetAsync方法发送一个HTTP GET请求。如果HTTP响应指示成功,响应体会含有一个JSON格式的产品列表。要解析这个列表,调用ReadAsAsync。这个方法会读取响应体,并试图把它解序列化成一个具体的CLR类型。

As their names imply, GetAsync and ReadAsAsync are asynchronous methods, meaning they return immediately, without waiting for the operation to complete. The await keyword suspends execution until the operation completes. For example:
正如其名称所暗示的,GetAsyncReadAsAsync是异步方法,意即,它们立即返回,不会等待操作完成。await关键字会挂起执行,直到操作完成。例如:

var response = await client.GetAsync("api/products");

The code that appears after this statement does not execute until the HTTP request is completed. But that does not mean the event handler blocks, waiting for GetAsync to complete. Just the opposite — control returns to the caller. When the HTTP request is completed, execution continues from the point where it was suspended.
出现在这条语句之后的代码直到HTTP请求完成时才会执行。但这并不意味着事件处理器(event handler,也可以叫做事件处理程序 — 译者注)会阻塞,以等待GetAsync完成。恰恰相反 — 控制会返回给调用者。当HTTP请求完成时,执行会从挂起点继续。

If a method uses await, it must have the async modifier:
如果一个方法使用await,它必须有async修饰符:

private async void GetProducts(object sender, RoutedEventArgs e)

Without the await keyword, you would need to call ContinueWith on the Task object:
没有这个await关键字,你就需要调用Task对象上的ContinueWith

private void GetProducts(object sender, RoutedEventArgs e) 
{ btnGetProducts.IsEnabled = false; 
client.GetAsync("api/products/2").ContinueWith((t) => { if (t.IsFaulted) { MessageBox.Show(t.Exception.Message); btnGetProducts.IsEnabled = true; } else { var response = t.Result; if (response.IsSuccessStatusCode) { response.Content.ReadAsAsync<IEnumerable<Product>>(). ContinueWith(t2 => { if (t2.IsFaulted) { MessageBox.Show(t2.Exception.Message); btnGetProducts.IsEnabled = true; } else { var products = t2.Result; _products.CopyFrom(products); btnGetProducts.IsEnabled = true; } }, TaskScheduler.FromCurrentSynchronizationContext()); } } }, TaskScheduler.FromCurrentSynchronizationContext()); }

This type of code is difficult to get right, so it's recommended to target .NET 4.5, or if that's not possible, install the Async Targeting Pack.
这种型式的代码难以正确,因此建议把目标定为.NET 4.5,或者,如果这不可能,需安装Async Targeting Pack(Async目标包)。

Creating a Resource (HTTP POST)
创建资源(HTTP POST)

Go back to the MainWindow.xaml file and add some (very) UI for creating a new product:
回到MainWindow.xaml文件,添加一些创建一个新产品的UI:

<Label FontWeight="ExtraBold">New Product</Label> 
<Label>Name</Label> 
<TextBox Name="textName"></TextBox> 
<Label>Price</Label> 
<TextBox Name="textPrice"></TextBox> 
<Label>Category</Label> 
<TextBox Name="textCategory"></TextBox> 
<Button Name="btnPostProduct" Click="PostProduct">Post Product</Button>

Now add the following code to the MainWindow class.
现在把以下代码添加到MainWindow类:

private async void PostProduct(object sender, RoutedEventArgs e) 
{ btnPostProduct.IsEnabled = false; 
try { var product = new Product() { Name = textName.Text, Price = decimal.Parse(textPrice.Text), Category = textCategory.Text }; var response = await client.PostAsJsonAsync("api/products", product); response.EnsureSuccessStatusCode(); // Throw on error code(有错误码时抛出).
_products.Add(product); } catch (HttpRequestException ex) { MessageBox.Show(ex.Message); } catch (System.FormatException) { MessageBox.Show("Price must be a number"); } finally { btnPostProduct.IsEnabled = true; } }

This code sends a POST request that contains a Product instance in JSON format. PostAsJsonAsync is an extension method defined in System.Net.Http.HttpClientExtensions. Internally, this method uses the JSON media-type formatter to serialize the Product to JSON and write it into the request body. For XML format, use the PostAsXmlAsync method.
这段代码发送一个POST请求,它含有一个JSON格式的Product实例。PostAsJsonAsync是一个在System.Net.Http.HttpClientExtensions中定义的扩展方法。内在地,这个方法使用JSON媒体类型格式化器把Product序列化成JSON,并把它写入请求体。对于XML格式,使用PostAsXmlAsync方法。

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

转载于:https://www.cnblogs.com/r01cn/archive/2012/11/20/2779779.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401097.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java开发过程中的命名规范

为什么80%的码农都做不了架构师&#xff1f;>>> 最近在读项目的过程中&#xff0c;发现好多同事的代码并不是很规范&#xff0c;有的包名也按照了驼峰的写法&#xff0c;虽说这样不是不行&#xff0c;但个人认为开发过程中应该遵守这些规范&#xff0c;现整理规范如…

git 使用方法自用(勿进)本地开发分支推上线上开发分支

一、//查看状态 1.git status 二、//查看改了哪个文件夹 1.git diff 2.//会出现改了哪个文件夹src/components/partials/Slider.js 三、//查看改了的文件夹里面具体改了啥内容 1.git diff src/components/partials/Slider.js 四、提交所有 1. git add . 五、写备注…

SVG 和 CSS3 实现一个超酷爱心 Like 按钮

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 在现代网页中&#xff0c;我们经常可以在一些文章、视频和图片页面上找到”Like”按…

redis简单学习3-redis常用命令总结

2019独角兽企业重金招聘Python工程师标准>>> 1.键值相关的命令 keys 返回满足给定pattern的所有key 表达式* 代表取出所有的key redis 127.0.0.1:6379> keys * 1) "myzset2" 2) "myzset3" 3) "mylist" 4) "myset2" 5)…

微软的创新还是败笔?Windows 8为苹果创造天赐良机

网络安全公司Avast近日公布的数据显示&#xff1a;Windows系统使用人数正在不断下降。这一结果对微软来说可谓噩梦&#xff0c;于此同时&#xff0c;苹果则不断加强市场占有率。又是什么导致了这样的结果&#xff1f;接下来就看看最主要的几点&#xff1a; 调查覆盖了13.5万Wi…

testbench常用任务之SPI slave输出数据

模仿了SPI master从SPI slave读取数据的MiSO数据状态 每8个clk后读取的数据加1 用的一些额外寄存器需要自己声明和初始化 //------------------------------------------------------------------------- //send serial data which is increase by 1 on MiSO line //----------…

Vue生产环境调试的方法

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 vue 生产环境默认是无法启用vue devtools的&#xff0c;如果生产应用出了问题&…

RavenDB:基于Windows/.NET平台的NoSQL数据库

众所周知&#xff0c;NoSQL运动旨在成为大数据时代传统关系数据库管理系统的替代品。如今Microsoft对开源的态度有所转变&#xff0c;RavenDB就是很好的例子。Microsoft对RavenDB&#xff08;NoSQL数据库&#xff09;的认可令很多人感到惊讶。RavenDB可以轻易的替代关系数据库管…

JDBC实例--JDBC连接池技术解密,连接池对我们不再陌生

一、为什么我们要用连接池技术&#xff1f; 前面的数据库连接的建立及关闭资源的方法有些缺陷。统舱传统数据库访问方式&#xff1a;一次数据库访问对应一个物理连接,每次操作数据库都要打开、关闭该物理连接, 系统性能严重受损。 解决方案&#xff1a;数据库连接池&#xff08…

重温51汇编指令(附实验)

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 重温51汇编指令&#xff08;附实验&#xff09; 写在前面&#xff1a; 在电子控制…

SSH HTTPS 公钥、秘钥、对称加密、非对称加密、 总结理解

2019独角兽企业重金招聘Python工程师标准>>> 作者&#xff1a;shede333主页&#xff1a;http://my.oschina.net/shede333 && http://blog.sina.com.cn/u/1509658847版权声明&#xff1a;原创文章&#xff0c;版权声明&#xff1a;自由转载-非商用-非衍生-保…

升级nginx,查看已经安装的模块,并隐藏或者修改版本号

升级前&#xff0c;查看已经安装的版本以及模块[rootmail ~]# /opt/nginx/sbin/nginx -Vnginx version: nginx/0.5.34 built by gcc 3.4.6 20060404 (Red Hat 3.4.6-3)configure arguments: --prefix/opt/nginx --sbin-path/opt/nginx/sbin/nginx --conf-path/opt/nginx/conf/n…

SpringCloudAlibaba微服务docker容器打包和部署示例实战

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 概述 我们使用前面《SpringCloudAlibaba注册中心与配置中心之利器Nacos实战与源码…

MongoVUE的Collections数据不显示的解决方法

问题描述&#xff1a; 使用 mongoDB数据库&#xff0c; 数据添加成功了&#xff0c;使用命令行能查询出来&#xff0c;但在MongoVUE 中数据却不显示 (我使用的是 mongoDB 3.4 的版本) 原因&#xff1a;引擎问题&#xff0c;只要降到2.X版本就可以显示了     3.x默认是wire…

SaltStack WEB UI Halite初体验

闲来无聊&#xff0c;话说saltstack webui halite还一直没玩&#xff0c;于是就凑今天体验一把&#xff1b;很多尝鲜的同学都说halite的功能较少&#xff0c;而其也正符合其说明console&#xff0c;不过其UI我还是蛮喜欢的&#xff0c;个人觉得比较清新简洁、挺好下面就来安装体…

Envoy熔断限流实践(二)Rainbond基于RLS服务全局限流

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

TAppEncoder的main函数

TAppEncoder是编码器工程&#xff0c;完成视频序列的编码。 运行时&#xff0c;首先调用encmain.cpp中的main函数 main函数中完成的工作主要有初始化encoder类&#xff0c;解析cfg文件&#xff0c;然后调用TAppEncTop::encode函数进入下一层&#xff0c;并且对编码过程进行计时…

【大话云原生】微服务篇-五星级酒店的服务方式

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

如何在Web前端实现CAD图文字全文搜索功能之技术分享

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

基于Java (spring-boot)的仓库管理系统

一、项目介绍 本系统的使用者一共有系统管理员、仓库管理员和普通用户这3种角色: 1.系统管理员&#xff1a;通过登录系统后&#xff0c;可以进行管理员和用户信息的管理、仓库和物品分类的管理&#xff0c;以及操作日志的查询&#xff0c;具有全面的系统管理权限。 2.仓库管理…