0

div内部に部分的なビューを含む単純なビューがあります。部分ビューには項目のリストが含まれています。各項目は、除外された状態 (XXX でマーク) で表示されるか、項目を除外するボタン ( を使用Ajax.BeginForm) とともに表示され、 を送信してIdその状態を更新し、リストを再描画します。

ページが最初に描画されたときは正しく動作しますが、項目を除外するための Ajax 呼び出しの後に部分ビューが再レンダリングされると、リスト内の各項目が固有のものではなく、itemIdすべてitemIdの項目によって除外された項目のフォームの送信。

Index.cshtml (メイン ビュー)

@model IEnumerable<StackOverflowMvc.Controllers.TestModel>

<div id="modelList">
    @Html.Partial("ItemList", Model)
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

ItemList.cshtml (部分ビュー)

@model IEnumerable<StackOverflowMvc.Controllers.TestModel>

<ul>
    @foreach (var item in Model)
    {
        <li>
            <label>@item.Name</label>
            @if(item.Excluded) {
                <label>XXX</label>
            } else {
                using (Ajax.BeginForm("ExcludeItem", new AjaxOptions
                                    {
                                        HttpMethod = "post",
                                        InsertionMode = InsertionMode.Replace,
                                        UpdateTargetId = "modelList"
                                    })) {      
                    @Html.Hidden("id", item.Id)
<!--                    <input type="hidden" name="id" value="@item.Id" />  -->
                        <input type="submit" value="Check" />
                }       
            } 
        </li>
    }
</ul>

非表示の入力をコメントアウトして@Html.Hiddenコメントを解除することで、ページを機能させることができます (この場合、アイテムの ID に正しい値が設定されます)。

何が起きてる?Html.Hiddenの使用方法または Ajax フォームに何か問題がありますか? それとも、この状況では機能しないはずですか?

HomeController.cs (関連する場合に備えて)

public class TestModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool Excluded { get; set; }
}

public class HomeController : Controller
{
    static List<TestModel> _items = new List<TestModel>{
        new TestModel { Id=1, Name="Item 1", Excluded=false },
        new TestModel { Id=2, Name="Item 2", Excluded=false },
        new TestModel { Id=3, Name="Item 3", Excluded=false },
        new TestModel { Id=4, Name="Item 4", Excluded=false }
    };

    public ActionResult Index()
    {
        return View(_items);
    }

    public ActionResult GetItems()
    {
        return PartialView("ItemList", _items);
    }

    [HttpPost]
    public ActionResult ExcludeItem(int id)
    {
        _items.Find(x=>x.Id == id).Excluded = true;
        return PartialView("ItemList", _items);
    }

}

問題の説明に役立つサンプル出力:

ページ読み込み時の modelList div

<div id="modelList">
    <ul>
        <li>
            <label>Item 1</label>
<form action="/Home/ExcludeItem" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#modelList" id="form0" method="post">
                        <input id="id" name="id" type="hidden" value="1" /><!--                        <input type="hidden" name="id" value="1" />  -->
                        <input type="submit" value="Check" />
</form>        </li>
        <li>
            <label>Item 2</label>
<form action="/Home/ExcludeItem" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#modelList" id="form1" method="post">
                        <input id="id" name="id" type="hidden" value="2" /><!--                        <input type="hidden" name="id" value="2" />  -->
                        <input type="submit" value="Check" />
</form>        </li>
        <li>
            <label>Item 3</label>
<form action="/Home/ExcludeItem" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#modelList" id="form2" method="post">
                        <input id="id" name="id" type="hidden" value="3" /><!--                        <input type="hidden" name="id" value="3" />  -->
                        <input type="submit" value="Check" />
</form>        </li>
        <li>
            <label>Item 4</label>
<form action="/Home/ExcludeItem" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#modelList" id="form3" method="post">
                        <input id="id" name="id" type="hidden" value="4" /><!--                        <input type="hidden" name="id" value="4" />  -->
                        <input type="submit" value="Check" />
</form>        </li>
</ul>
</div>

アイテム 2 を除外するために送信した後の modelList (すべての入力に value="2" があることに注意してください)

<div id="modelList">
    <ul>
        <li>
            <label>Item 1</label>
<form action="/Home/ExcludeItem" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#modelList" id="form0" method="post">
                        <input id="id" name="id" type="hidden" value="2" /><!--                        <input type="hidden" name="id" value="1" />  -->
                        <input type="submit" value="Check" />
</form>        </li>
        <li>
            <label>Item 2</label>
            <label>XXX</label>
        </li>
        <li>
            <label>Item 3</label>
<form action="/Home/ExcludeItem" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#modelList" id="form1" method="post">
                        <input id="id" name="id" type="hidden" value="2" /><!--                        <input type="hidden" name="id" value="3" />  -->
                        <input type="submit" value="Check" />
</form>        </li>
        <li>
            <label>Item 4</label>
<form action="/Home/ExcludeItem" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#modelList" id="form2" method="post">
                        <input id="id" name="id" type="hidden" value="2" /><!--                        <input type="hidden" name="id" value="4" />  -->
                        <input type="submit" value="Check" />
</form>        </li>
</ul>
</div>
4

1 に答える 1

2

この問題は、すべてのinput要素が同じ ID/名前を持ち (同じ ID を持つ要素が複数あると無効な HTML が発生するため)、ASP.NET MVC がデータに基づいて入力を再バインドしているという事実によって引き起こされます。モデルからでModelStateはありません (これは、ユーザーが入力した値を含むフォームを返すためにデフォルトで使用されるメカニズムです)。

バインドを回避するModelStateには、POST アクションで単純にクリアします。

[HttpPost]
public ActionResult ExcludeItem(int id)
{
    _items.Find(x=>x.Id == id).Excluded = true;
    ModelState.Clear();
    return PartialView("ItemList", _items);
}

Html.HiddenID の重複を避けるために、呼び出しを次のように変更することもお勧めします。

@Html.Hidden("id", item.Id, new { @id = "id_" + item.Id });

このようにして、入力は次のようにレンダリングされます。

<input id="id_4" name="id" type="hidden" value="4" />

これは完全に有効であり、適切にバインドされます。

于 2013-11-13T12:48:07.573 に答える