【问题标题】:why need hidden value for passing model in ASP.NET为什么在 ASP.NET 中传递模型需要隐藏值
【发布时间】:2017-01-21 13:52:35
【问题描述】:

假设我在 SQL Server 中有一个 City 表。 这是 HomeController:

  [HttpGet]
    public ActionResult Index()
    {
        SampleDBContex db = new SampleDBContex();
        return View(db.Cities);
    }
    [HttpPost]
    public string Index(IEnumerable<City> cities)
    {
        if (cities.Count(x => x.IsSelected) == 0)
        {
            return "You didn't select city";
        }
        else
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("You selected -");
            foreach (City city in cities)
            {
                if (city.IsSelected)
                {
                    sb.Append(city.Name + ", ");
                }
            }
            sb.Remove(sb.ToString().LastIndexOf(","), 1);
            return sb.ToString();
        }

    }

}

这是索引视图(get 方法):

@model IEnumerable<Part38MVCCheckBoxList.Models.City>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Html.BeginForm())
{
    @Html.EditorForModel()
    <br />
    <input type="submit" value="Submit" />
}

这是编辑器模板:

@model Part38MVCCheckBoxList.Models.City

@Html.HiddenFor(x => x.ID)
@Html.HiddenFor(x => x.Name)



@Html.CheckBoxFor(x => x.IsSelected)
@Html.DisplayFor(x => x.Name)

我不明白为什么我们需要使用@Html.HiddenFor(x => x.Name),否则它无法显示城市名称。我认为我们通过模型 IEnumerable 所以我们应该已经存在城市名称当我们从数据库中检索它们时

【问题讨论】:

    标签: asp.net-mvc html-helper


    【解决方案1】:

    您需要 hiddenfor,因为 HTTP 消息传递是无状态的,因此如果您从控制器获取一个对象,它将在您的页面上拥有完整的对象,但如果您将除 Name 和 Id 变量之外的所有内容作为输入发送回表单上的值将丢失。

    您的控制器只会在需要时保留它,并且在控制器的 HttpGet 回答完成后,控制器将不再保留该值。

    我也觉得这很反直觉,但这就是 HTTP 协议的构建方式。

    【讨论】:

    • 但是我们不只是将城市实例/对象传递给回发视图吗,该对象应该包含我们需要的一切?就像我们有一个创建新城市的表单然后我们像 ActionResult Index(City city) 一样传递它,所以城市对象将包含名称、id 等所有内容
    • 在 Edit 动作中你想编辑一个特定的实体,所以控制器需要知道要映射到哪个实体。文档说:The ASP.NET MVC model binder takes the posted form values and creates a Movie object that's passed as the movie parameter.See docs here
    【解决方案2】:

    我们采用了隐藏属性,因为在控制器端,我们需要在后端过滤某些内容,或者这些属性可能在查询数据库时形成键。所以完全取决于您的设计和控制器需求。如果不需要,您可以选择删除。

    【讨论】:

      【解决方案3】:

      HTTP 是无状态的,因此一旦将数据作为模型的一部分发送到客户端,控制器就不会拥有数据。

      也没有必要也必须为视图中的每个模型属性创建隐藏控件。

      一般规则是需要作为模型的一部分回发的值应该在 HTML 中呈现为输入(文本、密码、隐藏、复选框等)。

      隐藏控件仅为应作为模型的一部分发送回控制器中的 POST 操作的属性创建。

      如果只是显示属性值,为它创建标签或在跨度中渲染它就足够了。

      【讨论】:

      • @Stephen Muecke 但我们不只是将城市实例/对象传递给回发视图吗,该对象应该包含我们需要的一切?就像我们有一个创建新城市的表单然后我们像 ActionResult Index(City city) 一样传递它,所以城市对象将包含名称、id 等所有内容
      • @grooveline,这不是我的答案 :) - 我刚刚编辑了它
      • 但是为了进一步解释正在发生的事情 - 您的客户端向您的 POST 方法发出请求。 DefaultModelBinder 然后初始化集合的一个新实例(Index() 方法中的参数),并从请求中读取值(来自表单控件的名称/值对)并初始化设置每个City 对象。如果您没有为Name 发布值,则它不在请求中,因此无法设置(将是null
      猜你喜欢
      • 1970-01-01
      • 2016-03-20
      • 1970-01-01
      • 1970-01-01
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-23
      相关资源
      最近更新 更多