ASP.NET CoreでWebSocketを使用するサンプルを作ってみたよ( `ー´)ノ
ごあいさつ
新年あけましておめでとうございます。
2017年もよろしくお願いします。
正月太り(´ ・ ω ・ `)
本題
SignalRではなくASP.NET CoreでWebSocketを使ったサンプルアプリを書いてみました。
今回作ったコードはこちらにあります。
ASP.NET CoreでWebSocketサーバを作るには
を使用すれば簡単に作成することができます。
今回のサンプリアプリはクライアントサイドにはVue.jsを使用しています。
解説
完成品の動き
アクセスしたらユーザ名の入力を行って接続を行います。
接続後にチャットで発言を行うと他のクライアントにも表示されてチャットができます。
接続、切断したユーザがいる場合にはその都度メッセージが送信されます。
参考にしたサイト
基本的にここに書かれている通りに作っていけばよい感じです。
ASP.NET CoreでVue使う場合にどうすればよいか考えるのに参考にしました。
使用したnugetパッケージ
- Microsoft.AspNetCore.WebSockets.Server
- Microsoft.AspNetCore.StaticFiles
- System.Reactive
- Newtonsoft.Json
サーバサイド
基本的に前述の参考サイトの通りに作成します。
今回はChatClientクラス ChatServerクラスの2クラスで構成しました。
ChatClientクラス
aspnetcore_webspcket_sample/ChatClient.cs at master · yuka1984/aspnetcore_webspcket_sample · GitHub
System.Net.WebSockets.WebSocketクラスを内包してクライアントとの通信を行うクラスです。
RecieveJoinAsyncでチャット参加メッセージを受け取って、RecieveAsyncでチャットメッセージを継続して受け取ります。
WebSocketのRecieveAsyncメソッドの引数にArraySegmentが使用されています。
WebSocketってプロトコルの仕様上メッセージが分割されることがあるのですが、連続してデータを取得しやすくするためにArraySegmentを使用してバッファ内でセグメント毎に受信します。
単純なテキストメッセージで分割するようなパターンってないと思いますが。
今回はObserver/Observableパターンで送信と受信を実装を行ってみました。
RecieveAsync中に受信したメッセージはIObservable.Subscribeにて購読を行っている人に配信されて、WebSocketがクローズされた場合にはOnCompleteが流れるて購読が解除される形になります。
OnNextが呼ばれるとメッセージをクライアントに送信します。
次にIObserver/IObservableをどのように利用しているかを見てみます。
ChatServerクラス
aspnetcore_webspcket_sample/ChatServer.cs at master · yuka1984/aspnetcore_webspcket_sample · GitHub
public void Map(IApplicationBuilder app) { app.UseWebSockets(); app.Use(Acceptor); }
マップ関数にてIApplicationBuilderへの登録を行っていてリクエストが来た時にAcceptor関数が実行されます。
Accepter関数はTask型になっていますが、この関数が終了するとHttpリクエストが返答されて終了します。
WebSocket接続だった場合にはクローズされます。
ですのでWebSocketを繋ぎっぱなしにしておくにはawaitで留まっている必要があります。
Accepter関数はこのようになっているのですが
まず最初にWebSocketリクエストなのかを判定しています。
そうでなかった場合はMiddlewareチェインの次を実行して関数を終了しています。
これは別にチェインの次を実行する必要はなくてhttpcontextのResponseにステータスコード400を指定してBadReqestにして終了してしまったりしてもOKです。
WebSocketリクエストであった場合には AcceptWebSocketAsyncを実行してWebSocketクラスを取得します。
このWebSocketクラスを使用して、先ほど説明したChatClientクラスを作成します。
ChatClient.RecieveJoinAsyncを実行してチャット参加メッセージを受信します。
参加がOKだった場合には接続中のクライアントに新規参加メッセージを送信し、クライアント間での接続を行っています。
// ほかのクライアントと相互接続 x.Subscribe(client); client.Subscribe(x);
この部分でIObserver/IObservableパターンが活きています。
クライアント間でお互いに購読登録を行うことで、メッセージストリームが流れた時にそのまま送信が行われます。
今回はそのままお互いにSubscribeしていますが、例えばWhereをいれて流れるメッセージを制御したりSelectでメッセージを調整したり色々な事が出来たりします。
Reactiveプログラミング面白い(^^)/
相互接続が完了したら受信待機します。
これだけでサーバ側でチャットが成り立ってしまいます(^◇^)
aspnetcore_webspcket_sample/Startup.cs at master · yuka1984/aspnetcore_webspcket_sample · GitHub
あとはStartupクラスでmiddlewareの登録を行ってあげればOKです。
クライアントサイド
aspnetcore_webspcket_sample/index.html at master · yuka1984/aspnetcore_webspcket_sample · GitHub
このファイル一つです。さぼってhtmlファイルの中にコードも書いちゃいました。
Vue.jsとかbootstrapとか取り込んでいる部分は前述の参考サイトを見てください。
実際のスクリプトはこんな感じです。
あんまり工夫もなくoldなJavaScriptな感じで大変申し訳ないです。
新しめのJavaScriptは今勉強中です。
Htmlはこんな感じ。
結構良い感じで書けます。
Vue.jsって凄くよくできてて感心してます。
今回はあまり使っていませんがC#のMVVMでReactivePropertyを使用したパターンをVue.jsだけで実現できる感じなんですよね。
今回は以上です。 ではでは(^^)/
ASP.NET MVCでVue.jsを使用するWeb開発環境を作って動かしてみよう('ω')ノ
ごあいさつ
年末ですね。皆さんはいかがお過ごしでしょうか。
今年もクリスマスとかいう私には縁の無いイベントを無事何事もなく家で寝て過ごし、来年に向けて断捨離を進めなければいけないのに全く進まず、色々とやってみたい事だけが溜まっていって一つも消化できていない、そんな年末を過ごしています\(^o^)/
はじめに
最近。WebフロントエンドとAzure Mobile AppとAzure Functionsの組み合わせでついぶくというサービスを作っていて今はWebフロントエンドの勉強などをしています。
4年くらい前で止まっていたWebフロントエンドの知識を、今時な?Webフロントエンドな知識に更新することが一つの目標です。
暫くはサービス開発で得た知識を記事にしていきたいと思います。
今回はVisualStudio2015でASP.NET WebAPIプロジェクトにてVue.js + Bootstrapな開発環境の構築を行ってみたいと思います。
インストール関連
まずはnode.jsをインストールします。VS2015にてnode.jsをインストールすることも可能なのですがバージョンが古くて(´・ω・`)なので最新版を入れてしまいます。
コマンドプロンプトにてnode -vを実行してインストールを行ったnodeバージョンが出ればOKです。
次にVisual Studioを開き[ツール]-[オプション]-[プロジェクトおよびソリューション]-[外部Webツール]にて
PATHの順位を一番に持っていきます。
さらに[ツール]-[拡張機能と更新プログラム]にて NPM Task Runnerをインストールします。
さらにWeb Compilerをインストールします。
プロジェクト作成
まずはWeb APIプロジェクトを作成します。
次のBundle処理の削除と余分なnugetパッケージの削除を行います。
BundleConfigクラスのRegusterBundle関数内をコメントアウトしてしまってください。
nugetパッケージマネージャにて以下のパッケージを削除します。
- bootstrap
- jquery
- Modernizr
- Respond
次にViews/Shared/_Layout.cshtmlにてBundleしたファイルの読み込みコードを削除してしまいます。
この状態にてデバッグを開始すると
スタイルがない状態になります。
Bootstrapの組み込み
今回はBootstrapをそのまま使うのではなく
を適用して、さらにscssにてスタイルの管理を行えるようにしてしまいます。
方法はこちらの記事を参考にしました。
まずはpackge.jsonをプロジェクトに追加します。
中身はこんな感じ
{ "version": "0.0.0", "name": "vuesample", "private": true, "devDependencies": { "grunt": "~0.4.5", "grunt-bower-task": "~0.4.0" } }
package.jsonはnpmというnode.js版nuget的なパッケージ管理ツールの設定を記述するためのファイルです。
作成しましたらタスクランナーエクスプローラよりInstallを実行します。
ここから表示できます。
次にbower.jsonファイルをプロジェクトに追加します。
bowerはWebフロントエンドに特化したパッケージマネージャーです。
bower.jsonはその設定ファイルになります。
中身はこんな感じ
{ "name": "VueSample", "private": true, "dependencies": { "jquery": "^3.1.1", "bootstrap-sass": "3.3.7", "Honoka": "^3.3.7" }, "exportsOverride": { "jquery": { "js": "dist/*.*" }, "bootstrap-sass": { "bootstrap.scss": "assets/stylesheets/bootstrap", "bootstrap.fonts": "assets/fonts/bootstrap/*.*", "js": "assets/javascripts/bootstrap.*" }, "Honoka": { "honoka.scss": "scss", "honoka.css": "dist/css", "honoka.font": "dist/fonts", "honoka.js": "dist/js" } } }
exportsOverrideという設定が重要です。 これにより各パッケージのファイルを、展開用にグループ分けしています。
次にgrundfile.jsというJavaScriptファイルをプロジェクトに追加します。
中身はこんな感じ
/// <binding /> module.exports = function (grunt) { grunt.initConfig({ bower: { install: { options: { targetDir: "", cleanTargetDir: false, layout: function (type, component, source) { if (type === "js") { return "Scripts"; } else if (type === "honoka.scss") { return "Content"; } else if (type === "bootstrap.scss") { return "Content/honoka/bootstrap"; } else if (type === "bootstrap.fonts") { return "fonts"; } else { return "__untyped__"; } } } } } }); grunt.registerTask("default", ["bower:install"]); grunt.loadNpmTasks("grunt-bower-task"); };
先ほどbower.jsonのexportsOverrideにて設定したグループごとにレイアウトを設定しています。
これによりreturnで返答しているフォルダにファイルが展開されます。
タスクランナーエクスプローラよりgruntfile.jsのbower:installを実行してください。
もしoperation not permitted, mkdir というエラーが出ていたら手作業でフォルダを作成して再度実行してください。
これらのファイルをプロジェクトに取り込みたいのでcsprojファイルを少し修正します。
csprojファイルをエディタで開いて以下を追加します。
<Content Include="Content\**\*.scss" /> <Content Include="Scripts\**\*.js" /> <Content Include="Scripts\**\*.map" /> <Content Include="fonts\**\*.*" />
これによりプロジェクトツリーのContentフォルダ下にbootstrap.scssファイルが追加されていますので右クリックしてコンパイルをしてみてください。
cssファイルが出来上がっていると思います。
ではViews/Shared/_Layout.cshtmlファイルに作成したcssファイルを指定してデバッグを実行します。
これでようやくスタイルが適用できた状態です。
ここからVue.jsの組み込みと簡単なコーディングを行っていきます。
Vue.jsの組み込み
まずは先ほど作成したpackage.jsonに追記を以下のように行ってください。
"version": "0.0.0", "name": "vuesample", "private": true, "dependencies": { "vue": "^2.1.7", "vue-route": "^1.5.1" }, "devDependencies": { "webpack": "^1.14.0", "webpack-dev-middleware": "^1.9.0", "webpack-hot-middleware": "^2.13.2", "webpack-merge": "^2.0.0", "babel-core": "6.21.0", "babel-loader": "6.2.10", "babel-preset-es2015": "^6.13.2", "grunt": "~0.4.5", "grunt-bower-task": "~0.4.0" }, "scripts": { "webpack": "webpack -d" } }
webpackというツールとbabelというツールのインストール、Vue.jsのインストールを行う設定を追記しました。
webpackは色々なライブラリを参照追加して作成したコードをコンパイルしてブラウザで実行できるスクリプトにしてくれるツールです。
それだけでなくスタイルとか画像とか色々と凄い事をしてくれるのですが詳しくは調べてみてください。
babelは新しい書き方をしているJavaScriptを古い形(ブラウザが理解できる形)にコンパイルしてくれるツールです。
追記後タスクランナーエクスプローラからpackageのインストールを行ってください。
次にプロジェクトにwebpack.config.jsというファイルを追加します。
中身は以下のようにしてください、
var path = require('path'); module.exports = { resolve: { root: path.resolve('./'), alias: { 'vue$': 'vue/dist/vue.common.js' } }, entry: { home: 'VueModels/home/Index.js' }, output: { path: "Scripts/app", filename: "[name].bundle.js" }, themeLoader: { themes: ['./node_modules/vuestrap/theme/bootstrap.scss'], // docs theme, default bootstrap }, module: { loaders: [{ test: /\.js$/, loader: 'babel' }, { test: /\.html$/, loader: 'html' }, { test: /\.json$/, loader: 'json' }] } };
次にプロジェクトに以下の画像のようにVueModelsフォルダ、その下にHomeフォルダを作成し、HomeフォルダにIndex.jsファイルを作成してください。
中身はこのような感じにしてください。
var Vue = require('vue'); var model = { message: "ASP.NET MVCでVue.jsを使用するWeb開発環境を作って動かしてみよう('ω')ノ" }; new Vue({ data: model, }).$mount('#app');
そうしたらタスクランナーエクスプローラからpackage.json/Custom/Webpackを実行してください。
もしWebPackというタスクがないのであればVisualStudioを再起動してみてください。
するとScriptsフォルダの下にapp/home.bundle.jsというファイルが作成されているかと思います。
これがIndex.jsをwebpackでコンパイルしてブラウザで使用できる形にしたファイルです。
Viewを修正して動かしてみましょう。
まずは_layout.cshtmlを修正します。
- classにContainerが設定されているdivタグにid=appを追加
- Script.Renderでコントローラ名.bundle.jsファイルを追加
次にHome/Index.cshtmlを修正します。
Jumbotronの中のPタグの中身を{{message}}と書き換えます。
これでデバッグ実行すると
とVueクラスとhtmlがバインドされるようになります。
ちょっとプログラムしてみよう
では、ちょっとそれっぽくプログラムしてみましょう。
ですがその前に、開発しやすくするためのタスクを追加します。
package.jsonを開きscriptsに"watch": "webpack -d -w"を追加しタスクランナーエクスプローラで実行します。
これを実行するとindex.jsファイルを監視し変更があった場合に自動的にビルドを行ってくれるようになります。
まずはIndex.jsをこのように修正してみましょう。
var Vue = require('vue'); var model = { message: "ASP.NET MVCでVue.jsを使用するWeb開発環境を作って動かしてみよう('ω')ノ", speakers:[] }; new Vue({ data: model, methods: { LoadSpeakers: function() { fetch("http://demo4404797.mockable.io/speakers") .then(function (response) { return response.json(); }) .then(function (json) { model.speakers = json; }); } } }).$mount('#app');
modelクラスにspeakersというプロパティを追加します。speakersは配列として宣言しておきます。
次にvueクラスにmethodsを追加しLoadSpeakersメソッドを追加します。
LoadSpeakersメソッドではfetchを使ってWebAPIにアクセスしてjsonを取得してmodelクラスのspeakersにセットします。
http://demo4404797.mockable.io/speakersにアクセスすればjsonを確認することができます。
次にIndex.cshtmlを修正します。
<div class="jumbotron"> <h1>ASP.NET</h1> <p class="lead">{{message}}</p> <p><button v-on:click="LoadSpeakers" class="btn btn-primary btn-lg">Get Speakers »</button></p> </div> <div class="row"> <div class="media" v-for="speaker in speakers"> <a class="media-left"> <img style="width: 128px" class="media-object" v-bind:src="speaker.Avatar"> </a> <div class="media-body"> <h4 class="media-heading">{{speaker.Name}} ({{speaker.Title}})</h4> {{speaker.Description}} </div> </div> </div>
jumbotron内にあったaタグをbuttonタグに書き換えてv-on:click="LoadSpeakers"を追加します。
これによりボタンがクリックされた場合には先ほどのLoadSpeakersメソッドが呼ばれます。
次にjumbotronに続くrowの中身をすべて消しmedia objectを追加します。
media objectはbootstrapのLayoutで画像付きの紹介文を書いたりするのに適しています。
mediaクラスを設定したdivタグにv-forアトリビュートを追加し speakersプロパティをループするように設定します。 これによりリストレンダリングを行うことができます。
子要素ではimgタグにv-bind:srcで画像アドレスをバインド、h4タグには名前や役割を表記、説明文にはDescriptionをバインドさせました。
では、デバッグ実行してみましょう。
ボタンを押してLoadSpeakersが実行されると
このような感じになると思います。
おしまいに
私自身始めたばっかりで全然知識が追い付いていない状態ですが、特に環境構築に関しては苦労しています。
この先VSでもWebフロントエンド開発が行いやすいように色々と進化していってくれると嬉しいなぁと思います。
ではよいお年を( `ー´)ノ
ついぶくテストにご協力いただいている方へ
ごあいさつ
クリスマスイブですね\(^o^)/
本題
仕様変更に関して
ついぶくテストにご協力いただいている皆様、本当にありがとうございます。
この度まとめツイートをツイートする方法を変更いたします。
こちらのアカウントよりユーザ様へメンションツイートにてまとめツイートを行います。
いったんユーザ様へメンションツイートを行い拡散を行うかはユーザ様に判断して頂きRTを行ってください。
この変更はついぶくアカウントをフォローした場合に適用されます。
フォローを行わなかった場合には、これまでと同様にユーザ様のツイートとしてまとめツイートを行います。
変更理由
7時に一斉にまとめツイートを行うという仕様はTLを荒らしがちになってしまうため。
以上、よろしくメリークリスマス('ω')ノ🎁🎄
ついぶくを公開しました。
ごあいさつ
断捨離が全然進みません(´・ω・`)
ついぶく
私事で大変恐縮なのですが
このたび「ついぶく」というサービスを試験リリースいたしました。
どういうサービスかと言いますと
1日のツイートの中からリンクを抽出してまとめページを作成してくれるサービスです。
サービスに参加すると朝7時頃にこのようなツイートが行われます。
12月20日のツイートをまとめたよ('◇')ゞhttps://t.co/TkWwWEtMso
— ゆうか🍣=3 🍣=3 🍣=3 (@yu_ka1984) 2016年12月20日
でリンクに飛んでみてもらえればわかるのですがツイート中からリンクを抽出し簡単にまとめてあります。
これだけのサービスです。
作成の経緯
理由1
私は結構ツイ廃なので1日に沢山ツイートします。
その中には技術的な調べ物をしていてそのリンクをツイートしたりしたものも含まれてます。
そんな中で1日単位くらいでまとめておけると楽だなぁというのが1つ目の理由です。
理由2
それだけだとはてブを使用すれば良いのですが
例えば
キュレーション活動としてフォローしている方に定期的に公開したいようなケースでははてブは少し使いづらいかな、という面があります。
ということでただツイートしていれば自動でまとめてくれるサービスがあったらなぁと思ったのが2つ目の理由です。
理由3
現在はWebフロントエンド技術の知識更新作業を行っているので勉強用にサービスを作りたかった。
Azure Functionsの勉強をするためにFunctionsを使用するサービスを作りたかった。
クラウド環境でのサービスデプロイに関して勉強するためにサービスを作りたかった。
以上の理由によりサービスの作成を行っています。
試験に協力して頂けるユーザさんを募集しています。
現時点で試験段階です。10人程度ユーザさんが使っていただけれるとうれしいかなぁとか思っています。
ただまだまだプログラム書いただけ~みたいな段階ですので色々と不具合も出てしまうかもしれません。
よく記事等のリンクをツイートされる方で協力して頂ける方がおりましたら、以下のサイトから登録してくれると嬉しいです。
ついぶく登録
https://yukasantestnet.azurewebsites.net/
こちらのサイトに移動するとツイッター認証画面が表示されます。
認証して頂いた後に設定画面に移動して「使います」ボタンを押していただければ登録が完了します。
以上、久々にプログラムがないブログ更新でした('ω')ノ
Azure Mobile Appsの.NETバックエンドでMVCを同居させてみよう🍣=3
ごあいさつ
衣類乾燥機が今すぐ欲しいのです(´・ω・`)
本題
はじめに
Azure Mobile Appsの.NET バックエンドはASP.NET Web APIがベースとなっていてMVCを追加できません。
でもMobileAppでもMVC使えるようにしたいですよねぇ。
ほらアプリの入口はやっぱりブラウザが多いと思いますし私がいま取り組んでいる課題で必要ですし。
ということで、Mobile AppでMVCを使えるようにしてみます。
前提
Mobile Appの.NET バックエンドプロジェクトをVSで作成してAzureにデプロイできている状態まで出来ている事を前提とします。
この辺を参考にすればすぐにできるかと思います。
コントローラーを追加する
Controllersフォルダに空のMVC5コントローラを追加します。
今回はPageControllerという名前にしてみました。
するとASP.NET MVCを構築するためのファイルが勝手に展開されます。
Viewを追加する
Viewを追加しちゃいます。
ルーティング設定を変更する
デフォルトコントローラ名を指定します。
これを行うとドメイン名のみのURL指定時のコントローラを指定できます。
MobileAppのスタートアップを変更する
今回の肝の部分です。
現在の状態でデバッグをスタートするとこのページが表示されると思います。
これはMobileAppのライブラリが表示しているページです。
このページを表示されないようにしMVC側のルーティング設定が適用されるようにします。
App_Start下にあるStartup.MobileApp.csを開きConfigureMobileApp関数をこのように変更します。
どういう意味かというと
UseDefaultConfigurationというMobileAppConfigurationに対する拡張メソッドを分解しAddMobileAppHomeControllerという拡張メソッドを呼ばないようにしています。
AddMobileAppHomeContollerによってMobileAppの機能に関係ないルーティングが設定されてしまうためです。
これにより
デバッグ実行すればPageコントローラのIndexがコールされIndexページが表示され、この状態でもMobileAppのAPIは正しく動作しているかと思います。
ではでは('ω')ノ
Prism.FormsでランダムにNavigationが変わるアプリを作ってみた(^^)/
こちらの記事は
8日目の記事になります。
初心者枠ということでお手柔らかにお願い致します。
Xamarin.Formsのナビゲーション
Xanarin,FormsのNavigationには大きく分けて4種類あります。
- NavigationPage
- MasterDetailPage
- TabbedPage
- CarouselPage
NavigationPageは非常にシンプルで1本道なナビゲーションです。
それに対してTabbedPage / CarouselPageはPageを横に並べます。
MasterDetailPageはMasterPageでページを選んでDetailにPageを表示するようなNavigationが可能です、
一般的に標準的なアプリにおいてiOSはTabナビゲーション、AndroidはMasterDetailが採用されていることが多いです。
これは各プラットフォームの推奨デザインによります。
同じアプリでもプラットフォーム毎にナビゲーションを最適化しておく事は大切です。
Xamarin.Formsはクロスプラットフォームで同じアプリを作る仕組み・・・・
ナビゲーションを簡単に変更するなんて出来ないんじゃないの・・・・?
そんなお考えのそこのあなた(; ・`д・´)m9
今回ご紹介する方法ならできるんです\(^o^)/
それでは方法をご紹介してみましょう。
Prism.Formsの利用
今回のサンプルではPrism.Formsを使用します。
Prism.FormsはMVVMライブラリでかなり巨大なライブラリになります。
Prismに関して、なにそれ美味しいの?という方は
こちらをご覧ください、
はじめに
考え方
TabbedPageを右に90度回転させるとMasterDetailっぽくありません?
そういう事です。
二つのアプローチ
TabbedPageを継承してCustomRendererでMasterDetailのような見た目のNavigationを作成する。
MasterDetailPageを継承してTabbedPageに近いインターフェースと仕組みを持ったクラスを作成する。
1番が理想形です。が・・・すいません。完成しませんでした・・・
今回は2番のアプローチで作成を行います。
プログラム
今回のサンプルプログラムはこちらになります。
MasterDetail拡張
MasterDetailクラスを継承し更に IViewContainer
この3つはabstractクラスであるMultiPage
実際には今回の範囲ではこのインターフェースを持つ必要はないのですが形だけでも似せるために実装しています。
MasterPageにはListViewをおいてChildrenと結び付けを行っています。
Childrenが選択された場合にはDetailに該当ページをNavigationPageに包んでセットします。
そのほかChangePageなどを実装しています。
PageNavigationServiceの拡張
本来であればPrism.FormsのPageNavigationServiceを継承してカスタム、という形にしたかったのですが期待する動作をさせるためにはどうしても無理であったためPrism.Formsのコードを持ってきてカスタマイズを行いました。
変更点は先ほど作成したTabbedMasterDetailPage用の処理関数ProcessNavigationForTabbedPageを追加し呼び出されるようにしたことです。
この関数の中身自体はTabbedPage用の関数とほぼ同じです。
先ほど説明した2つのアプローチの1番であればNavigationServiceをカスタマイズする必要はなく、そういういみでもアプローチ1は理想形と言えます。
Appクラス
Prism.Forms_NavigationSample/App.cs at master · yuka1984/Prism.Forms_NavigationSample · GitHub
Appクラスはこのように実装しています。
あまり良い実装ではないです。
RegisterTypesにてランダムにNavigationPageを登録しています。
この時に名前をRootPageという名前で登録することでawait NavigationService.NavigateAsync("RootPage/Content2");というように指定することができます。
ここまでの実装によりMasterDetailな見た目だけどロジック的にはTabbedPageと共通で実装することができました。
終わりに
Xamarin.FormsはMVVMパターン・・・みたいに言われることがあるのですがなんか違う気がしてきています。
というよりMVVMってなんだろう。MVVMとはいったいなんだろう・・・・なんなんだぁ(/・ω・)/
MVVMを考えるときにNavigationを入れちゃだめだ(;^ω^)
clean architecture Reactive・・・・
:(´◦ω◦`):
Xamarin.FormsのPCLプロジェクトを.NET Standardライブラリプロジェクトにしてみた(*'▽')
はじめに
本記事は
の4日目の記事になります。
あいさつ
今年は既にXamarin最前線から退いてしまっているのでAdventCalendarへの参加は見送ろうと思っていたのですがXamarin Adventalendarの枠が4枚目のカレンダーに余っていたのでコッソリと投稿することにしてみました。
初心者枠という事でお手柔らかにお願いします。
今年は公私共に色々なことに関してある程度目標を達成することができて良かったです。
来年は今年以上に忙しくなるかもしれないので頑張っていかねばと思います。
なお去年に引き続き今年も一人ぼっちのクリスマスです('◇')ゞ
.NET Standardねぇ
未だにいまいち浸透していないように思える.NET Standard・・・
同時期に.NET Coreというワードが登場し、浸透する前に.NET Standardというワードが出てしまった為に余計にごちゃごちゃしてしまったなぁという印象です(´・ω・`)
各用語に関して
私の中ではこんな感じで考えてます。
PCL・・・クロスプラットフォームなライブラリを実現するために使いたいプラットフォームの公約数APIのみを使用できるライブラリ作成環境。使用できる.NET FrameworkのAPIは使いたいプラットフォームによって増減する。
.NET Core・・・.NET FrameworkのサブセットでWindows Linux Mac等のクロスプラットフォーム環境で使えるフレームワーク。Monoベースでない点が重要でMonoは.NET Framework互換であったのに対して.NET Coreは.NET Frameworkのサブセット。.NET Coreをベースに作られたフレームワークにASP.NET Coreがある。あと.NET Coreベースのコンソールアプリも作れる。.NET CoreにプラットフォームAPIを足してできているのがUWPかな?
.NET Standard・・・プラットフォーム関係なくAPIセットという形で.NET Foundationが定義したクラスライブラリ環境。概念としてはプラットフォームには非依存。現在1.0~1.6まであるがバージョンが上がるごとに使えるAPIが増えていく。1.3までは下位互換のバージョンであって.NET Standardの本質は1.4以降と思う。1.4以降のバージョンは.NET Framework/.NET Core/Xamarin/UWPの進化に対してAPIを調整したバージョンと考える。要するにこれまでと同じ環境で作る分にはPCLから変更する必要がないけれど、今後.NET基盤の進化に対応していく為には,NET Standardに乗り換えておかないと不便になる。ということだと思う。たぶん(;'∀') 1.4以降であっても最小APIセットは.NET Coreとなるので.NET Core以上に使えるAPIが増えることはない。
nugetの方ではPCL用が用意されいた主要なライブラリは概ね.NET Standardに対応してきたのかなというイメージです。
Xamarin.Formsと.NET Standard
Xamarin.Formsの共有プロジェクトに関してはAndroid/iOSのみであればSharedも考えられるがUWP/Tizenまで入れるとPCLにすることが現状の定石じゃないでしょうか?
PCLを.NET Standardプロジェクトに変更することは現時点でメリットは特にありません。
メリットがあるとすれば共有プロジェクトのcsprojの中身がきれいになってnugetでのライブラリ設定がproject.json記述になることで操作しやすくなる??
ですがこの先.NET StadardのAPIセットが進んでいく中ではメリットが生まれる事もあるかと思います。
直近ではvNextでしょうか。
今回はXamarin.FormsプロジェクトのPCLを.NET Standardに変更する手順を記したいと思います。
手順
今回の環境はVisual Studio 2015 Update3にて行っています。
プロジェクトを作る
まずはXamarin.FormsのPCLプロジェクトを作成します。
こんな感じのソリューションが出来上がるかと思います。
PCLプロジェクトからXamarin.Formsパッケージを一度外す
PCLプロジェクトのnugetマネージャーを開いてXamarin.Formsパッケージをアンインストールしてしまいます。
Xamarin.Formsのバージョンは覚えておいてください。
PCL -> .NET Standard
PCLプロジェクトのプロパティを開いてTarget .NET Platform Standardを選択します。
ダイアログが出てくるので「はい」を選択してください。
こんな感じに画面が変わるかと思います。
Xamarin.Formsを追加する。
プロジェクトにproject.jsonが追加されていますので開きます。
project.jsonをこう書き換えてください。
{ "supports": {}, "dependencies": { "Microsoft.NETCore.Portable.Compatibility": "1.0.1", "NETStandard.Library": "1.6.0", "Xamarin.Forms" : "2.3.3.168" }, "frameworks": { "netstandard1.1": { "imports": "portable-net45+win8+wpa81+wp8" } } }
Xamarin.Formsのバージョンはアンインストールしたバージョンと同じものにしてください。
これで.NET Standardへの移行が終わりましたので実行できる状態になっていると思います。
この例ではプロジェクトにWindows8.1やWindowsPhoneプロジェクトが入っているので.NET Standard1.1になっています。
これらが必要なくAndroid/iOS/UWPであれば1.4 Android/iOSであれば1.5にあげることができます。Tizenはよくわかりませんが,NET CoreベースということなのでAndroid/iOS/Tizenであれば1.5が可能かと思います。
1.6も本来は可能なはずなのですが、どうもバグっぽい挙動でうまくビルドができません。
まだVS2017 RCでは.NET Standard 2.0はまだ使えないのですかねぇ。
いまいちVS2017への関心が高くなくて現状調べていません(´・ω・`)
以上、ありがとうございました。