2010-02-08 19 views
5

Sto cercando di utilizzare DataAnnotations per aggiungere convalida per i miei modelli in asp.NET MVC 2 RC2, utilizzando TryUpdateModelasp.NET MVC 2 DataAnnotations UpdateModel <T> convalida

 var user = UserManager.Find(id); 

     this.TryUpdateModel<IProvisioningObject>(user, form.ToValueProvider()); 

Questa aggiorna il modello, ma la convalida non viene mai chiamato. Ho provato a utilizzare TryUpdateModel (che è il tipo diretto dell'utente), non utilizzando il provider del valore del modulo, utilizzando ProvisioningObject direttamente (che ha i metadati di convalida), senza alcun risultato.

Googling per gli esempi mi dà solo il modo di utilizzare DataAnnotations legandosi attraverso un parametro

public ActionResult Update(User user) 

che non amo per gli scenari di aggiornamento.

Eventuali suggerimenti e/o soluzioni?

EDIT I miei oggetti sono oggetti generati automaticamente da un servizio WCF.

Ho creato partial per aggiungere DataAnnotations. Io chiamo TryUpdateModel tre volte perché apparentemente non supporta l'ereditarietà, il che credo sia anche il mio problema con DataAnnotations. Specifico gli attributi di convalida per ProvisioningObject e l'associazione non ricerca elementi ereditati come quello.

[MetadataType(typeof(ProvisioningObjectMetadata))] 
public partial class ProvisioningObject : IProvisioningObject 
{ 
    public string DisplayNameInvariant { get { return string.IsNullOrEmpty(this.DisplayName) ? this.Name : this.DisplayName; } } 
} 


[MetadataType(typeof(UserMetadata))] 
public partial class User : IUser 
{ 
} 


public class ProvisioningObjectMetadata 
{ 
    [DisplayName("Country")] 
    public string CountryIsoCode { get; set; } 

    [Required(ErrorMessageResourceType = typeof(Properties.Validation), ErrorMessageResourceName = "DisplayNameIsRequired")] 
    [TempValidator] 
    public string DisplayName { get; set; } 
} 


public class UserMetadata 
{ 
    [DisplayName("Username")] 
    public string Name { get; set; } 
} 


// Controller action 
    public ActionResult Update(string id, FormCollection form) 
    { 
     var user = UserManager.Find(id); 

     this.TryUpdateModel<IUser>(user.User, form.ToValueProvider()); 
     this.TryUpdateModel<IPerson>(user.User, form.ToValueProvider()); 
     this.TryUpdateModel<IProvisioningObject>(user.User, form.ToValueProvider()); 

     if (ModelState.IsValid) // always true 
     { 
      return Redirect; 
     } 
     else 
     { 
      return View(); 
     } 
    } 

Se posso aggiungere i metadati per DisplayName in UserMetadata, esso funziona come previsto, ma che sembra molto ridondante per niente. E significherebbe che dovrei anche copiare/incollare tutte le mie interfacce ereditate in modo che TryUpdateModel si comporti in modo appropriato.

Suppongo che sto cercando un modo che non mi imponga di copiare e incollare i miei attributi di convalida in classi ereditate.

risposta

1

Nuova Risposta:

"I miei oggetti sono oggetti generati automaticamente da un servizio WCF."

Gli oggetti generati automaticamente non avranno alcun attributo su di essi. Stai definendo i tuoi oggetti e i loro attributi sul lato server o sul lato client?

Vecchia risposta: Se i metadati non sono su IProvisioningObject, non verrà effettuata alcuna convalida. Il raccoglitore modello predefinito MVC2 sa solo come trovare informazioni di convalida "extra" [MetadataType (buddyClass)].

Per gli scenari di aggiornamento, eseguire il bind contro DTO e quindi associare i DTO, se IsValid() alle classi del modello principale.

+0

Ho solo cercato di fare UpdateModel (dato che non posso mettere MetadataType su un'interfaccia) e non cambia nulla. Ho creato un validatore temporaneo e non sembra aver mai colpito il metodo IsValid. Per lo scenario di aggiornamento, non sono sicuro di seguirti. Se hai buoni collegamenti a blog o esempi, sarebbe sufficiente per farmi iniziare. Grazie per l'input! –

+0

Puoi pubblicare più codice per favore? Non sono chiaro su cosa stai cercando di fare più. – jfar

+0

Nuovo commento di risposta: gli attributi sono lato client. Uso le classi parziali per aggiungere gli attributi appropriati agli oggetti generati automaticamente. –

0

Come fai a sapere che la convalida non viene chiamata? Stai controllando ModelState.IsValid nel tuo controller di aggiornamento e stai scoprendo che è erroneamente tornato vero?

Un tipico modello di aggiornamento è:

UpdateModel(model); 
if(!ModelState.IsValid) return View(model); 
return RedirectToAction("Index"); 

Se vi aspettate un po ' "IsValid" sul modello da automaticamente chiamato, che non accadrà. Le annotazioni dei dati funzionano dietro le quinte con il dizionario ModelState sulla classe di base Controller.

+0

ModelState.IsValid è sempre true, anche se inserisco un attributo di convalida personalizzato che restituisce sempre false. Un punto di interruzione in quell'attributo di convalida non viene mai raggiunto. Funziona se metto la convalida giusta sul tipo e non sull'interfaccia. Inserirò altro codice in un secondo. –

+0

Hai provato a inserire l'attributo del tipo di metadati nella dichiarazione della classe? Esempio: interfaccia IDataObject {... contiene dataannotations ...} [MetadataType (typeof (IDataObject))] classe DataObject {....} – kmehta

+0

Mehta stesso problema. Funziona se metto le DataAnnotation direttamente sull'interfaccia, ma non voglio duplicare la convalida dalla classe/interfaccia genitore. –