ASP.NETからASP.NET Coreに移行した話

この記事はASP.NET Advent Calendar 2016の2日目の記事です。(空いていたのでひょっこり書いてみました。)

前日は@tanaka_733さんの『<a href="http://tech.tanaka733.net/entry/signalr-with-asp-net-core">ASP.NET Core on Linux でも SignalR が使いたい</a>』でした。

早速本題ですが、昨日12/1に日本最大のビットコイン取引所を運営している<a href="https://bitflyer.jp/">bitFlyerさん</a>でmeetupイベントがあり、そこで件名についての内容でLTをしてきました。(イベントページは<a href="https://bitflyer.connpass.com/event/45476/">こちら</a>です。)

発表資料はSlideShareにアップロードしてあります。(Qiitaはiframeの埋め込みが出来なくてスライドがリンク共有のみになってしまうのですが、どなたか良い方法があれば教えてください…。)

<div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/ssuser9701a6/aspnetaspnet-core-69730375" title="ASP.NETからASP.NET Coreに移行した話" target="_blank">ASP.NETからASP.NET Coreに移行した話</a> </strong> from <strong><a target="_blank" href="//www.slideshare.net/ssuser9701a6">Taiga Takahari</a></strong> </div>

ただスライドを共有しただけだと何なので、当日スライドには載ってないけど話したこと、話できなかったことをツラツラと書いていきます。

## ASP.NET Coreとは

この辺は特に詳しくは話さなかったのですが、Linux上でもIISで動くのか？という質問がありました。

端的に言うとIISはWindowsの機能の一部なのでマイクロソフトがLinux向けのIISを開発しない限りは動きません。

またASP.NETはIIS上にホストされることを前提に作られていましたが、ASP.NET CoreはIISを必ずしも必要とはせずKestrelという独自のWebサーバー(実行環境)を内包しています。

## 移行の経緯

当日質問も頂いたのですがなぜ今回のシステムをASP.NET Coreに移行したのかというと、今回のシステムがアーキテクチャ的にASP.NETよりASP.NET Coreの方が適していたから…ではなく、ASP.NET Coreで作られたアプリの実績を作りたかったという意図が強いです。

ただスライドにも書かれている通り新規で作るよりも移行の実績の方が珍しくなるかもと思ったので、今回は既存システムを対象にしてみました。

結果として移行する時の手順や注意点のナレッジが溜まったので良かったんじゃないかと思ってます。(溜まったナレッジもゆくゆくどこかで発表できればと思います。)

## アーキテクチャ

### フレームワーク

移行前と移行後で変わった部分を太字にしてありますが、フレームワークの部分の各バージョンがこの記事を書いている今日2016年12月2日時点で最新よりも古いバージョンを使っているのは、移行作業を行ったのが2016年夏で以降バージョンの更新をしていないためです。

今日時点でのフレームワークの最新バージョンは以下の通りとなっています。

* .NET Core 1.1
* ASP.NET Core MVC 1.1

今後もこの辺りは更新していく予定で、現状Visual Studio 2017の正式リリース時のバージョンを次のバージョンの予定としています。

というのも個人的見解ですが、.NET Core 1.1はプロジェクト情報をJSON形式のファイルからXML形式のファイルに戻してる途中の過渡期と思ってるので、このバージョンをスルーしようとしているからです。(ただしVS2017正式リリース時のバージョンが1.1よりも上がってるとも限りませんが…。)

### ライブラリ

また、移行前にJSONシリアライザとして使用していた<a href="https://www.nuget.org/packages/Jil/">Jil</a>は.NET Core対応が出来ていなかったためJson.NETに変更しました。

そのJilですが、今日時点でもまだ.NET Core対応のパッケージはリリースされていないようです。(ただJilの基底となっている<a href="https://www.nuget.org/packages/Sigil/">Sigil</a>は対応版のパッケージがリリースされているようです。)

## 移行のしやすさ

移行にかかった期間を載せましたが、実際この辺はアプリケーションの規模に大きく依存すると思います。

今回移行したアプリケーションの規模はざっくりですが、以下のような規模となっています。

* 画面数 → 8画面
* 機能数 → 15 ~ 20機能

移行のしやすさで一番重要なのはアーキテクチャで、今回のLTで一番言いたかったのはこの部分でした。

