4

私はMVCにかなり慣れていませんが、同じ結果を得るために2つのケースの最善かつ適切な方法をまだ混乱させています。一部のユーザーが特定のルート カテゴリに新しいサブカテゴリを追加する必要があるとします。

ケース 1: SubCategory は EF によってマップされたクラスであり、すべてのプロパティが null 可能ではありません。

コントローラー:

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

どちらの方法でも同じになりますが、最初の方法は、クライアント側で変更できる隠し要素があるため、安全性が低く見えます。Client や Product などのリッチ オブジェクトに対して同じ方法を想像してみてください。どちらを選択すればよいでしょうか。それとも何か他の方法がありますか?

4

2 に答える 2

2

最初のケースは単純にするのに適しています。モデルを拡張すると、変更を加える必要がある場所が少なくなります。それほど安全ではありません。非表示の入力フィールドの作成またはバインドを回避するには、いくつかの方法があります。

BindAttributeプロパティのバインドをバイパスするために使用します。

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

またはScaffoldColumnAttribute、モデル クラス プロパティで (たとえば、編集テンプレートを使用する場合):

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

または、単純に公開しないでください(Html.HiddenInputヘルパーを使用した例で行ったように)。


あなたが説明した 2 番目のアプローチは、多くの場合ViewModel パターンと呼ばれます。プレゼンテーション層とドメイン層の分離を促進します。利点は、ドメイン モデルがプレゼンテーション層固有のコード (さまざまな表示属性など) で汚染されないことです。ただし、ドメイン モデルとビュー モデル間のマッピングの別のオーバーヘッドが発生します。

一般的な経験則はおそらくありません。アプリケーションの種類によって異なります。

それが基本的に単純なデータ駆動型の CRUD アプリケーションである場合は、最初のアプリケーションを簡単に使用できます。それにもかかわらず、アプリケーションが大きくなると、別々のレイヤーを自由に操作できることは間違いなく高く評価されます。また、ASP MVC 以外の他の種類の「クライアント」(Web サービス、デスクトップなど) で BLL コードが使用されている場合は、間違いなく 2 番目のオプションを使用します。

また、この素晴らしい記事を読むことをお勧めします:レイヤー化はマッピングする価値がありますか?

于 2013-02-02T21:16:39.213 に答える
2

私が取り組んでいる小さなプロジェクトであろうと大きなプロジェクトであろうと、私は常にケース 2 を使用します。私は常にデータ層 (エンティティ フレームワーク) と UI 層を分離しています。特に Entity Framework を使用している場合は、これらのオブジェクトが巨大になる可能性があり、多くの場合必要のないものを渡しているので、多くのがらくたです。

Helperそれをクラスと呼ぶ代わりに、それらをViewModelまたはModel. あなたの場合、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 に答える