ASP.Net Core MVC 中的模型绑定/ViewModel 绑定
Model binding / ViewModel binding in ASP.Net Core MVC
让我们从简单的代码开始:
public class SomeViewModel
{
public int State { get; set; }
}
public class SomeController : Controller
{
public IActionResult DoSomething(int state)
{
var viewModel = new SomeViewModel();
if(state % 2 == 0)
viewModel.State = state * 2;
else
viewModel.State = state;
return View("MyView", viewModel)
}
}
MyView.cshtml:
@model SomeViewModel;
...
<form method="get" asp-action="BlablaAction" asp-controller="OtherController">
<input asp-for="State">
<button type="submit">Save</button>
</form>
...
我提出要求:
/some/dosomething?state=4 => 输入值 = 4
/some/dosomething?state=5 => 输入值 = 5
/some/dosomething?state=6 => 输入值 = 6
/some/dosomething?state=7 => 输入值 = 7
但根据我在 DoSomething 操作中的逻辑,它应该是:
/some/dosomething?state=4 => 输入值 = 8
/some/dosomething?state=5 => 输入值 = 5
/some/dosomething?state=6 => 输入值 = 12
/some/dosomething?state=7 => 输入值 = 7
我的问题是:为什么将输入值分配给查询参数而不是传递的模型对象的 属性...
第二件事我知道我可以将 param 的名称从 state 更改为 param1 但也许还有其他方法可以做到......
我读过 2 本关于 ASP.net 核心的书,但没有遇到过任何相关内容。
如果您的表单方法是“获取”输入作为查询字符串发送,但如果您想 post 它们作为表单,您应该 post 您的表单并分配类型“post”到您的表单方法。
<form method="post" asp-action="DoSomething" asp-controller="Some">
<input asp-for="State">
<button type="submit">Save</button>
</form>
在此代码中,如果您的操作参数是 SomeViewModel 类型,则 State 将绑定到您的 SomeViewModel。
默认情况下,如果我们将 GET
分配给表单的方法属性,它会通过查询字符串公开数据。为了避免这种情况,我们将方法属性设置为 POST
<form method="post" asp-action="DoSomething" asp-controller="Some">
<input asp-for="State">
<button type="submit">Save</button>
</form>
其次,.NET Core提高了安全性,所以官方文档推荐使用Model in Post这样的方法。 (这是可选的最佳实践。不是强制性的)
public class StateModel
{
public int State { get; set; }
}
public class SomeController : Controller
{
public IActionResult DoSomething(StateModel model)
{
var viewModel = new SomeViewModel();
if(model.State % 2 == 0)
viewModel.State = state * 2;
else
viewModel.State = state;
return View("MyView", viewModel)
}
}
当<input asp-for="">
标签符合HTML时,它在从您的视图模型获取值之前从 ModelState 获取值,因此您可以清除 ModelState
中的值
public IActionResult DoSomething(int state)
{
var viewModel = new SomeViewModel();
if (state % 2 == 0)
{
viewModel.State = state * 2;
ModelState.Clear();
}
else
viewModel.State = state;
return View(viewModel);
}
另外,你可以把代码放在controller里面,只修改label:
<input type="number" data-val="true" data-val-required="The State field is required." id="State" name="State" value="@Model.State">
让我们从简单的代码开始:
public class SomeViewModel
{
public int State { get; set; }
}
public class SomeController : Controller
{
public IActionResult DoSomething(int state)
{
var viewModel = new SomeViewModel();
if(state % 2 == 0)
viewModel.State = state * 2;
else
viewModel.State = state;
return View("MyView", viewModel)
}
}
MyView.cshtml:
@model SomeViewModel;
...
<form method="get" asp-action="BlablaAction" asp-controller="OtherController">
<input asp-for="State">
<button type="submit">Save</button>
</form>
...
我提出要求:
/some/dosomething?state=4 => 输入值 = 4
/some/dosomething?state=5 => 输入值 = 5
/some/dosomething?state=6 => 输入值 = 6
/some/dosomething?state=7 => 输入值 = 7
但根据我在 DoSomething 操作中的逻辑,它应该是:
/some/dosomething?state=4 => 输入值 = 8
/some/dosomething?state=5 => 输入值 = 5
/some/dosomething?state=6 => 输入值 = 12
/some/dosomething?state=7 => 输入值 = 7
我的问题是:为什么将输入值分配给查询参数而不是传递的模型对象的 属性... 第二件事我知道我可以将 param 的名称从 state 更改为 param1 但也许还有其他方法可以做到...... 我读过 2 本关于 ASP.net 核心的书,但没有遇到过任何相关内容。
如果您的表单方法是“获取”输入作为查询字符串发送,但如果您想 post 它们作为表单,您应该 post 您的表单并分配类型“post”到您的表单方法。
<form method="post" asp-action="DoSomething" asp-controller="Some">
<input asp-for="State">
<button type="submit">Save</button>
</form>
在此代码中,如果您的操作参数是 SomeViewModel 类型,则 State 将绑定到您的 SomeViewModel。
默认情况下,如果我们将 GET
分配给表单的方法属性,它会通过查询字符串公开数据。为了避免这种情况,我们将方法属性设置为 POST
<form method="post" asp-action="DoSomething" asp-controller="Some">
<input asp-for="State">
<button type="submit">Save</button>
</form>
其次,.NET Core提高了安全性,所以官方文档推荐使用Model in Post这样的方法。 (这是可选的最佳实践。不是强制性的)
public class StateModel
{
public int State { get; set; }
}
public class SomeController : Controller
{
public IActionResult DoSomething(StateModel model)
{
var viewModel = new SomeViewModel();
if(model.State % 2 == 0)
viewModel.State = state * 2;
else
viewModel.State = state;
return View("MyView", viewModel)
}
}
当<input asp-for="">
标签符合HTML时,它在从您的视图模型获取值之前从 ModelState 获取值,因此您可以清除 ModelState
public IActionResult DoSomething(int state)
{
var viewModel = new SomeViewModel();
if (state % 2 == 0)
{
viewModel.State = state * 2;
ModelState.Clear();
}
else
viewModel.State = state;
return View(viewModel);
}
另外,你可以把代码放在controller里面,只修改label:
<input type="number" data-val="true" data-val-required="The State field is required." id="State" name="State" value="@Model.State">