XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2016/07/15

Xamarin.Forms Web 服務存取 RESTful Web API & WCF

Web 服務存取

在這個範例專案中,將會實作 RESTful Web API 與 WCF 這兩種 Web 服務的呼叫方式。
在這裡,網路上提供了兩個Web 服務的網址:
這兩個 Web 服務都會把傳入的兩個整數相加,並且把相加的結果,回傳回來。

建立標籤式的樣板式頁面方案

  1. 首先,開啟您的 Visual Studio 2015
  2. 接著透過 Visual Studio 2015 功能表,選擇這些項目 檔案 > 新增 > 專案 準備新增一個專案。
  3. 接著,Visual Studio 2015 會顯示 新增專案 對話窗,請在這個對話窗上,進行選擇 Visual C# >Cross-Platform > Blank Xaml App (Xamarin.Forms Portable)
  4. 接著,在最下方的 名稱 文字輸入盒處,輸入 XFWebSrv 這個名稱,最後使用滑鼠右擊右下方的 確定按鈕。
  5. 當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到 Xamarin Mac Agent Instructions 對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。
  6. 接著會看到 新的通用Windows專案 對話視窗,此時,您只需要按下 確定 按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。
  7. 最後,整個新的 Xamarin.Forms 專案就建立完成了。

WCF 的事前準備

了解 PCL profile

在 Xamarin.Forms 內,想要呼叫 WCF Web 服務,需要先建立出 WCF 代理 (Proxy),之後就可以透過 WCF 代理還呼叫 WCF 服務提供的各項方法。因此,加入 WCF 的方法是在專案內的 參考 節點上,使用滑鼠右擊,透過 加入服務參考 選項,把 WCF 位址輸入到 加入服務參考 對話窗內。
可是,當您在 核心PCL 專案內的 參考 節點上,使用滑鼠右擊,卻沒有看到 加入服務參考 選項可以選擇。
核心PCL的參考功能表
這是因為 核心PCL 是 可移植類別庫 (Portable Class Library),也就是說,為了要讓這個類別庫可以支援更多的平台專案可以使用,因此,在 PCL 專案內,把許多無法跨平台的 API 或者功能,將無法使用。而在 PCL 內,有個欄位 TargetFrameworkProfile 定義了 PCL 的設定檔(Profile)資訊(您可以開啟 XFWebSrv.csproj 檔案茶看到),如下圖所示。
現在(Visual Studio 2015 with Update 2),若是透過 Visual Studio 專案樣版建立的 Xamarin.Forms 跨平台專案,其產生的核心PCL專案,使用的是 Profile111 設定檔;而這個 Profile111 PCL 設定檔內,是不提供 WCF Proxy 支援的。
XFWebSrv.csproj內的PCL版本Profile111
更多關於 PCL 不同設定檔案資訊,可以參考底下連結

解決方案1 利用原生專案

  • 雖然 核心PCL 專案內無法產生與建立 WCF 代理,不過,原生 Android 與 iOS 專案內,卻可以支援
  • 因此,您可以在原生專案內的 參考 節點上,使用滑鼠右擊,就會看到 加入 Web 參考 這個選項,透過這項功能,就可以產生 WCF 代理。
    XFWebSrv.Droid的參考功能表

