Bagikan melalui


Memeriksa Metode Edit dan Edit Tampilan (VB)

oleh Rick Anderson

Tutorial ini akan mengajari Anda dasar-dasar membangun aplikasi Web MVC ASP.NET menggunakan Microsoft Visual Web Developer 2010 Express Service Pack 1, yang merupakan versi gratis dari Microsoft Visual Studio. Sebelum memulai, pastikan Anda telah menginstal prasyarat yang tercantum di bawah ini. Anda dapat menginstal semuanya dengan mengklik tautan berikut: Penginstal Platform Web. Atau, Anda dapat menginstal prasyarat secara individual menggunakan tautan berikut:

Jika Anda menggunakan Visual Studio 2010 alih-alih Visual Web Developer 2010, instal prasyarat dengan mengklik tautan berikut: Prasyarat Visual Studio 2010.

Proyek Visual Web Developer dengan kode sumber VB.NET tersedia untuk menyertai topik ini. Unduh versi VB.NET. Jika Anda lebih suka C#, beralihlah ke versi C# dari tutorial ini.

Di bagian ini, Anda akan memeriksa metode tindakan dan tampilan yang dihasilkan untuk pengontrol film. Kemudian Anda akan menambahkan halaman pencarian kustom.

Jalankan aplikasi dan telusuri pengontrol Movies dengan menambahkan /Movies ke URL di bilah alamat browser Anda. Tahan penunjuk mouse di atas tautan Edit untuk melihat URL yang ditautkannya.

Cuplikan layar memperlihatkan MVC Move App dengan tautan Edit untuk salah satu film yang dipilih.

Tautan Edit dihasilkan oleh Html.ActionLink metode dalam tampilan Views\Movies\Index.vbhtml :

@Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |

Cuplikan layar memperlihatkan Html.ActionLink di editor kode.

Objek Html adalah pembantu yang diekspos menggunakan properti di WebViewPage kelas dasar. Metode ActionLink pembantu memudahkan untuk secara dinamis menghasilkan hyperlink HTML yang ditautkan ke metode tindakan pada pengontrol. Argumen pertama untuk ActionLink metode ini adalah teks tautan untuk dirender (misalnya, <a>Edit Me</a>). Argumen kedua adalah nama metode tindakan yang akan dipanggil. Argumen akhir adalah objek anonim yang menghasilkan data rute (dalam hal ini, ID 4).

Tautan yang dihasilkan yang ditampilkan pada gambar sebelumnya adalah http://localhost:xxxxx/Movies/Edit/4. Rute default mengambil pola {controller}/{action}/{id}URL . Oleh karena itu, ASP.NET diterjemahkan http://localhost:xxxxx/Movies/Edit/4 ke dalam permintaan ke Edit metode Movies tindakan pengontrol dengan parameter ID sama dengan 4.

Anda juga dapat meneruskan parameter metode tindakan menggunakan string kueri. Misalnya, URL http://localhost:xxxxx/Movies/Edit?ID=4 juga meneruskan parameter ID 4 ke Edit metode Movies tindakan pengontrol.

EditQueryString

Movies Buka pengontrol. Dua Edit metode tindakan ditunjukkan di bawah ini.

'
' GET: /Movies/Edit/5

Function Edit(id As Integer) As ViewResult
    Dim movie As Movie = db.Movies.Find(id)
    Return View(movie)
End Function

'
' POST: /Movies/Edit/5

<HttpPost()>
Function Edit(movie As Movie) As ActionResult
    If ModelState.IsValid Then
        db.Entry(movie).State = EntityState.Modified
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    Return View(movie)
End Function

Perhatikan metode tindakan kedua Edit didahului oleh HttpPost atribut . Atribut ini menentukan bahwa kelebihan beban Edit metode hanya dapat dipanggil untuk permintaan POST. Anda dapat menerapkan atribut ke HttpGet metode edit pertama, tetapi itu tidak perlu karena itu adalah default. (Kami akan merujuk ke metode tindakan yang secara implisit ditetapkan HttpGet atribut sebagai HttpGet metode.)

