似乎在ASP.NET Core中,asp-*
属性(例如asp-for
)中的值取自模型之前的请求有效内容。例如:
发布此值:
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
属性时覆盖用户输入的值?
答案 0 :(得分:2)
我可以确认你的观察。真正让你大吃一惊的是:
[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是一个很好的模式可以遵循。
答案 1 :(得分:2)
我相信这是预期的行为/设计。因为当您提交表单时,表单数据将存储到ModelState字典中,当razor呈现表单元素时,它将使用Model状态字典中的值。这就是为什么即使没有将视图模型的对象传递给View()
方法,也会看到表单元素值。
如果要更新输入值,则需要明确清除模型状态字典。您可以使用ModelState.Clear(
)方法来执行此操作。
[HttpPost]
public IActionResult Create(YourviewModel model)
{
ModelState.Clear();
model.YourProperty = "New Value";
return View(model);
}
它使用模型状态字典来呈现表单元素值的原因是支持用例,当出现验证错误时显示表单中先前提交的值。
编辑:我找到了一个指向aspnet mvc官方github repo的链接,其中this is confirmed是Eilon(asp.net团队成员)
https://github.com/aspnet/Mvc/issues/4486#issuecomment-210603605