CodeZine(コードジン)

特集ページ一覧

ASP.NET MVCの開発応用編1
~リポジトリパターンをマスターする~

ASP.NET MVCフレームワーク 正式版 入門(4)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2009/10/05 14:00
目次

3.アプリケーションロジック(Controller)への適用

 それでは実際にリポジトリクラスをControllerクラスへ適用してみましょう。

 最初に設定するのはコンストラクタです。通常実行時用と、単体テスト用のコンストラクタの2種類を設定します。

PubsControllerクラスの一部
using System;
using System.Web.Mvc;
using RepositorySample.Models;

namespace RepositorySample.Controllers
{
    public class PubsController : Controller
    {
        IPubsRepository pubsrepository;
        public PubsController() : this(new PubsRepository())
        {
        }
        public PubsController(IPubsRepository repository)
        {
            pubsrepository = repository;
        }

       <中略>

    }
}

 最初にIPubsRepositoryインターフェイスを宣言し、パラメタなしのコンストラクタが呼ばれた時、自身のオブジェクトをPubsRepositoryクラスのパラメタ付きで再生成しています。パラメタ付きのコンストラクタで、PubsRepositoryクラスをIPubsRepositoryインターフェイスに代入して利用します。続いて各項目メソッドのコードです。

Index/Detailsメソッド

 Index(一覧取得)・Details(詳細表示)は値を取得後、LINQ結果を各ページに渡すだけだったので、非常にシンプルになります。

PubsControllerクラスの一部
using System;
using System.Web.Mvc;
using RepositorySample.Models;

namespace RepositorySample.Controllers
{
    public class PubsController : Controller
    {
        IPubsRepository pubsrepository;

        <中略>

        public ActionResult Index()
        {
            // titlesエンティティのレコードを全取得
            var _titles = pubsrepository.FindAllTitles();

            // Index.aspxページにLINQ結果のModelを渡す
            return View(_titles);
        }

        //
        // GET: /Pubs/Details/5

        public ActionResult Details(string id)
        {
            // idと一致するレコードを取得
            var _titles = pubsrepository.GetDetailTitles(id);

            // Details.aspxページにLINQ結果のModelを渡す
            return View(_titles);
        }

    }
}

 前述したように、FindAllTitlesメソッドでエンティティ内のレコードを全取得を、GetDetailTitlesメソッドでは、idと一致するレコードを取得し返します。

Createメソッド

 Create(新規レコード作成)は初回アクセス時にCreate.aspxページを表示させ、ポストアクセス時にレコードを登録します。検証部分などは第2回の内容と変わりないので割愛します。

 今回はControllerクラスに検証機能を格納していますが、検証機能はControllerクラス内に置く必要はないので、リポジトリクラス内に格納するか(ただし、リポジトリはデータアクセスのみに集中させることが筆者のおススメ)または、検証クラスを作成し、そちらにすべて委譲することで、よりControllerクラス内がすっきりします。

PubsControllerクラスの一部
using System;
using System.Web.Mvc;
using RepositorySample.Models;

namespace RepositorySample.Controllers
{
    public class PubsController : Controller
    {
        IPubsRepository pubsrepository;

        <中略>

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

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(titles Titles, FormCollection collection)
        {
               <中略~検証コードは前回と同じです~>

            // 検証メッセージが格納されているかチェック(なければTrue)
            if (ModelState.IsValid)
            {
                try
                {
                    // titlesEntityにレコードを追加する
                    pubsrepository.Add(Titles);

                    // Index.aspxページにリダイレクト
                    return RedirectToAction("Index");
                }
                catch
                {
                    return View();
                }
            }
            return View();
        }

 Createメソッドもリポジトリクラスを利用することで、データアクセス部分がすっきりしています。Model(titlesエンティティ)をパラメタとして渡しているので、既に登録予定のレコードはTitlesオブジェクトにバインドされています。バインドされている値をAddメソッドを使い、リポジトリクラス側でEDMに登録し、DBへデータ反映を行っています。

Editメソッド