スライドには『Webアプリケーション(ASP.NET)の部分を切り離す』とだけ書かれていますが、詳細には『プレゼンテーションとドメインの分離(PDS:Presentation Domain Separation』というアーキテクチャパターンを採用しています。

PDSを適用するとWebアプリケーションのフレームワーク(ASP.NETやASP.NET Core)に依存する部分とそうでない部分に分離され、Webアプリケーションのフレームワークに依存しない部分は移行する必要がなくなるため移行性が高まるはずです。(実際は.NET Frameworkから.NET Coreへの移行性が問われるようになったり、後ほど説明するDIを使うために若干のコードの変更が必要にはなります。)

PDSについては以下のスライドにわかりやすい詳細の説明が書かれているので気になった方は読んでみて下さい。

* <a href="http://www.slideboom.com/presentations/591514/GUI%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89MVVM%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%B8">GUIアーキテクチャパターンの基礎からMVVMパターンへ</a>

## ツライこともある

### ConfigurationManager

ConfigurationManagerは元々.NET FrameworkのアプリケーションでXML形式の構成ファイルの値を取得するものでしたが、.NET Coreでは構成ファイルがJSON形式になったためなくなりました。(ただ使うライブラリによっては.NET CoreでもXML形式も使うことはできるようです)。

### DataTable

DataTableは負の遺産と言われることもありますがSQL Serverのテーブル値パラメータという機能を使うのにマストなため、これがなくなったおかげて効率の良いSQLを実行することが出来なくなりました。

資料にも書いていますが、.NET Core 1.1で復活を遂げたようです。(テーブル値パラメータを使えるようにして欲しかっただけでDataTableの復活は望んでいなかったんですが…。)

ちなみにテーブル値パラメータは以下のエントリがわかりやすいです。

* <a href="http://kiyokura.hateblo.jp/entry/2015/04/04/111657">テーブル値パラメータについて少し整理とメモ - きよくらの備忘録</a>

### HttpContext

ASP.NETではHttpContextクラスにCurrentという静的プロパティが用意されており、このプロパティを呼び出せばどこからでもHttpContextの値を取得・設定することが出来たのですが、ASP.NET CoreにはプロパティなくControllerやAction Filterなど以外のASP.NET Coreの機能ではない部分からHttpContextを取得するにはIHttpContextAccessorをいうインターフェースをDI(依存性の注入:Dependency Injection)で解決しないといけないようになりました。

しかもこのDI機能を使用するにはIServiceProviderというインターフェース(実際にDIを解決している実体)をどこからでも取得できるようにしておかないといけなくなります。

### ツール

ここでのツールとは.NET Core Tools for Visual Studio 2015のことです。

Visual Studio 2015で.NET Core開発を行う上で必要なツールなんですがプレビュー版ということもあり、挙動がおかしい部分があります。

.NET CoreではプロジェクトファイルもJSON形式になったのですが、このJSONファイルを操作する時、特にdependenciesというパッケージの参照を記述するスキーマを触るとにVisual Studioがフリーズしました。

恐らく裏側でNuGetサーバーにパッケージの情報を問い合せているんだろうと思いますが、キーボードで入力しても何のレスポンスも返ってこないなんてことが頻繁にありました。

この事象に対してソリューションエクスプローラ上で選択したファイルをVisual Studio Codeで開くOpen in Visual Studio Codeという拡張機能を使って、Visual Studio Codeで編集するようにしていたのですが、パッケージのバージョンが正しく取得できなかったりプライベートなNuGetサーバーの情報が取得できなかったりで、完全代替にはなりませんでした。

Visual Studio 2017 RCでも.NET Coreのアプリケーションを操作しようとすると落ちる、みたいな話がイベントの懇親会でも上がっていて、まだまだ改善すべき箇所なので今後に期待したいところではあります。

## パフォーマンス

計測済みなんですが今回はあえて載せていません。

というのもインフラレイヤーの影響を考慮していなくてアプリケーションレイヤーだけで見ればASP.NET Coreの方が速いんですが、インフラ含めるとASP.NETの方が速いという結果になってしまったので、もう少し色んなパターンで計測してから公表したいと思っています。

## まとめ

### ASP.NET Coreへの移行

先ほども書きましたが、今回一番伝えたかったことはフレームワークの移行性を確保したASP.NETアプリケーションであれば、ASP.NET Coreへの移行は十分可能だということです。(LTではあまり推さなかったので伝わってなかったかもしれません…。)

またフレームワークだけでなく各ライブラリ(データストアアクセス、ロギング、シリアライザなど)の移行性も確保しておくと新しいフレームワークに対応してない場合に他の対応しているライブラリで代替しやすいため、よりスムーズに移行できると思います。

ただ全体的に疎結合になると開発効率が落ちることもあるので、その辺りはトレードオフとして考えた方が良さそうです。

### 移行すべきかどうか

ASP.NET Coreを開発しているメンバーの方のエントリを載せてあります。

* <a href="http://www.jeffreyfritz.com/2016/08/should-i-use-asp-net-core-or-mvc-5/">Should I Use ASP.NET Core or MVC 5?</a>

移行すべきか、というよりASP.NET( MVC 5)とASP.NET Coreのどちらを選ぶべきかがケース別で書かれています。

現在のシステム、またはこれから作ろうとしているシステムがこれらのどのケースに当てはまるのかを考えた上で本当にASP.NET Coreを選択すべきかの基準になれば思います。

## 最後に

LTということもあってあまり多くは話せなかったですが、今回のこの話がASP.NETからASP.NET Coreへの移行を考えてる方の何かの役に立てばと思います。