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

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

问题描述

我目前正在尝试移动到一个MVC开发的WebForms。我超级兴奋MVC和我真的有乐趣,但我遇到一个奇怪的问题。所以,我想要做的就是创建一个小部件的高级编辑。我已经张贴低于code。

一切似乎很好地工作,当您添加的第一个项目4-5,但是当你删除第二项出现问题。这里是一个视觉的例子。

首先添加了4个值。

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

似乎我无法理解的是为什么这财物的行为code以下两个行之间的不同。

  @ Model.Values​​ [I]
@ Html.TextBoxFor(M = GT; m.Values​​ [I])

我的猜测是,@Model和(M => M)不引用相同的对象?

下面是我的widget类。

 公共类的Widget
{
    #区域构造    公共小工具()
    {
        ID = 0;
        NAME =的String.Empty;
        值=新的List<串GT;();
    }    #endregion    #区域属性    [需要]
    [显示(名称=ID)]
    公众诠释ID {搞定;组; }    [需要]
    [显示(名称=名称)]
    公共字符串名称{;组; }    [需要]
    [显示(名称=值)]
    公开名单<串GT;值{搞定;组; }    #endregion
}

我的控制器看起来是这样的。

 公开的ViewResult EditWidget(INT ID)
{
    返回查看(_widgets.GetWidgetByID(ID));
}[HttpPost]
公众的ActionResult EditWidget(小部件小部件)
{
    如果(!TryUpdateModel(部件))
    {
        ViewBag.Message =错误......;
        返回视图(部件);
    }    如果(的Request.Form [AddWidgetValue]!= NULL)
    {
        widget.Values​​.Add(的Request.Form [TextBoxWidgetValue]);
        返回视图(EditWidget窗口小部件);
    }    如果(的Request.Form [DeleteWidgetValue]!= NULL)
    {
        widget.Values​​.Remove(的Request.Form [ListBoxWidgetValues​​]);
        返回视图(EditWidget窗口小部件);
    }    _widgets.UpdateWidget(部件);
    _widgets.Save();    返回RedirectToAction(「指数」);
}

最后我的看法。

  @model MvcTestApplication.Models.Widget@ {
    ViewBag.Title =EditWidget;
}< H2> EditWidget< / H><脚本的src =@ Url.Content(〜/脚本/ jquery.validate.min.js)TYPE =文/ JavaScript的>< / SCRIPT>
<脚本的src =@ Url.Content(〜/脚本/ jquery.validate.unobtrusive.min.js)TYPE =文/ JavaScript的>< / SCRIPT>@using(Html.BeginForm()){
    @ Html.ValidationSummary(真)
    <&字段集GT;
        <传奇>窗口小部件< /传说>        @ Html.HiddenFor(型号=> model.ID)        < D​​IV CLASS =编辑标记>
            @ Html.LabelFor(型号=> model.Name)
        < / DIV>
        < D​​IV CLASS =主编场>
            @ Html.EditorFor(型号=> model.Name)
            @ Html.ValidationMessageFor(型号=> model.Name)
        < / DIV>        @for(VAR I = 0; I< Model.Values​​.Count;我++)
        {
            @ Model.Values​​ [I]
            @ Html.TextBoxFor(M = GT; m.Values​​ [I])
            @ Html.HiddenFor(M = GT; m.Values​​ [I])
            < BR />
        }        @ Html.ListBox(ListBoxWidgetValues​​,新的SelectList(Model.Values​​),新{风格=宽度:100%})< BR />
        @ Html.TextBox(TextBoxWidgetValue的String.Empty,新{风格=宽度:100%})
        <输入类型=提交值=添加ID =AddWidgetValueNAME =AddWidgetValue级=提交按钮/>
        <输入类型=提交值=删除ID =DeleteWidgetValueNAME =DeleteWidgetValue级=提交按钮/>        &所述p为H.;
            <输入类型=提交值=保存/>
        &所述; / P>
    < /字段集>
}< D​​IV>
    @ Html.ActionLink(返回目录,索引)
< / DIV>


解决方案

这样做的原因发生是因为HTML助手先来看看的ModelState发布绑定时的值,然后在模型。这意味着,如果你的帖子控制器动作里面你尝试修改一些价值,这同样值为初始POST请求的HTML帮助将使用初始值,而不是修改了其中的一部分。

例如在EditWidget行动,你这样做是:

 如果(的Request.Form [DeleteWidgetValue]!= NULL)
{
    widget.Values​​.Remove(的Request.Form [ListBoxWidgetValues​​]);
    返回视图(EditWidget窗口小部件);
}

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

 如果(的Request.Form [DeleteWidgetValue]!= NULL)
{
    VAR itemToRemove =的Request.Form [ListBoxWidgetValues​​];
    VAR指数= widget.Values​​.IndexOf(itemToRemove);
    ModelState.Remove(值[+指数+]);
    widget.Values​​.Remove(itemToRemove);
    返回视图(EditWidget窗口小部件);
}

因此​​,POST请求包含:

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

在里面你比如删除了POST操作的第二个项目,所以你也应该从模型状态或TextBoxFor助手将仍然使用旧的删除它。

您还可以找到的以下博客帖子有用。它是ASP.NET MVC 2的WebForms,但是这将是微不足道的,以使其适应剃刀。

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.

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.

First add the 4 values.

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])

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

Here is my widget class.

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");
}

And finally my view.

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

解决方案

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.

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);
}

So the POST request contained:

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

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天全站免登陆