3

私は次の2つのエンティティを持っています:

 public class Product
{
    [Key]
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    public virtual Category Category { get; set; }
}
public class Category
{
    [Key]
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    public ICollection<Product> Products { get; set; }
}

とビューモデル

public class ProductCreateOrEditViewModel
{
    public Product Product { get; set; }
    public IEnumerable<Category> Categories { get; set; }
}

製品の作成ビューはこのViewModelを使用します。カテゴリIDは、ビューで次のように設定されます。

<div class="editor-field">
@Html.DropDownListFor(model => model.Product.Category.ID,new SelectList   
(Model.Categories,"ID","Name"))
    @Html.ValidationMessageFor(model => model.Product.Category.ID)
</div>

フォームが投稿されると、製品と選択されたカテゴリオブジェクトが設定されたビューモデルのインスタンスを取得しますが、Categoryの「Name」プロパティに[Required]属性があるため、ModelStateは無効です。

製品の作成に関しては、「Name」プロパティは必要ありません。これがModelStateエラーとして報告されないように、モデルバインディングを機能させるにはどうすればよいですか?

4

1 に答える 1

4

ビューに適切なViewModelを作成する必要があります。

imoの最善のアプローチは、ドメインエンティティをビューに公開しないことです。

エンティティからビューモデルへの単純なDTOフラット化を実行する必要があります。

そのようなクラス

public class ProductViewModel
{
   public int ID { get; set; }
   [Required]
   public string Name { get; set; }
   public int CategoryId? { get; set; }
   public SelectList Categories { get; set; }
}

コントローラから、製品をビューモデルにマッピングします

public ViewResult MyAction(int id)
{
   Product model = repository.Get(id);

   //check if not null etc. etc.

   var viewModel = new ProductViewModel();
   viewModel.Name = model.Name;
   viewModel.CategoryId = model.Category.Id;
   viewModel.Categories = new SelectList(categoriesRepo.GetAll(), "Id", "Name", viewModel.CategoryId)

   return View(viewModel);
}

次に、投稿に応答するアクションで、viewModelを製品にマップし直します

[HttpPost]
public ViewResult MyAction(ProductViewModel viewModel)
{
   //do the inverse mapping and save the product
}

私はあなたがアイデアを得ることを願っています

于 2012-04-11T16:17:00.537 に答える