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

时间:2013-02-02 20:23:29

标签: c# .net asp.net-mvc razor

我对MVC很陌生,并且仍然混淆了2个案例的最佳和正确方法,并且结果相同。 假设某些用户应为特定的根类别添加新的子类别。

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

的Controler:

    [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对象

的Controler:

    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" />

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

2 个答案:

答案 0 :(得分:2)

第一种情况是为了简化。如果您扩展模型,则必须在较少的地方进行更改。它并不那么安全。您可以通过多种方式绕过创建或绑定隐藏的输入字段。

使用BindAttribute绕过属性绑定:

ActionResult Create([Bind(Exclude = "RootCategoryId")]
                    SubCategoryHelper thisSubCategory) {//....}
模型类属性上的

ScaffoldColumnAttribute(例如,当您使用编辑模板时):

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

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


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

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

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

我还建议您阅读这篇精彩的文章:Is layering worth mapping

答案 1 :(得分: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...

    }
}