Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Stephen Walther illustra come visualizzare messaggi di errore di convalida personalizzati implementando l'interfaccia IDataErrorInfo in una classe del modello.
L'obiettivo di questa esercitazione è illustrare un approccio all'esecuzione della convalida in un'applicazione MVC ASP.NET. Si apprenderà come impedire a un utente di inviare un modulo HTML senza fornire valori per i campi modulo obbligatori. In questa esercitazione si apprenderà come eseguire la convalida usando l'interfaccia IErrorDataInfo.
Presupposti
In questa esercitazione si useranno il database MoviesDB e la tabella di database Movies. Questa tabella contiene le colonne seguenti:
| Nome colonna | Tipo di dati | Consenti valori NULL |
|---|---|---|
| ID | Int | Falso |
| Titolo | Nvarchar (100) | Falso |
| Responsabile | Nvarchar (100) | Falso |
| DateReleased | Datetime | Falso |
In questa esercitazione si usa Microsoft Entity Framework per generare le classi del modello di database. La classe Movie generata da Entity Framework viene visualizzata nella figura 1.
Figura 01: Entità Movie (Fare clic per visualizzare l'immagine a dimensione intera)
Nota
Per altre informazioni sull'uso di Entity Framework per generare le classi del modello di database, vedere l'esercitazione intitolata Creazione di classi di modelli con Entity Framework.
Classe controller
Usiamo il controller Home per elencare i film e creare nuovi film. Il codice per questa classe è contenuto nell'elenco 1.
Elenco 1 - Controllers\HomeController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
private MoviesDBEntities _db = new MoviesDBEntities();
public ActionResult Index()
{
return View(_db.MovieSet.ToList());
}
public ActionResult Create()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Movie movieToCreate)
{
// Validate
if (!ModelState.IsValid)
return View();
// Add to database
try
{
_db.AddToMovieSet(movieToCreate);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
La classe controller Home in Listing 1 contiene due azioni Create(). La prima azione visualizza il modulo HTML per la creazione di un nuovo filmato. La seconda azione Create() esegue l'inserimento effettivo del nuovo filmato nel database. La seconda azione Create() viene richiamata quando il modulo visualizzato dalla prima azione Create() viene inviato al server.
Si noti che la seconda azione Create() contiene le righe di codice seguenti:
// Validate
if (!ModelState.IsValid)
return View();
La proprietà IsValid restituisce false quando si verifica un errore di convalida. In tal caso, la visualizzazione Crea che contiene il modulo HTML per la creazione di un filmato viene riprodotta nuovamente.
Creazione di una classe parziale
La classe Movie viene generata da Entity Framework. È possibile visualizzare il codice per la classe Movie se si espande il file MoviesDBModel.edmx nella finestra Esplora soluzioni e aprire MoviesDBModel.Designer. file cs nell'editor di codice (vedere la figura 2).
Figura 02: Codice per l'entità Movie (Fare clic per visualizzare l'immagine a dimensione intera)
La classe Movie è una classe parziale. Ciò significa che è possibile aggiungere un'altra classe parziale con lo stesso nome per estendere la funzionalità della classe Movie. La logica di convalida verrà aggiunta alla nuova classe parziale.
Aggiungere la classe in Listato 2 alla cartella Models.
Elenco 2 - Models\Movie.cs
using System.Collections.Generic;
using System.ComponentModel;
namespace MvcApplication1.Models
{
public partial class Movie
{
}
}
Si noti che la classe in Listing 2 include il modificatore parziale . Tutti i metodi o le proprietà aggiunti a questa classe diventano parte della classe Movie generata da Entity Framework.
Aggiunta di metodi parziali OnChanging e OnChanged
Quando Entity Framework genera una classe di entità, Entity Framework aggiunge automaticamente metodi parziali alla classe . Entity Framework genera metodi parziali OnChanging e OnChanged che corrispondono a ogni proprietà della classe .
Nel caso della classe Movie, Entity Framework crea i metodi seguenti:
- OnIdChanging
- OnIdChanged
- OnTitleChanging
- OnTitleChanged
- OnDirectorChanging
- OnDirectorChanged
- OnDateReleasedChanging
- OnDateReleasedChanged
Il metodo OnChanging viene chiamato subito prima della modifica della proprietà corrispondente. Il metodo OnChanged viene chiamato subito dopo la modifica della proprietà.
È possibile sfruttare questi metodi parziali per aggiungere la logica di convalida alla classe Movie. La classe Movie di aggiornamento in Listing 3 verifica che alle proprietà Title e Director siano assegnati valori non vuoti.
Nota
Un metodo parziale è un metodo definito in una classe che non è necessario implementare. Se non si implementa un metodo parziale, il compilatore rimuove la firma del metodo e tutte le chiamate al metodo in modo che non siano previsti costi di runtime associati al metodo parziale. Nell'editor di Visual Studio Code è possibile aggiungere un metodo parziale digitando la parola chiave parziale seguita da uno spazio per visualizzare un elenco di parziali da implementare.
Elenco 3 - Models\Movie.cs
using System.Collections.Generic;
using System.ComponentModel;
namespace MvcApplication1.Models
{
public partial class Movie : IDataErrorInfo
{
private Dictionary<string, string> _errors = new Dictionary<string, string>();
partial void OnTitleChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Title", "Title is required.");
}
partial void OnDirectorChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Director", "Director is required.");
}
}
}
Ad esempio, se si tenta di assegnare una stringa vuota alla proprietà Title, viene assegnato un messaggio di errore a un dizionario denominato _errors.
A questo punto, non accade nulla quando si assegna una stringa vuota alla proprietà Title e viene aggiunto un errore al campo _errors privato. È necessario implementare l'interfaccia IDataErrorInfo per esporre questi errori di convalida al framework MVC ASP.NET.
Implementazione dell'interfaccia IDataErrorInfo
L'interfaccia IDataErrorInfo fa parte di .NET Framework dalla prima versione. Questa interfaccia è un'interfaccia molto semplice:
public interface IDataErrorInfo
{
string this[string columnName] { get; }
string Error { get; }
}
Se una classe implementa l'interfaccia IDataErrorInfo, il framework ASP.NET MVC userà questa interfaccia durante la creazione di un'istanza della classe . Ad esempio, l'azione Home controller Create() accetta un'istanza della classe Movie:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Movie movieToCreate)
{
// Validate
if (!ModelState.IsValid)
return View();
// Add to database
try
{
_db.AddToMovieSet(movieToCreate);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Il framework MVC ASP.NET crea l'istanza di Movie passata all'azione Create() usando un gestore di associazione di modelli (DefaultModelBinder). Lo strumento di associazione di modelli è responsabile della creazione di un'istanza dell'oggetto Movie associando i campi del modulo HTML a un'istanza dell'oggetto Movie.
DefaultModelBinder rileva se una classe implementa o meno l'interfaccia IDataErrorInfo. Se una classe implementa questa interfaccia, il gestore di associazione di modelli richiama l'indicizzatore IDataErrorInfo.questo indicizzatore per ogni proprietà della classe. Se l'indicizzatore restituisce un messaggio di errore, lo strumento di associazione di modelli aggiunge automaticamente questo messaggio di errore allo stato del modello.
DefaultModelBinder controlla anche la proprietà IDataErrorInfo.Error. Questa proprietà è progettata per rappresentare errori di convalida specifici della proprietà associati alla classe . Ad esempio, è possibile applicare una regola di convalida che dipende dai valori di più proprietà della classe Movie. In tal caso, viene restituito un errore di convalida dalla proprietà Error.
La classe Movie aggiornata in Listing 4 implementa l'interfaccia IDataErrorInfo.
Listato 4 - Models\Movie.cs (implementa IDataErrorInfo)
using System.Collections.Generic;
using System.ComponentModel;
namespace MvcApplication1.Models
{
public partial class Movie : IDataErrorInfo
{
private Dictionary<string, string> _errors = new Dictionary<string, string>();
partial void OnTitleChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Title", "Title is required.");
}
partial void OnDirectorChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Director", "Director is required.");
}
#region IDataErrorInfo Members
public string Error
{
get
{
return string.Empty;
}
}
public string this[string columnName]
{
get
{
if (_errors.ContainsKey(columnName))
return _errors[columnName];
return string.Empty;
}
}
#endregion
}
}
Nell'elenco 4 la proprietà dell'indicizzatore controlla l'insieme _errors per verificare se contiene una chiave che corrisponde al nome della proprietà passato all'indicizzatore. Se alla proprietà non è associato alcun errore di convalida, viene restituita una stringa vuota.
Non è necessario modificare il controller Home in alcun modo per usare la classe Movie modificata. La pagina visualizzata nella figura 3 illustra cosa accade quando non viene immesso alcun valore per i campi del modulo Title o Director.
Figura 03: modulo con valori mancanti (Fare clic per visualizzare l'immagine full-size)
Si noti che il valore DateReleased viene convalidato automaticamente. Poiché la proprietà DateReleased non accetta valori NULL, DefaultModelBinder genera automaticamente un errore di convalida per questa proprietà quando non ha un valore. Se si vuole modificare il messaggio di errore per la proprietà DateReleased, è necessario creare un binding del modello personalizzato.
Riepilogo
In questa esercitazione si è appreso come usare l'interfaccia IDataErrorInfo per generare messaggi di errore di convalida. Prima di tutto, è stata creata una classe Movie parziale che estende la funzionalità della classe Movie parziale generata da Entity Framework. Successivamente, è stata aggiunta la logica di convalida ai metodi parziali OnTitleChanging() e OnDirectorChanging(). Infine, è stata implementata l'interfaccia IDataErrorInfo per esporre questi messaggi di convalida al framework ASP.NET MVC.