Изучение методов Edit и представления Edit (VB)Examining the Edit Methods and Edit View (VB)

по Рик Андерсон (by Rick Anderson

В этом учебнике вы узнаете об основах создания веб-приложения ASP.NET MVC с помощью Microsoft Visual Web Developer 2010 Express с пакетом обновления 1 (SP1), который является бесплатной версией Microsoft Visual Studio.This tutorial will teach you the basics of building an ASP.NET MVC Web application using Microsoft Visual Web Developer 2010 Express Service Pack 1, which is a free version of Microsoft Visual Studio. Прежде чем начать, убедитесь, что установлены предварительные требования, перечисленные ниже.Before you start, make sure you've installed the prerequisites listed below. Чтобы установить все эти компоненты, щелкните следующую ссылку: установщик веб-платформы.You can install all of them by clicking the following link: Web Platform Installer. Кроме того, вы можете отдельно установить необходимые компоненты, используя следующие ссылки:Alternatively, you can individually install the prerequisites using the following links:

Если вы используете Visual Studio 2010 вместо Visual Web Developer 2010, установите необходимые компоненты, щелкнув следующую ссылку: Предварительные требования для Visual studio 2010.If you're using Visual Studio 2010 instead of Visual Web Developer 2010, install the prerequisites by clicking the following link: Visual Studio 2010 prerequisites.

Для этого раздела доступен проект Visual Web Developer с исходным кодом VB.NET.A Visual Web Developer project with VB.NET source code is available to accompany this topic. Скачайте версию VB.NET.Download the VB.NET version. Если вы предпочитаете C#, перейдите к версии этого руководства для c#.If you prefer C#, switch to the C# version of this tutorial.

В этом разделе вы изучите созданные методы действий и представления для контроллера фильмов.In this section, you'll examine the generated action methods and views for the movie controller. Затем вы добавите пользовательскую страницу поиска.Then you'll add a custom search page.

Запустите приложение и перейдите к Movies контроллеру, добавив /Movies в URL-адрес в адресной строке браузера.Run the application and browse to the Movies controller by appending /Movies to the URL in the address bar of your browser. Наведите указатель мыши на ссылку Edit (изменить ), чтобы просмотреть URL-адрес, на который он ссылается.Hold the mouse pointer over an Edit link to see the URL that it links to.

EditLink_sm

Ссылка для редактирования была создана Html.ActionLink методом в представлении виевс\мовиес\индекс.вбхтмл :The Edit link was generated by the Html.ActionLink method in the Views\Movies\Index.vbhtml view:

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

EditLink_smEditLink_sm

HtmlОбъект является вспомогательным объектом, который предоставляется с помощью свойства WebViewPage базового класса.The Html object is a helper that's exposed using a property on the WebViewPage base class. ActionLinkМетод вспомогательного метода упрощает динамическое создание ГИПЕРССЫЛОК HTML, которые связываются с методами действий на контроллерах.The ActionLink method of the helper makes it easy to dynamically generate HTML hyperlinks that link to action methods on controllers. Первым аргументом ActionLink метода является текст ссылки для отрисовки (например, <a>Edit Me</a> ).The first argument to the ActionLink method is the link text to render (for example, <a>Edit Me</a>). Вторым аргументом является имя вызываемого метода действия.The second argument is the name of the action method to invoke. Последний аргумент — это Анонимный объект , создающий данные маршрута (в данном случае — идентификатор 4).The final argument is an anonymous object that generates the route data (in this case, the ID of 4).

Созданная ссылка показана на предыдущем рисунке http://localhost:xxxxx/Movies/Edit/4 .The generated link shown in the previous image is http://localhost:xxxxx/Movies/Edit/4. Маршрут по умолчанию принимает шаблон URL-адреса {controller}/{action}/{id} .The default route takes the URL pattern {controller}/{action}/{id}. Таким образом, ASP.NET преобразует http://localhost:xxxxx/Movies/Edit/4 запрос к Edit методу действия Movies контроллера с параметром, ID равным 4.Therefore, ASP.NET translates http://localhost:xxxxx/Movies/Edit/4 into a request to the Edit action method of the Movies controller with the parameter ID equal to 4.

Можно также передать параметры метода действия с помощью строки запроса.You can also pass action method parameters using a query string. Например, URL-адрес http://localhost:xxxxx/Movies/Edit?ID=4 также передает параметр ID 4 Edit методу действия Movies контроллера.For example, the URL http://localhost:xxxxx/Movies/Edit?ID=4 also passes the parameter ID of 4 to the Edit action method of the Movies controller.

едиткуеристрингEditQueryString

Откройте Movies контроллер.Open the Movies controller. EditНиже показаны два метода действия.The two Edit action methods are shown below.

'
' 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

Обратите внимание на второй метод действия Edit, которому предшествует атрибут HttpPost.Notice the second Edit action method is preceded by the HttpPost attribute. Этот атрибут указывает, что перегрузка Edit метода может быть вызвана только для запросов POST.This attribute specifies that overload of the Edit method can be invoked only for POST requests. Атрибут можно применить HttpGet к первому методу Edit, но это не обязательно, так как это значение по умолчанию.You could apply the HttpGet attribute to the first edit method, but that's not necessary because it's the default. (Мы будем называть методы действий, которым неявно назначается HttpGet атрибут в качестве HttpGet методов.)(We'll refer to action methods that are implicitly assigned the HttpGet attribute as HttpGet methods.)

HttpGet Edit Метод принимает параметр идентификатора фильма, находит фильм с помощью Find метода Entity Framework и возвращает выбранный фильм в представление редактирования.The HttpGet Edit method takes the movie ID parameter, looks up the movie using the Entity Framework Find method, and returns the selected movie to the Edit view. Если в представлении редактирования создана система формирования шаблонов, она проверяет класс Movie и создает код для отображения элементов <label> и <input> для каждого свойства класса.When the scaffolding system created the Edit view, it examined the Movie class and created code to render <label> and <input> elements for each property of the class. В следующем примере показано созданное представление изменения:The following example shows the Edit view that was generated:

@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>

Обратите внимание, что в шаблоне представления есть @ModelType MvcMovie.Models.Movie оператор в верхней части файла — это указывает, что представление ожидает, что модель шаблона представления будет иметь тип Movie .Notice how the view template has a @ModelType MvcMovie.Models.Movie statement at the top of the file — this specifies that the view expects the model for the view template to be of type Movie.

Сформированный код использует несколько вспомогательных методов для упрощения разметки HTML.The scaffolded code uses several helper methods to streamline the HTML markup. Html.LabelForВспомогательное приложение отображает имя поля ( " title " , " ReleaseDate " , " Жанр " или " Price " ).The Html.LabelFor helper displays the name of the field ("Title", "ReleaseDate", "Genre", or "Price"). В Html.EditorFor вспомогательном приложении отображается HTML- <input> элемент.The Html.EditorFor helper displays an HTML <input> element. В Html.ValidationMessageFor вспомогательном модуле отображаются все сообщения проверки, связанные с этим свойством.The Html.ValidationMessageFor helper displays any validation messages associated with that property.

Запустите приложение и перейдите по URL-адресу /Movies .Run the application and navigate to the /Movies URL. Щелкните ссылку Edit (Изменить).Click an Edit link. Просмотрите исходный код страницы в окне браузера.In the browser, view the source for the page. HTML-код на странице выглядит, как в следующем примере.The HTML in the page looks like the following example. (Для ясности была исключена разметка меню.)(The menu markup was excluded for clarity.)

<!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>

<input>Элементы находятся в ЭЛЕМЕНТЕ HTML, <form> атрибут которого action имеет значение POST для URL-адреса /мовиес/едит .The <input> elements are in an HTML <form> element whose action attribute is set to post to the /Movies/Edit URL. Данные формы будут отправлены на сервер при нажатии кнопки " изменить ".The form data will be posted to the server when the Edit button is clicked.

Обработка запроса POSTProcessing the POST Request

В следующем листинге демонстрируется версия HttpPost метода действия Edit.The following listing shows the HttpPost version of the Edit action method.

'
' 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

Связыватель модели ASP.NET Framework принимает значения отправленной формы и создает Movie объект, который передается в качестве movie параметра.The ASP.NET framework model binder takes the posted form values and creates a Movie object that's passed as the movie parameter. ModelState.IsValidПроверка кода подтверждает, что данные, отправленные в форме, можно использовать для изменения Movie объекта.The ModelState.IsValid check in the code verifies that the data submitted in the form can be used to modify a Movie object. Если данные являются допустимыми, код сохраняет данные фильмов в Movies коллекцию MovieDBContext экземпляра.If the data is valid, the code saves the movie data to the Movies collection of the MovieDBContext instance. Затем код сохраняет новые данные фильмов в базе данных, вызывая SaveChanges метод MovieDBContext , который сохраняет изменения в базе данных.The code then saves the new movie data to the database by calling the SaveChanges method of MovieDBContext, which persists changes to the database. После сохранения данных код перенаправляет пользователя к Index методу действия MoviesController класса, что приводит к отображению обновленного фильма в списке фильмов.After saving the data, the code redirects the user to the Index action method of the MoviesController class, which causes the updated movie to be displayed in the listing of movies.

Если опубликованные значения не являются допустимыми, они отображаются в форме.If the posted values aren't valid, they are redisplayed in the form. Html.ValidationMessageForВспомогательные методы в шаблоне представления Edit. vbhtml отвечают за отображение соответствующих сообщений об ошибках.The Html.ValidationMessageFor helpers in the Edit.vbhtml view template take care of displaying appropriate error messages.

абкнотвалидabcNotValid

Примечание о языковых стандартах Если вы обычно работаете с локальным языковым стандартом, отличным от английского, см . статью поддержка ASP.NET MVC 3 с использованием национальных стандартов, отличных от английского.Note about locales If you normally work with a locale other than English, see Supporting ASP.NET MVC 3 Validation with Non-English Locales.

Повышение надежности метода EditMaking the Edit Method More Robust

HttpGet Edit Метод, созданный системой формирования шаблонов, не проверяет, что переданный ей идентификатор является допустимым.The HttpGet Edit method generated by the scaffolding system doesn't check that the ID that's passed to it is valid. Если пользователь удаляет сегмент идентификатора из URL-адреса ( http://localhost:xxxxx/Movies/Edit ), отображается следующая ошибка:If a user removes the ID segment from the URL (http://localhost:xxxxx/Movies/Edit), the following error is displayed:

Null_IDNull_ID

Пользователь также может передать идентификатор, который не существует в базе данных, например http://localhost:xxxxx/Movies/Edit/1234 .A user could also pass an ID that doesn't exist in the database, such as http://localhost:xxxxx/Movies/Edit/1234. Чтобы устранить это ограничение, можно внести два изменения в HttpGet Edit метод действия.You can make two changes to the HttpGet Edit action method to address this limitation. Во-первых, измените ID параметр, чтобы значение по умолчанию было равно нулю, если идентификатор не был явно передан.First, change the ID parameter to have a default value of zero when an ID isn't explicitly passed. Кроме того, можно проверить, что Find метод обнаружил фильм перед возвратом объекта Movie в шаблон представления.You can also check that the Find method actually found a movie before returning the movie object to the view template. Обновленный Edit метод показан ниже.The updated Edit method is shown below.

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

Если фильм не найден, HttpNotFound вызывается метод.If no movie is found, the HttpNotFound method is called.

Все HttpGet методы соответствуют аналогичному шаблону.All the HttpGet methods follow a similar pattern. Они получают объект Movie (или список объектов, в случае использования Index ) и передают модель в представление.They get a movie object (or list of objects, in the case of Index), and pass the model to the view. CreateМетод передает пустой объект Movie в представление создания.The Create method passes an empty movie object to the Create view. Все методы, которые создают, редактируют, удаляют или иным образом изменяют данные, делают это в перегрузке метода HttpPost.All the methods that create, edit, delete, or otherwise modify data do so in the HttpPost overload of the method. Изменение данных в методе HTTP GET является угрозой безопасности, как описано в записи блога совет ASP.NET #46 — не использовать ссылки DELETE, так как они создают бреши в системе безопасности.Modifying data in an HTTP GET method is a security risk, as described in the blog post entry ASP.NET MVC Tip #46 – Don't use Delete Links because they create Security Holes. Изменение данных в методе GET также нарушает рекомендации по протоколу HTTP и шаблон архитектуры RESTFUL, указывающий, что запросы GET не должны изменять состояние приложения.Modifying data in a GET method also violates HTTP best practices and the architectural REST pattern, which specifies that GET requests should not change the state of your application. Иными словами, выполнение операции GET должно быть безрезультатной операцией без побочных эффектов.In other words, performing a GET operation should be a safe operation that has no side effects.

Добавление метода поиска и представления поискаAdding a Search Method and Search View

В этом разделе вы добавите SearchIndex метод действия, позволяющий искать фильмы по жанру или названию.In this section you'll add a SearchIndex action method that lets you search movies by genre or name. Это будет доступно с помощью URL-адреса /мовиес/сеарчиндекс .This will be available using the /Movies/SearchIndex URL. В запросе будет отображаться HTML-форма, содержащая элементы ввода, которые пользователь может заполнить для поиска фильма.The request will display an HTML form that contains input elements that a user can fill in in order to search for a movie. Когда пользователь отправляет форму, метод действия получает значения поиска, размещенные пользователем, и использует значения для поиска в базе данных.When a user submits the form, the action method will get the search values posted by the user and use the values to search the database.

SearchIndx_SM

Отображение формы СеарчиндексDisplaying the SearchIndex Form

Начните с добавления SearchIndex метода действия в существующий MoviesController класс.Start by adding a SearchIndex action method to the existing MoviesController class. Метод вернет представление, содержащее HTML-форму.The method will return a view that contains an HTML form. Вот этот код:Here's the code:

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

Первая строка SearchIndex метода создает следующий запрос LINQ для выбора фильмов:The first line of the SearchIndex method creates the following LINQ query to select the movies:

Dim movies = From m In db.Movies    Select m

Запрос определен на этом этапе, но еще не выполнялся в хранилище данных.The query is defined at this point, but hasn't yet been run against the data store.

Если searchString параметр содержит строку, запрос фильмов изменяется для фильтрации по значению строки поиска с помощью следующего кода:If the searchString parameter contains a string, the movies query is modified to filter on the value of the search string, using the following code:

Если не String. IsNullOrEmpty (searchString), тоIf Not String.IsNullOrEmpty(searchString) Then
Фильмы — Фильмы. WHERE (функции s. Title. Contains (searchString))movies = movies.Where(Function(s) s.Title.Contains(searchString))
Окончание, еслиEnd If

Запросы LINQ не выполняются, если они определены или изменяются путем вызова метода, такого как Where или OrderBy .LINQ queries are not executed when they are defined or when they are modified by calling a method such as Where or OrderBy. Вместо этого выполнение запроса откладывается, что означает, что вычисление выражения откладывается до тех пор, пока его реализованное значение фактически не будет перебираться или ToList метод не будет вызван.Instead, query execution is deferred, which means that the evaluation of an expression is delayed until its realized value is actually iterated over or the ToList method is called. В этом SearchIndex примере запрос выполняется в представлении сеарчиндекс.In the SearchIndex sample, the query is executed in the SearchIndex view. Дополнительные сведения об отложенном и немедленном выполнении запросов см. в разделе Выполнение запроса.For more information about deferred query execution, see Query Execution.

Теперь можно реализовать SearchIndex представление, которое будет отображать форму для пользователя.Now you can implement the SearchIndex view that will display the form to the user. Щелкните правой кнопкой мыши внутри SearchIndex метода и выберите Добавить представление.Right-click inside the SearchIndex method and then click Add View. В диалоговом окне Добавление представления укажите, что вы собираетесь передать Movie объект в шаблон представления в качестве класса модели.In the Add View dialog box, specify that you're going to pass a Movie object to the view template as its model class. В списке шаблон формирования шаблона выберите Список, а затем нажмите кнопку добавить.In the Scaffold template list, choose List, then click Add.

аддсеарчвиевAddSearchView

При нажатии кнопки Добавить создается шаблон представления виевс\мовиес\сеарчиндекс.вбхтмл .When you click the Add button, the Views\Movies\SearchIndex.vbhtml view template is created. Так как вы выбрали список в списке шаблонов шаблонов , Visual Web Developer автоматически создал (с формированием шаблонов) содержимое по умолчанию в представлении.Because you selected List in the Scaffold template list, Visual Web Developer automatically generated (scaffolded) some default content in the view. Формирование шаблонов создало HTML-форму.The scaffolding created an HTML form. Он проверил Movie класс и создал код для отрисовки <label> элементов для каждого свойства класса.It examined the Movie class and created code to render <label> elements for each property of the class. В приведенном ниже списке показано созданное представление Create.The listing below shows the Create view that was generated:

@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>

Запустите приложение и перейдите по адресу /мовиес/сеарчиндекс.Run the application and navigate to /Movies/SearchIndex. Добавьте в URL-адрес строку запроса, например ?searchString=ghost.Append a query string such as ?searchString=ghost to the URL. Отображаются отфильтрованные фильмы.The filtered movies are displayed.

сеарчкристрSearchQryStr

Если изменить сигнатуру SearchIndex метода для параметра с именем id , id параметр будет соответствовать {id} заполнительу для маршрутов по умолчанию, заданных в файле Global. asax .If you change the signature of the SearchIndex method to have a parameter named id, the id parameter will match the {id} placeholder for the default routes set in the Global.asax file.

{controller}/{action}/{id}

Измененный SearchIndex метод будет выглядеть следующим образом:The modified SearchIndex method would look as follows:

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

Теперь можно передать заголовок поиска в качестве данных маршрута (сегмент URL-адреса) вместо значения строки запроса.You can now pass the search title as route data (a URL segment) instead of as a query string value.

сеарчраутедатаSearchRouteData

Тем не менее пользователи вряд ли будут каждый раз изменять URL-адрес для поиска фильмов.However, you can't expect users to modify the URL every time they want to search for a movie. Итак, теперь вы добавите пользовательский интерфейс, чтобы помочь им фильтровать фильмы.So now you you'll add UI to help them filter movies. Если вы изменили сигнатуру SearchIndex метода, чтобы проверить, как передать параметр идентификатора, привязанного к маршруту, измените его обратно, чтобы метод задавал SearchIndex строковый параметр с именем searchString :If you changed the signature of the SearchIndex method to test how to pass the route-bound ID parameter, change it back so that your SearchIndex method takes a string parameter named searchString:

Откройте файл виевс\мовиес\сеарчиндекс.вбхтмл и сразу после @Html.ActionLink("Create New", "Create") добавьте следующее:Open the Views\Movies\SearchIndex.vbhtml file, and just after @Html.ActionLink("Create New", "Create"), add the following:

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

Html.BeginFormВспомогательный объект создает открывающий <form> тег.The Html.BeginForm helper creates an opening <form> tag. Html.BeginFormВспомогательная функция заставляет форму опубликовать себя, когда пользователь отправит форму, нажав кнопку Фильтр .The Html.BeginForm helper causes the form to post to itself when the user submits the form by clicking the Filter button.

Запустите приложение и попробуйте найти фильм.Run the application and try searching for a movie.

SearchIndxIE9_titleSearchIndxIE9_title

HttpPostПерегрузка SearchIndex метода отсутствует.There's no HttpPost overload of the SearchIndex method. Это не требуется, так как метод не изменяет состояние приложения, просто отфильтровывая данные.You don't need it, because the method isn't changing the state of the application, just filtering data. Если вы добавили следующий HttpPost SearchIndex метод, вызывающий объект действия будет соответствовать HttpPost SearchIndex методу, и HttpPost SearchIndex метод будет выполняться, как показано на рисунке ниже.If you added the following HttpPost SearchIndex method, the action invoker would match the HttpPost SearchIndex method, and the HttpPost SearchIndex method would run as shown in the image below.

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

сеарчпостгхостSearchPostGhost

Добавление поиска по жанруAdding Search by Genre

Если вы добавили HttpPost версию SearchIndex метода, удалите ее сейчас.If you added the HttpPost version of the SearchIndex method, delete it now.

Далее предстоит добавить функцию, позволяющую пользователям искать фильмы по жанрам.Next, you'll add a feature to let users search for movies by genre. Замените метод SearchIndex следующим кодом:Replace the SearchIndex method with the following code:

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

Эта версия SearchIndex метода принимает дополнительный параметр, а именно movieGenre .This version of the SearchIndex method takes an additional parameter, namely movieGenre. Первые несколько строк кода создают List объект для хранения жанров фильмов из базы данных.The first few lines of code create a List object to hold movie genres from the database.

Следующий код определяет запрос LINQ, который извлекает все жанры из базы данных.The following code is a LINQ query that retrieves all the genres from the database.

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

Код использует AddRange метод универсальной List коллекции, чтобы добавить в список все отдельные жанры.The code uses the AddRange method of the generic List collection to add all the distinct genres to the list. (Без Distinct модификатора добавляются дубликаты жанров, например, в нашем примере комедия будет добавляться дважды).(Without the Distinct modifier, duplicate genres would be added — for example, comedy would be added twice in our sample). Затем в коде сохраняется список жанров в ViewBag объекте.The code then stores the list of genres in the ViewBag object.

В следующем коде показано, как проверить movieGenre параметр.The following code shows how to check the movieGenre parameter. Если он не пуст, код дополнительно ограничивает запрос фильмов, чтобы ограничить выбранные фильмы указанным жанром.If it's not empty the code further constrains the movies query to limit the selected movies to the specified genre.

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

Добавление разметки в представление Сеарчиндекс для поддержки поиска по жанруAdding Markup to the SearchIndex View to Support Search by Genre

Добавьте Html.DropDownList вспомогательную функцию в файл виевс\мовиес\сеарчиндекс.вбхтмл непосредственно перед TextBox вспомогательным модулем.Add an Html.DropDownList helper to the Views\Movies\SearchIndex.vbhtml file, just before the TextBox helper. Готовая разметка показана ниже:The completed markup is shown below:

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

Запустите приложение и перейдите по /мовиес/сеарчиндекс.Run the application and browse to /Movies/SearchIndex. Попробуйте поиск по жанру, по имени фильма и по обоим критериям.Try a search by genre, by movie name, and by both criteria.

В этом разделе вы проверили методы действия CRUD и представления, созданные платформой.In this section you examined the CRUD action methods and views generated by the framework. Вы создали метод и представление действия поиска, которые позволяют пользователям выполнять поиск по названию и жанру фильма.You created a search action method and view that let users search by movie title and genre. В следующем разделе вы узнаете, как добавить свойство в Movie модель и как добавить инициализатор, который будет автоматически создавать тестовую базу данных.In the next section, you'll look at how to add a property to the Movie model and how to add an initializer that will automatically create a test database.