2011-01-28 8 views
6

Per ciascuna delle entità aziendali ho un modello di visualizzazione corrispondente.ASP.NET MVC: come posso ottenere la convalida della mia regola aziendale fino a raggiungere il livello di presentazione?

Ho un regolatore di CRUD generico che funziona così:

[HttpPost] 
    public virtual ActionResult Create(TViewModel model, int? id) 
    { 
     // Validate input 
     if (!ModelState.IsValid) 
      return Json(Failure(createView, model.SelectLists(repository))); 

     // Prepare Model 
     var entity = new TModel(); 

     // Add to repository 
     UpdateModel(entity); 
     repository.Add(entity); 
     repository.Save(); 
     return Json(CreateSuccess(entity)); 
    } 

Io uso le annotazioni di dati sul mio punto di vista e proprietà modello Questa grande opera per semplice convalida dell'input.

Ora ho un caso in cui voglio essere sicuro che un record duplicato non venga creato per caso.

Il mio primo istinto è mettere questa logica nel metodo Aggiungi del repository. Questa implementazione sarebbe facile, ma come faccio a ottenere il repository per aggiungere un errore di stato del modello e restituire all'utente alcune informazioni utili? Mi sento come se ci fosse una soluzione là fuori, ma non ho avuto molta fortuna a cercare.

Grazie per qualsiasi aiuto!

risposta

3

Vorrei utilizzare le eccezioni.

  • Lancia l'eccezione dell'applicazione personalizzata con il metodo Aggiungi, se l'entità viene raddoppiata.
  • Avvolgi il metodo Aggiungi in un blocco try per catturare questa eccezione specifica nel metodo Create.
  • Aggiungi un errore di modello di Stato sulla base dei dati di eccezione al blocco catch

    try 
    { 
        repository.Add(entity); 
    } 
    catch(MyRepositoryException ex) 
    { 
        ViewData.ModelState.AddModelError(ex.Key, ex.Value.ToString(), ex.Message) 
    } 
    
    if (!ModelState.IsValid) 
          return Json(Failure(createView, model.SelectLists(repository))); 
    
+0

Sembra un buon riassunto del concetto base di Nerd Dinner che ho postato qui sotto. Come ho affermato nella mia risposta, non mi piace l'idea di usare le eccezioni e invece chiamerò proattivamente un metodo Validate() sull'entità (o repository in questo caso). Grazie! –

1

odio rispondere alle mie domande, ma penso che mi sono imbattuto la risposta che cercavo durante la ricerca di un'altra cosa:

http://nerddinnerbook.s3.amazonaws.com/Part3.htm

sembra che era il momento per una revisione back-to-basics! Avrei dovuto pensare di tornare indietro e rivedere il mio primo tutorial in quanto non c'era alcun modo per assorbire tutto quando stavo iniziando.

parte 3 dei colloqui tutorial su attuazione convalida modello di dominio che restituisce gli errori con il nome della proprietà e le stringhe dei messaggi di errore che sono da aggiungere al ModelState del controller, che permette questo tipo di convalida:

if (ModelState.IsValid) { 

    try { 
     dinner.HostedBy = "SomeUser"; 

     dinnerRepository.Add(dinner); 
     dinnerRepository.Save(); 

     return RedirectToAction("Details", new{id=dinner.DinnerID}); 
    } 
    catch { 
     ModelState.AddModelErrors(dinner.GetRuleViolations()); 
    } 
} 

Non so se mi piace l'idea di aumentare le eccezioni per le violazioni delle regole aziendali, ma il modello di base funzionerà bene per il mio progetto. Spero che questo aiuti qualcun altro!

+0

Ho modificato il codice nel blocco catch: dovrebbe essere "ModelState.AddModelErrors ...". E per le persone che si stanno chiedendo perché non esiste il metodo "AddModelErrors" in ModelState, è un metodo di estensione. http://forums.asp.net/t/1409804.aspx/1 – Rohit

1

Un'alternativa al tuo approccio sarebbe quella di utilizzare l'idea di un ModelStateWrapper implementando IValidationDictionary. In pratica disaccoppia il modelState, ma lascia comunque che il repository/servizio interagisca con il dizionario degli errori. In questo modo la gestione degli errori viene eseguita tramite un'interfaccia e non è necessario fare riferimento a nessun oggetto dati specifico MVC.

C'è un buon interessante resoconto su di esso qui: http://www.asp.net/mvc/tutorials/validating-with-a-service-layer-cs, ma l'idea di base è:

1) passare un'istanza del vostro ModelStateWrapper al repository durante l'inizializzazione del controller:

public MyController() 
{ 
    repository = new MyRepository(new ModelStateWrapper(this.ModelState)); 
} 

2) Aggiungere gli errori ad esso all'interno della vostra repository:

_validatonDictionary.AddError("Name", "Name is required."); 

3) gestione degli errori, come si farebbe normalmente nel controller:

if (!repository.Save()) 
    return View(); 
Problemi correlati