解決方案2 建立新 類別庫(可攜式)

  • 在方案 XFWebSrv 節點上滑鼠右擊,選擇 加入 > 新的專案 > Visual C# > 類別庫(可攜式) ,接著在下方名稱欄位旁的文字輸入盒,輸入 XFWCFPCL
    千萬注意,不可以選擇 類別庫 (可移植到 iOS、Android、Windows) 這個類別庫
  • 當出現 加入可攜式類別庫 對話窗,點選 確定 按鈕
    加入可攜式類別庫
  • 在 XFWCFPCL 專案內,滑鼠右擊 參考 節點,選擇 加入服務參考 選項
    XFWCFPCL加入服務參考
  • 當 加入服務參考 對話窗出現的時候,在位置欄位,輸入http://wcfservice120160626121524.azurewebsites.net/Service1.svc,接著點選 移至 按鈕,確認所要定義的命名空間,最後按下 確定 按鈕,產生 WCF Proxy Class
    加入服務參考1
  • 滑鼠右擊 XFWCFPCL 專案節點,選擇 加入 > 類別 選項,在名稱欄位文字輸入盒中填入WCFServiceBase,接著按下 確定 按鈕
  • 將底下程式碼複製到這個檔案內。
  • WCFServiceBase 這個類別將會透過相依性服務注入的方式,讓核心PCL專案可以使用這個 WCF 功能。
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace XFWCFPCL
{
    public class WCFServiceBase
    {
        public Task<int> Sum(int v1, int v2)
        {
            TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();

            var binding = new BasicHttpBinding()
            {
                Name = "basicHttpBinding",
                MaxReceivedMessageSize = 67108864,
            };

            var timeout = new TimeSpan(0, 1, 0);
            binding.SendTimeout = timeout;
            binding.OpenTimeout = timeout;
            binding.ReceiveTimeout = timeout;

            var client = new ServiceReference1.Service1Client(binding, new EndpointAddress("http://wcfservice120160626121524.azurewebsites.net/Service1.svc"));
            client.GetSumDataCompleted += (s,e) =>
            {
            };
            client.GetSumDataAsync(v1, v2);
            return tcs.Task;
        }
    }
}

MainPage

  • 當上述準備工作已經就緒,接下來就可以開始在核心PCL專案內寫相關商業邏輯程式碼了。
  • 打開核心PCL 的 MainPage.xaml 檔案,將底下的 XAML 宣告定義複製到這個檔案內。
  • 這個頁面宣告內容相當簡單,使用版面配置 StackLayout 將其包含的控制項,以垂直的方式排列
  • 共有兩個按鈕,一個是呼叫 RESTful Web API,另外一個是呼叫 WCF,他們皆會先從 Entry 控制項中取得使用者所輸入的整數值,經會 Web 服務計算過後,將計算後的值,顯示在 Label 控制項內
  • Entry 控制項內,使用了 Keyboard 屬性,定義使用者只能夠輸入數字。

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XFWebSrv"
             x:Class="XFWebSrv.MainPage">

  <ContentPage.Padding>30</ContentPage.Padding>

  <StackLayout
    Orientation="Vertical"
    >

    <Entry x:Name="entryValue1" Keyboard="Numeric" Text="168" />
    <Entry x:Name="entryValue2" Keyboard="Numeric" Text="99" />

    <Label x:Name="labelRESTful" />
    <Button x:Name="buttonRESTful" Text="呼叫 RESTful" Clicked="OnRESTfulClicked" />

    <Label x:Name="labelWCF" />
    <Button x:Name="buttonWCF" Text="呼叫 WCF" Clicked="OnWCFClicked" />

  </StackLayout>

</ContentPage>
  • 請將下列 C# 程式碼複製到 MainPage.xaml.cs內。
  • 在建構式內,使用了 MessagingCenter 訂閱了一個訊息事件,也就是當使用者有選擇某個日期之後,其相對應的 callback 就會執行,在這裡,將會取出透過訊息中心所傳遞過來的日期參數,並且將其顯示在指定 Label 上。
  • 在 掃描QRCode 按鈕事件內, 使用了相依性注入服務 DependencyService 取得當時行動平台實作的 QRCode 掃描物件,並且呼叫 ScanAsync 這個方法,取得QRCode掃描結果,並且顯示到指定的Label
  • 在 選擇日期 按鈕事件內,則是透過 Navigation.PushModalAsync 方法,開啟一個對話窗頁面,該頁面為 CalendarPage

