程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 【ASP.NET Web API教程】3.3 通過WPF應用程序調用Web API(C#),

【ASP.NET Web API教程】3.3 通過WPF應用程序調用Web API(C#),

編輯:C#入門知識

【ASP.NET Web API教程】3.3 通過WPF應用程序調用Web API(C#),


參考頁面:

http://www.yuanjiaocheng.net/ASPNET-CORE/core-static-files.html

http://www.yuanjiaocheng.net/ASPNET-CORE/setup-mvc.html

http://www.yuanjiaocheng.net/ASPNET-CORE/mvc-design-pattern.html

http://www.yuanjiaocheng.net/ASPNET-CORE/mvc-routing.html

http://www.yuanjiaocheng.net/ASPNET-CORE/attribute-route.html

注:本文是【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包管理器,按如下步驟安裝。

上述安裝過程如圖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客戶端庫包添加到你的項目。步驟如下:

上述安裝步驟如圖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方法。

看完此文如果覺得有所收獲,懇請給個推薦

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved