为什么在 ASP.NET 中传递模型需要隐藏值
why need hidden value for passing model in ASP.NET
假设我在 SQL 服务器中有一个城市 table。
这是家庭控制器:
[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();
}
}
}
这是索引视图(获取方法):
@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),不然不能显示city name.I以为模型通过了IEnumerable 所以当我们从数据库中检索它们时我们应该已经存在城市名称
我们采用了隐藏属性,因为在控制器端我们需要在后端过滤某些东西,或者可能 属性 可能在查询数据库时形成键。所以完全取决于你的设计和控制器的需要。如果你不需要,你可以选择删除。
您需要一个 hiddenfor,因为 HTTP 消息传递是无状态的,所以如果您从控制器获取一个对象,它将在您的页面上包含完整的对象,但如果您将除 Name 和 Id 变量之外的所有内容发回输入表单上的值将丢失。
您的控制器只会在需要时保留它,并且在您从控制器获得 HttpGet 答复后,控制器已完成,它将不再保留该值。
我也觉得这有违直觉,但这就是 HTTP 协议的构建方式。
HTTP 是无状态的,因此一旦数据作为视图模型的一部分发送到客户端,控制器将不会拥有数据。
也没有必要而且必须为视图中的每个模型属性创建隐藏控件。
一般规则是需要作为模型的一部分回发的值应该作为输入(文本、密码、隐藏、复选框等)在 HTML 中呈现。
仅为应作为模型的一部分发送回控制器中的 POST 操作的属性创建隐藏控件。
如果 属性 值只是为了显示,为其创建标签或在范围内渲染就足够了。
假设我在 SQL 服务器中有一个城市 table。 这是家庭控制器:
[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();
}
}
}
这是索引视图(获取方法):
@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),不然不能显示city name.I以为模型通过了IEnumerable 所以当我们从数据库中检索它们时我们应该已经存在城市名称
我们采用了隐藏属性,因为在控制器端我们需要在后端过滤某些东西,或者可能 属性 可能在查询数据库时形成键。所以完全取决于你的设计和控制器的需要。如果你不需要,你可以选择删除。
您需要一个 hiddenfor,因为 HTTP 消息传递是无状态的,所以如果您从控制器获取一个对象,它将在您的页面上包含完整的对象,但如果您将除 Name 和 Id 变量之外的所有内容发回输入表单上的值将丢失。
您的控制器只会在需要时保留它,并且在您从控制器获得 HttpGet 答复后,控制器已完成,它将不再保留该值。
我也觉得这有违直觉,但这就是 HTTP 协议的构建方式。
HTTP 是无状态的,因此一旦数据作为视图模型的一部分发送到客户端,控制器将不会拥有数据。
也没有必要而且必须为视图中的每个模型属性创建隐藏控件。
一般规则是需要作为模型的一部分回发的值应该作为输入(文本、密码、隐藏、复选框等)在 HTML 中呈现。
仅为应作为模型的一部分发送回控制器中的 POST 操作的属性创建隐藏控件。
如果 属性 值只是为了显示,为其创建标签或在范围内渲染就足够了。