SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

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

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

  • X ポスト
  • このエントリーをはてなブックマークに追加

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を分離できていることをご確認いただけたかと思います。続いて、単体テストについて触れてみます。

次のページ
リポジトリパターンにおける単体テスト

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
ASP.NET MVCフレームワーク 正式版 入門連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4354 2009/10/05 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング