xamarin.forms と web api による実践的クロスデ...

Post on 22-May-2020

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

本日のサンプルコードは後日公開します作業手順も暗記する必要はありません

ちょっと分量多めなので、少し(?)早口です

-クロスデバイス開発の必要性

iOS WinRTAndroid

Objective-C

Storyboard

Java

AXML

C#/VB

XAML

iOS ライブラリ .NET BCLAndroid ライブラリ

iOS Native API WinRT Native APIAndroid Native API

異なる言語 異なる

ツール

-Xamarin & Xamarin.Forms による解決

iOS WinRTAndroid

C#

Storyboard

C#

AXML

C#/VB

XAML

Xamarin.Forms

Portable Class Library(または Shared Asset Project)

C# で記述可能!

C#XAML

共有可能!

共有可能!

-Xamarin.Forms の向き・不向き

Xamarin.Forms が得意なアプリ Xamarin.Forms が苦手なアプリ

• アニメーションを多用• 複雑な UI 操作が必要• プラットフォーム固有処理が大量に必要

• 比較的シンプルな UI

• データ参照・更新が主体• プラットフォーム固有処理が比較的少ない

-具体例)データバインドアプリケーション

iPhone 6 (実機)

Nexus 7 2013 (実機)

iPad 2 (実機)

シングルコードマルチデバイス

-Hello World, Xamarin.Forms !

Hello World, Xamarin.Forms !

-Hello World, Xamarin.Forms !

PCL タイプの Xamarin.Forms プロジェクトを作成※手作業でソリューションファイルを組み立てることも可能

業務構造を意識した形で XAML ファイルを追加

ブートストラップコードが含まれるプロジェクト

Xamarin.Forms を利用する共有 PCL プロジェクト

-Hello World, Xamarin.Forms !

HelloWorldPage.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"

x:Class="Decode2015.MainPage"Title="メインメニュー">

<StackLayout><Button x:Name="btnBizA" Text="Hello World サンプル" />

</StackLayout>

</ContentPage>

<?xml version="1.0" encoding="utf-8" ?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"

xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

x:Class="Decode2015.BizA.HelloWorldPage"

Title="Hello World">

<StackLayout>

<Entry x:Name="entName" Text="Nobuyuki" /><Button x:Name="btnGetMessage" Text="メッセージ取得" />

<Label x:Name="lblMessage" />

</StackLayout>

</ContentPage>

MainPage.xaml

-Hello World, Xamarin.Forms !

public HelloWorldPage()

{

InitializeComponent();

btnGetMessage.Clicked += btnGetMessage_Clicked;

}

void btnGetMessage_Clicked(object sender, EventArgs e)

{

lblMessage.Text = "Hello World, " + entName.Text;

}

HelloWorldPage.xaml.cs

public MainPage()

{

InitializeComponent();

btnBizA.Clicked += btnBizA_Clicked;

}

void btnBizA_Clicked(object sender, EventArgs e)

{

Navigation.PushAsync(new BizA.HelloWorldPage());

}

MainPage.xaml.cs

-Hello World, Xamarin.Forms !

public class App : Application

{

public App()

{

this.MainPage = new NavigationPage(new MainPage());

}

}

C#

NavigationPage でページをラップすると...

ヘッダーが付与されるようになり、iOS でも前画面に戻れるようになる

-デバイスによる実行結果の差異について

-デバイスによる実行結果の差異について

XAML

<Label><Label.Text>

<OnPlatform x:TypeArguments="x:String" iOS="Hello World, iOS" Android="Hello World, Android" WinPhone="Hello World, WinPhone" />

</Label.Text></Label>

// 値を変えたい場合lblMessage.Text = Device.OnPlatform<string>(

"iOS", "Android", "WinPhone");

// 処理を分けたい場合Device.OnPlatform(

() => { lblMessage.Text = "iOS"; },() => { lblMessage.Text = "Android"; },() => { lblMessage.Text = "WinPhone"; }

);

C#① OnPlatform 属性の利用 ② Device.OnPlatform メソッドの利用

-WinRT XAML と Xamarin.Forms XAML の類似点と相違点

【主な類似点】

• XAML の基本的な構文• リソースデータの扱い• スタイルの考え方• データバインドの考え方• 主要なレイアウト部品や

UI 部品

【主な相違点】

• UI 部品やレイアウト部品の名前

