2009-10-09 9 views
6

c'è un sacco di post molto buona e le spiegazioni su come implementare la convalida con ASP.NET MVC, e preferisco uno di questi:

Tuttavia, mi piace molto chiamare ActionMethods tramite il metodo jquery $ .ajax. Uno dei motivi per cui voglio usare $ .ajax è perché ci saranno molte viste parziali caricate nella pagina dinamicamente (anche il modulo per la creazione di entità) tramite chiamate $ .ajax e non posso semplicemente restituire la vista - Perderò tutto il contenuto caricato in modo dinamico.

Per avere una visione migliore del problema, inserirò del codice semplice per spiegare come mi piacerebbe chiamare le azioni del controllore e gestire le risposte nel codice jquery del client.

I controller ActionMethod:

public ActionResult CreateCustomer(string name, string accountNumber) 
    { 
     try 
     { 
      CustomerService.InsertCustomer(name, accountNumber); 

      return Json(new ActionInfo() 
      { 
       Success = true, 
       Message = "Customer Is Successfully Created" 
      }); 

     } 
     catch (Exception ex) 
     { 
      return Json(new ActionInfo() 
      { 
       Success = false, 
       Message = ex.Message 
      }); 
     } 
    } 

di chiamata e la gestione in codice client:

$.ajax({ 
type: "POST", 
url: $form.attr('action'),// /MyController/CreateCustomer 
data: $form.serialize(), 
error: HandleUnespectedError, 
dataType: "json", 
success: function(response) { 

    if (response.Success) 
     alert("Success: " + response.Message); 
    else 
     alert("Error: " + response.Message); 
}}); 

C'è un buon modo per fare alcuni di questi quadri di validazione per lavorare nel modo che ho bisogno? So che posso aggiungere errori di validazione in ActionInfo, e quindi gestirlo nel client, ma credo che sarebbe già una costruzione della mia convalida.

risposta

5

Ho avuto un grande successo facendo convalida tramite AJAX utilizzando gli attributi delle annotazioni dei dati. Per verificare la validità dei dati, è necessario utilizzare la proprietà ModelState del controller, che ha una proprietà propria denominata IsValid. Consiglio vivamente di dare un'occhiata allo data annotations validation attributes tutorial dal sito MVC ufficiale di ASP.NET.

Innanzitutto, è necessario modificare l'azione del controller per accettare l'oggetto modello come parametro, anziché un nome e un numero di account separati. Ciò renderà molto più semplice l'esecuzione della convalida, che illustrerò di seguito. Dal tuo esempio, la mia ipotesi migliore è che il tuo oggetto modello sia, o sarebbe, chiamato Cliente. Si potrebbe avere il seguente codice per definire l'oggetto del modello e la vostra azione di controllo ...

// model object 
public class Customer 
{ 
    public Int32 Id {get; set;} 
    public String Name {get; set;} 
    public String AccountNumber {get; set;} 
} 

// controller 
public class CustomerController : Controller 
{ 
    public ActionResult CreateCustomer([Bind(Exclude = "Id")] Customer customer) 
    { 
    // controller action code 
    } 
} 


Assicurarsi che i campi del modulo sono chiamati a corrispondere ai nomi delle proprietà dell'oggetto cliente in modo ASP .NET MVC può vincolarli automaticamente. L'attributo "Bind", in questo caso, indica a ASP.NET MVC di ignorare la proprietà "Id" della classe Customer durante l'associazione dei campi modulo alle proprietà del modello. Poiché si tratta di un nuovo cliente, non abbiamo ancora un ID, quindi possiamo tranquillamente lasciare l'ID come qualsiasi valore predefinito e lasciare il livello dati per capire come migliorarlo.

Una volta che il controllore ha creato l'oggetto modello per il metodo di azione, la sua validità può essere facilmente verificata tramite la proprietà ModelState.IsValid. Come ci si potrebbe aspettare, restituirà true se le proprietà del modello sono valide o false se 1 o più proprietà non sono valide.

Dalla domanda originale, sembra che il metodo CustomerService.InsertCustomer stia generando eccezioni quando la validazione fallisce.Questo è completamente inutile. InsertCustomer deve solo eseguire tutte le operazioni sui dati necessarie per inserire il nuovo record. A meno che non si desideri astrarre specifiche eccezioni di implementazione, come SqlException, InsertCustomer non dovrebbe realmente catturare o lanciare eccezioni, ma molto probabilmente lascia che bolle di eccezione sul controller (o chiunque sia il chiamante).

Il risultato finale di tutto questo, potrebbe essere un'azione di controllo che è simile al seguente:

public ActionResult CreateCustomer([Bind(Exclude = "Id")] Customer customer) 
{ 
    // model is invalid 
    if (!ModelState.IsValid) 
    { 
    return Json(new ActionInfo() 
    { 
     Success = false, 
     Message = "Validation failed" // you will probably want a more robust message :-) 
    }); 
    } 

    // service method accepts a Customer object rather than arbitrary strings 
    CustomerService.InsertCustomer(customer); 

    return Json(new ActionInfo() 
    { 
    Success = true, 
    Message = "Customer created successfully." 
    }); 

} 


Se volete segnalare errori inaspettati, come eccezioni relative del database, allora si può certamente aggiungere un blocco try/catch attorno alla chiamata a InsertCustomer e restituire il risultato necessario per la visualizzazione del messaggio di errore al client.

+0

Hey thedude! Grazie mille per lo sforzo :) Sono completamente d'accordo con te per l'entità Cliente per l'associazione (volevo fare così, non so perché ho messo il metodo con parametri semplici) e per la gestione delle eccezioni di sicuro. Con xVal posso facilmente implementare la validazione del client, e se qualcuno lo eviterà lo prenderò in azione. Ma come potrei presentare i messaggi di convalida accanto ai campi in quel caso? –

+0

Per questo, si desidera restituire una vista parziale anziché JSON dall'azione del controller. Nella vista parziale, si utilizzerà il metodo helper Html.ValidationMessage() per visualizzare un messaggio di errore per ciascun campo. I messaggi di errore a livello di campo generati dagli attributi delle annotazioni dei dati sono disponibili per il controllore tramite la proprietà 'ModelState'. Ad esempio, per ottenere il primo messaggio di errore per un campo chiamato name, lo si otterrà tramite 'ModelState [" Nome "]. Errori [0] .ErrorMessage'. Inoltre, dai un'occhiata al metodo 'Ajax.BeginForm'. L'ho usato con grande successo in passato. –

+1

Questo è quello che ho capito, o restituirò la vista parziale di JSON, e questa è la cosa che non mi piace ... Comunque, vedrò come gestirlo usando MS con caratteristiche Ajax, sebbene il mio desiderio era quello di evitarlo :) Grazie –

2

Questo è più di un anno dopo che hai fatto la tua domanda, ma ho coperto la convalida lato server con le chiamate Ajax nel mio blog post che potrebbero essere di tuo interesse. Vedo che si restituiscono risultati non riusciti come chiamate HTTP di successo. Ho gestito questo in modo diverso (suppongo che sia più corretto dal momento che $.ajax ha la capacità di funzionalità di risposta success e error). E il tuo esempio particolare è un esempio perfetto che potrebbe essere implementato con la funzionalità che spiegherò nel post del mio blog.

Fondamentalmente invece di restituire sempre una risposta corretta (ma con le proprietà impostate per comunicare al client che l'elaborazione lato server non è riuscita), piuttosto lancio un'eccezione sul server e la gestisco di conseguenza sul client. Sto utilizzando una classe ModelStateException personalizzata insieme a un filtro azione HandleModelStateException.

Problemi correlati