Bagikan melalui


Menambahkan Validasi

oleh Rick Anderson

Catatan

Versi terbaru dari tutorial ini tersedia di sini menggunakan versi terbaru Visual Studio. Tutorial baru menggunakan ASP.NET Core MVC, yang memberikan banyak peningkatan atas tutorial ini.

Tutorial ini mengajarkan ASP.NET Core MVC dengan pengontrol dan tampilan. Razor Pages adalah alternatif baru dalam ASP.NET Core, model pemrograman berbasis halaman yang membuat membangun UI web lebih mudah dan lebih produktif. Kami sarankan Anda mencoba tutorial Razor Pages sebelum versi MVC. Tutorial Halaman Razor:

  • Lebih mudah diikuti.
  • Mencakup lebih banyak fitur.
  • Adalah pendekatan yang disukai untuk pengembangan aplikasi baru.

Di bagian ini Anda akan menambahkan logika validasi ke Movie model, dan Anda akan memastikan bahwa aturan validasi diberlakukan setiap kali pengguna mencoba membuat atau mengedit film menggunakan aplikasi.

Menjaga Hal-hal TETAP KERING

Salah satu tenet desain inti ASP.NET MVC adalah DRY ("Don't Repeat Yourself"). ASP.NET MVC mendorong Anda untuk menentukan fungsionalitas atau perilaku hanya sekali, dan kemudian membuatnya tercermin di mana-mana dalam aplikasi. Ini mengurangi jumlah kode yang perlu Anda tulis dan membuat kode yang Anda tulis lebih sedikit rawan kesalahan dan lebih mudah dipertahankan.

Dukungan validasi yang diberikan oleh ASP.NET MVC dan Entity Framework Code First adalah contoh yang bagus dari prinsip DRY yang sedang berjalan. Anda dapat secara deklaratif menentukan aturan validasi di satu tempat (di kelas model) dan aturan diberlakukan di mana saja dalam aplikasi.

Mari kita lihat bagaimana Anda dapat memanfaatkan dukungan validasi ini di aplikasi film.

Menambahkan Aturan Validasi ke Model Film

Anda akan mulai dengan menambahkan beberapa logika validasi ke Movie kelas .

Buka file Movie.cs. Perhatikan bahwa System.ComponentModel.DataAnnotations namespace tidak berisi System.Web. DataAnnotations menyediakan sekumpulan atribut validasi bawaan yang dapat Anda terapkan secara deklaratif ke kelas atau properti apa pun. (Ini juga berisi atribut pemformatan seperti DataType yang membantu pemformatan dan tidak memberikan validasi apa pun.)

Sekarang perbarui Movie kelas untuk memanfaatkan atribut bawaan Required, , StringLengthRegularExpression, dan Range validasi. Movie Ganti kelas dengan yang berikut:

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

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime ReleaseDate { get; set; }
  
    [RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
    [StringLength(5)]
    public string Rating { get; set; }
}

Atribut StringLength mengatur panjang maksimum string, dan menetapkan batasan ini pada database, oleh karena itu skema database akan berubah. Klik kanan pada tabel Film di Penjelajah server dan klik Buka Definisi Tabel:

Cuplikan layar yang memperlihatkan jendela Server Explorer terbuka dan pada tab d b o dot Movies Design.

Pada gambar di atas, Anda dapat melihat semua bidang string diatur ke NVARCHAR (MAX). Kami akan menggunakan migrasi untuk memperbarui skema. Bangun solusi, lalu buka jendela Konsol Manajer Paket dan masukkan perintah berikut:

add-migration DataAnnotations
update-database

Setelah perintah ini selesai, Visual Studio membuka file kelas yang menentukan kelas turunan baru DbMigration dengan nama yang ditentukan (DataAnnotations), dan dalam metode Anda Up dapat melihat kode yang memperbarui batasan skema:

public override void Up()
{
    AlterColumn("dbo.Movies", "Title", c => c.String(maxLength: 60));
    AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false, maxLength: 30));
    AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
}

Bidang Genre tidak lagi dapat diubah ke null (artinya, Anda harus memasukkan nilai). Bidang Rating ini memiliki panjang maksimum 5 dan Title memiliki panjang maksimum 60. Panjang minimum 3 aktif Title dan rentang pada Price tidak membuat perubahan skema.

Periksa skema Film:

Cuplikan layar yang memperlihatkan tab d b o dot Movies Design. Judul dan Peringkat dicentang di kolom Izinkan Nulls.