Metode mengambil HttpGet Edit parameter ID film, mencari film menggunakan metode Kerangka Kerja Find Entitas, dan mengembalikan film yang dipilih ke tampilan Edit. Ketika sistem perancah membuat tampilan Edit, sistem memeriksa Movie kelas dan membuat kode untuk merender <label> dan <input> elemen untuk setiap properti kelas. Contoh berikut menunjukkan tampilan Edit yang dihasilkan:

@ModelType MvcMovie.Movie

@Code
    ViewData("Title") = "Edit"
End Code

<h2>Edit</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>

        @Html.HiddenFor(Function(model) model.ID)

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.Title)
            @Html.ValidationMessageFor(Function(model) model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.ReleaseDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.ReleaseDate)
            @Html.ValidationMessageFor(Function(model) model.ReleaseDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.Genre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.Genre)
            @Html.ValidationMessageFor(Function(model) model.Genre)
        </div>

        <div class="editor-label">
            @Html.LabelFor(Function(model) model.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(Function(model) model.Price)
            @Html.ValidationMessageFor(Function(model) model.Price)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
End Using

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Perhatikan bagaimana templat tampilan memiliki @ModelType MvcMovie.Models.Movie pernyataan di bagian atas file — ini menentukan bahwa tampilan mengharapkan model untuk templat tampilan berjenis Movie.

Kode perancah menggunakan beberapa metode pembantu untuk menyederhanakan markup HTML. Pembantu Html.LabelFor menampilkan nama bidang ("Judul", "ReleaseDate", "Genre", atau "Harga"). Pembantu Html.EditorFor menampilkan elemen HTML <input> . Pembantu menampilkan pesan validasi apa pun yang terkait dengan properti tersebut Html.ValidationMessageFor .

Jalankan aplikasi dan navigasikan ke URL /Movies . Klik tautan Edit. Di browser, lihat sumber untuk halaman tersebut. HTML di halaman terlihat seperti contoh berikut. (Markup menu dikecualikan untuk kejelasan.)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Edit</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
    <script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>MVC Movie App</h1>
            </div>
           ...
        </header>
        <section id="main">

<h2>Edit</h2>

<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>

<form action="/Movies/Edit/4" method="post">    <fieldset>
        <legend>Movie</legend>

        <input data-val="true" data-val-number="The field ID must be a number." 
    data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />

        <div class="editor-label">
            <label for="Title">Title</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" />
            <span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="ReleaseDate">ReleaseDate</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" data-val="true" data-val-required="The ReleaseDate field is required." 
    id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" />
            <span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="Genre">Genre</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" />
            <span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="Price">Price</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." 
    data-val-required="The Price field is required." id="Price" name="Price" type="text" value="9.99" />
            <span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
</form>
<div>
    <a href="/Movies">Back to List</a>
</div>

        </section>
        <footer>
        </footer>
    </div>
</body>
</html>

Elemen <input> berada dalam elemen HTML <form> yang atributnya action diatur untuk memposting ke URL /Movies/Edit . Data formulir akan diposting ke server saat tombol Edit diklik.

Memproses Permintaan POST

Daftar berikut menunjukkan HttpPost versi Edit metode tindakan.

'
' POST: /Movies/Edit/5

<HttpPost()>
Function Edit(movie As Movie) As ActionResult
    If ModelState.IsValid Then
        db.Entry(movie).State = EntityState.Modified
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If

    Return View(movie)
End Function

Pengikat model kerangka kerja ASP.NET mengambil nilai formulir yang diposting dan membuat Movie objek yang diteruskan sebagai movie parameter . Pemeriksaan ModelState.IsValid kode memverifikasi bahwa data yang dikirimkan dalam formulir dapat digunakan untuk mengubah Movie objek. Jika data valid, kode akan menyimpan data film ke Movies pengumpulan MovieDBContext instans. Kode kemudian menyimpan data film baru ke database dengan memanggil SaveChanges metode MovieDBContext, yang terus berubah ke database. Setelah menyimpan data, kode mengalihkan pengguna ke Index metode MoviesController tindakan kelas, yang menyebabkan film yang diperbarui ditampilkan dalam daftar film.

Jika nilai yang diposting tidak valid, nilai tersebut akan diputar ulang dalam formulir. Pembantu Html.ValidationMessageFor dalam templat tampilan Edit.vbhtml mengurus menampilkan pesan kesalahan yang sesuai.

abcNotValid

Catatan tentang lokal Jika Anda biasanya bekerja dengan lokal selain bahasa Inggris, lihat Mendukung Validasi MVC 3 ASP.NET dengan Lokal Non-Bahasa Inggris.

Membuat Metode Edit Lebih Kuat

Metode HttpGet Edit yang dihasilkan oleh sistem perancah tidak memeriksa apakah ID yang diteruskan ke itu valid. Jika pengguna menghapus segmen ID dari URL (http://localhost:xxxxx/Movies/Edit), kesalahan berikut ditampilkan:

Null_ID

Pengguna juga dapat meneruskan ID yang tidak ada di database, seperti http://localhost:xxxxx/Movies/Edit/1234. Anda dapat membuat dua perubahan pada HttpGet Edit metode tindakan untuk mengatasi batasan ini. Pertama, ubah ID parameter agar memiliki nilai default nol saat ID tidak diteruskan secara eksplisit. Anda juga dapat memeriksa apakah metode benar-benar Find menemukan film sebelum mengembalikan objek film ke templat tampilan. Metode yang diperbarui Edit ditunjukkan di bawah ini.

Public Function Edit(Optional ByVal id As Integer = 0) As ActionResult
    Dim movie As Movie = db.Movies.Find(id)
    If movie Is Nothing Then
        Return HttpNotFound()
    End If
    Return View(movie)
End Function

Jika tidak ada film yang ditemukan, HttpNotFound metode dipanggil.

HttpGet Semua metode mengikuti pola yang sama. Mereka mendapatkan objek film (atau daftar objek, dalam kasus Index), dan meneruskan model ke tampilan. Metode Create meneruskan objek film kosong ke tampilan Buat. Semua metode yang membuat, mengedit, menghapus, atau memodifikasi data melakukannya dalam HttpPost kelebihan beban metode. Memodifikasi data dalam metode HTTP GET adalah risiko keamanan. Memodifikasi data dalam metode GET juga melanggar praktik terbaik HTTP dan pola REST arsitektur, yang menentukan bahwa permintaan GET tidak boleh mengubah status aplikasi Anda. Dengan kata lain, melakukan operasi GET harus menjadi operasi aman yang tidak memiliki efek samping.

Menambahkan Metode Pencarian dan Tampilan Pencarian

Di bagian ini Anda akan menambahkan SearchIndex metode tindakan yang memungkinkan Anda mencari film berdasarkan genre atau nama. Ini akan tersedia menggunakan URL /Movies/SearchIndex . Permintaan akan menampilkan formulir HTML yang berisi elemen input yang dapat diisi pengguna untuk mencari film. Saat pengguna mengirimkan formulir, metode tindakan akan mendapatkan nilai pencarian yang diposting oleh pengguna dan menggunakan nilai untuk mencari database.

SearchIndx_SM

Menampilkan Formulir SearchIndex

Mulailah dengan menambahkan SearchIndex metode tindakan ke kelas yang MoviesController ada. Metode ini akan mengembalikan tampilan yang berisi formulir HTML. Berikut kodenya:

Public Function SearchIndex(ByVal searchString As String) As ActionResult
    Dim movies = From m In db.Movies
                 Select m 

    If Not String.IsNullOrEmpty(searchString) Then 
        movies = movies.Where(Function(s) s.Title.Contains(searchString)) 
    End If
    Return View(movies) 
End Function

Baris SearchIndex pertama metode membuat kueri LINQ berikut untuk memilih film:

Dim movies = From m In db.Movies    Select m

Kueri didefinisikan pada saat ini, tetapi belum dijalankan terhadap penyimpanan data.

searchString Jika parameter berisi string, kueri film dimodifikasi untuk memfilter nilai string pencarian, menggunakan kode berikut:

Jika Bukan String.IsNullOrEmpty(searchString) Maka
film = film. Where(Functions s.Title.Contains(searchString))
Akhiri Jika

Kueri LINQ tidak dijalankan ketika didefinisikan atau ketika dimodifikasi dengan memanggil metode seperti Where atau OrderBy. Sebaliknya, eksekusi kueri ditangguhkan, yang berarti bahwa evaluasi ekspresi tertunda sampai nilai yang direalisasikan benar-benar diulang atau ToList metode dipanggil. SearchIndex Dalam sampel, kueri dijalankan dalam tampilan SearchIndex. Untuk informasi selengkapnya tentang eksekusi kueri yang ditangguhkan, lihat Eksekusi Kueri.

Sekarang Anda dapat menerapkan SearchIndex tampilan yang akan menampilkan formulir kepada pengguna. Klik kanan di SearchIndex dalam metode lalu klik Tambahkan Tampilan. Dalam kotak dialog Tambahkan Tampilan , tentukan bahwa Anda akan meneruskan Movie objek ke templat tampilan sebagai kelas modelnya. Di daftar Templat perancah, pilih Daftar, lalu klik Tambahkan.

TambahkanSearchView

Saat Anda mengklik tombol Tambahkan , templat tampilan Views\Movies\SearchIndex.vbhtml dibuat. Karena Anda memilih Daftar dalam daftar templat Perancah, Pengembang Web Visual secara otomatis membuat (perancah) beberapa konten default dalam tampilan. Perancah membuat formulir HTML. Ini memeriksa Movie kelas dan membuat kode untuk merender <label> elemen untuk setiap properti kelas. Daftar di bawah ini memperlihatkan tampilan Buat yang dihasilkan:

@ModelType IEnumerable(Of MvcMovie.Movie)

@Code
    ViewData("Title") = "SearchIndex"
End Code

<h2>SearchIndex</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Title
        </th>
        <th>
            ReleaseDate
        </th>
        <th>
            Genre
        </th>
        <th>
            Price
        </th>
        <th></th>
    </tr>

@For Each item In Model
    Dim currentItem = item
    @<tr>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Title)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.ReleaseDate)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Genre)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Details", "Details", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Delete", "Delete", New With {.id = currentItem.ID})
        </td>
    </tr>