• 主要プロパティの名前• 任意のコンテンツ合成や高度な UI 指定ができない

-Xamarin.Forms でどこまでの UI が開発できるのか?

-Xamarin.Forms アプリからのサーバ連携

Web サーバ各種の

DB サーバ

既存の各システム

XML 形式などのデータ

業務データ

Xamarin.Formsアプリケーション 開発!

-PCL におけるサービス参照について

• PCL プロジェクトでもサービス参照の機能は利用できるように見えるが...

• 実際に作成してみると、Android,

iOS では残念ながら動作しない

-スクラッチでのリモート通信開発

Web サーバ DB サーバ業務データ

クライアント

ツールベースの開発

通信手法

サービス参照(プロキシクラス)

SOAPWCF

(または *.asmx)

スクラッチでの開発 HttpClientXML または

JSONASP.NET Web API

こちらを利用!

-HttpClient + Web API + EF によるサーバアプリ開発

Web サーバ

pubsデータベース

Xamarin.Formsアプリケーション

データ転送オブジェクト(AuthorDTO)

Web API コントローラ(ListAuthors

WebApiController)

O/R マッパー(Pubs.dbml)

(ListAuthorsPage.xaml)

HttpClient

-HttpClient + Web API + EF によるサーバアプリ開発

• データ転送用の POCO (DTO) を別建てで PCL として定義

• サーバとクライアントの両方から参照設定して共有するWeb サーバ DB サーバ

業務データクライアント データ転送オブジェクト

iOS

Android

Xamarin

.FormsDTO

ASP.NET

Web API参照! 参照!

-HttpClient + Web API + EF によるサーバアプリ開発

開発機 Macintosh

Xamarin.iOS

Build Host シミュレータVisual Studio 実機

配置と実行

IIS Express 実機エミュレータ

仮想化環境

開発用 Web サーバ

エミュレータ/シミュレータ/実機いずれからもアクセスできない!

Azure Web サイト開発用 Web サーバやAzure Web サイトを使い、開発とテストを行う

HttpClient + Web API + EF によるサーバアプリ開発

-HttpClient + Web API + EF によるサーバアプリ開発

-HttpClient + Web API + EF によるサーバアプリ開発

public MainPage()

{

InitializeComponent();

btnBizA.Clicked += btnBizA_Clicked;

btnBizB.Clicked += btnBizB_Clicked;

}

void btnBizB_Clicked(object sender, EventArgs e)

{

Navigation.PushAsync(new BizB.ListAuthorsPage());

}

C#

<?xml version="1.0" encoding="utf-8" ?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"

xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

x:Class="Decode2015.MainPage"Title="メインメニュー">

<StackLayout><Button x:Name="btnBizA" Text="Hello World サンプル" />

<Button x:Name="btnBizB" Text="著者データ参照" />

</StackLayout>

</ContentPage>

MainPage.xaml

-HttpClient + Web API + EF によるサーバアプリ開発

-HttpClient + Web API + EF によるサーバアプリ開発

[DataContract]

public class AuthorDTO

{

[DataMember]

public string AuthorId { get; set; }

[DataMember]

public string AuthorName { get; set; }

}

C#

-HttpClient + Web API + EF によるサーバアプリ開発

[Route("BizB/ListAuthors/{action}")]

public class ListAuthorsWebApiController : ApiController

{

[HttpGet]

public List<AuthorDTO> GetAllAuthors()

{

... (完全なソースコードは次ページ参照)}

}

C#

重要!

[Route("BizB/ListAuthors/{action}")]

public class ListAuthorsWebApiController : ApiController

{

[HttpGet]

public List<AuthorDTO> GetAllAuthors()

{

using (pubsEntities pubs = new pubsEntities())

{

var query = from a in pubs.authors

select new AuthorDTO

{

AuthorId = a.au_id,

AuthorName = a.au_fname + " " + a.au_lname

};

return query.ToList();

}

}

}

C#

-HttpClient + Web API + EF によるサーバアプリ開発

-HttpClient + Web API + EF によるサーバアプリ開発

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"x:Class="Decode2015.BizB.ListAuthorsPage" Title="著者データ参照">

<StackLayout>

<ListView x:Name="lvwAuthors" RowHeight="60" VerticalOptions="FillAndExpand">

<ListView.ItemTemplate>

<DataTemplate>

<ViewCell>

<ViewCell.View>

<StackLayout Orientation="Vertical" Padding="0,6,0,0">

