2015-06-04 13 views
5

ho annidato ViewModels come questi due:ModelState non validare modelli annidati dopo la modifica controller

public class FirstViewModel 
{ 
    public SecondViewModel SecondViewModel { get; set; } 
} 

public class SecondViewModel 
{ 
    [Range(1, 12)] 
    public int month { get; set; } 
} 

Se metto month = 13; e quindi chiamare ModelState.IsValid (nel controllore) la validazione è sempre true.

Edit:

Questo è il controller:

public ActionResult Create() 
{ 
    return PartialView(new FirstViewModel);  
} 

public HttpStatusCodeResult Create (FirstViewModel viewModel){ 

    viewModel.SecondViewModel = new SecondViewModel(); 
    viewModel.SecondViewModel.month = 13; 

    if (ModelState.IsValid) 
    { 
     return new HttpStatusCodeResult(200); 
    } 
    else 
    { 
     return new HttpStatusCodeResult(304); 
    } 
} 

sto facendo astrazione del problema, quelle non sono le variabili reali.

+1

Vuoi mostrarci il tuo controller ** GET ** e ** Post ** metodo? –

+0

Qualsiasi aggiornamento ci aiuterà a trovare una soluzione. Mostraci il tuo modello e ModelState quando non hai impostato il mese. –

+1

Non esiste ** Convalida ** Proprietà su ** ModelState **. Come compilate il vostro progetto? Dovresti avere qualche errore. –

risposta

3

La tua domanda afferma che "chiama ModelState.Validate" nel tuo controller. Non esiste un tale metodo, quindi suppongo che intenda lo if (ModelState.IsValid).

Il primo passaggio nel processo di associazione modello è l'inizializzazione dei parametri del metodo, nel caso si tratta di una nuova istanza di FirstViewModel. Quindi i valori del modello vengono impostati in base ai dati del modulo, ai valori del percorso, ai valori della stringa di query ecc. E gli eventuali errori di convalida associati alle proprietà del modello vengono aggiunti a ModelState.

Successivamente modificare il valore degli immobili nel modello non ha alcun effetto sulla ModelState, quindi se il valore iniziale di month è valido, allora ModelState.IsValid restituisce true indipendentemente dalla regolazione viewModel.SecondViewModel.month = 13;

Se si vuole ri-convalidare il modello, il bisogno di usare TryUpdateModel che restituisce un bool che indica se l'aggiornamento è riuscito

public HttpStatusCodeResult Create (FirstViewModel viewModel) 
{ 
    viewModel.SecondViewModel = new SecondViewModel(); 
    viewModel.SecondViewModel.month = 13; 
    if (TryUpdateModel(viewModel) 
    { 
    return new HttpStatusCodeResult(200); 
    } 
    else 
    { 
    return new HttpStatusCodeResult(304); 
    } 
} 
+0

Grazie per la risposta, ho aggiornato il codice con il metodo corretto. Esiste un metodo simile a TryUpdateModel che restituisce gli errori con i loro messaggi? Voglio restituire un Json con tutti gli errori. –

+1

Dopo aver chiamato 'TryUpdateModel', gli errori vengono aggiunti a' ModelState'. Esistono diverse opzioni da considerare, ad esempio 'var errors = ModelState.Keys.Where (k => ModelState [k] .Errors.Count> 0) .Seleziona (k => new {propertyName = k, errorMessage = ModelState [k] .Errors [0] .ErrorMessage}); 'ti darà una collezione di tutti i nomi di proprietà che hanno errori e il primo errore ad essi associato, quindi potresti usare' return Json (errors); 'e quindi esegui un ciclo su di loro sul client. –

+0

Grazie per l'aiuto, funziona bene. –

0

Poiché la proprietà SecondViewModel della classe FirstViewModel è null, non verrà convalidata. Prova ad aggiungere un attributo necessario per la proprietà:

public class FirstViewModel 
{ 
    [Required] 
    public SecondViewModel SecondViewModel { get; set; } 
} 

public class SecondViewModel 
{ 
    [Range(1, 12)] 
    public int month { get; set; } 
} 

EDIT

Sulla base della sua aggiornamento, sono d'accordo con @StephenMuecke. Non è possibile creare un'istanza di classe e aspettarsi che il framework lo convalidi per te. TryUpdateModel è ciò che stai cercando in questo caso o devi lasciare che il framework istanzia la classe per te. Dovresti passare in SecondViewModel.month = 13 da qualche parte nella tua richiesta per vederlo in azione.

+0

O forse provare ad istanziare il SecondViewModel nel get? –

+0

Quando aggiungo "è richiesto", ModelState.IsValid è falso e l'eccezione dice che SecondViewModel è null. Si può si il controller nella domanda originale! –

+0

** È possibile vedere il controller ... –

-1

È possibile convalidare si modella in qualsiasi momento utilizzando this

Validator.TryValidateObject(). 

o, solo per una proprietà, vedere this

Validator.TryValidateProperty() 

Diciamo che avete classe Indirizzo

public class Address 
{ 
    [Required] 
    public string Address2 { get; set; } 
    [Required] 
    public string ZipCode{ get; set; } 
} 

Si potrebbe utilizzare questo frammento per convalidare l'oggetto. Tutti gli errori saranno nel "varibale" dei risultati.

var addresse = new Address() { Street = null, ZipCode = null}; 
var context = new ValidationContext(addresse, null, null); 
var results = new List<ValidationResult>(); 
bool isValid = Validator.TryValidateObject(addresse, context, results, true); 
+0

Non sono sicuro delle prestazioni. Consiglierei di testare le prestazioni se è in loop! – Iannick

Problemi correlati