Next

</table>

Jalankan aplikasi dan navigasikan ke /Movies/SearchIndex. Tambahkan string kueri seperti ?searchString=ghost ke URL. Film yang difilter ditampilkan.

SearchQryStr

Jika Anda mengubah tanda tangan SearchIndex metode agar memiliki parameter bernama id, id parameter akan cocok dengan {id} tempat penampung untuk rute default yang diatur dalam file Global.asax .

{controller}/{action}/{id}

Metode yang dimodifikasi SearchIndex akan terlihat sebagai berikut:

Public Function SearchIndex(ByVal id As String) As ActionResult
Dim searchString As String = id
Dim movies = From m In db.Movies
             Select m

If Not String.IsNullOrEmpty(searchString) Then
    movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If

Return View(movies)
End Function

Sekarang Anda dapat meneruskan judul pencarian sebagai data rute (segmen URL) alih-alih sebagai nilai string kueri.

SearchRouteData

Namun, Anda tidak dapat mengharapkan pengguna untuk memodifikasi URL setiap kali mereka ingin mencari film. Jadi sekarang Anda akan menambahkan UI untuk membantu mereka memfilter film. Jika Anda mengubah tanda tangan SearchIndex metode untuk menguji cara melewati parameter ID yang terikat rute, ubah kembali sehingga metode Anda SearchIndex mengambil parameter string bernama searchString:

