处理 MVC 发布模型的最佳实践是什么?

本文关键字:最佳 是什么 模型 MVC 布模型 处理 | 更新日期: 2023-09-27 17:57:18

我对 MVC 很陌生,仍然对 2 种具有相同结果的案例的最佳和正确方法感到困惑。假设某个用户应该为特定的根类别添加新的子类别。

案例1:子类别是 EF 映射的类,其中所有属性都不可为空。

控制器:

    [Authorize]
    public ActionResult Create()
    {
        SubCategory subCategory = new SubCategory();
        subCategory.RootCategoryID = 1;
        return View(subCategory);
    }
    [Authorize]
    [HttpPost]
    public ActionResult Create(SubCategory thisSubCategory)
    {
        if (ModelState.IsValid)
        {
           //And some BL logic called here to handle new object...
        }
    }

视图:

    @Html.HiddenFor(model => model.ID)
    @Html.HiddenFor(model => model.RootCategoryID)
    <h3>Sub Category Name: </h3>
    @Html.EditorFor(model => model.CategoryName)
    @Html.ValidationMessageFor(model => model.CtaegoryName)
    <input id="btnAdd" type="submit" value="Add" />

案例2:将帮助程序类添加为控制器的模型,并在发布后填充 EF 对象

控制器:

    class SubCategoryHelper
    {
       public string Name { get; set; }
    }
    [Authorize]
    public ActionResult Create()
    {
       SubCategoryHelper subCategory = new SubCategoryHelper();
       return View(subCategory);
    }
    [Authorize]
    [HttpPost]
    public ActionResult Create(SubCategoryHelper thisSubCategory)
    {
        if (ModelState.IsValid)
        {
           SubCategory newSubCategory = new SubCategory();
           newSubCategory.RootCategoryID = 1;
           newSubCategory.CtaegoryName = thisSubCategory.Name;
           //And some BL logic called here to handle new object...
        }
    }

视图:

子类别名称:

    @Html.EditorFor(model => model.Name)
    @Html.ValidationMessageFor(model => model.Name)
    <input id="btnAdd" type="submit" value="Add" />

这两种方式都是一样的,但第一种方法看起来不太安全,因为可以在客户端更改隐藏。第二种方式更长,想象一下对于客户端或产品等丰富对象相同的方式......我应该选择什么?还是有其他方法?

处理 MVC 发布模型的最佳实践是什么?

第一种情况有利于简单。如果您扩展模型,则必须在较少的地方进行更改。它同样安全。您可以通过多种方式绕过创建或绑定隐藏的输入字段。

使用 BindAttribute 绕过属性绑定:

ActionResult Create([Bind(Exclude = "RootCategoryId")]
                    SubCategoryHelper thisSubCategory) {//....}

或者ScaffoldColumnAttribute模型类属性(例如,当您使用编辑模板时):

[ScaffoldColumn(false)]
public int RootCategoryId {get; set;}

或者只是简单地不要公开它(就像您在示例中使用 Html.HiddenInput 帮助程序所做的那样)。


您已经描述的第二种方法通常称为视图模型模式。它鼓励将演示文稿和域图层分开。优点是,您的域模型不会被表示层特定的代码(如各种显示属性等)污染。Hovewer 它带来了域模型和视图模型之间映射的另一个开销。

可能没有通用的经验法则。这取决于您的应用类型。

如果它基本上是一些简单的数据驱动的CRUD应用程序,则可以轻松地使用第一个。然而,当您的应用程序变得更大时,您肯定会欣赏在单独的层上自由发挥双手的自由。如果您的 BLL 代码与除 ASP MVC 之外的其他类型的"客户端"(Web 服务、桌面等)一起使用,我肯定会选择第二个选项。

我还建议阅读这篇很棒的文章:分层值得映射吗

我总是使用案例 2,无论是我从事的小项目还是大项目,我总是将数据层(实体框架)和 UI 层分开。 特别是如果您使用的是实体框架,因为这些对象可能会变得很大,并且您传递的废话很多,您通常不需要。

与其称其为Helper类,不如称它们为 ViewModelModel . 在您的情况下,SubCategoryViewModel.

public class SubCategoryViewModel
{
   public int Id {get;set;}
   public int RootCategoryId {get;set;}
   [Required]
   public string Name { get; set; }
}
[Authorize]
public ActionResult Create()
{
   var subCategoryViewModel = new SubCategoryViewModel();
   return View(subCategoryViewModel);
}
[Authorize]
[HttpPost]
public ActionResult Create(SubCategoryViewModel viewModel)
{
    if (ModelState.IsValid)
    {
       var subCategory = new SubCategory();
       subCategory.RootCategoryID = 1;
       subCategory.CategoryName = viewModel.Name;
       //And some BL logic called here to handle new object...
    }
}