OWINの仕組みとOWIN上のフレームワーク(ミドルウェア)の作り方
- 2014-05-13
2014/2/8に北海道のCLR/HでOwinについて話してきたんですが、なんと!今の今までスライド公開してなかった!これはひどい!3ヶ月放置してた!熟成肉!ウルフギャング!ということでやっとこさ公開。若干加筆してあります。
前半はOWINとは何か、というのとキーワードや仕組みについての解説。後半はLightNodeという私の作っているWebAPIフレームワークの実装を通して、フレームワークに必要な要素と実装例、そして性能の出し方を見て行きましょうという感じです。
発表した時は、失敗した感があって公開できないでいたんですが、読み直すと結構いいこと書いてありますね、とか自画自賛。あんましこういう内容のセッションってないですし、いい感じなんじゃないでしょうか、改めて読むと。こういう内容も割とレアいですしね、レア度大事。後半部分がじっくり読む系な内容になっていて、あんまし発表向けじゃなかったのは良くなかったかな……(資料を当日のその場で作ってて、どう話すか、どう見せるかについて考えてこなかったのが悪いというところもあるというかかなり悪いのでその辺は大反省)
Demo Walkthrough
あ、そうそう、LightNodeもver.3になってます。今回からUnity用のジェネレータが追加されているのと、それと何度かデモやってて手間取った箇所があったので、スムーズに行えるようにデフォルトパラメータ類を調整しました。この辺、実際にやってくの大事ですねえと実感。そんなわけで1から見て行きましょふ。ちなみに画像は全部英語ですが、日本語のスクリーンショット取るのが面倒だっただけなので、実際は別にちゃんと日本語です。
まずVSをを立ち上げて新規プロジェクト作成します。そしてASP.NET Web Applicationを選択。
そのまま、空のプロジェクトを選択します。
さて、これで空のASP.NETプロジェクトが出来ました。続いてOwinでホストするためNuGetを開いて「Microsoft.Owin.Host.SystemWeb」をインストール。
そのままServer用のLightNode、「LightNode.Server」をインストール。
これでDLL参照はオシマイ。まだファイルがゼロなので、追加していきましょう。まずはOwinとLightNodeの利用を関連付けるため、OWIN Startup Classを追加します。このテンプレートはVSに用意されてるので、Add→New Item→OWIN Startup Class。
そしてそのファイルに、app.UseLightNode();の一行だけ足します。
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseLightNode();
}
}
これで準備は完了です!最後に実際のAPIを作りましょう。Add→ClassでCalc.csというのを作ります。そしてそのファイルに以下のコードを書いてください。
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
public class User : LightNode.Server.LightNodeContract
{
public Person Show(string name, int age)
{
return new Person { Name = name, Age = age };
}
}
これで最初のAPIの作成は完了です。Ctrl+F5で実行し、 /User/Show?name=john&age=20 にアクセスしてみてください。例えば http://localhost:8708/User/Show?name=john&age=20 。JSONが表示されたことを確認できるでしょう。このように /クラス名/メソッド名?パラメータ が露出するAPIとして、 戻り値の型がJSONとなります。Web APIを実装する手段として、限りなく最小の手順です。
最後に、OWINとは関係ありませんが、実際にインターネットへの発行、Azure WebSitesでホストしてみましょう。WEBサイトを作成し、発行プロファイルをダウンロードします。
次にソリューションファイルを右クリックし、発行。ダイアログでダウンロードした.publishファイルを選択すると、発行先、ユーザー名、パスワードが入力されています。
必要ならば発行の設定で、Remove additional files at destinationもチェック入れておきましょう。
そしてPublishボタンを押せば、Webへの公開は完了です。例えば http://lightnodedemo.azurewebsites.net/User/Show?name=Mary&age=30 といったところに!5分あれば全部デモしきれます!(と言いつつ毎回どっかではまって10分かかってる説)
Demo Client
というわけでWeb API作成まではそんな感じなのですが、LightNodeのもう一つの特徴にクライアントサイドの自動生成があるので、引き続きそれを見て行きます。
まず、新規にクラスライブラリとしてShareDataを作り、WebApplicationに作っていたPersonクラスを移します。また、ConsoleApplicationも同じソリューションに作り、WebApplicationとConsoleApplicationがShareDataを参照するようにします。
次にConsoleApplicationのNuGetを開いて、LightNode.Client.PCL.T4とLightNode.Formatter.JsonNetをインストールします。
この状態になったら、まずWebApplicationをビルド(Personクラスを移した影響でコンパイルエラー出たら適宜名前空間をusingしたりしてね)。そしてConsoleAppのほうにインストールされたLightNodeClient.ttを開いて、先頭行を、WebApplicationのdllのパスに修正します。
<#@ assembly name="$(SolutionDir)\WebApplication4\bin\WebApplication4.dll" #>
するとドバッとコードが生成されてるはずです!はずです!
このクライアントコードは、HttpClientベースで全て非同期なモダンな形態になっています。ということでSystem.Net.Httpの参照が必要なので、それも参照しておきます(ConsoleApp以外の場合はNuGetからHttpClientを参照する)。
あとはProgram.csに以下のように書いてもらえれば通信できます。
async static Task Run()
{
var client = new LightNode.Client.LightNodeClient("http://localhost:8708");
// client.Class.MethodAsync(argument)
ShareData.Person person = await client.User.ShowAsync("John", 30);
Console.WriteLine(person.Name + ":" + person.Age);
}
static void Main(string[] args)
{
Run().Wait();
}
Server側にあるクラス名.メソッド名Async(引数)というのが、(自動生成なので当たり前ですが)型付けされて、戻り値も自動でデシリアライズされるといった、自然な操作で扱えます。サーバーAPIの数が増えれば増えるほど大変だし、修正した時も再生性するだけなので、色々楽ちんですよね、と。
ASP.NET vNext
ちょうどTechEdが開催されていて(海の向こうの話です!)、Introducing ASP.NET vNextとか、わくわくするような話も出てきましたん。さて、LightNodeはWebAPIなのですが、100% WebAPIじゃなくてHTML返したいといったシチュエーションもあると思います。簡単なものならRazor EngineやT4 Templateでstringを返せばいいでしょふけれど、数が多かったりする時は、UseMvc()でASP.NET MVCと共存すりゃあいいかなー、って思っています。全然問題ない。そういった共存もまたOWINのモデルかな、って思ってます。
最後に
そうそう、OWIN使っているからカッコイイ、なんてことはないし、軽量なものならNancy使えばモダンでイケてる、なんてことも全くありません。私だったらビューが必要なものの実装は絶対にASP.NET MVC使うし、APIならLightNodeで書きます。当たり障りのないことをいえば、トータルのバランスで優れたものを選択できる嗅覚が大事ってところですね。とはいえまぁ、その選択の基準を作るためにも、OWINについてしっかり知っておく必要はあるでしょう。間違いなく。
OWIN、ASP.NET vNextと、取るべき選択肢が多くなってきました、からこそ、しっかりした判断が求められるので、逆に言えばシビアです。シビアですが、だからこそ面白い、面白くなってきた!って私は思ってます。ね、こういうのを楽しみましょう。イイ時代です。