<Label Text="{Binding AuthorId}" FontAttributes="Bold" FontSize="18" />

<Label Text="{Binding AuthorName}" FontSize="18" LineBreakMode="TailTruncation" />

</StackLayout>

</ViewCell.View>

</ViewCell>

</DataTemplate>

</ListView.ItemTemplate>

</ListView><Button x:Name="btnGetAllAuthors" Text="データ取得" />

</StackLayout>

</ContentPage>

-HttpClient + Web API + EF によるサーバアプリ開発

public ListAuthorsPage()

{

InitializeComponent();

btnGetAllAuthors.Clicked += btnGetAllAuthors_Clicked;

}

async void btnGetAllAuthors_Clicked(object sender, EventArgs e)

{

string apiUrl = "http://decode2015webapi.azurewebsites.net/BizB/ListAuthors/GetAllAuthors";

HttpClient httpClient = new HttpClient();

HttpResponseMessage response = await httpClient.GetAsync(apiUrl);

string responseString = await response.Content.ReadAsStringAsync();

List<AuthorDTO> results = JsonDeserialize<List<AuthorDTO>>(responseString);

lvwAuthors.ItemsSource = results;

}

C#

-HttpClient + Web API + EF によるサーバアプリ開発

public static T JsonDeserialize<T>(string stringToDeserialize)

{

DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));

byte[] bytes = Encoding.UTF8.GetBytes(stringToDeserialize);

MemoryStream ms = new MemoryStream(bytes);

return (T)serializer.ReadObject(ms);

}

C#

-HttpClient + Web API + EF によるサーバアプリ開発

-アプリケーションアーキテクチャ上のポイント

-1. RESTful 型設計 vs RPC 型設計

商品発注サービス

カタログ管理サービス

注文伝票

注文結果伝票

サービス呼び出し

商品

口コミ

GET

PUT

DELETE

GET

PUT

DELETE

CRUD 処理RESTful 設計 RPC スタイル設計

業務アプリではこちらの方が設計しやすい

-1. RESTful 型設計 vs RPC 型設計

public class AuthorsController : ApiController

{

public List<Author> Get() { ... }

public Author Get(string authorId) { ... }

public void Put(Author authorToUpdate) { ... }

public void Post(Author authorToInsert) { ... }

public void Delete(string authorId) { ... }

}

C#

HTTP Verb 意味

GET READ

POST CREATE

PUT UPDATE

DELETE DELETE

-1. RESTful 型設計 vs RPC 型設計

-2. JSON vs XML

{"result":"Hello World Nobuyuki"}

簡単なデータならよいが、日付型や byte[] 型などの扱いは面倒

-2. JSON vs XML

string apiUrl = "http://decode2015webapi.azurewebsites.net/BizB/ListAuthors/GetAllAuthors";

HttpClient httpClient = new HttpClient();

httpClient.DefaultRequestHeaders.Accept.Add(

new MediaTypeWithQualityHeaderValue("text/xml"));

HttpResponseMessage response = await httpClient.GetAsync(apiUrl);

string responseString = await response.Content.ReadAsStringAsync();

C#

-WCF vs ASP.NET Web API

WCF ASP.NET Web API

API 設計スタイル RPC 型のみ自由(RPC 型、RESTful 型など)

メッセージフォーマット SOAP のみ

自由(XML、JSON など)

通信プロトコル自由(HTTP、TCP/IP など)

HTTP のみ

-WCF vs ASP.NET Web API

Web サーバ DB サーバ業務データ

クライアント

ツールベースの開発

通信手法

サービス参照(プロキシクラス)

SOAPWCF

(または *.asmx)

スクラッチでの開発 HttpClientXML または

JSONASP.NET Web API

要設計

-ASP.NET Web API + EF で開発する場合のテクニック

本日のランチセッションにて開催!

1. WinRT と Xamarin.Forms XAML の主な相違点2. ASP.NET Web API + EF の開発テクニック

-レイアウト部品の名称の違い

Xamarin.Forms WinRT

積み重ね StackLayout StackPanel

絶対座標 AbsoluteLayout Canvas

格子状 GridLayout Grid

相対座標 RelativeLayout (なし)

スクロール ScrollView ScrollViewer

枠線 Frame Border

サイズフィット (なし) Viewbox

-StackLayout の活用テクニック

Xamarin.Forms XAML

