我已经阅读StackOverflow很长一段时间了,是时候发表我的第一篇文章了:
我目前使用的是C#/ASP.NET Core 3.1。设计包含HttpGet和HttpPost的显示数据和绑定数据的ViewModel的最佳实践是什么。我发现了一些关于保持显示和绑定数据分离或不分离的讨论,但没有任何例子。在HttpPost上使用相同的ViewModel(没有绑定属性(的问题是,显示数据引用会得到无效的模型状态,因为它们在传入模型中当然是null。
我通常倾向于使用下面的精简代码。继承是一种方式还是其他模式?还是将所有内容都放在具有非绑定数据的绑定属性的视图模型中更好?
谢谢大家!
public class CMyBindModel
{
public int ProductQuantity ( get; set; } // Binding Data
// Other Binding properties ...
}
public class CMyViewModel : CMyBindModel
{
public string ProductName ( get; set; } // Display Data
// Other Display properties ...
}
public IActionResult Cart ()
{
CMyViewModel viewModel = BuildViewModel () ;
return View (viewModel) ;
}
[HttpPost]
public IActionResult Cart (CMyBindModel bindModel)
{
if (ModelState.IsValid)
{
SetProductQuantity (bindModel.ProductQuantity) ;
return RedirectToAction ("Cart") ;
}
CMyViewModel viewModel = BuildViewModel () ;
return View (viewModel) ;
}
Cart.cshtml
@model CMyViewModel
<div>@Model.ProductName</div>
<form method="post" asp-area="" asp-controller="CartController" asp-action="Cart">
<input asp-for="ProductQuantity" />
<button type="submit">Update</button>
</form>
在HttpPost上使用相同的ViewModel(没有绑定属性(的问题是,显示数据引用会得到无效的模型状态,因为它们在传入模型中当然为null。
通过使用相同的ViewModel(这里是CMyViewModel
(,您可以通过在判断ModelState.IsValid
之前从ModelState
中删除字段来克服验证错误。
参考我的简单演示:
型号:
public class CMyViewModel
{
[Required]
public int ProductQuantity { get; set; } // Binding Data
// Other Binding properties ...
[Required]
public string ProductName{get; set; } // Display Data
// Other Displaying properties ...
}
行动:
public void RemoveDisplayingDataValidation()
{
ModelState.Remove("ProductName");
//remove other Displaying properties' validation
}
[HttpPost]
public IActionResult Cart(CMyViewModel viewModel)
{
RemoveDisplayingDataValidation();
if (ModelState.IsValid)
{
SetProductQuantity (viewModel.ProductQuantity) ;
return RedirectToAction("Cart");
}
CMyViewModel viewModel = BuildViewModel () ;
return View(viewModel);
}
请参阅ModelState.IsValid不排除所需的属性
此外,Christoph Lütjen关于分别使用两种模型的建议也将起作用。