2013-06-17 8 views
6

Mettere semplici annotazioni di dati sulle proprietà è grande,Applicazione di annotazioni dati alle proprietà secondarie del modello di vista in MVC?

public class UnicornViewModel 
{ 
    [Required] 
    public string Name { get; set; } 

ma lascia dire che sto avere qualcosa di simile:

public class SuperPower 
{ 
    public class Name { get; set; } 
} 

public class UnicornViewModel 
{ 
    [Required] 
    public string Name { get; set; } 

    public SuperPower PrimarySuperPower { get; set; } 

    public SuperPower SecondarySuperPower { get; set; } 

Come faccio ad applicare l'attributo richiesto sul PrimarySuperPower.Name lasciandolo opzionale per SecondarySuperPower.Name? Preferibilmente 1. qualcosa che si lega alla convalida lato client e 2. senza alcuna gestione speciale come la verifica del valore di PrimarySuperPower.Name nel validatore Azione/Personalizzato e aggiungere un errore ModelState se è vuoto. Sarebbe bello se ci fosse qualcosa di simile:

[Required(p => p.Name)] 
    public SuperPower PrimarySuperPower { get; set; } 

    public SuperPower SecondarySuperPower { get; set; } 
+0

Come viene rilevato l'attributo su cosa è collegato? Gli attributi sono solo metadati. – Romoku

risposta

1

In genere questo non è supportato: ASP.NET MVC3 Validation of nested view model object fields

Ma è possibile implementare la validazione dei modelli personalizzati, ma in questo modo sia per il lato client e server diventa piuttosto complicato.

Se si dispone di un modello personalizzato per l'oggetto SuperPower, si potrebbe cercare un attributo della vostra creazione:

[RequiredSubProperty("Name")] 
    public SuperPower PrimarySuperPower { get; set; } 

E nel modello appena passato la validazione discreto attributi nel parametro htmlAttributes del TextBoxFor o qualsiasi altro assistente di input che usi.

Se non si utilizza un modello, si rinuncia a tutto ciò e si passano gli attributi di convalida non invadenti nel parametro htmlAttributes durante la visualizzazione del nome ma non del secondo.

Un'altra opzione è per l'UnicornViewModel per essere appiattito come

public class UnicornViewModel 
{ 
    [Required] 
    public string Name { get; set; } 

    [Required] 
    public string PrimarySuperPowerName { get; set; } 

    public string SecondarySuperPowerName { get; set; } 

Tutto dipende da quanto il riutilizzo si potrebbe ottenere da approcci più complicati. Quando ho provato ad usare il template molto, ho trovato che in contesti diversi certe cose sui template non avevano senso, e avrei avuto bisogno di molte variazioni su un modello di oggetto (quando un template secondario è visualizzato sulla pagina di un genitore, non ha senso che il bambino abbia un URL che si collega ai dettagli del genitore, dato che si è già su quella pagina, ma in qualsiasi altro luogo viene usato il modello secondario, dovrebbe mostrare quel collegamento al genitore). Alla fine ho smesso di usare i template, e occasionalmente uso i partial dove c'è un buon caso per un sacco di riutilizzo. L'interfaccia utente è dove la gomma incontra la strada e ViewModels non sarà strutturato così come potrebbe essere la tua entità/modelli di business.

0

Non è possibile eseguire questa operazione con gli attributi dati standard. La sintassi richiesta che hai menzionato non sarebbe possibile in un'implementazione personalizzata, in quanto non vi è alcun riferimento all'oggetto che stai cercando di utilizzare contro lambda.

Potrebbe essere meglio utilizzare una libreria di convalida di terze parti, come FluentValidation. Offre una notevole flessibilità ai requisiti di convalida.

0

Personalmente, sono un fan dell'uso di ModelMetadataClass per la gestione dei miei ViewModels. Se siete disposti ad andare avanti passo in più e utilizzare AutoMapper si potrebbe creare un ViewModel come segue:

public class SuperPower 
{ 
    public string Name { get; set; } 
} 

[MetadataType(typeof(UnicornViewModel.UnicornViewModelMetaData))] 
public class UnicornViewModel 
{ 
    public string Name { get; set; } 

    public RequiredSuperPowerViewModel PrimarySuperPower { get; set; } 

    public SuperPower SecondarySuperPower { get; set; } 

    public class UnicornViewModelMetaData 
    { 
     [Required] 
     public string Name { get; set; } 

    } 
} 

[MetadataType(typeof(UnicornViewModel.UnicornViewModelMetaData))] 
public class RequiredSuperPowerViewModel : SuperPower 
{ 
    public class RequiredSuperPowerModelMetaData 
    { 
     [Required] 
     public string Name { get; set; } 

    } 
} 

questo vi permetterà di scegliere quali campi gradireste richiesta per una determinata classe del modello senza impattare il vostro modello.

Se si utilizza automapper è possibile reidratare la superpotenza originale come segue:

SuperPower reqSuperPower = AutoMapper.Mapper.Map<RequiredSuperPowerViewModel, SuperPower>(Data.PrimarySuperPower); 
0

Questa potrebbe essere una risposta in ritardo, ma ho trovato questa domanda durante la ricerca per la stessa cosa. Ecco come ho risolto il mio situazione particolare:

Prima ho avuto questo:

public class ProductVm 
{ 
    //+ some other properties   

    public Category Category {get; set;} 
    public Category ParentCategory {get; set;} 
} 

Per cui volevo avere qualcosa del calibro di:

public class ProductVm 
{ 
    //some other properties   

    [DisplayName("Product Category", e => e.Description)] 
    public Category Category {get; set;} 
    [DisplayName("Parent Category", e => e.Description)] 
    public Category ParentCategory {get; set;} 
} 

non ho potuto entrare questo nel modello stesso poiché entrambi sono la stessa classe di oggetti.

ho risolto in questo modo (da quando ho solo bisogno di leggere il valore descrizione in questo caso e non scriverlo):

public class ProductVm 
{ 
    //some other properties   

    public Category Category {get; set;} 
    public Category ParentCategory {get; set;} 

    [DisplayName("Product Category")] 
    public string Category => Category.Description; 

    [DisplayName("Main Category")] 
    public string ParentCategory => ParentCategory.Description; 
} 

cui si può avere solo riscrivere un po 'di più per mantenere il sostegno privato rimanenti campi e rimuovere l'incapsulamento di proprietà degli oggetti Categoria, ma nel mio caso ho ancora bisogno che siano pubblici per altri usi.

Per quanto riguarda la domanda di cui sopra vorrei fare le seguenti operazioni:

public class UnicornViewModel 
{ 
    [Required] 
    public string Name { get; set; } 

    public SuperPower PrimarySuperPower { get; set; } 

    public SuperPower SecondarySuperPower { get; set; } 

    [Required] 
    public string PrimarySuperPowerName 
    { 
     get { return PrimarySuperPower.Name; } 
     set { PrimarySuperPower.Name = value; } 
    } 

    public string SecondarySuperPowerName 
    { 
     get { return SecondarySuperPower.Name; } 
     set { SecondarySuperPower.Name = value; } 
    } 
} 

E poi mi piacerebbe legare la mia vista per le proprietà di stringa ed escludere le proprietà superpotenza.

Problemi correlati