 Edit(レコード編集)は初回アクセス時にDetails同様の処理でページに値をバインドし、ポストアクセス時にレコードを編集します。

PubsControllerクラスの一部
using System;
using System.Web.Mvc;
using RepositorySample.Models;

namespace RepositorySample.Controllers
{
    public class PubsController : Controller
    {
        IPubsRepository pubsrepository;

        <中略>

        public ActionResult Edit(string id)
        {
            // idと一致するレコードを取得
            var _titles = pubsrepository.GetDetailTitles(id);
            // Edit.aspxページにLINQ結果のModelを渡す
            return View(_titles);
        }

        // ②編集更新ボタンクリック時
        // POST: /Pubs/Edit/5

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(string id, FormCollection collection)
        {
            // idと一致するレコードを取得
            var _titles = pubsrepository.GetDetailTitles(id);

            try
            {
                // 主キーとなるtitle_id以外の項目の更新があればそれを更新する
                UpdateModel(_titles);
                // 更新を反映させる
                pubsrepository.Save();
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

 ポストアクセス時のEditメソッドでは、GetDetailTitlesメソッドでレコード抽出後、UpdateModelメソッドで、編集レコードの更新を行います。その後、Saveメソッドで更新を反映させ、最後にIndex.aspxページにリダイレクトしています。

Deleteメソッド

 今回新規で追加するDeleteメソッドですが、ASP.NET MVCで作成する際に1点注意事項があります。それは、ActionLinkヘルパーメソッドから直接削除処理をさせないことです。

 少し考えれば分かることですが、インターネット上に公開する際、検索エンジンからのクロールを意識する必要があります。もし、リンクで直接削除処理ができてしまう場合、検索エンジンのクロールにより、データがすべて消えてしまう可能性があります。そこで、DELETE機能を実装する場合の1つの手法として、ポストアクセス時に実装するということも押さえておいてください。

 もう少しセキュアな方法を推奨するならば認証ユーザーしか削除できないようにすると良いでしょう(これはCreateメソッドや場合によってはIndex/Details/Editにも当てはまります)。

 さて、本題です。

 Delete(レコード削除)は初回アクセス時にDetails同様の処理でページに値をバインドし、ポストアクセス時にレコードを削除します。

PubsControllerクラスの一部
using System;
using System.Web.Mvc;
using RepositorySample.Models;

namespace RepositorySample.Controllers
{
    public class PubsController : Controller
    {
        IPubsRepository pubsrepository;

        <中略>

        public ActionResult Delete(string id)
        {
            // idと一致するレコードを取得
            var _titles = pubsrepository.GetDetailTitles(id);
            // Edit.aspxページにLINQ結果のModelを渡す
            return View(_titles);
        }

        // ②DELETEボタンクリック時
        // POST: /Pubs/Edit/5

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(string id, FormCollection collection)
        {
            // idと一致するレコードを取得
            var _titles = pubsrepository.GetDetailTitles(id);

            try
            {
                // 更新を反映させる
                pubsrepository.Delete(_titles);
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

 処理的に言うと、Createメソッドとほぼ同じです。違う点は、GetDetailTitlesメソッドでidと一致するレコードを取得後、Addメソッドの代わりにDeleteメソッドでレコードを削除している点です。

 なお、ViewPage側は今回Add Viewダイアログで、次のように設定しています。

Add Viewの設定
項目名 設定内容
View name Delete
Create a strongly-typed view チェック
View data class RepositorySample.Models.titles
View content Details
その他の項目 既定のまま

 ViewPage側の設定で修正している点は次の部分です。

Detlete.aspxの一部
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Delete</h2>
    <% using (Html.BeginForm())
       {%>
        <p>
            以下の項目を削除します。よろしいですか?
            <input type="submit" value="Delete" />
        </p>
    <% } %>

    <以下Detailsの表示部分>

 BeginFormヘルパーメソッドを利用してポストアクセスを行っています。

 Index/Details/Create/Edit/Deleteと見てきましたが、データアクセス部分とControllerを分離できていることをご確認いただけたかと思います。続いて、単体テストについて触れてみます。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:ASP.NET MVCフレームワーク 正式版 入門

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト ナオキ(ナオキ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5