C# 处理数组';回发数据中的s-MVC3

C# 处理数组';回发数据中的s-MVC3,c#,asp.net-mvc,asp.net-mvc-3,razor,C#,Asp.net Mvc,Asp.net Mvc 3,Razor,我目前是一名WebForms开发人员,正试图转向MVC。我对MVC超级兴奋,我真的很开心,但我遇到了一个奇怪的问题。所以我要做的是为“小部件”创建一个高级编辑器。我已经把代码贴在下面了 当您添加前4-5项时,一切看起来都正常,但当您删除第2项时,问题就出现了。这是一个直观的例子 首先添加4个值 但是当我们删除第二个值时,问题就出现了。我们以这个结束 我似乎无法理解的是,为什么这个属性在下面两行代码中的行为不同 @Model.Values[i] @Html.TextBoxFor(m =>

我目前是一名WebForms开发人员,正试图转向MVC。我对MVC超级兴奋,我真的很开心,但我遇到了一个奇怪的问题。所以我要做的是为“小部件”创建一个高级编辑器。我已经把代码贴在下面了

当您添加前4-5项时,一切看起来都正常,但当您删除第2项时,问题就出现了。这是一个直观的例子

首先添加4个值

但是当我们删除第二个值时,问题就出现了。我们以这个结束

我似乎无法理解的是,为什么这个属性在下面两行代码中的行为不同

@Model.Values[i]
@Html.TextBoxFor(m => m.Values[i])
我的猜测是@Model和(m=>m)没有引用同一个对象

这是我的widget类

public class Widget
{
    #region Constructor

    public Widget()
    {
        ID = 0;
        Name = string.Empty;
        Values = new List<string>();
    }

    #endregion

    #region Properties

    [Required]
    [Display(Name = "ID")]
    public int ID { get; set; }

    [Required]
    [Display(Name = "Name")]
    public string Name { get; set; }

    [Required]
    [Display(Name = "Values")]
    public List<string> Values { get; set; }

    #endregion
}
最后是我的观点

@model MvcTestApplication.Models.Widget

@{
    ViewBag.Title = "EditWidget";
}

<h2>EditWidget</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Widget</legend>

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

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        @for (var i = 0; i < Model.Values.Count; i++)
        {
            @Model.Values[i]
            @Html.TextBoxFor(m => m.Values[i])
            @Html.HiddenFor(m => m.Values[i])
            <br />
        }

        @Html.ListBox("ListBoxWidgetValues", new SelectList(Model.Values), new { style = "width: 100%" })<br />
        @Html.TextBox("TextBoxWidgetValue", string.Empty, new { style = "width: 100%" })
        <input type="submit" value="Add" id="AddWidgetValue" name="AddWidgetValue" class="submitButton" />
        <input type="submit" value="Delete" id="DeleteWidgetValue" name="DeleteWidgetValue" class="submitButton" />

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

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@model MvcTestApplication.Models.Widget
@{
ViewBag.Title=“EditWidget”;
}
编辑小部件
@使用(Html.BeginForm()){
@Html.ValidationSummary(true)
小装置
@Html.HiddenFor(model=>model.ID)
@LabelFor(model=>model.Name)
@EditorFor(model=>model.Name)
@Html.ValidationMessageFor(model=>model.Name)
@对于(var i=0;im.Values[i])
@Html.HiddenFor(m=>m.Values[i])

} @Html.ListBox(“ListBoxWidgetValues”,新建SelectList(Model.Values),新建{style=“width:100%”)
@TextBox(“TextBoxWidgetValue”,string.Empty,new{style=“width:100%”)

} @ActionLink(“返回列表”、“索引”)
发生这种情况的原因是,HTML帮助程序在绑定时首先查看ModelState发布的值,然后在模型中查看。这意味着,如果在POST控制器操作中尝试修改某些值,并且该值是初始POST请求的一部分,则HTML帮助程序将使用初始值,而不是您修改的值

例如,在EditWidget操作中,您正在执行以下操作:

if (Request.Form["DeleteWidgetValue"] != null)
{
    widget.Values.Remove(Request.Form["ListBoxWidgetValues"]);
    return View("EditWidget", widget);
}
您应该从模型状态中删除最初发布的值:

if (Request.Form["DeleteWidgetValue"] != null)
{
    var itemToRemove = Request.Form["ListBoxWidgetValues"];
    var index = widget.Values.IndexOf(itemToRemove);
    ModelState.Remove("Values[" + index + "]");
    widget.Values.Remove(itemToRemove);
    return View("EditWidget", widget);
}
因此,POST请求包含:

Values[0] = 1
Values[1] = 2
Values[2] = 3
Values[3] = 4
在POST操作中,您删除了第二项,因此您也应该将其从模型状态中删除,否则TextBoxFor helper仍将使用旧项


你也可能会发现这个方法很有用。这是针对ASP.NET MVC 2 WebForms的,但将其应用于Razor并不重要。

感谢您的回答,我将对其进行测试。我这样做对吗?有没有更好的方法来处理列表框中的字符串列表?@Bobby Cannon,看看我链接的博文:它说明了使用AJAX的另一种方法。我想让我感到不快的是,我希望“return View(“EditWidget”,widget”)”更新/替换模型状态。我想这不会发生。@Bobby Cannon,
return View(“EditWidget”,widget)
将更新后的模型传递给视图,但在视图中,您使用的是TextBoxFor helper,它使用的是发布的值,而不是从模型中传递给此视图并在操作中更新的值。@Darin Dimitrov,因此@model是更新后的模型,但(m=>m)引用发布的值?那么有没有办法对@Model对象执行@Html.TextBoxFor?
Values[0] = 1
Values[1] = 2
Values[2] = 3
Values[3] = 4