c# - ASP.NET MVC : removing item from a list in a nested structure always removes the last item 中的异常行为

标签 c# .net asp.net-mvc asp.net-mvc-2

场景

我有一个父/子模型(确切地说是一个小调查表和一个或多个联系人)。由于历史原因,所有这些都将在同一个表单上完成,因此用户将拥有一个用于 parent 和一个 child 的表单,然后他们可以点击一个按钮来添加更多 child 。子项有一些标准字段,与父项相同,没什么特别的。主要要求是在所有数据都有效和设置之前,数据不得接触数据库,而我必须返回服务器以添加删除子项。

实现

在 ASP.NET MVC 中(使用 MVC 2 和 VS 2010)很快就可以完成这项工作。我有两个模型,一个给 parent ,一个给 child ,只有一个 Controller 。 Controller 有一个 Create 方法,它是一个 get 并获取默认 View ,其中包含一个包含一个子项的全新父项。我为子模型使用编辑器模板,效果很好。

我有一个 HTML 表单,其中有一个“保存”和“添加子项”,每个表单都有一个“删除”按钮。由于这不能存储在数据库中,我将临时模型存储在表单本身中,并在浏览器和服务器之间来回传递。在这里,性能不是什么大问题,而是开发成本,因为有很多这样的形式 - 所以尽管我很欣赏评论,但请不要因为提出替代方法而分心太多。

为了找出要删除的子项,我创建了临时 GUID ID 并将它们与子项相关联。这将进入删除按钮的 HTML 输入值(当您有多个操作和相同的表单时通常的技巧)。

我已禁用缓存。

问题

请看下面的片段。我已经调试了代码,我看到总是传递正确的 GUID,从 Controller 列表中删除正确的项目,并在模板中呈现正确的项目。但总是最后一个被删除!!我通常点击第一个删除,可以看到最后一个被删除。我继续,第一项是最后一项被删除。

Controller

    public ActionResult Create()
    {
        EntryForm1 entryForm1 = new EntryForm1();
        entryForm1.Children.Add(new Child("FILL ME", "FILL ME"){ TempId = Guid.NewGuid()});
        return View("EntryForm1View", entryForm1);
    }

    [HttpPost]
    public ActionResult Create(EntryForm1 form1, FormCollection collection, string add)
    {
        if (add == "add")
            form1.Children.Add(new Child("FILL ME", "FILL ME") {TempId = Guid.NewGuid()});

        var deletes = collection.AllKeys.Where(s => s.StartsWith("delete_"));
        collection.Clear();
        if (deletes.Count() > 0)
        {
            string delete = deletes.FirstOrDefault();
            delete = delete.Replace("delete_", "");
            Guid g = Guid.Parse(delete);
            var Children = form1.Children.Where(x => x.TempId == g).ToArray();
            foreach (Child child in Children)
            {
                form1.Children.Remove(child);
            }               
            // HERE CORRECT ITEM IS DELETED, BELIEVE ME!!
        }
        if (ModelState.IsValid)
        {
            return Redirect("/");
        }
        return View("EntryForm1View", form1);
    }

查看片段

    <% for (int i = 0; i < Model.Children.Count;i++ )
  {%>
        <h4> <%: Html.EditorFor(m=>m.Children[i])%></h4>

        <%
  }%>
        <p>
            <input type="submit" value="Create" name="add" />
            <input type="submit" value="add" name="add" />
        </p>

子编辑器模板片段

        <%: Html.HiddenFor(x=>x.TempId) %>
        </span>
        <input type="submit" name='delete_<%: Html.DisplayTextFor(m => m.TempId) %>' value="Delete" />

非常感谢您的时间和关注


更新

我被要求提供模型类(class),我将按原样分享它们。 Entryform1父级Somesing子级

公开课Somesing {

    public Somesing()
    {

    }

    public Somesing(string o, string a) : this()
    {
        OneSing = o;
        AnozerSing = a;
    }

    [StringLength(2)]
    public string OneSing { get; set; }

    [StringLength(2)]
    public string AnozerSing { get; set; }

    public Guid TempId { get; set; }

}

public class EntryForm1
{

    public EntryForm1()
    {
        Sings = new List<Somesing>();
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int Age { get; set; }

    public List<Somesing> Sings { get; set; }

}

最佳答案

我认为问题在于 ModelState。当 View 被呈现时,我认为这是问题所在,在 POST 之后,最后一个值不会显示,即从 View 中删除。

问题是 Model.Children.Count 将返回要显示的正确元素数。

让我们分解一下...

因此,如果您最初有 5 个,然后根据 Guid 删除了索引为 0 的第一个,您现在有 4 个项目,索引为 1 到 4。

但是,在发布后呈现 View 时,HtmlHelpers 不会查看发布的模型中的值,而是查看 ModelState 中包含的值。因此在 ModelState 中,索引为 0 的项目仍然存在,并且由于循环现在循环到 4,因此不会显示最后一个元素。

解决方法,使用ModelState.Clear()

关于c# - ASP.NET MVC : removing item from a list in a nested structure always removes the last item 中的异常行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4438904/

相关文章:

asp.net-mvc - MVC 3 : Email notifications

.net - 使用 ASP.NET MVC 进行 jQuery 表单例份验证

c# - 反序列化json树结构并设置父级

c# - 文本属性中的全局资源

c# - 通过网络从 Xbox Kinect 流式传输视频

.net - XslTransform 与 XslCompiledTransform

C# 基于简单值的 DTO 比较(和 GetHashCode 困境)

.net - 如何判断流编写器是否已关闭?

c# - 如何关闭 MVC 请求的缓存而不是 IIS7 中的静态文件?

jquery - 如何在asp.net mvc中将Textbox值发送到ActionLink