1

私のアプリケーションには、検索ボックスがほとんどないページがあります。ユーザーがそれぞれの検索ボタンをクリックすると、結果グリッドが読み込まれることが期待されます。そのグリッドには、データを保存するために必要に応じてユーザーが変更して保存ボタンを押すことができる編集可能なコントロールがほとんどありません。

AjaxForm と部分ビューを使用して機能を実装しました。

  1. 検索ボックスと検索ボタンを含む検索領域は、Ajax.BeginForm を使用して作成され、送信時にコントローラーからポストバック Search メソッドが呼び出されます。SearchModel がこのメソッドに渡されます。
  2. 結果を表示するために部分ビューが作成され、ステップ 1 の Ajax フォームがコントローラーのポストバック メソッドから正常にロードされます。SearchModel.Results プロパティは、そのモデルとしてビューに渡されます。
  3. 結果を示すこの部分ビューには、コントローラーで別のメソッドを呼び出すが、コントローラーでモデル null を取得する [保存] ボタン (これも Ajax フォーム) があります。

多くのトリックを試みましたが、失敗しました。これを機能させるための実際の例や提案はありますか? データをロードするための AjaxForm の使用法が説明されている Web 上の多くの例がありますが、複数の (またはネストされた?) ものは見つかりませんでした。

前もって感謝します。

編集 - 2月24日

これは、Visual Studio の既定の MVC テンプレートを使用して作成したサンプルです。これは、上記で説明した実際の基準に似ており、部分ページの送信で同じ問題があります。

ビュー:

インデックス.cshtml

    @using MvcApplication1.Models
    @model SearchModel

    @{
        ViewBag.Title = "Home Page";
    }

     <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" ></script>
    <h2>@ViewBag.Message</h2>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
    </p>



@Ajax.BeginForm("Search", "Home", new AjaxOptions { HttpMethod = "Post", 
InsertionMode = InsertionMode.Replace,UpdateTargetId = "SearchResults"})
{
     <table>
    <tr>
        <td>
            First Name:
        </td>
        <td>
            @Html.TextBoxFor(m => m.SearchString)
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="submit" value="Submit" />
        </td>
    </tr>
</table>

}
<div id="SearchResults" style="color: Green;"></div>

部分ビュー - _SearchResult.cshtml

    @using MvcApplication1.Models
    @model MvcApplication1.Models.SearchModel
    @{
        ViewBag.Title = "Result Partial";
    }
    <h2>
        testPartial</h2>
    @Ajax.BeginForm("SearchResult", "Home", new AjaxOptions
    {
        HttpMethod = "Post"
    })
    {
    <table>
        @foreach (ResultModel item in Model.Result)
        {
            <tr>
                <td>
                    Name:
                </td>
                <td>
                    @Html.DisplayFor(m => item.Name)
                </td>
            </tr>
            <tr>
                <td>
                    Address:
                </td>
                <td>
                    @Html.TextAreaFor(m => item.Address)
                </td>
            </tr>

        }
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit" />
            </td>
        </tr>
    </table>
    }

モデル:

SearchModel.cs

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

    namespace MvcApplication1.Models
    {
        public class SearchModel
        {
            public string SearchString  { get; set; }

            public List<ResultModel> Result { get; set; }
        }
    }

ResultModel.cs

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

    namespace MvcApplication1.Models
    {
        public class ResultModel
        {
            public string Name { get; set; }
            public string Address { get; set; }
        }
    }

コントローラ:

HomeController.cs

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

    namespace MvcApplication1.Controllers
    {
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                ViewBag.Message = "Welcome to ASP.NET MVC!";

                return View();
            }

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

            [HttpPost]
            public ActionResult Search(SearchModel model)
            {
                //dummy search for result
                List<ResultModel> result = new List<ResultModel>();

                ResultModel res1 = new ResultModel();
                res1.Name = model.SearchString + " 1";
                res1.Address = "Dummy address";

                result.Add(res1);

                ResultModel res2 = new ResultModel();
                res2.Name = model.SearchString + " 2";
                res2.Address = "Rummy address";

                result.Add(res2);

                //assign seach results to model
                model.Result = result;

                return PartialView("_SearchResult", model);
            }

            [HttpPost]
            public ActionResult SearchResult(SearchModel model)
            {
                //do something with results

                List<ResultModel> res = model.Result; // null here !!

                return RedirectToAction("Index");
            }
        }
    }

SO、上記のサンプルは

  1. ホームページに検索ボックスを表示する - Index.cshtml
  2. 送信をクリックすると、検索の下に結果を表示する部分ビューが読み込まれます
  3. 検索結果を編集して結果フォームで [送信] を押すと、そこにブレークポイントを設定してください。返されるモデルが null であることがわかります。

これで私の問題が説明できることを願っています。

4

1 に答える 1

1

実際のコードと完全な例を示したので、質問に答えることができます。

あなたが得てnullいる理由は、デフォルトのモデルバインダーが期待する入力フィールドの標準命名規則を尊重していないためです. Phil Haackの を読んで、following articleこれらの規則に慣れてください。

コードの問題はforeach、エディター テンプレートを使用する代わりに、パーシャル内でループを使用して結果をレンダリングしたことです。したがって、内部のコードを_SearchResult.cshtml次のように置き換えます。

@using MvcApplication1.Models
@model SearchModel
@{
    ViewBag.Title = "Result Partial";
}
<h2>testPartial</h2>

@using(Ajax.BeginForm("SearchResult", "Home", new AjaxOptions()))
{
    <table>
        @Html.EditorFor(x => x.Result)
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit" />
            </td>
        </tr>
    </table>
}

次に、そのタイプのカスタム エディター テンプレートを定義しますResultModel( ~/Views/Shared/EditorTemplates/ResultModel.cshtml- 警告、エディター テンプレートの名前と場所は、規則に従って機能するため重要です)。

@using MvcApplication1.Models
@model ResultModel

<tr>
    <td>
        Name:
    </td>
    <td>
        @Html.DisplayFor(m => m.Name)
        @Html.HiddenFor(m => m.Name)
    </td>
</tr>
<tr>
    <td>
        Address:
    </td>
    <td>
        @Html.TextAreaFor(m => m.Address)
    </td>
</tr>

注意事項:

  • Ajax.BeginFormヘルパーをusingステートメントでラップしました。Index.cshtmlビュー内で同じことを行う必要があります
  • @Html.HiddenFor(m => m.Name)フォームが送信されたときにこの値をサーバーに送信するために、カスタム エディター テンプレート ( ) 内に Name プロパティの非表示フィールドを追加しました。あなたのサーバーに。
于 2013-02-24T13:46:29.763 に答える