处理回发数据中的数组-MVC3 [英] Handling array's in post back data - MVC3

查看:63
本文介绍了处理回发数据中的数组-MVC3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前是一个WebForms开发人员,正在尝试迁移到MVC.我对MVC感到非常兴奋,我真的很开心,但是我遇到了一个奇怪的问题.所以我想做的是为小部件"创建一个高级编辑器.我已经在下面发布了代码.

I'm current a WebForms developer that is trying to move to MVC. I'm super excited about MVC and I'm really have fun but I'm running into a weird issue. So what I'm trying to do is create an advanced editor for a "widget". I've posted the code below.

当您添加第一个4-5个项目时,一切似乎都可以正常工作,但是当您删除第二个项目时,就会出现问题.这是一个直观的示例.

Everything appears to work fine when you add the first 4-5 items but the problem occurs when you delete the 2nd item. Here is a visual example.

首先添加4个值.

但是当我们删除第二个值时会发生问题.我们最终得到了这个...

But the problem occurs when we delete the 2nd value. We end up with this...

我似乎无法理解的是,为什么此属性在以下两行代码之间的行为有所不同.

What I cannot seem to understand is why does this property act different between the two following lines of code.

@Model.Values[i]
@Html.TextBoxFor(m => m.Values[i])

我的猜测是@Model和(m => m)没有引用同一对象?

My guess is that the @Model and (m =>m) do not reference the same object?

这是我的小部件类.

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
}

我的控制器看起来像这样.

My controller looks like this.

public ViewResult EditWidget(int id)
{
    return View(_widgets.GetWidgetByID(id));
}

[HttpPost]
public ActionResult EditWidget(Widget widget)
{
    if (!TryUpdateModel(widget))
    {
        ViewBag.Message = "Error...";
        return View(widget);
    }

    if (Request.Form["AddWidgetValue"] != null)
    {
        widget.Values.Add(Request.Form["TextBoxWidgetValue"]);
        return View("EditWidget", widget);
    }

    if (Request.Form["DeleteWidgetValue"] != null)
    {
        widget.Values.Remove(Request.Form["ListBoxWidgetValues"]);
        return View("EditWidget", widget);
    }

    _widgets.UpdateWidget(widget);
    _widgets.Save();

    return RedirectToAction("Index");
}

最后是我的看法.

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

推荐答案

发生这种情况的原因是因为HTML助手在绑定时首先查看ModelState发布的值,然后在模型中查看.这意味着,如果在POST控制器操作中尝试修改一些值,并且该值是初始发布请求的一部分,则HTML帮助程序将使用初始值,而不是您修改的值.

The reason for this happening is because HTML helpers first look at ModelState posted values when binding and then in model. This means that if inside your POST controller action you try to modify some value and this same value was part of the initial post request the HTML helper will use the initial value and not the one you modified.

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

For example in your EditWidget action you are doing this:

if (Request.Form["DeleteWidgetValue"] != null)
{
    widget.Values.Remove(Request.Form["ListBoxWidgetValues"]);
    return View("EditWidget", widget);
}

您应该从模型状态中删除初始发布的值:

You should remove the initially posted value from the model state:

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请求包含:

So the POST request contained:

Values[0] = 1
Values[1] = 2
Values[2] = 3
Values[3] = 4

在POST操作中,您删除了第二个项目,例如第二个项目,因此您也应该将其从模型状态中删除,否则TextBoxFor帮助程序仍将使用旧的项目.

Inside the POST action you removed for example the second item so you should also remove it from the model state or the TextBoxFor helper will still use the old one.

您还可以找到

You may also find the following blog post useful. It's for ASP.NET MVC 2 WebForms but it would be trivial to adapt it to Razor.

这篇关于处理回发数据中的数组-MVC3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