Buka file Views\Movies\SearchIndex.vbhtml, dan tepat setelah @Html.ActionLink("Create New", "Create"), tambahkan yang berikut ini:

@Code
    ViewData("Title") = "SearchIndex"
    Using (Html.BeginForm())
         @<p> Title: @Html.TextBox("SearchString") 
         <input type="submit" value="Filter" /></p>
        End Using
End Code

Pembantu Html.BeginForm membuat tag pembuka <form> . Pembantu Html.BeginForm menyebabkan formulir diposting ke dirinya sendiri ketika pengguna mengirimkan formulir dengan mengklik tombol Filter .

Jalankan aplikasi dan coba cari film.

SearchIndxIE9_title

Tidak ada HttpPost kelebihan metode SearchIndex . Anda tidak memerlukannya, karena metode tidak mengubah status aplikasi, hanya memfilter data. Jika Anda menambahkan metode berikut HttpPost SearchIndex , pemanggil tindakan akan cocok dengan HttpPost SearchIndex metode , dan HttpPost SearchIndex metode akan berjalan seperti yang ditunjukkan pada gambar di bawah ini.

<HttpPost()>
 Public Function SearchIndex(ByVal fc As FormCollection, ByVal searchString As String) As String
     Return "<h3> From [HttpPost]SearchIndex: " & searchString & "</h3>"
 End Function

