Zkoumání metod Edit a zobrazení pro úpravy (VB)
V tomto kurzu se naučíte základy vytváření webové aplikace ASP.NET MVC pomocí sady Microsoft Visual Web Developer 2010 Express Service Pack 1, což je bezplatná verze sady Microsoft Visual Studio. Než začnete, ujistěte se, že jste nainstalovali níže uvedené požadavky. Všechny z nich můžete nainstalovat kliknutím na následující odkaz: Instalační program webové platformy. Případně můžete jednotlivé požadavky nainstalovat pomocí následujících odkazů:
- Požadavky pro Visual Studio Web Developer Express SP1
- aktualizace nástrojů ASP.NET MVC 3
- SQL Server Compact 4.0 (podpora modulu runtime a nástrojů)
Pokud používáte Sadu Visual Studio 2010 místo visual web developeru 2010, nainstalujte požadované součásti kliknutím na následující odkaz: Požadavky sady Visual Studio 2010.
K tomuto tématu je k dispozici projekt Visual Web Developer s VB.NET zdrojovým kódem. Stáhněte si VB.NET verzi. Pokud dáváte přednost jazyku C#, přepněte do verze jazyka C# tohoto kurzu.
V této části prozkoumáte vygenerované metody akcí a zobrazení řadiče videa. Pak přidáte vlastní vyhledávací stránku.
Spusťte aplikaci a přejděte na Movies
kontroler připojením /Movies k adrese URL v adresním řádku prohlížeče. Podržte ukazatel myši nad odkazem pro úpravy a zobrazte adresu URL, na kterou odkazuje.
Odkaz Edit byl vygenerován metodou Html.ActionLink
v zobrazení Views\Movies\Index.vbhtml :
@Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
Objekt Html
je pomocná rutina, která je vystavena pomocí vlastnosti základní WebViewPage
třídy. Metoda ActionLink
pomocné rutiny usnadňuje dynamické generování hypertextových odkazů HTML, které odkazují na metody akcí na řadičích. Prvním argumentem ActionLink
metody je text odkazu, který se má vykreslit (například <a>Edit Me</a>
). Druhým argumentem je název metody akce, která se má vyvolat. Posledním argumentem je anonymní objekt , který generuje směrovací data (v tomto případě ID 4).
Vygenerovaný odkaz zobrazený na předchozím obrázku je http://localhost:xxxxx/Movies/Edit/4
. Výchozí trasa přebírá vzor {controller}/{action}/{id}
adresy URL . Proto ASP.NET převede http://localhost:xxxxx/Movies/Edit/4
na požadavek na Edit
metodu Movies
akce kontroleru s parametrem ID
rovnajícím se 4.
Parametry metody akce můžete předat také pomocí řetězce dotazu. Například adresa URL http://localhost:xxxxx/Movies/Edit?ID=4
předá parametr ID
4 metodě Edit
akce Movies
kontroleru.
Movies
Otevřete kontroler. Níže jsou uvedené dvě Edit
metody akcí.
'
' 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
Všimněte si, že před atributem HttpPost
předchází druhá Edit
metoda akce. Tento atribut určuje, že přetížení Edit
metody lze vyvolat pouze pro požadavky POST. Atribut můžete použít HttpGet
u první metody úprav, ale to není nutné, protože je to výchozí. (Budeme odkazovat na metody akcí, které jsou implicitně přiřazeny HttpGet
atributu jako HttpGet
metody.)
Metoda HttpGet
Edit
přebírá parametr ID videa, vyhledá film pomocí metody Entity Framework Find
a vrátí vybraný film do zobrazení Edit. Když systém generování uživatelského rozhraní vytvořil zobrazení Edit, prozkoumal Movie
třídu a vytvořil kód pro vykreslení <label>
a <input>
prvky pro každou vlastnost třídy. Následující příklad ukazuje vygenerované zobrazení pro úpravy:
@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>
Všimněte si, že šablona zobrazení obsahuje @ModelType MvcMovie.Models.Movie
příkaz v horní části souboru – určuje, že zobrazení očekává model šablony zobrazení typu Movie
.
Vygenerovaný kód používá několik pomocných metod ke zjednodušení kódu HTML. Pomocník Html.LabelFor
zobrazí název pole (Název, Datum vydání, Žánr nebo Cena). Pomocník Html.EditorFor
zobrazí element HTML <input>
. Pomocník Html.ValidationMessageFor
zobrazí všechny ověřovací zprávy přidružené k této vlastnosti.
Spusťte aplikaci a přejděte na adresu URL /Movies . Klikněte na odkaz Upravit. V prohlížeči zobrazte zdroj stránky. Kód HTML na stránce vypadá jako v následujícím příkladu. (Revize nabídky byla vyloučena z důvodu přehlednosti.)
<!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>
Prvky <input>
jsou v elementu HTML <form>
, jehož action
atribut je nastaven pro publikování na adresu URL /Movies/Edit . Data formuláře se publikují na server po kliknutí na tlačítko Upravit .
Zpracování požadavku POST
Následující výpis ukazuje HttpPost
verzi Edit
metody akce.
'
' 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
Pořadač modelu ASP.NET architektury přebírá publikované hodnoty formuláře a vytvoří Movie
objekt, který se předá jako movie
parametr. Vrácení ModelState.IsValid
kódu se změnami ověří, že data odeslaná ve formuláři lze použít k úpravě objektu Movie
. Pokud jsou data platná, uloží kód data videa do Movies
kolekce MovieDBContext
instance. Kód pak uloží nová filmová data do databáze voláním SaveChanges
metody MovieDBContext
, která zachovává změny v databázi. Po uložení dat kód přesměruje uživatele na Index
metodu MoviesController
akce třídy, která způsobí zobrazení aktualizovaného videa v seznamu filmů.
Pokud publikované hodnoty nejsou platné, zobrazí se ve formuláři znovu. Pomocné Html.ValidationMessageFor
rutiny v šabloně zobrazení Edit.vbhtml se postará o zobrazení odpovídajících chybových zpráv.
Poznámka o národních prostředích Pokud obvykle pracujete s jiným národním prostředím než v angličtině, přečtěte si téma Podpora ASP.NET ověřování MVC 3 s neanglické národní prostředí.
Zajištění robustnější metody úprav
Metoda HttpGet
Edit
vygenerovaná systémem generování uživatelského rozhraní nekontroluje platnost ID, které mu bylo předáno. Pokud uživatel odebere segment ID z adresy URL (http://localhost:xxxxx/Movies/Edit
), zobrazí se následující chyba:
Uživatel může také předat ID, které v databázi neexistuje, například http://localhost:xxxxx/Movies/Edit/1234
. Pokud chcete toto omezení vyřešit, můžete v metodě akce provést dvě změny HttpGet
Edit
. Nejprve změňte ID
parametr tak, aby měl výchozí hodnotu nula, pokud id není explicitně předáno. Můžete také zkontrolovat, zda Find
metoda skutečně našla film před vrácením objektu videa do šablony zobrazení. Aktualizovaná Edit
metoda je zobrazena níže.
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
Pokud se nenajde žádný film, volá se HttpNotFound
metoda.
HttpGet
Všechny metody se řídí podobným vzorem. Načte objekt videa (nebo seznam objektů v případě Index
) a předají model do zobrazení. Metoda Create
předá prázdný objekt filmu do zobrazení Create. Všechny metody, které vytvářejí, upravují, odstraňují nebo jinak upravují data, to dělají v HttpPost
přetížení metody. Úprava dat v metodě HTTP GET představuje bezpečnostní riziko. Úprava dat v metodě GET také porušuje osvědčené postupy HTTP a vzor architektury REST, který určuje, že požadavky GET by neměly měnit stav vaší aplikace. Jinými slovy, provedení operace GET by mělo být bezpečná operace, která nemá žádné vedlejší účinky.
Přidání metody hledání a zobrazení hledání
V této části přidáte metodu SearchIndex
akcí, která umožňuje hledat filmy podle žánru nebo názvu. Bude k dispozici pomocí adresy URL /Movies/SearchIndex . Požadavek zobrazí formulář HTML, který obsahuje vstupní prvky, které uživatel může vyplnit, aby mohl vyhledat film. Když uživatel odešle formulář, metoda akce získá hodnoty hledání publikované uživatelem a použije hodnoty k vyhledávání v databázi.
Zobrazení formuláře SearchIndex
Začněte přidáním SearchIndex
metody akce do existující MoviesController
třídy. Metoda vrátí zobrazení, které obsahuje formulář HTML. Tady je kód:
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
První řádek SearchIndex
metody vytvoří následující dotaz LINQ pro výběr filmů:
Dim movies = From m In db.Movies Select m
Dotaz je v tomto okamžiku definovaný, ale zatím nebyl spuštěn proti úložišti dat.
searchString
Pokud parametr obsahuje řetězec, dotaz filmy se upraví tak, aby filtrovaly hodnotu hledaného řetězce pomocí následujícího kódu:
Pokud není String.IsNullOrEmpty(searchString) Pak
filmy = filmy. Where(Funkce) s.Title.Contains(searchString))
Ukončit
Dotazy LINQ se nespouštějí, pokud jsou definovány nebo když jsou upraveny voláním metody, jako Where
OrderBy
je nebo . Místo toho je odloženo provádění dotazu, což znamená, že vyhodnocení výrazu je zpožděné, dokud se jeho dosažená hodnota ve skutečnosti iterated over nebo ToList
metoda volá. V ukázce SearchIndex
se dotaz spustí v zobrazení SearchIndex. Další informace o odložené spuštění dotazu naleznete v tématu Provádění dotazů.
Teď můžete implementovat SearchIndex
zobrazení, které zobrazí formulář uživateli. Klikněte pravým tlačítkem myši do SearchIndex
metody a potom klikněte na přidat zobrazení. V dialogovém okně Přidat zobrazení určete, že chcete předat Movie
objekt šabloně zobrazení jako její třídu modelu. V seznamu šablon uživatelského rozhraní zvolte Seznam a potom klikněte na Přidat.
Když kliknete na tlačítko Přidat , vytvoří se šablona zobrazení Views\Movies\SearchIndex.vbhtml . Vzhledem k tomu, že jste v seznamu šablon uživatelského rozhraní vybrali seznam, visual web developer automaticky vygeneroval (vygenerovaný) nějaký výchozí obsah v zobrazení. Generování uživatelského rozhraní vytvořilo formulář HTML. Prozkoumal třídu Movie
a vytvořil kód pro vykreslení <label>
prvků pro každou vlastnost třídy. Následující výpis ukazuje vygenerované zobrazení Pro vytvoření:
@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>
Spusťte aplikaci a přejděte na /Movies/SearchIndex. Připojte řetězec dotazu, například ?searchString=ghost
k adrese URL. Zobrazí se filtrované filmy.
Pokud změníte podpis SearchIndex
metody tak, aby měl název id
parametru , id
bude parametr odpovídat {id}
zástupného symbolu pro výchozí trasy nastavené v souboru Global.asax .
{controller}/{action}/{id}
Upravená SearchIndex
metoda by vypadala takto:
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
Název hledání teď můžete předat jako směrovací data (segment adresy URL) místo jako hodnotu řetězce dotazu.
Nemůžete ale očekávat, že uživatelé upraví adresu URL pokaždé, když chtějí hledat film. Teď tedy přidáte uživatelské rozhraní, které jim pomůže filtrovat filmy. Pokud jste změnili podpis SearchIndex
metody tak, aby testoval, jak předat parametr ID vázané na trasu, změňte ho zpět tak, aby vaše SearchIndex
metoda přebírá řetězcový parametr s názvem searchString
:
Otevřete soubor Views\Movies\SearchIndex.vbhtml a hned za @Html.ActionLink("Create New", "Create")
, přidejte následující:
@Code
ViewData("Title") = "SearchIndex"
Using (Html.BeginForm())
@<p> Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" /></p>
End Using
End Code
Pomocná rutina Html.BeginForm
vytvoří levou <form>
značku. Pomocná Html.BeginForm
rutina způsobí, že se formulář publikuje, když uživatel odešle formulář kliknutím na tlačítko Filtr .
Spusťte aplikaci a zkuste vyhledat film.
Metoda není HttpPost
přetížená SearchIndex
. Nepotřebujete ji, protože metoda nemění stav aplikace, pouze filtrování dat. Pokud jste přidali následující HttpPost
SearchIndex
metodu, vyvolání akce by odpovídalo SearchIndex
HttpPost
metodě a HttpPost
SearchIndex
metoda by se spustila, jak je znázorněno na obrázku níže.
<HttpPost()>
Public Function SearchIndex(ByVal fc As FormCollection, ByVal searchString As String) As String
Return "<h3> From [HttpPost]SearchIndex: " & searchString & "</h3>"
End Function
Přidání hledání podle žánru
Pokud jste přidali HttpPost
verzi SearchIndex
metody, odstraňte ji teď.
Dále přidáte funkci, která uživatelům umožní vyhledávat filmy podle žánru. Nahraďte metodu SearchIndex
následujícím kódem:
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
Tato verze SearchIndex
metody přebírá další parametr, konkrétně movieGenre
. Prvních několik řádků kódu vytvoří List
objekt, který bude obsahovat filmové žánry z databáze.
Následující kód je dotaz LINQ, který načte všechny žánry z databáze.
Dim GenreQry = From d In db.Movies
Order By d.Genre
Select d.Genre
Kód používá AddRange
metodu obecné List
kolekce k přidání všech různých žánrů do seznamu. (Bez modifikátoru Distinct
by se přidaly duplicitní žánry – například comedy by byly přidány dvakrát v našem vzorku). Kód pak uloží seznam žánrů v objektu ViewBag
.
Následující kód ukazuje, jak zkontrolovat movieGenre
parametr. Pokud kód nevyprázdní, omezí dotaz na filmy, aby omezil vybrané filmy na zadaný žánr.
If String.IsNullOrEmpty(movieGenre) Then
Return View(movies)
Else
Return View(movies.Where(Function(x) x.Genre = movieGenre))
End If
Přidání značek do zobrazení SearchIndex pro podporu vyhledávání podle žánru
Přidejte pomocnou Html.DropDownList
rutinu do souboru Views\Movies\SearchIndex.vbhtml těsně před pomocnou rutinou TextBox
. Dokončená revize je znázorněna níže:
<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>
Spusťte aplikaci a přejděte na /Movies/SearchIndex. Zkuste hledat podle žánru, podle názvu filmu a podle obou kritérií.
V této části jste prozkoumali metody akcí CRUD a zobrazení vygenerovaná architekturou. Vytvořili jste metodu akce hledání a zobrazení, které uživatelům umožní hledat podle názvu filmu a žánru. V další části se podíváte, jak do modelu přidat vlastnost Movie
a jak přidat inicializátor, který automaticky vytvoří testovací databázi.