Windows ストアアプリから Windows Azure へアクセスする(その2)

10月4日-5日に開催された、Developer Camp 2012 Japan Fall にて、「デバイス + クラウドで実現するこれからのサービス ~ Windows 8 + Windows Azure 編 ~」を担当させていただきました。

本エントリーは前回説明しました、「Windows ストアアプリから Windows Azure へアクセスする(その1)」の続きになります。Azure 側の環境構築と、ベースとなる Azure サービスを作成し、デプロイしてみるところまで行きましたので、今回は Windows Azure から画像と詳細情報を公開するロジックを追加して、再デプロイするところまで行きましょう。

 

  1. ASP.NET MVC アプリケーションの作成

    前回作成した PicMgr.WebApi プロジェクトにモデル クラスを追加します。
    [Models] フォルダを右クリックして [追加] – [クラス] を選択します。 
    01

    クラス名を”Picture.cs” にします。内容を以下のコードに置き換えます。

     namespace PicMgr.Models
    {
        using System.Runtime.Serialization;
        using System.Collections.Generic;
        using System.ComponentModel.DataAnnotations;
        using System.Linq;
        using System;
    
        [DataContract]
        public class Picture
        {
    
            [Key]
            public int PrimaryKey { get; set; }
    
            [DataMember]
            public string UniqueId { get; set; }
    
            [DataMember]
            public string Title { get; set; }
    
            [DataMember]
            public string SubTitle { get; set; }
    
            [DataMember]
            public string Description { get; set; }
    
            [DataMember]
            public string ImagePath { get; set; }
    
        }
    }
    

                     
    [参照設定] で”System.Runtime.Serialization” を追加します。

    02

    ここで一度 [Shift] + [Ctrl] + [B] キーを押してビルドしてください。

    次に、[Controllers] フォルダを右クリックして[追加] – [コントローラー] を選択します。 
    03

    コントローラー名を「PicturesController」、モデルクラスは「Picture (PicMgr.Models)」を選択、データコンテキストクラスは新規で「PicMgr.WebApi.Models.PictureContext」をデータコンテキスト型として入力し、追加ボタンを押します。

    04

    ModelsフォルダにPictureContext.csが作成されていることを確認します。

    05

    PictureContext.cs の内容は以下のようになっているはずです。

     using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web;
    using System.Web.Http;
    using PicMgr.Models;
    using PicMgr.WebApi.Models;
    
    namespace PicMgr.WebApi.Controllers
    {
        public class PicturesController : ApiController
        {
            private PictureContext db = new PictureContext();
    
            // GET api/Pictures
            public IEnumerable<Picture> GetPictures()
            {
                return db.Pictures.AsEnumerable();
            }
    
            // GET api/Pictures/5
            public Picture GetPicture(int id)
            {
                Picture picture = db.Pictures.Find(id);
                if (picture == null)
                {
                    throw new HttpResponseException(
    Request.CreateResponse(HttpStatusCode.NotFound));
                }
    
                return picture;
            }
    
            // PUT api/Pictures/5
            public HttpResponseMessage PutPicture(int id, Picture picture)
            {
                if (ModelState.IsValid && id == picture.PrimaryKey)
                {
                    db.Entry(picture).State = EntityState.Modified;
    
                    try
                    {
                        db.SaveChanges();
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        return Request.CreateResponse(
    HttpStatusCode.NotFound);
                    }
    
                    return Request.CreateResponse(HttpStatusCode.OK);
                }
                else
                {
                    return Request.CreateResponse(
    HttpStatusCode.BadRequest);
                }
            }
    
            // POST api/Pictures
            public HttpResponseMessage PostPicture(Picture picture)
            {
                if (ModelState.IsValid)
                {
                    db.Pictures.Add(picture);
                    db.SaveChanges();
    
                    HttpResponseMessage response = 
    Request.CreateResponse(HttpStatusCode.Created, picture);
                    response.Headers.Location = 
    new Uri(Url.Link("DefaultApi", new { id = picture.PrimaryKey }));
                    return response;
                }
                else
                {
                    return Request.CreateResponse(
    HttpStatusCode.BadRequest);
                }
            }
    
            // DELETE api/Pictures/5
            public HttpResponseMessage DeletePicture(int id)
            {
                Picture picture = db.Pictures.Find(id);
                if (picture == null)
                {
                    return Request.CreateResponse(
    HttpStatusCode.NotFound);
                }
    
                db.Pictures.Remove(picture);
    
                try
                {
                    db.SaveChanges();
                }
                catch (DbUpdateConcurrencyException)
                {
                    return Request.CreateResponse(
    HttpStatusCode.NotFound);
                }
    
                return Request.CreateResponse(HttpStatusCode.OK, picture);
            }
    
            protected override void Dispose(bool disposing)
            {
                db.Dispose();
                base.Dispose(disposing);
            }
        }
    }
    
  2. サンプルデータの挿入と Windows Azure SQL データベースへの移行、Web Sites へのデプロイ

    パッケージマネージャーコンソールを表示します。[ツール] - [ライブラリパッケージマネージャー] - [パッケージマネージャーコンソール] を選択します。

    06

    コンソールから次の2つのコマンドを順番に実行します:

    enable-migrations -ContextTypeName PicMgr.WebApi.Models.PictureContext

    add-migration Initial

    07

    [Migrations] フォルダがが作成されていることを確認し、”Configuration.cs” を開きます。

    08

         
    PicMgr.Models 名前空間の宣言を追加します。

     namespace PicMgr.WebApi.Migrations
    {
        using System;
        using System.Data.Entity;
        using System.Data.Entity.Migrations;
        using System.Linq;
        using PicMgr.Models;
    
        ...
    

    Seed メソッドに以下のコードを追加して、データの挿入を行います。 (ご自分の Azure 環境でお試しになる際は、下記コード内の BLOB URL から画像を入手し、ご自分の Azure Storage BLOB へアップロードした上で URL を置き換えてください。)

     protected override void Seed(
    PicMgr.WebApi.Models.PictureContext context)
    {
        //  This method will be called after migrating to the latest
     version.
    
        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //
        string dummy = "\n\nPellentesque porta, mauris quis interdum 
    vehicula, urna sapien ultrices velit, nec venenatis dui odio in augue.
     Cras posuere, enim a cursus convallis, neque turpis malesuada erat,
     ut adipiscing neque tortor ac erat.";
    
        context.Pictures.AddOrUpdate(p => p.UniqueId, new Picture
        {
            UniqueId = "1001",
            Title = "January",
            SubTitle = "January",
            Description = "お正月" + dummy,
            ImagePath = 
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_Jan.jpg"
        });
    
        context.Pictures.AddOrUpdate(p => p.UniqueId, new Picture
        {
            UniqueId = "1002",
            Title = "February",
            SubTitle = "February",
            Description = "バレンタインデー" + dummy,
            ImagePath = 
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_Feb.jpg"
        });
    
        context.Pictures.AddOrUpdate(p => p.UniqueId, new Picture
        {
            UniqueId = "1003",
            Title = "March",
            SubTitle = "March",
            Description = "ひな祭り" + dummy,
            ImagePath = 
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_Mar.jpg"
        });
    
        context.Pictures.AddOrUpdate(p => p.UniqueId, new Picture
        {
            UniqueId = "1004",
            Title = "April",
            SubTitle = "April",
            Description = "桜吹雪" + dummy,
            ImagePath = 
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_Apr.jpg"
        });
    
        context.Pictures.AddOrUpdate(p => p.UniqueId, new Picture
        {
            UniqueId = "1005",
            Title = "May",
            SubTitle = "May",
            Description = "風薫る" + dummy,
            ImagePath = 
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_May.jpg"
        });
    
        context.Pictures.AddOrUpdate(p => p.UniqueId, new Picture
        {
            UniqueId = "1006",
            Title = "June",
            SubTitle = "June",
            Description = "梅雨" + dummy,
            ImagePath = 
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_Jun.jpg"
        });
    
        context.SaveChanges();
    
    }
    

    パッケージマネージャーコンソールに戻り、以下のコマンドを実行します。

    update-database

    10

    ビルドします。これで Azure アプリケーションは完成です。

  3. Azure Web Sites へのデプロイと動作確認

    ソリューション エクスプローラーから [PicMgr.WebApi] プロジェクトを右クリックし、[発行…] メニューを選択します。

    11

     
    前回のエントリーと同様に「Web を発行」ダイアログが表示されますので、[設定] タブを選択します。

    [データベース] の下にある [PictureContext] にリモート接続文字列を入力します。右の[…] を選択し、こちらも前回のエントリーで作成した SQL データベースに接続するための設定情報を参考に以下のように入力します。[テスト接続] ボタンを押してデータベースに接続できることを確認し、[OK] ボタンを押します。

    12

    [この接続文字列を実行時に使用する(更新先 web.config)] 及び [Code First Migrations を実行する(アプリケーションの起動時に実行する)] をチェックし、[次へ >] ボタンを押して、[プレビュー] タブから [発行] ボタンを押します。

    13

    アプリケーションが発行されてデプロイが完了すると、前回のエントリーと同様に Web API 対応アプリのデフォルト ページが表示されます。

    14

    今度は URL の後ろに”api/pictures”を追加して、JSON データの内容を確認します。HTTP GET が PicturesController クラスの GetPictures メソッドにバインドされ、SQL データベースへアクセスし、以下のように先ほど Seed メソッドで挿入された内容が返されるはずです。

     [
    {"UniqueId":"1001","Title":"January","SubTitle":"January",
    "Description":"お正月 ...(省略)","ImagePath":
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_Jan.jpg"},
    ...(省略)
    {"UniqueId":"1006","Title":"June","SubTitle":"June",
    "Description":"梅雨 ...(省略)","ImagePath":
    "https://claudiapicmgr.blob.core.windows.net/pictures/Claudia_Jun.jpg"}
    ]
    

               
    Windows Azure Web Sites にクラウドサービス環境を作成し、アプリケーション フレームワーク技術としては ASP.NET MVC Web API、Entity Framework を活用することで、非常に簡単かつ素早く Azure 対応クラウドサービスが作成できることが実感できましたでしょうか?また、Web Sites の高速簡単デプロイ、デスクトップ上の Web サービスが何のコード変更なしに SQL データベースへの移行も含めてクラウド環境に乗っかってしまうのも、なかなか魅力的ではないかと思います。

    本エントリーではアプリケーション開発の手順を中心に説明していますが、もう少し詳しく知りたい方は英語ですが「Deploying an ASP.NET Web Application to a Windows Azure Web Site and SQL Database」 が参考になるかと思います。

    いよいよ次のエントリーでは、Windows ストアアプリからこの Web サービスへアクセスして返された JSON データをグリッドビューにバインドして表示させます。