ASP.NET 核心:asp-* 属性在模型上使用请求负载?
ASP.NET Core: asp-* attributes use request payload over model?
似乎在ASP.NET Core中,asp-*
属性中的值(例如asp-for
)是从模型之前的请求负载中获取的。示例:
Post这个值:
MyProperty="User entered value."
此操作:
[HttpPost]
public IActionResult Foo(MyModel m)
{
m.MyProperty = "Change it to this!";
return View();
}
或此操作
[HttpPost]
public IActionResult Foo(MyModel m)
{
m.MyProperty = "Change it to this!";
return View(m);
}
视图呈现:
<input asp-for="MyProperty" />
表单输入中的值是 User entered value.
而不是 Change it to this!
。
首先,令我惊讶的是我们不需要将模型传递给视图并且它可以工作。其次,令我震惊的是,请求负载优先于传递到视图中的模型。任何人都知道这个设计决定的基本原理是什么?使用 asp-for
属性时有没有办法覆盖用户输入的值?
我可以证实你的观察。真正让您大吃一惊的是:
[HttpPost]
public IActionResult Foo (MyModel m)
{
m.MyProperty = "changed";
var result = new MyModel { MyProperty = "changed" };
return View(result);
}
...给你同样的结果。
我认为你应该记录一个错误:https://github.com/aspnet/mvc/issues
编辑: 我现在记得我自己以前遇到的这个问题,并承认它不一定是一个错误,而是一个意外的结果。执行此代码的结果的原因并不明显。可能没有一种非常简单的方法来对此发出警告,但 PRG 是一个值得遵循的好模式。
我相信这是预期的behavior/by设计。因为当您提交表单时,表单数据将存储到 ModelState 字典中,当 razor 呈现您的表单元素时,它将使用 Model 状态字典中的值。这就是为什么即使您没有将视图模型的对象传递给 View()
方法,您也会看到表单元素值的原因。
如果要更新输入值,需要明确清除模型状态字典。您可以使用 ModelState.Clear(
) 方法。
[HttpPost]
public IActionResult Create(YourviewModel model)
{
ModelState.Clear();
model.YourProperty = "New Value";
return View(model);
}
它使用模型状态字典来呈现表单元素值的原因是为了支持用例,例如在发生验证错误时在表单中显示先前提交的值。
编辑: 我在 aspnet mvc 的官方 github 回购中找到了一个 link,其中 this is confirmed 由 Eilon (asp.net 团队成员)
https://github.com/aspnet/Mvc/issues/4486#issuecomment-210603605
似乎在ASP.NET Core中,asp-*
属性中的值(例如asp-for
)是从模型之前的请求负载中获取的。示例:
Post这个值:
MyProperty="User entered value."
此操作:
[HttpPost]
public IActionResult Foo(MyModel m)
{
m.MyProperty = "Change it to this!";
return View();
}
或此操作
[HttpPost]
public IActionResult Foo(MyModel m)
{
m.MyProperty = "Change it to this!";
return View(m);
}
视图呈现:
<input asp-for="MyProperty" />
表单输入中的值是 User entered value.
而不是 Change it to this!
。
首先,令我惊讶的是我们不需要将模型传递给视图并且它可以工作。其次,令我震惊的是,请求负载优先于传递到视图中的模型。任何人都知道这个设计决定的基本原理是什么?使用 asp-for
属性时有没有办法覆盖用户输入的值?
我可以证实你的观察。真正让您大吃一惊的是:
[HttpPost]
public IActionResult Foo (MyModel m)
{
m.MyProperty = "changed";
var result = new MyModel { MyProperty = "changed" };
return View(result);
}
...给你同样的结果。
我认为你应该记录一个错误:https://github.com/aspnet/mvc/issues
编辑: 我现在记得我自己以前遇到的这个问题,并承认它不一定是一个错误,而是一个意外的结果。执行此代码的结果的原因并不明显。可能没有一种非常简单的方法来对此发出警告,但 PRG 是一个值得遵循的好模式。
我相信这是预期的behavior/by设计。因为当您提交表单时,表单数据将存储到 ModelState 字典中,当 razor 呈现您的表单元素时,它将使用 Model 状态字典中的值。这就是为什么即使您没有将视图模型的对象传递给 View()
方法,您也会看到表单元素值的原因。
如果要更新输入值,需要明确清除模型状态字典。您可以使用 ModelState.Clear(
) 方法。
[HttpPost]
public IActionResult Create(YourviewModel model)
{
ModelState.Clear();
model.YourProperty = "New Value";
return View(model);
}
它使用模型状态字典来呈现表单元素值的原因是为了支持用例,例如在发生验证错误时在表单中显示先前提交的值。
编辑: 我在 aspnet mvc 的官方 github 回购中找到了一个 link,其中 this is confirmed 由 Eilon (asp.net 团队成员)
https://github.com/aspnet/Mvc/issues/4486#issuecomment-210603605