web-dev-qa-db-ja.com

@ Html.BeginForm()はどのように機能しますか?

私はASP.NETが初めてで、asp.netでMVCチュートリアルを開始しました。ここに来ました http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view =

これまでのところ、問題は:

私のビューには次のコードがあります(モデルは@model MyFirstMVC4.Models.Movieのビューに設定されています)

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Movie</legend>

        @Html.HiddenFor(model => model.ID)

        //... bla bla html input
        <p>
             <input type="submit" value="Save" />
        </p>
    </fieldset>
}

私のMovieController

    // Shows the view
    public ActionResult Edit(int id = 0)
    {
        Movie movie = db.Movies.Find(id);
        if (movie == null)
        {
            return HttpNotFound();
        }
        return View(movie);
    }

    //
    // POST: /Movie/Edit/5

    [HttpPost] // Handles the view above
    public ActionResult Edit(Movie movie)
    {
        if (ModelState.IsValid)
        {
            db.Entry(movie).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(movie);
    }

そして、ここに質問があります-どうやってMovieオブジェクトを上記のPOSTメソッドに渡すのですか?!クライアント側を観察すると

<form action = "/Movie/Edit/1" ... />

ここで、なぜ同じビューページのaction = urlなのか理解できません!1また、サーバー側にもHtml.BeginForm()があります:動作しますが、理由がわかりません

20
Ivan Prodanov

コードのBeginFormのバージョンは、パラメーターなしで、HTTP POST=を現在のURLに送信します。したがって、ビューが/Movie/Edit/5、開始フォームタグは次のようになります:< form action="/Movie/Edit/5" method="post">

BeginForm HTMLヘルパーは、MovieControllerのEditアクションに到達する方法をルーティングエンジンに要求します。舞台裏では、RouteTableによって公開されるRoutesプロパティでGetVirtualPathというメソッドを使用します。これは、Webアプリケーションがglobal.asaxですべてのルートを登録した場所です。 HTMLヘルパーなしでこれをすべて実行した場合、次のすべてのコードを記述する必要があります。

  @{
 var context = this.ViewContext.RequestContext;
  var values = new RouteValueDictionary{
  { "controller", "movie" }, { "action", "edit" }
 };
  var path = RouteTable.Routes.GetVirtualPath(context, values);
 }
 <form action="@path.VirtualPath" method="get">
  ...
 </form>

ムービーオブジェクトがどのように渡されるかを尋ねました。と呼ばれます モデルバインディング。パラメーターを持つアクションがある場合、MVCランタイムはモデルバインダーを使用してパラメーターを構築します。複数のモデルバインダーを異なるタイプのモデルのMVCランタイムに登録できますが、デフォルトでは主力はDefaultModelBinderになります。

Movieオブジェクトの場合、デフォルトのモデルバインダーはMovieを検査し、バインドに使用できるすべてのムービープロパティを見つけます。前に検討した命名規則に従って、デフォルトのモデルバインダーは、要求からムービーオブジェクトに値を自動的に変換および移動できます(モデルバインダーは、入力するオブジェクトのインスタンスを作成することもできます)。言い換えると、モデルバインダーは、MovieにTitleプロパティがあることを認識すると、リクエストで「Title」という名前の値を探します。モデルバインダーは「フォームコレクションではなく」「リクエスト内」に見えることに注意してください。モデルバインダーは、値プロバイダーと呼ばれるコンポーネントを使用して、リクエストのさまざまな領域の値を検索します。モデルバインダーはルートデータ、クエリ文字列、およびフォームコレクションを参照できます。必要に応じて、カスタム値プロバイダーを追加できます。

39
Vlado Pandžić

パラメータなしでBeginForm()を呼び出すと、デフォルトで現在のページのレンダリングに使用したのと同じコントローラ/アクションが使用されます。コントローラーに正しい名前のアクションがあり、ポストバックを受け入れるアクションがあることを前提としています。これにはRouteValuesを使用します。

各入力コントロールを(名前で)ポストバックを受け入れるアクションのパラメーターに自動的にバインドします-場合によっては、ポストバックを受け入れるアクションのオブジェクトパラメーターのプロパティにバインドします。

9
Nick Albrecht

_[HttpPost]_属性は、フォームのPOST送信時に呼び出されるアクションに与えられます。

@using (Html.BeginForm())がどのように機能するかを理解するには、既にどのページにあるかを知る必要があります。 2つの異なるビューで@using (Html.BeginForm())を使用すると、2つの異なるコントローラーに戻ります

4
Scott Selby

単純なhtmlまたはhtmlヘルパーを入力してフォームを作成できます。それらの1つはHtml.BeginForm();この特定のヘルパーはC#でIDisposableを実装するオブジェクトを返すため、実際にusingステートメントでラップできるため、少し奇妙です。最初に開始タグで書き出します。そして、生成されたコードがそのオブジェクトに対してdisposeを呼び出したとき、それは終了タグを書き出すときです。したがって、BeginFormは、開始フォームタグと終了タグを書き出すオブジェクトを提供します。その後は、ラベルと入力のみに集中できるので、心配する必要はありません。

0