Details および Delete アクション メソッドの確認

作成者: Rick Anderson

Note

ASP.NET MVC 5 と Visual Studio 2013 を使用するこのチュートリアルの更新版は、こちらで入手できます。 より安全で、より簡単に操作でき、より多くの機能を備えています。

チュートリアルのこのパートでは、自動的に生成された Details メソッドと Delete メソッドを確認します。

Details メソッドと Delete メソッドの確認

Movie コントローラーを開いて、Details メソッドを確認します。

Screenshot that shows the Movies Controller dot c s tab. Details is selected in the drop down menu on the right.

public ActionResult Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

このアクション メソッドを作成した MVC スキャフォールディング エンジンにより、メソッドを呼び出した HTTP 要求を示すコメントが追加されます。 この場合は、GET 要求で、Movies コントローラー、Details メソッド、ID 値という 3 つの URL セグメントが含まれます。

Code First は、Find メソッドによるデータの検索を容易にします。 このメソッドに組み込まれている重要なセキュリティ機能は、Find メソッドがムービーだと認識したことを、コードがそれに対して何かを実行する前にコードで検証することです。 たとえば、ハッカーは、リンクによって作成される URL を http://localhost:xxxx/Movies/Details/1 から http://localhost:xxxx/Movies/Details/12345 など (または、実際のムービーを表していないその他の値) に変更することで、サイトでエラーを発生させる可能性があります。 null ムービーをチェックしなかった場合、null ムービーによりデータベース エラーが発生します。

Delete メソッドと DeleteConfirmed メソッドを調べます。

// GET: /Movies/Delete/5
public ActionResult Delete(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

// POST: /Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
    Movie movie = db.Movies.Find(id);
    db.Movies.Remove(movie);
    db.SaveChanges();
    return RedirectToAction("Index");
}

HTTP Get``Delete メソッドは指定されたムービーを削除するのではなく、削除を送信 (HttpPost) できるムービーのビューを返すことに注意してください。 GET 要求の応答で削除操作を実行すると (さらに言えば、編集操作、作成操作、データを変更するその他のあらゆる操作を実行すると)、セキュリティに穴が空きます。 詳細については、Stephen Walther のブログ「ASP.NET MVC Tip #46 — Don't use Delete Links because they create Security Holes」を参照してください。

データを削除する HttpPost メソッドの名前は「DeleteConfirmed」になり、HTTP POST メソッドに一意のシグネチャまたは名前が与えられます。 2 つのメソッド シグネチャは下の画像のようになります。

// GET: /Movies/Delete/5
public ActionResult Delete(int? id)

//
// POST: /Movies/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)

共通言語ランタイム (CLR) は、オーバーロードのメソッドに一意のパラメーター シグネチャを持つことを要求します (メソッド名は同じであるが、パラメーターの一覧が異なる)。 ただし、ここでは、同じパラメーター シグネチャを持つ 2 つの Delete メソッド (GET 用と POST 用) が必要です。 (いずれも、1 つの整数をパラメーターとして受け取る必要があります。)

これらを区別するために、いくつかのことを行えます。 1 つは、メソッドに異なる名前を付けることです。 先の例では、スキャフォールディング メカニズムがこれを行いました。 しかし、これは小さな問題を引き起こします。ASP.NET が URL のセグメントをアクション メソッドに名前でマッピングします。メソッドの名前を変更すると、通常、ルーティングでそのメソッドが見つからなくなります。 この解決策はこの例で確認できます。ActionName("Delete") 属性を DeleteConfirmed メソッドに追加しています。 これは実質的に、ルーティング システムに対してマッピングを行って、POST 要求の /Delete/ を含む URL が DeleteConfirmed を見つけられるようにすることです。

同じ名前とシグネチャを持つメソッドの問題を回避するもう 1 つの一般的な方法は、POST メソッドのシグネチャを人為的に変更して使われていないパラメーターを含めることです。 たとえば、一部の開発者は POST メソッドに渡すパラメーター型 FormCollection を追加してから、そのパラメーターを単に使用しないことにしています:

public ActionResult Delete(FormCollection fcNotUsed, int id = 0)
{
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    db.Movies.Remove(movie);
    db.SaveChanges();
    return RedirectToAction("Index");
}

まとめ

これで、ローカル DB データベースにデータを格納する完全な ASP.NET MVC アプリケーションが完成しました。 ムービーの作成、読み取り、更新、削除、検索を行うことができます。

Screenshot that shows the M V C Movie Search Index page.

次のステップ

Web アプリケーションを構築してテストしたら、次の手順は、他のユーザーがそのアプリケーションをインターネット経由で使用できるようにすることです。 そのためには、Web ホスティング プロバイダーにデプロイする必要があります。 Microsoft は、無料の Windows Azure 試用版アカウントで最大 10 個の Web サイトに対応する無料の Web ホスティングを提供しています。 次に、メンバーシップ、OAuth、SQL Database を使ってセキュリティで保護された ASP.NET MVC アプリを Windows Azure Web サイトにデプロイするチュートリアルに従うことをお勧めします。 優れたチュートリアルは、Tom Dykstra の中級レベルの ASP.NET MVC アプリケーション用の Entity Framework データ モデルの作成です。 StackoverflowASP.NET MVC フォーラムは、質問するのに最適な場所です。 Twitter で筆者をフォローして、最新のチュートリアルの更新情報を入手してください。

ご意見をお待ちしております。

- Rick Anderson twitter: @RickAndMSFT
- Scott Hanselman twitter: @shanselman