2012-04-11 21 views
3

Ich habe folgende 2 Einheiten:Validierung von Viewmodel verschachtelte Domain-Objekte enthalten

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; } 
} 

und eine Ansicht Modell

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

Die Ansicht erstellen für Produkte dieses Ansichtsmodell verwendet. Die Kategorie-ID wird eingestellt, wie in der Ansicht folgt:

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

Wenn die Form Beiträge ich eine Instanz der View-Modell erhalten mit einem Produkt und der gewählten Kategorie Objekt gesetzt, aber da die Eigenschaft „Name“ der Kategorie verfügt über ein [Erforderlich] -Attribut Der ModelState ist nicht gültig.

Soweit ein Produkt erstellen geht, brauche ich nicht oder kümmern Sie sich um die Eigenschaft "Name". Wie kann ich die Modellbindung so einrichten, dass sie nicht als ModelState-Fehler gemeldet wird?

Antwort

3

Sie sollten ein korrektes ViewModel für Ihre Ansicht erstellen.

Der beste Ansatz Imo besteht nicht darin, Ihre Domain-Entitäten der Ansicht auszusetzen.

Sie sollten eine einfache DTO-Abflachung von Ihren Entitäten zu Ihrem Ansichtsmodell durchführen.

Eine Klasse wie die

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

Von Ihrem Controller ordnen Sie das Produkt zu Ihrem Viewmodel

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); 
} 

Dann in der Aktion, die sich auf die Post reagieren, ordnen Sie Ihre Viewmodel auf das Produkt zurück

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

ich hoffe, Sie bekommen die Idee

+0

Sinnvoll, der einzige Nebeneffekt ist, dass Sie die Modellvalidierung für alle Ansichtsmodellklassen duplizieren müssten, oder gibt es dafür einen empfohlenen Ansatz? –

+1

Sie werden am Ende zwei Validierungslayer haben. Eine "clientseitige" über Viewmodel und eine "serverseitige" über Ihre Business-Logik-Ebene, wie es sein sollte – Iridio

Verwandte Themen