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>

提交后的modelList排除项目2(注意所有输入的值=“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/name(顺便说一下,具有相同 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.Hidden以避免重复的 id 像这样:

@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 回答