2009-08-14 15 views
2

J'ai un modèle de vue personnalisé dans lequel j'ai deux champs et une entité linq2sql .. tous les champs ont des attributs de validation attachés. Même si tous les champs ne sont pas valides, seuls les champs de la classe linq2sql sont visuellement indiqués pour l'erreur et les champs du viewmodel sont affichés normalement. Mais les messages d'erreur sont affichés pour tous les champs non valides.Custom ViewModel Class - Tous les champs ne sont pas marqués comme invalides sauf si un préfixe est spécifié

My Custom ViewModel ressemble à ceci:

public class BooksViewModel 
{ 
    public SelectList BookCategories { get; set; } 

    public Book Book { get; set; } 

    [Required(ErrorMessage="Field1 is required")] 
    [StringLength(10)] 
    public string Field1 { get; set; } 

    [Required(ErrorMessage = "Field2 question is required")] 
    [StringLength(100)] 
    public string Field2 { get; set; } 
} 

La classe livre est une entité linq2sql qui a un attribut metadatatype ci-joint pour la validation.

[MetadataType(typeof(BookMetadata))] 
public partial class Book 
{ 
} 
public class BookMetadata 
{ 
    [Required(ErrorMessage="Choose a category")] 
    public int CategoryID { get; set; } 

    [Required(ErrorMessage = "Title is required")] 
    [StringLength(100)] 
    public string Title { get; set; } 

    [Required(ErrorMessage = "Published date is required")] 
    [DataType(DataType.Date, ErrorMessage="Enter a valid date")] 
    public DateTime PublishedDate { get; set; } 

    [Required(ErrorMessage = "Author is required")] 
    [StringLength(50)] 
    public string Author { get; set; } 
} 

Il existe une méthode AddBook dans le référentiel avec deux surcharges. On prend le viewmodel et on prend un type de livre:

public void AddBook(Book book) 
{ 
    var errors = DataAnnotationsValidationRunner.GetErrors(book); 

    if (errors.Any()) { 
     throw new RulesException(errors); 
    } 

    _db.Books.InsertOnSubmit(book); 
    _db.SubmitChanges(); 
} 

public void AddBook(BooksViewModel model) 
{ 
    var errors = DataAnnotationsValidationRunner.GetErrors(model); 

    if (errors.Any()) { 
     throw new RulesException(errors); 
    } 
} 

L'action Créer dans le contrôleur ressemble à ceci:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Exclude = "Book.ID")]BooksViewModel booksViewModel) 
{ 
    try { 
     // Validate Book 
     _repository.AddBook(booksViewModel.Book); 
    } catch(RulesException ex) { 
     ex.AddModelStateErrors(ModelState, "Book"); 
    } 

    try { 
     // Validate other fields in the view model 
     _repository.AddBook(booksViewModel); 
    } catch (RulesException ex) { 
     ex.AddModelStateErrors(ModelState, ""); 
    } 

    if (ModelState.IsValid) { 
     return RedirectToAction("Index"); 
    } else { 
     booksViewModel.BookCategories = new SelectList(_repository.GetAllCategories().AsEnumerable(), "ID", "CategoryName", booksViewModel.Book.CategoryID); 
     return (ActionResult)View(booksViewModel); 
    } 
} 

J'utilise xVal pour générer des règles de validation côté client .. Ma créer vue ressemble à ceci:

<% using (Html.BeginForm()) {%> 

    <fieldset> 
     <legend>Fields</legend> 
     <p> 
      <label for="Book.CategoryID">CategoryID:</label> 
      <%= Html.DropDownList("Book.CategoryID", Model.BookCategories, "Select")%> 
      <%= Html.ValidationMessage("Book.CategoryID", "*")%> 
     </p> 
     <p> 
      <label for="Book.Title">Title:</label> 
      <%= Html.TextBox("Book.Title")%> 
      <%= Html.ValidationMessage("Book.Title", "*")%> 
     </p> 
     <p> 
      <label for="Book.PublishedDate">PublishedDate:</label> 
      <%= Html.TextBox("Book.PublishedDate")%> 
      <%= Html.ValidationMessage("Book.PublishedDate", "*")%> 
     </p> 
     <p> 
      <label for="Book.Author">Author:</label> 
      <%= Html.TextBox("Book.Author")%> 
      <%= Html.ValidationMessage("Book.Author", "*")%> 
     </p> 
     <p> 
      <label for="Field1">Field1:</label> 
      <%= Html.TextBox("Field1")%> 
      <%= Html.ValidationMessage("Field1", "*")%> 
     </p> 
     <p> 
      <label for="Field2">Field2:</label> 
      <%= Html.TextBox("Field2")%> 
      <%= Html.ValidationMessage("Field2", "*")%> 
     </p> 
     <p> 
      <input type="submit" value="Create" /> 
     </p> 
    </fieldset> 

<% } %> 

<div> 
    <%=Html.ActionLink("Back to List", "Index") %> 
</div> 
<%= Html.ClientSideValidation<BooksViewModel>() %> 
<%= Html.ClientSideValidation<Book>("Book") %> 

le travail de validation côté client bien .. mais si j'éteins javascript puis republier sous forme message d'erreur sont affichés pour tous les champs, mais la Champ1 & Le champ 2 n'est pas marqué comme invalide. Il n'y a pas de classe css ajoutée aux champs et aucune balise span n'est générée pour l'indication d'erreur visuelle.

Screenshot http://img22.imageshack.us/img22/324/26677634.jpg

Mais si je pefix les champs ViewModel avec quoi que ce soit

public ActionResult Create([Bind(Prefix = "VM", Exclude = "Book.ID")]BooksViewModel booksViewModel) 

et de modifier la vue en conséquence alors tout fonctionne très bien:

<p> 
    <label for="VM.Book.Title">Title:</label> 
    <%= Html.TextBox("VM.Book.Title")%> 
    <%= Html.ValidationMessage("VM.Book.Title", "*")%> 
</p> 

<p> 
    <label for="VM.Field1">Field1:</label> 
    <%= Html.TextBox("VM.Field1")%> 
    <%= Html.ValidationMessage("VM.Field1", "*")%> 
</p> 

<%= Html.ClientSideValidation<BooksViewModel>("VM") %> 
<%= Html.ClientSideValidation<Book>("Book") %> 

ce que je fais mal ici?

Désolé pour faire ce poste si longtemps ..

+0

Un long message a pas de problème ... info était clair et nécessaire. Upvoted! –

Répondre

1

Je pense que le problème pourrait être votre nom de variable et nom de classe sont identiques.

Peut-être dans votre ViewModel renommer quelque chose comme,

public Book BookInstance { get; set; } 

Cela va me falloir un peu de refactoring à travers, mais je pense qu'il est la cause de votre problème.

Bonté,

Dan

+0

Ne pas changer le nom de la propriété ne fait aucune différence – Zuhaib