【问题标题】:Loop seems to yield the same value every time循环似乎每次都产生相同的值
【发布时间】:2014-03-27 16:07:42
【问题描述】:

我有一个名为 Groups 的字符串数组,其中包含以下两个字符串

  1. 阿尔法组
  2. 集体喝彩

控制器

public ActionResult Task(TaskModel model)
{

    return PartialView(model);
}

调用我的任务操作的索引视图

<div id="update">

    @using (Ajax.BeginForm("Task", "Home", new AjaxOptions { UpdateTargetId = "update", InsertionMode = InsertionMode.Replace}))
    {

        <input value="Group Alpha" name="Groups"/>
        <input value="Group Bravo" name="Groups"/>

        <button type="submit">Submit</button>
    }

</div>

我的任务视图

@model MvcApplication4.Models.TaskModel

<div id="container">

        @if (Model.Groups != null)
        {

            foreach (var group in Model.Groups)
            {

                @Html.TextBox("Groups", group, new { @id = String.Empty })                                                         

            }
        } 
</div>

我的任务模型

public class TaskModel : IValidatableObject
{
    public Guid TaskId { get; set; }
    public String Name { get; set; }

    public string[] Groups { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {

        yield break;
    }
}

这仅输出 Group Alpha Group Alpha。哪里出了问题??

抱歉之前没说清楚

复制问题https://www.dropbox.com/s/s2o59cu00am3eov/MvcApplication4.zip的示例项目

【问题讨论】:

  • 您认为您是第一个在foreach 循环中使用@Html.TextBox 的人吗?这是非常不可能的,因此错误更有可能出现在您的代码中。您确定要调用正确的重载吗?你能展示你如何填写Model.Groups吗?你能打印@Html.Raw(group)吗?
  • 很可能,无论您使用什么IEnumerable,它都会在迭代时改变其结果,一个常见的例子是在 C# 5.0 之前关闭循环变量,尽管肯定还有其他制作像这样真正邪恶的迭代器的方法。
  • @JoachimIsaksson 关闭循环变量的问题不会出现在显示的代码中;它将在Groups 的实现中。此处的代码将评估循环体内的任何 lambda。
  • 您可以您看到它有效,但我不相信,因为对我来说它按预期工作。请更新您的问题以显示实际将此模型返回到视图的代码。尝试像我这样的硬编码模型。我们真的无法按原样处理您的问题。
  • @heymega 鉴于问题显然不在于您显示的代码,向我们展示我们要求查看的代码,而不仅仅是告诉我们认为“这是正确的”。显然不是,或者 something 在其他地方不正确。显示的代码并没有复制您的问题。

标签: c# asp.net-mvc asp.net-mvc-3 model-view-controller


【解决方案1】:

您发布了一些名为Groups 的输入字段。在处理该 POST 的操作方法中,您呈现使用 @Html.TextBox("Groups", ...) 的部分。

@Html.TextBox 使用 ModelState 根据输入元素名称用先前发布的值填充值。在这种情况下,它采用在 POST 中找到的第一个 Groups 值,即“Group Alpha”。

在渲染局部视图之前清除 ModelState(或只是 Groups 键)。

这个:

ModelState.Clear();
ModelState.Remove("Groups");

return PartialView(model);

工作。

下次尝试预先显示所有相关代码,这样我们就不需要那么多 cmets 要求您这样做了。 :-)

【讨论】:

  • 啊,我实际上在另一个动作中遇到了这个 :( 谢谢你的帮助,但我已经尽可能快了。它的公司代码,所以我必须先重构它 :(
  • @CodeCasterv - 这不是缺陷吗?为什么它会基于输入元素名称?拥有多个同名元素是完全合法的
  • 这是有效的(您可以完美地从代码中读取值),但这不是 PHP,也不是您应该如何处理同一属性的值列表。请参阅Submitting form elements with the same name,了解如何使用 MVC 实现相同的行为。
  • 我完全知道你从哪里来,但如果是这样的话,defaultmodelbinder 不应该绑定基于此处提到的同名的集合 - haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx 谢谢你的帮助,虽然这让我很紧张:)
【解决方案2】:

我认为这是一个封闭问题。试试这个代码:

<div id="container">

    @if (Model.Groups != null)
    {
        foreach (var group in Model.Groups)
        {
            var currentGroup = group;
            @Html.TextBox("Groups", currentGroup, new {@id = String.Empty});
        }
    } 
</div>

【讨论】:

  • 在显示的代码中关闭了该变量,即使他是,也不会产生指示的问题(不可能导致第一项被打印两次;最多可能导致最后一项被打印两次)。问题出在其他地方的代码中。
  • @Servy - 你能解释一下他是如何不关闭变量的吗?
  • 你能解释一下他是如何关闭变量的,因为没有匿名方法,这是在 C# 中创建闭包的唯一方法?
  • 我认为它在@Html.TextBox 方法中,因为它在他的代码中不可见。那个,或者 Razor 编译。我不完全确定,这就是为什么我说我认为而不是我知道。只是想帮忙。
猜你喜欢
  • 2016-03-29
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 2015-08-02
  • 1970-01-01
相关资源
最近更新 更多