0

我已经阅读 StackOverflow 很长一段时间了,是时候发表我的第一篇文章了:

我目前正在使用 C#/ASP.NET Core 3.1。为 HttpGet 和 HttpPost 设计包含显示数据和绑定数据的 ViewModel 的最佳实践是什么。我发现了一些关于保持显示和绑定数据分开或不分开但没有任何示例的讨论。在 HttpPost 上使用相同的 ViewModel(没有绑定属性)的问题是 Display Data 引用会获得无效的模型状态,因为它们在传入模型中当然是 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>
4

1 回答 1

2

The problem on using the same ViewModel on HttpPost (without binding attributes) is that Display Data references get an invalid modelstate because they are of course null in the incoming model.

By using the same ViewModel(here is CMyViewModel),you could overcome the validation error by removing the field from ModelState prior to judging ModelState.IsValid.

Refer to my simple demo:

Model:

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 ...
}

Actions:

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);
}

Refer to ModelState.IsValid does not exclude required property

Besides, Christoph Lütjen's suggestion of using two models separately also will work.

于 2020-02-18T05:55:51.297 回答