【问题标题】:MVC3 - Problem using editorsMVC3 - 使用编辑器的问题
【发布时间】:2011-04-09 00:12:31
【问题描述】:

如果这是 MVC3 的问题,会有关于此的帖子,但我找不到。我一定做错了什么。我有一个简单的视图(Index.cshtml),它使用 for 循环遍历列表。在每次迭代中,我输出两个文本输入,其中包含来自列表项之一的值。

@{Html.BeginForm();}
@Html.Encode("\n")
@for (int i = 0; i < Model.SortOptions.Count; i++ )
{
    @Html.TextBoxFor(m => m.SortOptions[i].ColumnName);
    @Html.Encode("\n");
    @Html.TextBoxFor(m => m.SortOptions[i].Direction);
    @Html.Encode("\n");
}
<input type="submit" value="Submit" />
@{Html.EndForm();}

我有两个视图控制器,一个用于 GET 请求,一个用于 POST。 POST 版本向列表中添加的项目与 GET 版本不同。这就是问题所在。重新加载页面后,文本框的值与在 GET 上加载页面时的值相同。

起初我认为这一定是缓存问题,但如果我修改代码(如下所示),手动添加文本输入并将值注入 html,新值将发送到浏览器。

@{Html.BeginForm();}
@Html.Encode("\n")
@for (int i = 0; i < Model.SortOptions.Count; i++ )
{
    var columnNameName = string.Format("SortOptions[{0}].ColumnName", i);
    var columnNameID = string.Format("SortOptions_{0}__ColumnName", i);
    var directionName = string.Format("SortOptions[{0}].Direction", i);
    var directionID = string.Format("SortOptions_{0}__Direction", i);

<input type="hidden" name="@columnNameName" id="@columnNameID" value="@Model.SortOptions[i].ColumnName" />
<input type="hidden" name="@directionName" id="@directionID" value="@Model.SortOptions[i].Direction" />

}
<input type="submit" value="Submit" />
@{Html.EndForm();}

我已单步执行代码以确保模型在将它们发送到视图时包含预期值。我什至通过单步执行视图中的代码来检查列表的值。它似乎具有正确的值,但是当我在浏览器中查看它时,它的值应与页面响应 GET 请求时对应的值相对应。这是编辑器模板的问题吗?我刚开始使用 mvc3 和 razor 引擎,所以有很多我不知道的。任何帮助将不胜感激。

----- 更新:添加了控制器代码----

    [HttpGet]
    public ActionResult Index()
    {
        var inv = new InventoryEntities();
        var model = new IndexModel(inv);
        model.SortOptions = new List<SortOption>();
        model.SortOptions.Add(new SortOption { ColumnName = "Model", Direction = SortDirection.Ascending });
        model.SortOptions.Add(new SortOption { ColumnName = "Make", Direction = SortDirection.Ascending });
        //Load data
        model.LoadEquipmentList();

        return View(model);
    }


    [HttpPost]
    [OutputCache(Duration = 1)]
    public ActionResult Index(List<SortOption> sortOptions, SortOption sort)
    {
        var inv = new InventoryEntities();
        var model = new IndexModel(inv);
        ModelState.Remove("SortOptions");
        model.SortOptions = new List<SortOption>();
        model.SortOptions.Add(new SortOption { ColumnName = "Type", Direction = SortDirection.Descending });
        model.SortOptions.Add(new SortOption { ColumnName = "SubType", Direction = SortDirection.Descending });
        model.EquipmentList = new List<EquipmentListItem>();
        model.EquipmentList.Add(new EquipmentListItem { ID = 3, AssignedTo = "Mike", Location = "Home", Make = "Ford", Model = "Pinto", Selected = false, SubType = "Car", Type = "Vehicle" });

        return View(model);
    }

【问题讨论】:

  • 能贴出控制器动作代码吗?
  • 控制器代码现已发布。

标签: asp.net-mvc-3 razor mvc-editor-templates


【解决方案1】:

请记住,TextBoxFor 等 Html 助手在绑定其值时首先使用模型状态,然后再使用模型。让我们考虑一个非常简单的例子来说明这意味着什么:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel { Name = "foo" });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        model.Name = "bar";
        return View(model);
    }
}

和视图:

@model MyViewModel
@using (Html.BeginForm())
{
    @Html.TextBoxFor(x => x.Name)
    <input type="submit" value="OK" />
}

现在,当您提交表单时,您会期望文本框中的值更改为 "bar",因为这是您在 POST 操作中输入的值,但值不会更改。这是因为模型状态中已经有一个键为 Name 的值,其中包含用户输入的内容。所以如果你想让它工作,你需要从模型状态中删除原始值:

[HttpPost]
public ActionResult Index(MyViewModel model)
{
    // remove the original value if you intend to modify it here
    ModelState.Remove("Name");
    model.Name = "bar";
    return View(model);
}

同样的事情也会发生在你的场景中。因此,您可能需要在 POST 操作中从模型状态中删除正在修改的值。

【讨论】:

  • 我尝试使用 ModelState.Remove,但没有成功。我得到相同的结果。我将使用两个控制器方法的代码更新我的帖子。
  • 好的,这基本上就是问题所在。我仍然不完全理解模型状态是如何工作的,但是如果我添加“ModelState.Clear();”在控制器方法的开头,它解决了这个问题。感谢您为我指明正确的方向。
【解决方案2】:

我突然想到了几件事——没有看到更多的东西很难说,但是……这两个都可以这样重写。不需要额外的@ 符号。

@using(Html.BeginForm()) {
    Html.Encode("\n")
    for (int i = 0; i < Model.SortOptions.Count; i++ ) {
        Html.TextBoxFor(m => m.SortOptions[i].ColumnName);
        Html.Encode("\n");
        Html.TextBoxFor(m => m.SortOptions[i].Direction);
        Html.Encode("\n");
    }
    <input type="submit" value="Submit" />
}


@using (Html.BeginForm()) { 
    Html.Encode("\n");
    for (int i = 0; i < Model.SortOptions.Count; i++ ) {
        var columnNameName = string.Format("SortOptions[{0}].ColumnName", i);
        var columnNameID = string.Format("SortOptions_{0}__ColumnName", i);
        var directionName = string.Format("SortOptions[{0}].Direction", i);
        var directionID = string.Format("SortOptions_{0}__Direction", i);

        <input type="hidden" name="@columnNameName" id="@columnNameID" value="@Model.SortOptions[i].ColumnName" />
        <input type="hidden" name="@directionName" id="@directionID" value="@Model.SortOptions[i].Direction" />

    }
    <input type="submit" value="Submit" />
}

否则你的东西看起来是对的,我看不出有什么问题。

【讨论】:

  • 感谢@用法的提示。我在两个项目中使用了 MVC2,但这是第一个使用 MVC3 和 razor 的项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多