Zkoumání metod a zobrazení akcí pro řadič videa
Poznámka:
Aktualizovaná verze tohoto kurzu je k dispozici zde , která používá ASP.NET MVC 5 a Visual Studio 2013. Je bezpečnější, mnohem jednodušší sledovat a demonstrovat další funkce.
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.cshtml :
@Html.ActionLink("Edit", "Edit", new { id=item.ID })
Objekt Html
je pomocná rutina, která je vystavena pomocí vlastnosti v Základní třídě System.Web.Mvc.WebViewPage . 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 (vytvořená v App_Start\RouteConfig.cs) 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. Zkontrolujte následující kód ze souboru App_Start\RouteConfig.cs .
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
}
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
public ActionResult Edit(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
//
// POST: /Movies/Edit/5
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
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. Parametr ID určuje výchozí hodnotu nula, pokud Edit
metoda je volána bez parametru. Pokud nelze najít video, vrátí se HttpNotFound . 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:
@model MvcMovie.Models.Movie
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
@Html.HiddenFor(model => model.ID)
<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>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Všimněte si, že šablona zobrazení obsahuje @model 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
vykreslí 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 pro element formuláře je zobrazen níže.
<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-date="The field ReleaseDate must be a date." 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="2.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>
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.
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
Pořadač modelu ASP.NET MVC přebírá publikované hodnoty formuláře a vytvoří Movie
objekt, který se předá jako movie
parametr. Metoda ModelState.IsValid
ověřuje, že data odeslaná ve formuláři lze použít k úpravě (úpravě nebo aktualizaci) objektu Movie
. Pokud jsou data platná, uloží se data videa do Movies
kolekce db(MovieDBContext
instance. Nová data videa jsou uložena do databáze voláním SaveChanges
metody MovieDBContext
. Po uložení dat kód přesměruje uživatele na Index
metodu MoviesController
akce třídy, která zobrazí kolekci filmů včetně právě provedených změn.
Pokud publikované hodnoty nejsou platné, zobrazí se ve formuláři znovu. Pomocné Html.ValidationMessageFor
rutiny v šabloně zobrazení Edit.cshtml se postará o zobrazení odpovídajících chybových zpráv.
Poznámka:
pokud chcete podporovat ověřování jQuery pro neanglické národní prostředí používající čárku (",") pro desetinnou čárku, musíte zahrnout globalize.js a konkrétní jazykové verze/globalize.cultures.js file(from https://github.com/jquery/globalize ) a JavaScript, aby bylo možné použít Globalize.parseFloat
. Následující kód ukazuje úpravy souboru Views\Movies\Edit.cshtml pro práci s jazykovou verzí "fr-FR":
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/globalize.js"></script>
<script src="~/Scripts/globalize.culture.fr-FR.js"></script>
<script>
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$(document).ready(function () {
Globalize.culture('fr-FR');
});
</script>
<script>
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
//Use the Globalization plugin to parse the value
var val = $.global.parseFloat(value);
return this.optional(element) || (
val >= param[0] && val <= param[1]);
}
});
</script>
}
Desetinné pole může vyžadovat čárku, nikoli desetinnou čárku. Jako dočasnou opravu můžete přidat element globalizace do kořenového souboru web.config projektů. Následující kód ukazuje element globalizace s jazykovou verzí nastavenou na USA angličtina.
<system.web>
<globalization culture ="en-US" />
<!--elements removed for clarity-->
</system.web>
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ěla být bezpečná operace, která nemá žádné vedlejší účinky a neupravuje trvalá data.
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 zadat, aby mohl hledat 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 ActionResult SearchIndex(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
První řádek SearchIndex
metody vytvoří následující dotaz LINQ pro výběr filmů:
var 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:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
Výše s => s.Title
uvedený kód je výraz lambda. Lambda se používají v dotazech LINQ založených na metodách jako argumenty pro standardní metody operátoru dotazu, jako je například metoda Where použitá ve výše uvedeném kódu. 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.cshtml . Vzhledem k tomu, že jste v seznamu šablon uživatelského rozhraní vybrali seznam, sada Visual Studio automaticky vygenerovala (vygenerovala) v zobrazení některé výchozí revize. 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í:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "SearchIndex";
}
<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>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</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}
Původní SearchIndex
metoda vypadá takto:
public ActionResult SearchIndex(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
Upravená SearchIndex
metoda by vypadala takto:
public ActionResult SearchIndex(string id)
{
string searchString = id;
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
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
:
public ActionResult SearchIndex(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
Otevřete soubor Views\Movies\SearchIndex.cshtml a hned za @Html.ActionLink("Create New", "Create")
, přidejte následující:
@using (Html.BeginForm()){
<p> Title: @Html.TextBox("SearchString")<br />
<input type="submit" value="Filter" /></p>
}
Následující příklad ukazuje část souboru Views\Movies\SearchIndex.cshtml s přidanou značkou filtrování.
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "SearchIndex";
}
<h2>SearchIndex</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm()){
<p> Title: @Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
</p>
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.
Můžete přidat následující HttpPost SearchIndex
metodu. V takovém případě by vyvolání akce odpovídalo HttpPost SearchIndex
metodě a HttpPost SearchIndex
metoda by se spustila, jak je znázorněno na následujícím obrázku.
[HttpPost]
public string SearchIndex(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]SearchIndex: " + searchString + "</h3>";
}
I když ale přidáte tuto HttpPost
verzi SearchIndex
metody, existuje omezení způsobu implementace. Představte si, že chcete vytvořit záložku určitého hledání nebo chcete poslat odkaz přátelům, na které můžou kliknout, aby se zobrazil stejný filtrovaný seznam filmů. Všimněte si, že adresa URL požadavku HTTP POST je stejná jako adresa URL požadavku GET (localhost:xxxxx/Movies/SearchIndex) – v samotné adrese URL nejsou žádné informace o hledání. Informace o vyhledávacím řetězci se teď odesílají na server jako hodnota pole formuláře. To znamená, že v adrese URL nemůžete zachytávat informace o hledání, které se mají posílat do záložek nebo posílat přátelům.
Řešením je použít přetížení BeginForm
, které určuje, že požadavek POST by měl přidat vyhledávací informace do adresy URL a že by měla být směrována do verze SearchIndex
HttpGet metody. Nahraďte existující metodu bez BeginForm
parametrů následujícím kódem:
@using (Html.BeginForm("SearchIndex","Movies",FormMethod.Get))
Když teď odešlete hledání, adresa URL obsahuje řetězec vyhledávacího dotazu. Hledání také přejde na metodu HttpGet SearchIndex
akce, i když máte metodu HttpPost SearchIndex
.
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 ActionResult SearchIndex(string movieGenre, string searchString)
{
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (string.IsNullOrEmpty(movieGenre))
return View(movies);
else
{
return View(movies.Where(x => x.Genre == movieGenre));
}
}
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.
var GenreQry = from d in db.Movies
orderby 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 není prázdný, kód dále omezuje dotaz na filmy, aby omezil vybrané filmy na zadaný žánr.
if (string.IsNullOrEmpty(movieGenre))
return View(movies);
else
{
return View(movies.Where(x => x.Genre == movieGenre));
}
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.cshtml těsně před pomocnou rutinou TextBox
. Dokončená revize je znázorněna níže:
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm("SearchIndex","Movies",FormMethod.Get)){
<p>Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" /></p>
}
</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.