Bidang string menunjukkan batas panjang baru dan Genre tidak lagi diperiksa sebagai nullable.

Atribut validasi menentukan perilaku yang ingin Anda terapkan pada properti model yang diterapkan. Atribut Required dan MinimumLength menunjukkan bahwa properti harus memiliki nilai; tetapi tidak ada yang mencegah pengguna memasukkan spasi kosong untuk memenuhi validasi ini. Atribut RegularExpression digunakan untuk membatasi karakter apa yang dapat dimasukkan. Dalam kode di atas, Genre dan Rating hanya boleh menggunakan huruf (spasi kosong, angka, dan karakter khusus tidak diperbolehkan). Atribut Range membatasi nilai dalam rentang yang ditentukan. Atribut ini StringLength memungkinkan Anda mengatur panjang maksimum properti string, dan secara opsional panjang minimumnya. Jenis nilai (seperti decimal, int, float, DateTime) secara inheren diperlukan dan tidak memerlukan Required atribut .

Code First memastikan bahwa aturan validasi yang Anda tentukan pada kelas model diberlakukan sebelum aplikasi menyimpan perubahan dalam database. Misalnya, kode di bawah ini akan melempar pengecualian DbEntityValidationException saat metode dipanggil SaveChanges , karena beberapa nilai properti yang diperlukan Movie hilang:

MovieDBContext db = new MovieDBContext();
Movie movie = new Movie();
movie.Title = "Gone with the Wind";
db.Movies.Add(movie);
db.SaveChanges();        // <= Will throw server side validation exception

Kode di atas melemparkan pengecualian berikut:

Validasi gagal untuk satu atau beberapa entitas. Lihat properti 'EntityValidationErrors' untuk detail selengkapnya.

Memiliki aturan validasi yang secara otomatis diberlakukan oleh .NET Framework membantu membuat aplikasi Anda lebih kuat. Ini juga memastikan bahwa Anda tidak bisa lupa untuk memvalidasi sesuatu dan secara tidak sengaja membiarkan data buruk ke dalam database.

UI Kesalahan Validasi di MVC ASP.NET

Jalankan aplikasi dan navigasikan ke URL /Movies .

Klik tautan Buat Baru untuk menambahkan film baru. Isi formulir dengan beberapa nilai yang tidak valid. Segera setelah validasi sisi klien jQuery mendeteksi kesalahan, ia menampilkan pesan kesalahan.

8_validationErrors

Catatan

untuk mendukung validasi jQuery untuk lokal non-Bahasa Inggris yang menggunakan koma (",") untuk titik desimal, Anda harus menyertakan NuGet globalisasi seperti yang dijelaskan sebelumnya dalam tutorial ini.

Perhatikan bagaimana formulir telah secara otomatis menggunakan warna batas merah untuk menyoroti kotak teks yang berisi data yang tidak valid dan telah memancarkan pesan kesalahan validasi yang sesuai di samping masing-masing kotak teks. Kesalahan diberlakukan baik sisi klien (menggunakan JavaScript dan jQuery) dan sisi server (jika pengguna menonaktifkan JavaScript).

Manfaat nyata adalah Anda tidak perlu mengubah satu baris kode di MoviesController kelas atau dalam tampilan Create.cshtml untuk mengaktifkan UI validasi ini. Pengontrol dan tampilan yang Anda buat sebelumnya dalam tutorial ini secara otomatis mengambil aturan validasi yang Anda tentukan dengan menggunakan atribut validasi pada properti Movie kelas model. Uji validasi menggunakan Edit metode tindakan, dan validasi yang sama diterapkan.

Data formulir tidak dikirim ke server sampai tidak ada kesalahan validasi sisi klien. Anda dapat memverifikasi ini dengan menempatkan titik henti dalam metode HTTP Post, dengan menggunakan alat fiddler, atau alat pengembang IE F12.

Bagaimana Validasi Terjadi dalam Buat Tampilan dan Buat Metode Tindakan

Anda mungkin bertanya-tanya bagaimana UI validasi dihasilkan tanpa pembaruan kode di pengontrol atau tampilan. Daftar berikutnya menunjukkan seperti apa Create metode di MovieController kelas tersebut. Mereka tidak berubah dari cara Anda membuatnya sebelumnya dalam tutorial ini.

public ActionResult Create()
{
    return View();
}
// POST: /Movies/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Movies.Add(movie);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

