Sdílet prostřednictvím


Zkoumání metod Edit a zobrazení pro úpravy (VB)

Rick Anderson

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ů:

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.

Snímek obrazovky ukazuje aplikaci MVC Přesunout s odkazem Upravit pro některý z vybraných filmů.

Odkaz Edit byl vygenerován metodou Html.ActionLink v zobrazení Views\Movies\Index.vbhtml :

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

Snímek obrazovky ukazuje Html.ActionLink v editoru kódu.

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.

EditQueryString

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.

abcNotValid

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:

Null_ID

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.

SearchIndx_SM

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 OrderByje 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.

AddSearchView

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.

SearchQryStr

Pokud změníte podpis SearchIndex metody tak, aby měl název idparametru , 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.

SearchRouteData

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.

SearchIndxIE9_title

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

SearchPostGhost

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.