MainPage.xaml.cs

  • OnRESTfulClicked
    這個按鈕事件,展示了如何呼叫 RESTful Web API 的方式,透過 HttpClient物件的 GetStringAsync 的非同步方法。
  • OnWCFClicked
    這個按鈕事件,展示了如何呼叫 WCF 的方式,透過 DependencyService.Get 靜態方法,取得在該行動裝置平台下實作的物件,並且呼叫實作的 Sum() 方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace XFWebSrv
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        async void OnRESTfulClicked(object sender, EventArgs e)
        {
            var fooURL = $"http://doggyrestfulapi.azurewebsites.net/api/SumData?value1={entryValue1.Text}&value2={entryValue2.Text}";
            var fooClient = new HttpClient();
            var fooResult = await fooClient.GetStringAsync(fooURL);
            labelRESTful.Text = $"透過 RESTful API 計算出的結果 : {fooResult}";
        }

        async void OnWCFClicked(object sender, EventArgs e)
        {
            int v1 = int.Parse(entryValue1.Text);
            int v2 = int.Parse(entryValue2.Text);
            int v3 = await DependencyService.Get<IWCFService>().Sum(v1, v2);
            labelWCF.Text = $"透過 WCF 計算出的結果 : {v3}"; ;
        }
    }
}

相依性服務定義

核心PCL

  • 請在 XFWebSrv 核心PCL 專案節點使用滑鼠右擊該節點,選擇 加入 > 類別,當 加入新項目 - XFWebSrv 對話窗出現後,點選 Visual C# > 類別,最後在下方名稱欄位的文字輸入盒內,輸入IWCFService
  • 請將底下 C# 程式碼複製到這個檔案內。

IWCFService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFWebSrv
{
    public interface IWCFService
    {
        Task<int> Sum(int v1, int v2);
    }
}

Android 專案

  • 請在 XFWebSrv.Droid 專案下的 參考 節點,使用滑鼠右擊該節點,選擇 加入參考,當 參考管理員 - XFWebSrv.Droid 對話窗出現後,點選 專案 > 方案,最後勾選 XFWCFPCL
    加入XFWCFPCL參考
  • 請在 XFWebSrv.Droid 專案節點使用滑鼠右擊該節點,選擇 加入 > 類別,當 加入新項目 - XFWebSrv.Droid 對話窗出現後,點選 Visual C# > Class,最後在下方名稱欄位的文字輸入盒內,輸入 WCFService
  • 請將底下 C# 程式碼複製到這個檔案內。

WCFService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using XFWCFPCL;
using XFWebSrv.Droid;

[assembly: Xamarin.Forms.Dependency(typeof(WCFService))]
namespace XFWebSrv.Droid
{
    public class WCFService : WCFServiceBase, IWCFService
    {
    }
}

iOS 專案

  • 請在 XFWebSrv.iOS 專案下的 參考 節點,使用滑鼠右擊該節點,選擇 加入參考,當 參考管理員 - XFWebSrv.Droid 對話窗出現後,點選 專案 > 方案,最後勾選 XFWCFPCL
    加入XFWCFPCL參考
  • 請在 XFWebSrv.iOS 專案節點使用滑鼠右擊該節點,選擇 加入 > 類別,當 加入新項目 - XFWebSrv.iOSDroid 對話窗出現後,點選 Apple > 類別,最後在下方名稱欄位的文字輸入盒內,輸入WCFService
  • 請將底下 C# 程式碼複製到這個檔案內。

WCFService.cs

using System;
using System.Collections.Generic;
using System.Text;
using XFWCFPCL;
using XFWebSrv.iOS;

[assembly: Xamarin.Forms.Dependency(typeof(WCFService))]
namespace XFWebSrv.iOS
{
    public class WCFService : WCFServiceBase, IWCFService
    {
    }
}

實際執行畫面

Android 執行結果

請在方案總管內,滑鼠右擊 XFWebSrv.Droid 專案,選擇 設定為起始專案,接著按下 F5 開始執行。
Android執行結果1

佈署注意事項

iOS 執行結果

請在方案總管內,滑鼠右擊 XFWebSrv.iOS 專案,選擇 設定為起始專案,接著按下 F5 開始執行。
iOS執行結果1

沒有留言:

張貼留言