きよくらの備忘録

「三日坊主と呼ばせない!日記」改め。主にソフトウェア開発関連の話題。

ASP.NET MVC と Azure Web Sites で VS Online のカスタムService Hookを作成してサクッとリモートデバッグする

本エントリはASP.NET Advent Calendar 2014 24日目対応エントリです。4日目に続き今年2回目のエントリですが、今回はもう少しASP.NET的な成分が多くなる…予定。

VS Online のカスタムService Hook

以前のエントリで少し触れましてが、Visual Studio Online は外部のサービスと連携可能です。

 

例えばHipChatをはじめJenkinsやAppVeyor、Hubot等々、色々なものとの連携がビルトインされてますが、仕様に沿ったWeb APIの口を用意するとこでカスタムのWeb Hookを行うことも可能になっています。

 

Web Hookを作成するにあたっては、もちろんですが特に言語などは選びません。規定の形式のJSONでPOSTされるデータを受信できるWeb APIさえ用意すればOKです。

言語はなんでもOKなんですが、Visual StudioASP.NET MVC、Azure Web Sitesを組み合わせると、ほぼ手間をかけずに試せます。ということで、一通り軽く紹介してみたいと思います。とりあえず前提条件としては以下を想定します。

 

Webアプリケーションの作成

1.ASP.NET MVC 5のプロジェクトを作成

MVC 5を適当に作成します。ミニマムのサンプルということで、テンプレートはEmptyでMVCだけ参照しておきます。 Web APIでも問題ないともうので、そっちがいい人はそっちで作って、以降は適当に読み替えてください。

f:id:kiyokura:20141224220936p:plain

 

2. コントローラーの追加

テンプレートが展開されたら、コントローラを一つ追加します。今回はGit関連の操作に対するアクションをHookするAPIで利用することを想定して、GitControllerとしました。

f:id:kiyokura:20141224220937p:plain

 

3. 引数をマップするクラスを定義する

アクションメソッドを作成する前に、APIに渡されるデータを格納するためのクラスを定義します。 データはVSOからJSONでPOSTされます。適切な型のクラスを定義してアクションメソッドの引数にしておくけばASP.NET MVCのモデルバインダがよしなにマッピングしてくれます。が、そのためにはもちろんですが適切にクラスを定義する必要があります。

POSTされるデータはAPI仕様の記載から読み取って定義する必要があり、一見すると面倒です。が、VSの機能を使うと瞬殺で完了します。 イベント引数クラスは、とりあえず前の手順で作成したGitController.cs内に作成することにします(まあサンプルですし)。

 

3.1 仕様からサンプルデータをクリップボードにコピーする

ここではCodePushのイベントでPOSTされるデータを対象にしてみます。下のAPI仕様の『Code pushed (git.push)』のSample event欄に記載されているサンプルのJSONを選択し、クリップボードにコピーします。

Service Hooks events

f:id:kiyokura:20141224220938p:plain

 

3.2 クラスとして貼り付ける

コピーしたら、クラスを記述したい場所にカーソルをポイントした後、メニューの[編集]-[形式を選択して貼り付け]から、[JSONをクラスとして貼り付ける]を選択します。

f:id:kiyokura:20141224220939p:plain

するとこんな感じで、JSONからクラスのスケルトンを作ってくれます*1。超便利ですね。

f:id:kiyokura:20141224220940p:plain

 

4. アクションメソッドを作成

あとはアクションメソッドを定義して完了です。 引数の型は先ほど貼り付けて作成したクラスの最上位のオブジェクト(Rootobject)、戻りの型はHttpResponseMessageとします。一応、属性でHttoPostをつけておきました。 (なお、HttpResponseMessage は System.Net.Http にあるので、参照の追加を行っておきます。)

ソースコードとしてはこんな感じですです。下記では受けた後に特に何もしていませんが、実際にはcontentの中身をDBに収めるなり他に通知するなりを行うと思ってください。

public class GitController : Controller
{
  [HttpPost]
  public HttpResponseMessage CodePushed(Rootobject content)
  {
    // 実際はcontentの中身をつかってやりたいことをやる!

    return new HttpResponseMessage(HttpStatusCode.OK);
  }
}

とりあえずGitでPushを受け付けた時の通知を受信できるアクションメソッドの大枠ができました。 ここから実際に何かに保存したりどこかに通知したりといった処理を実装することになります…が本当にVSOからの通知を受信できるか試してみたいですよね。

 

動作確認

ということで、軽く動作確認をしてみたいと思います。VSOからHTTPが届くところならどこでもいいですが、手軽なのでここではAzure Web Sitesを使ってみます*2。 Azure WebSitesにデプロイしてリモートデバッグを設定し、データの受信ができているかどうかを確認してみます。

 

1. Azure Web Sitesにデプロイ

適当にAzure WebSitesにデプロイしましょう。とりあえずVisual Studioの『発行』からWebサイトを新規作成してそのままデプロイしてみます。

[発行]から「Microsoft Azure Websites」を選んで…

f:id:kiyokura:20141224220942p:plain

WebSitesを新規に作成して…

f:id:kiyokura:20141224220943p:plain

デプロイ…の前に、リモートデバッグでステップ実行できるように、[設定]で構成を[Debug]に設定してから発行します。

f:id:kiyokura:20141224220944p:plain

f:id:kiyokura:20141224220945p:plain

これで完了です(ブラウザが立ち上がってエラーが表示されてるかもしれませんが、とりあえず気にせず)。

 

2. リモートデバッグの設定

デプロイができたら、リモートデバッグの設定をしておきます。「サーバーエクスプローラー」を開き、[Azure]-[Webサイト]から、デプロイしたサイトのノードを右クリック、[デバッガーの接続]を選択。

f:id:kiyokura:20141224220946p:plain

 

特にエラー等表示されず、Visual Studioデバッグ実行モードになっていればOKです。とりえあず、CodePushedアクションメソッド内にブレークポイントを張っておきます。

f:id:kiyokura:20141224220947p:plain

 

3. VSOでService Hookを設定してテスト実行

次にService Hookの設定をします。VS OnlineでService Hookを設定したいプロジェクトコレクションを開き、設定の[Service Hooks]タブで[+]マークで追加でダイアログを表示。Serviceから『Web Hooks』を選びます。

f:id:kiyokura:20141224220948p:plain

 

Triggerに『Code Pushed』を選択して…

f:id:kiyokura:20141224220949p:plain

 

Actionの『URL』に、デプロイしたサービスのURLを記載します。たとえばこんな感じ。

f:id:kiyokura:20141224220950p:plain

 

ここで[Test]を実行すると……しばらくするとVisual Studioでステップインされてきます。

f:id:kiyokura:20141224220951p:plain

 

引数をクイックウォッチで確認すると…ちゃんと入ってますね!

f:id:kiyokura:20141224220952p:plain

 

まとめ

簡単にではありますが、VSOのWeb Hooksと連携するオリジナルのWebアプリケーションのひな形を作成して動作確認してみました。 サンプルコードもまとめておいておきます。

 

VSO で Gitを使う場合はこんな感じでPullRequest駆動開発も可能です。

またこんな感じでこのあたりの機能は日々追加されていて、VSO+Gitも割といい感じになってきていると思います。

興味ある方は色々触ってみるとよいのではないでしょうか。

*1:C#的には小文字始まりのプロパティが気になりますが、とりあえず今回は放っておきます。

*2:VSO使ってるなら、おそらくAzureにアカウントもあるはずですし