Condividi tramite


Aggiunta della convalida al modello (C#)

di Rick Anderson

Nota

Una versione aggiornata di questa esercitazione è disponibile qui che usa ASP.NET MVC 5 e Visual Studio 2013. È più sicuro, molto più semplice da seguire e dimostra più funzionalità.

Questa esercitazione illustra le nozioni di base per la creazione di un'applicazione Web MVC ASP.NET con Microsoft Visual Web Developer 2010 Express Service Pack 1, una versione gratuita di Microsoft Visual Studio. Prima di iniziare, assicurarsi di aver installato i prerequisiti elencati di seguito. È possibile installarli tutti facendo clic sul collegamento seguente: Programma di installazione della piattaforma Web. In alternativa, è possibile installare singolarmente i prerequisiti usando i collegamenti seguenti:

Se si usa Visual Studio 2010 anziché Visual Web Developer 2010, installare i prerequisiti facendo clic sul collegamento seguente: Prerequisiti di Visual Studio 2010.

Per questo argomento è disponibile un progetto Visual Web Developer con codice sorgente C#. Scaricare la versione C#. Se si preferisce Visual Basic, passare alla versione visual Basic di questa esercitazione.

In questa sezione si aggiungerà la logica di convalida al Movie modello e si assicurerà che le regole di convalida vengano applicate ogni volta che un utente tenta di creare o modificare un filmato usando l'applicazione.

Mantenere le cose DRY

Uno dei principali set di progettazione di ASP.NET MVC è DRY ("Non ripetere se stessi"). ASP.NET MVC incoraggia a specificare funzionalità o comportamento una sola volta e quindi rifletterla ovunque in un'applicazione. In questo modo si riduce la quantità di codice che è necessario scrivere e rende il codice molto più semplice da gestire.

Il supporto di convalida fornito da ASP.NET MVC ed Entity Framework Code First è un ottimo esempio del principio DRY in azione. È possibile specificare in modo dichiarativo le regole di convalida in un'unica posizione (nella classe modello) e quindi tali regole vengono applicate ovunque nell'applicazione.

Di seguito viene illustrato come sfruttare questo supporto per la convalida nell'applicazione film.

Aggiunta di regole di convalida al modello di film

Si inizierà aggiungendo una logica di convalida alla Movie classe .

Aprire il file Movie.cs. Aggiungere un'istruzione using all'inizio del file che fa riferimento allo System.ComponentModel.DataAnnotations spazio dei nomi :

using System.ComponentModel.DataAnnotations;

Lo spazio dei nomi fa parte di .NET Framework. Fornisce un set predefinito di attributi di convalida che è possibile applicare in modo dichiarativo a qualsiasi classe o proprietà.

Aggiornare ora la Movie classe per sfruttare i vantaggi degli Requiredattributi di convalida predefiniti , StringLengthe Range . Usare il codice seguente come esempio di dove applicare gli attributi.

public class Movie
{
    public int ID { get; set; }

    [Required(ErrorMessage = "Title is required")]
    public string Title { get; set; }

    [Required(ErrorMessage = "Date is required")]
    public DateTime ReleaseDate { get; set; }

    [Required(ErrorMessage = "Genre must be specified")]
    public string Genre { get; set; }

    [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")]
    public decimal Price { get; set; }

    [StringLength(5)]
    public string Rating { get; set; }
}

Gli attributi di convalida specificano il comportamento da applicare per le proprietà del modello a cui vengono applicati. L'attributo Required indica che una proprietà deve avere un valore. In questo esempio, un filmato deve avere valori per le Titleproprietà , GenreReleaseDate, e Price per essere valide. L'attributo Range vincola un valore all'interno di un intervallo specificato. L'attributo StringLength consente di impostare la lunghezza massima di una proprietà stringa e, facoltativamente, la lunghezza minima.

Code First garantisce che le regole di convalida specificate in una classe modello vengano applicate prima che l'applicazione salvi le modifiche nel database. Ad esempio, il codice seguente genererà un'eccezione quando viene chiamato il SaveChanges metodo , perché mancano diversi valori di proprietà obbligatori Movie e il prezzo è zero (che non rientra nell'intervallo valido).

MovieDBContext db = new MovieDBContext();

Movie movie = new Movie();
movie.Title = "Gone with the Wind";
movie.Price = 0.0M;

db.Movies.Add(movie);
db.SaveChanges();        // <= Will throw validation exception

La presenza di regole di convalida applicate automaticamente da .NET Framework consente di rendere l'applicazione più affidabile. In questo modo inoltre non è possibile omettere la convalida di un elemento e quindi inserire involontariamente dati errati nel database.

Ecco un elenco di codice completo per il file di Movie.cs aggiornato:

using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [Required(ErrorMessage = "Title is required")]
        public string Title { get; set; }

        public DateTime ReleaseDate { get; set; }

        [Required(ErrorMessage = "Genre must be specified")]
        public string Genre { get; set; }

        [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")]
        public decimal Price { get; set; }

        [StringLength(5)]
        public string Rating { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}

Interfaccia utente degli errori di convalida in ASP.NET MVC

Eseguire di nuovo l'applicazione e passare all'URL /Movies .

Fare clic sul collegamento Crea film per aggiungere un nuovo film. Compilare il modulo con alcuni valori non validi e quindi fare clic sul pulsante Crea .

8_validationErrors

Si noti che il modulo ha utilizzato automaticamente un colore di sfondo per evidenziare le caselle di testo che contengono dati non validi e ha generato un messaggio di errore di convalida appropriato accanto a ognuno di essi. I messaggi di errore corrispondono alle stringhe di errore specificate quando è stata annotata la Movie classe . Gli errori vengono applicati sia sul lato client (usando JavaScript) che sul lato server (nel caso in cui un utente abbia disabilitato JavaScript).

Un vantaggio reale è che non è necessario modificare una singola riga di codice nella MoviesController classe o nella visualizzazione Create.cshtml per abilitare questa interfaccia utente di convalida. Il controller e le visualizzazioni create in precedenza in questa esercitazione hanno selezionato automaticamente le regole di convalida specificate usando gli attributi nella Movie classe modello.

Modalità di esecuzione della convalida nel metodo Crea visualizzazione e Crea azione

Ci si potrebbe chiedere come la convalida dell'interfaccia utente sia stata generata senza aggiornamenti al codice nel controller o nelle viste. L'elenco successivo mostra l'aspetto dei Create metodi nella MovieController classe . Sono invariati rispetto al modo in cui sono stati creati in precedenza in questa esercitazione.

//
// GET: /Movies/Create

public ActionResult Create()
{
    return View();
}

//
// POST: /Movies/Create

[HttpPost]
public ActionResult Create(Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Movies.Add(movie);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(movie);
}

Il primo metodo di azione visualizza il modulo Create iniziale. Il secondo gestisce il post del modulo. Il secondo Create metodo chiama ModelState.IsValid per verificare se il filmato presenta errori di convalida. La chiamata a questo metodo valuta tutti gli attributi di convalida applicati all'oggetto. Se l'oggetto presenta errori di convalida, il Create metodo riproduce il modulo. Se non sono presenti errori, il metodo salva il nuovo film nel database.

Di seguito è riportato il modello di visualizzazione Create.cshtml di cui è stato eseguito lo scaffolding in precedenza nell'esercitazione. Viene usata dai metodi di azione illustrati in precedenza per visualizzare il modulo iniziale e per visualizzarlo nuovamente in caso di errore.

@model MvcMovie.Models.Movie
@{
    ViewBag.Title = "Create";
}
<h2>
    Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Movie</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.ReleaseDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ReleaseDate)
            @Html.ValidationMessageFor(model => model.ReleaseDate)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Genre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Genre)
            @Html.ValidationMessageFor(model => model.Genre)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Price)
            @Html.ValidationMessageFor(model => model.Price)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Rating)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Rating)
            @Html.ValidationMessageFor(model => model.Rating)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Si noti che il codice usa un Html.EditorFor helper per restituire l'elemento <input> per ogni Movie proprietà. Accanto a questo helper è una chiamata al Html.ValidationMessageFor metodo helper. Questi due metodi helper funzionano con l'oggetto modello passato dal controller alla visualizzazione (in questo caso, un Movie oggetto ). Cercano automaticamente gli attributi di convalida specificati nel modello e visualizzano i messaggi di errore in base alle esigenze.