Metode tindakan pertama (HTTP GET) Create menampilkan formulir Buat awal. Versi kedua ([HttpPost]) menangani posting formulir. Metode kedua Create ( HttpPost versi) memeriksa ModelState.IsValid untuk melihat apakah film memiliki kesalahan validasi. Mendapatkan properti ini mengevaluasi atribut validasi apa pun yang telah diterapkan ke objek. Jika objek memiliki kesalahan validasi, Create metode akan memutar ulang formulir. Jika tidak ada kesalahan, metode menyimpan film baru dalam database. Dalam contoh film kami, formulir tidak diposting ke server ketika ada kesalahan validasi yang terdeteksi di sisi klien; metode kedua Create tidak pernah dipanggil. Jika Anda menonaktifkan JavaScript di browser Anda, validasi klien dinonaktifkan, dan metode HTTP POST Create akan ModelState.IsValid memeriksa apakah film memiliki kesalahan validasi.

Anda dapat mengatur titik henti dalam HttpPost Create metode dan memverifikasi metode tidak pernah dipanggil, validasi sisi klien tidak akan mengirimkan data formulir ketika kesalahan validasi terdeteksi. Jika Anda menonaktifkan JavaScript di browser Anda, kirim formulir dengan kesalahan, titik henti akan tertembak. Anda masih mendapatkan validasi penuh tanpa JavaScript. Gambar berikut menunjukkan cara menonaktifkan JavaScript di Internet Explorer.

Cuplikan layar yang memperlihatkan jendela Opsi Internet terbuka dan pada tab keamanan. Jendela Tingkat kustom terbuka dan Skrip aktif dinonaktifkan.

Cuplikan layar yang memperlihatkan posting H t t p dan jika titik status Model valid disorot.

Gambar berikut menunjukkan cara menonaktifkan JavaScript di browser FireFox.

Cuplikan layar yang memperlihatkan jendela Opsi. Konten dipilih dan Aktifkan Skrip Java dilingkari dengan warna merah.

Gambar berikut menunjukkan cara menonaktifkan JavaScript di browser Chrome.

Cuplikan layar yang memperlihatkan pengaturan Skrip Java dan opsi untuk mengizinkan atau menonaktifkan.

Di bawah ini adalah templat tampilan Create.cshtml yang Anda perancah sebelumnya dalam tutorial. Ini digunakan oleh metode tindakan yang ditunjukkan di atas untuk menampilkan formulir awal dan untuk memutarnya kembali jika terjadi kesalahan.

@model MvcMovie.Models.Movie
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>
        @*Fields removed for brevity.*@        




        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Perhatikan bagaimana kode menggunakan pembantu Html.EditorFor untuk menghasilkan <input> elemen untuk setiap Movie properti. Di samping pembantu ini adalah panggilan ke metode pembantu Html.ValidationMessageFor . Kedua metode pembantu ini bekerja dengan objek model yang diteruskan oleh pengontrol ke tampilan (dalam hal ini, objek Movie ). Mereka secara otomatis mencari atribut validasi yang ditentukan pada model dan menampilkan pesan kesalahan yang sesuai.

Apa yang benar-benar bagus tentang pendekatan ini adalah bahwa baik pengontrol maupun Create templat tampilan tidak tahu apa-apa tentang aturan validasi aktual yang diberlakukan atau tentang pesan kesalahan tertentu yang ditampilkan. Aturan validasi dan string kesalahan hanya ditentukan di Movie kelas . Aturan validasi yang sama ini secara otomatis diterapkan ke Edit tampilan dan templat tampilan lain yang mungkin Anda buat yang mengedit model Anda.

Jika Anda ingin mengubah logika validasi nanti, Anda dapat melakukannya tepat di satu tempat dengan menambahkan atribut validasi ke model (dalam contoh ini, movie kelas ). Anda tidak perlu khawatir tentang berbagai bagian aplikasi yang tidak konsisten dengan bagaimana aturan diberlakukan - semua logika validasi akan didefinisikan di satu tempat dan digunakan di mana-mana. Ini menjaga kode sangat bersih, dan membuatnya mudah untuk dipertahankan dan berkembang. Dan itu berarti bahwa Anda akan sepenuhnya menghormati prinsip DRY .

Menggunakan Atribut DataType

Buka file Movie.cs dan periksa Movie kelas . Namespace System.ComponentModel.DataAnnotations menyediakan atribut pemformatan selain kumpulan atribut validasi bawaan. Kami telah menerapkan DataType nilai enumerasi ke tanggal rilis dan ke bidang harga. Kode berikut menunjukkan ReleaseDate properti dan Price dengan atribut yang sesuai DataType .

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

