Azureの小ネタ (改)

~Azureネタを中心に、色々とその他の技術的なことなどを~

ASP.NET MVC3を勉強するよ (再録)その1

LiveWriterでつらつらと書いていたらあまりに本人にも読みづらくなってしまったため、さいど編集しなおしました。
昔のやつは消しましたw。

概要

元ネタは以下です。

元ネタのチュートリアルの手番を多少変更してあります。

プロジェクト作成

VSを起動して、「ASP.NET MVC3 Webアプリケーション」を作成します。


新しいプロジェクト作成ダイアログが表示されるので、
・テンプレートの種類を「空」
・ビューエンジンを「Razor」
HTML5セマンティックをオン
にします。


命名規則(Naming Convention)によるフォルダが作成されます。
・Controllers
・View
・Models
・Contents
・Script
MVCの名の通り、それに乗っ取ったフォルダ群作成されるようですね。

コントローラー

引き続きコントローラーを作成します。この時点では、コントローラーが何たるかを知っているわけではないため、淡々と進めていきます。

HomeControllerの追加

Controllersフォルダのコンテキストメニューから、[追加]−[コントローラー]を選択します。コントローラー名を、「HomeController」に変更して追加します。

HomeController.csには自動生成のコードが展開されます。#if false部分が元々の部分ですが、メソッドの型をstringに変更て実行してみます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
#if false
        public ActionResult Index()
        {
            return View();
        }
#else
        public string Index()
        {
            return "こんにちは MVC3";
        }
#endif
    }
}

デバッグ実行

デバッグ実行すると、ブラウザが立ち上がります。Indexメソッドで返却された文字列が表示されたのが確認できるでしょう。URLとマッピングされているようですので、Indexメソッドはオーバロードは許可されておらず、コンパイルエラーになるようです。

StoreControllerの追加

同じ要領でStoreControllerを追加します。チュートリアルではいくつか細かい手番を解説していますが、すっ飛ばして以下のコードを入力します。
Index以外に、Browse、Detailsメソッドを追加します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class StoreController : Controller
    {
        //
        // GET: /Store/
        public string Index()
        {
            return "Hello from Store.Index()";
        }

        //
        // GET: /Store/Browse?genre=Disco
        public string Browse(string genre)
        {
            string message = HttpUtility.HtmlEncode("Store.Browse, Genre = " + genre);
            return message;
        }
        //
        // GET: /Store/Details/5
        public string Details(int id)
        {
            string message = "Store.Details, ID = " + id;

            return message;
        }
    }
}

実行して、/Store/Browse?Genre=J-POPにアクセス。


/Store/Details/1111 にアクセス。

URLのパラメータ(っていうの?)が処理できているのが分かります。

ビューテンプレート

HomeControllerクラスのIndexメソッドを初期状態に戻した後、

    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            return View();
        }

    }


Indexの辺りからコンテキストメニューを表示して、[ビューの追加]を選択します。


ビューの追加ダイアログが表示されるので、そのまま追加を選択。


View/Homeに、Index.cshtmlファイルが追加されます。


Index.cshtmlを以下に修正して実行。

@{
    ViewBag.Title = "Index";
}
<h2>ホームページ</h2>

共通レイアウトの設定

多くのWebページは共通のレイアイトを持っていたりするわけです。ナビゲーション、フッタ、ロゴ、イメージ、スタイルシートなどなど。Razaorでは、Shared/_Layout.cshtmlを使って色々できるようです。
既定のコードは以下。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
</head>

<body>
    @RenderBody()
</body>
</html>

これを以下に置き換えます。Javascriptバージョンが古くなっているのはご愛敬なんでしょうか。@RenderBody がメインのコンテンツの表示エリアらしいです。

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
</head>
<body>
    <div id="header">
        <h1>
            ASP.NET MVC MUSIC STORE</h1>
        <ul id="navlist">
            <li class="first"><a href="/" id="current">Home</a></li>
            <li><a href="/Store/">Store</a></li>
        </ul>
    </div>
    @RenderBody()
</body>
</html>

スタイルシートの更新

http://mvcmusicstore.codeplex.com からMvcMusicStore-Asset.zipをダウンロードしてきて、その中からImagesフォルダとSite.cssを取り出して、プロジェクトのContentフォルダに取り込みます。


再度実行すると、なんとも古めかしい感じのページになりましたw。

モデルの追加

いよいよMVCのM部分の追加です。
Modelフォルダにジャンルとアルバムクラスを追加します。

Genre.cs

    public class Genre
    {
        public string Name { get; set; }
    }

Album.cs

    public class Album
    {
        public string Title { get; set; }
        public Genre Genre { get; set; }
    }

次にStoreControllerを修正します。Detailsメソッドのコンテキストメニューから、[ビューの追加]を選択します。
・厳密に型指定されたモジュールをチェック
・モデルクラスにAlbumを指定


次は、Browseからビューを追加。モデルクラスには、Genreを指定します。


次は、Indexから。モデルクラスには、「Genre」を追加します。


それぞれのcshtmlファイルが追加されます。

ここで再びStoreControllerを修正します。

        //
        // GET: /Store/
        public ActionResult Index()
        {
            var genres = new List<Genre>
                             {
                                 new Genre {Name = "Disco"},
                                 new Genre {Name = "Jazz"},
                                 new Genre {Name = "Rock"}
                             };
            return View(genres);
        }

        //
        // GET: /Store/Browse
        public ActionResult Browse(string genre)
        {
            var genreModel = new Genre { Name = genre };
            return View(genreModel);
        }
        //
        // GET: /Store/Details
        public ActionResult Details(string id)
        {
            var album = new Album { Title = "Album" + id };
            return View(album);
        }
    }

そしてそれぞれのcshtmlファイルを修正。

Browse.cshtml

@model MvcMusicStore.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>

Detail.cshtml

@model MvcMusicStore.Models.Album
@{
    ViewBag.Title = "Details";
}
<h2>
    Album: @Model.Title</h2>

Index.cshtml

@model IEnumerable<MvcMusicStore.Models.Genre>
@{
    ViewBag.Title = "Store";
}
<h3>
    Browse Genres</h3>
<p>Select from @Model.Count()
    genres:</p>
<ul>
    @foreach (var genre in Model)
    {
        <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
    }
</ul>

とりあえず、細かい部分は分かってませんが、なにをやろうとしているかは読み取れます。

再びデバッグ実行し、/Store/をアクセスしたところ。



リストがリンクになっているので、Discoをクリック。

リンク

先ほど、Index.cshtml部分には、hrefとかハードコードしていましたが、この作法はよろしくないとのことで、HTMLHelperを使うのがよいらしいです。ちなみに、 @* *@がコメントらしいです。

    @foreach (var genre in Model)
    {
@*       <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>  *@
       <li>@Html.ActionLink(genre.Name, "Browse", new { genre = genre.Name })</li>
    }

実行しても、結果は同じなので割愛。

まとめ

ざっくり1〜3までのチュートリアルをサクッと終わらしたかんじでしょうか。
なんとなく雰囲気はつかめたので、次回。にして、はてな記法はむづいですね。

Part 1: Overview and File->New Project : The Official Microsoft ASP.NET Site
Part 2: Controllers : The Official Microsoft ASP.NET Site
Part 3: Views and ViewModels : The Official Microsoft ASP.NET Site