Ciò che è davvero interessante di questo approccio è che né il controller né il modello di visualizzazione Crea sanno nulla sulle regole di convalida effettive applicate o sui messaggi di errore specifici visualizzati. Le regole di convalida e le stringhe di errore vengono specificate solo nella classe Movie.

Se si vuole modificare la logica di convalida in un secondo momento, è possibile farlo in un'unica posizione. Non è necessario preoccuparsi dell'incoerenza delle diverse parti dell'applicazione con la modalità di applicazione delle regole perché tutta la logica di convalida verrà definita in un'unica posizione e usata ovunque. In questo modo il codice rimane molto pulito e facile da gestire e sviluppare. Il principio DRY sarà ampiamente rispettato.

Aggiunta della formattazione al modello di film

Aprire il file Movie.cs. Lo spazio dei nomi System.ComponentModel.DataAnnotations fornisce gli attributi di formattazione oltre al set predefinito di attributi di convalida. Si applicherà l'attributo DisplayFormat e un DataType valore di enumerazione alla data di rilascio e ai campi prezzo. Il codice seguente illustra le proprietà ReleaseDate e Price con l'attributo appropriato DisplayFormat.

[DataType(DataType.Date)] 
public DateTime ReleaseDate { get; set; }

[DataType(DataType.Currency)] 
public decimal Price { get; set; }

In alternativa, è possibile impostare in modo esplicito un DataFormatString valore. Il codice seguente mostra la proprietà data di rilascio con una stringa di formato data (vale a dire "d"). Usare questa opzione per specificare che non si vuole eseguire l'ora come parte della data di rilascio.

[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime ReleaseDate { get; set; }

Il codice seguente formatta la Price proprietà come valuta.

[DisplayFormat(DataFormatString = "{0:c}")]
public decimal Price { get; set; }

La classe completa Movie è illustrata di seguito.

public class Movie
{
    public int ID { get; set; }

    [Required(ErrorMessage = "Title is required")]
    public string Title { get; set; }

    [DisplayFormat(DataFormatString = "{0:d}")]
    public DateTime ReleaseDate { get; set; }

    [Required(ErrorMessage = "Genre must be specified")]
    public string Genre { get; set; }

    [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")]
    [DisplayFormat(DataFormatString = "{0:c}")]
    public decimal Price { get; set; }

    [StringLength(5)]
    public string Rating { get; set; }
}

Eseguire l'applicazione e passare al Movies controller.

8_format_SM

Nella parte successiva della serie verrà esaminata l'applicazione e verranno apportati alcuni miglioramenti ai metodi Details e Delete generati automaticamente.