SearchPostGhost

Menambahkan Pencarian menurut Genre

Jika Anda menambahkan HttpPost versi SearchIndex metode , hapus sekarang.

Selanjutnya, Anda akan menambahkan fitur untuk memungkinkan pengguna mencari film berdasarkan genre. Ganti metode SearchIndex dengan kode berikut:

Public Function SearchIndex(ByVal movieGenre As String, ByVal searchString As String) As ActionResult
    Dim GenreLst = New List(Of String)()

    Dim GenreQry = From d In db.Movies
                   Order By d.Genre
                   Select d.Genre
    GenreLst.AddRange(GenreQry.Distinct())
    ViewBag.movieGenre = New SelectList(GenreLst)

    Dim movies = From m In db.Movies
                 Select m

    If Not String.IsNullOrEmpty(searchString) Then
        movies = movies.Where(Function(s) s.Title.Contains(searchString))
    End If

    If String.IsNullOrEmpty(movieGenre) Then
        Return View(movies)
    Else
        Return View(movies.Where(Function(x) x.Genre = movieGenre))
    End If

End Function

Versi SearchIndex metode ini mengambil parameter tambahan, yaitu movieGenre. Beberapa baris kode pertama membuat List objek untuk menahan genre film dari database.

Kode berikut adalah kueri LINQ yang mengambil semua genre dari database.

Dim GenreQry = From d In db.Movies
                   Order By d.Genre
                   Select d.Genre

Kode menggunakan AddRange metode koleksi generik List untuk menambahkan semua genre yang berbeda ke daftar. (Tanpa pengubah Distinct , genre duplikat akan ditambahkan — misalnya, komedi akan ditambahkan dua kali dalam sampel kami). Kode kemudian menyimpan daftar genre dalam ViewBag objek.

Kode berikut menunjukkan cara memeriksa movieGenre parameter. Jika tidak kosong, kode akan membatasi kueri film lebih lanjut untuk membatasi film yang dipilih ke genre yang ditentukan.

If String.IsNullOrEmpty(movieGenre) Then
        Return View(movies)
    Else
        Return View(movies.Where(Function(x) x.Genre = movieGenre))
    End If

Menambahkan Markup ke Tampilan SearchIndex untuk Mendukung Pencarian berdasarkan Genre

Html.DropDownList Tambahkan pembantu ke file Views\Movies\SearchIndex.vbhtml, tepat sebelum pembantuTextBox. Markup yang telah selesai ditunjukkan di bawah ini:

<p>
    @Html.ActionLink("Create New", "Create")
    @Code
    ViewData("Title") = "SearchIndex"
    Using (Html.BeginForm())
         @<p> Genre: @Html.DropDownList("movieGenre", "All")
         Title: @Html.TextBox("SearchString") 
         <input type="submit" value="Filter" /></p>
        End Using
End Code
</p>

Jalankan aplikasi dan telusuri ke /Movies/SearchIndex. Coba cari berdasarkan genre, berdasarkan nama film, dan menurut kedua kriteria.

Di bagian ini Anda memeriksa metode tindakan CRUD dan tampilan yang dihasilkan oleh kerangka kerja. Anda membuat metode tindakan pencarian dan tampilan yang memungkinkan pengguna mencari berdasarkan judul dan genre film. Di bagian berikutnya, Anda akan melihat cara menambahkan properti ke Movie model dan cara menambahkan penginisialisasi yang akan secara otomatis membuat database pengujian.