<ContentPage ...><StackLayout><Frame OutlineColor="Accent"> ... </Frame><ScrollView Orientation="Vertical" VerticalOptions="FillAndExpand"><StackLayout>... (表示する内容) ...

</StackLayout></ScrollView><Button x:Name="btnUpdate" Text="更新" BorderWidth="2" /><Button x:Name="btnGoBack" Text="前の画面に戻る" BorderWidth="2" />

</StackLayout></ContentPage>

FillAndExpand

余白いっぱいに引き伸ばす

-UI 部品の名前の違い

Xamarin.Forms WinRT の場合は...

ActivityIndicator ProgressRing

BoxView Rectangle

Button Button

DatePicker DatePicker

Editor TextBox

Entry TextBox

Image Image

Label TextBlock

ListView ListView

Xamarin.Forms WinRT の場合は...

Map BingMaps

Picker ComboBox

ProgressBar ProgressBar

Slider Slider

Switch ToggleButton

TimePicker TimePicker

WebView WebView

- CheckBox

- GridView

-主要プロパティの名前の違い

WinRT Xamarin.Forms

余白制御 Margin Padding

位置制御 VerticalAlignment/HorizontalAlignment VerticalOptions/HorizontalOptions

前景色 Foreground TextColor など

背景色 Background BackgroundColor/BackgroundImage など

データバインド DataContext BindingContext

-データアノテーションを利用した単体入力エラーチェック

[DataContract]

public class FindAuthorRequestDTO

{

[DataMember]

[Required]

[RegularExpression(@"^[0-9]{3}-[0-9]{2}-[0-

9]{4}$")]

public string AuthorId { get; set; }

}

C#

[HttpPost]

public AuthorDetailDTO

FindAuthor(FindAuthorRequestDTO request)

{

if (ModelState.IsValid == false) throw new

HttpResponseException(HttpStatusCode.BadRe

quest);

....

}

C#

-EF エンティティデータモデルのシリアル化

-EF エンティティデータモデルのシリアル化

public string Property(EdmProperty edmProperty){

return string.Format(..., "[System.Runtime.Serialization.DataMember]¥r¥n{0} {1} {2} {{ {3}get; {4}set; }}",...);

}

public string NavigationProperty(NavigationProperty navProp){

...return string.Format( ..,

"[System.Runtime.Serialization.DataMember]¥r¥n{0} {1} {2} {{ {3}get; {4}set; }}", ...);}

public string EntityClassOpening(EntityType entity){

return string.Format(...,"[System.Runtime.Serialization.DataContract(IsReference = true)]¥r¥n {0} {1}partial class {2}{3}", ...);

}

Pubs.tt

i.

ii.

iii.

-3 種類の POCO オブジェクトの使い分け

DAC

データベース

*.edmx

SI + BC

ASP.NET Web API

API Controller

POCO

(エンティティ)

BEC

ADO.NET

Entity Framework

POCO

(DTO)

BEC

SA

HttpClient

BC

サーバ呼び出しロジック

Xamarin

.Forms

*.xaml

*.xaml.cs

コードビハインド

POCO

(ViewModel)

UI

-3 種類の POCO オブジェクトの使い分け

ViewModel DTO エンティティモデル

内容 • 双方向データバインドの実装に利用する • データの転送に利用する• 上り電文と下り電文とで別の DTO が利用される

• Entity Framework によるデータベースからのデータ取得に利用する

特徴 • UI に併せて最適化されて定義される• 入力で期待するデータの型と、POCO 上に定義されるデータ型がずれることがある

• データ入力チェックのために、データアノテーションが利用される

• エラー検証などのために、特定の基底クラスから派生して作られることが多い

• シリアル化のために、[DataContract] 属性が利用される

• サーバ側でのデータ入力チェックのために、データアノテーションが利用される

• データベース構造に併せて定義される• 遅延ローディング機能などを有効にするために、多くのプロパティが virtual 定義されている

• EF から読み取ったデータはそのままではシリアル化できない

• データベースからリバースして作った場合には、データアノテーション定義がない

データ構造 UI に最適化 通信に最適化 DB 構造に最適化

データアノテーション

○ (UIに最適化) ○ (上り電文のみ) △ (DB構造に最適化)

シリアル化 × (不要なことが多い) ○ (必須) × (既定ではシリアル化不可)

-3 種類の POCO オブジェクトの使い分け

top related