Atribut DataType hanya memberikan petunjuk bagi mesin tampilan untuk memformat data (dan menyediakan atribut seperti <a> untuk URL dan <a href="mailto:EmailAddress.com"> untuk email. Anda dapat menggunakan atribut RegularExpression untuk memvalidasi format data. Atribut DataType digunakan untuk menentukan jenis data yang lebih spesifik daripada jenis intrinsik database, mereka bukan atribut validasi. Dalam hal ini kita hanya ingin melacak tanggal, bukan tanggal dan waktu. Enumerasi DataType menyediakan banyak jenis data, seperti Tanggal, Waktu, Nomor Telepon, Mata Uang, EmailAddress, dan banyak lagi. Atribut ini DataType juga dapat memungkinkan aplikasi untuk secara otomatis menyediakan fitur khusus jenis. Misalnya, mailto: tautan dapat dibuat untuk DataType.EmailAddress, dan pemilih tanggal dapat disediakan untuk DataType.Date di browser yang mendukung HTML5. Atribut DataType memancarkan atribut data HTML 5- (tanda hubung data yang diucapkan) yang dapat dipahami browser HTML 5. Atribut DataType tidak memberikan validasi apa pun.

DataType.Date tidak menentukan format tanggal yang ditampilkan. Secara default, bidang data ditampilkan sesuai dengan format default berdasarkan CultureInfo server.

Atribut DisplayFormat digunakan untuk secara eksplisit menentukan format tanggal:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }

Pengaturan ApplyFormatInEditMode menentukan bahwa pemformatan yang ditentukan juga harus diterapkan saat nilai ditampilkan dalam kotak teks untuk pengeditan. (Anda mungkin tidak menginginkannya untuk beberapa bidang — misalnya, untuk nilai mata uang, Anda mungkin tidak ingin simbol mata uang dalam kotak teks untuk diedit.)

Anda dapat menggunakan atribut DisplayFormat dengan sendirinya, tetapi umumnya merupakan ide yang baik untuk menggunakan atribut DataType juga. Atribut DataType ini menyampaikan semantik data dibandingkan dengan cara merendernya di layar, dan memberikan manfaat berikut yang tidak Anda dapatkan dengan DisplayFormat:

  • Browser dapat mengaktifkan fitur HTML5 (misalnya untuk menampilkan kontrol kalender, simbol mata uang yang sesuai dengan lokal, tautan email, dll.).
  • Secara default, browser akan merender data menggunakan format yang benar berdasarkan lokal Anda.
  • Atribut DataType dapat mengaktifkan MVC untuk memilih templat bidang yang tepat untuk merender data ( DisplayFormat jika digunakan dengan sendirinya menggunakan templat string). Untuk informasi selengkapnya, lihat Templat Brad Wilson ASP.NET MVC 2. (Meskipun ditulis untuk MVC 2, artikel ini masih berlaku untuk versi ASP.NET MVC saat ini.)

Jika Anda menggunakan DataType atribut dengan bidang tanggal, Anda harus menentukan DisplayFormat atribut juga untuk memastikan bahwa bidang dirender dengan benar di browser Chrome. Untuk informasi selengkapnya, lihat utas StackOverflow ini.

Catatan

Validasi jQuery tidak berfungsi dengan atribut Rentang dan DateTime. Misalnya, kode berikut akan selalu menampilkan kesalahan validasi sisi klien, bahkan ketika tanggal berada dalam rentang yang ditentukan:

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Anda harus menonaktifkan validasi tanggal jQuery untuk menggunakan atribut Rentang dengan DateTime. Ini umumnya bukan praktik yang baik untuk mengkompilasi tanggal keras dalam model Anda, jadi menggunakan atribut Rentang dan DateTime tidak disarankan.

Kode berikut menunjukkan menggabungkan atribut pada satu baris:

public class Movie
{
   public int ID { get; set; }
   [Required,StringLength(60, MinimumLength = 3)]
   public string Title { get; set; }
   [Display(Name = "Release Date"),DataType(DataType.Date)]
   public DateTime ReleaseDate { get; set; }
   [Required]
   public string Genre { get; set; }
   [Range(1, 100),DataType(DataType.Currency)]
   public decimal Price { get; set; }
   [Required,StringLength(5)]
   public string Rating { get; set; }
}

Di bagian berikutnya dari seri ini, kita akan meninjau aplikasi dan melakukan beberapa penyempurnaan pada metode dan Delete yang dihasilkan Details secara otomatis.