4

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

情况 1: SubCategory 是 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" />

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

4

2 回答 2

2

第一种情况很简单。如果您扩展您的模型,您将不得不在更少的地方进行更改。它的安全性并不低。您可以通过多种方式绕过创建或绑定隐藏的输入字段。

用于BindAttribute绕过属性绑定:

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

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

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

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


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

可能没有一般的经验法则。这取决于您的应用程序的类型。

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

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

于 2013-02-02T21:16:39.213 回答
2

我总是选择案例 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...

    }
}
于 2013-02-02T21:17:38.857 回答