MVC 音乐商店 第 5 部分: 编辑窗体和模板化

来源:互联网 发布:淘宝网店保证金怎么交 编辑:程序博客网 时间:2024/05/16 09:55

MVC 音乐商店是介绍,并分步说明了如何使用 ASP.NET MVC 和 Visual Studio 为 web 开发教程应用程序。

MVC 音乐商店是一个轻量级的示例存储实现它卖音乐专辑在线,并实现基本的网站管理、 用户登录,和购物车功能。

这个系列教程详细说明所有为构建 ASP.NET MVC 音乐商店示例应用程序采取的步骤。第 5 部分涵盖编辑窗体和模板化。

在过去的章中,我们从我们的数据库中装载数据并显示它。在这一章,我们还会启用编辑数据。

创建 StoreManagerController

我们会首先创建一个新的控制器,称为StoreManagerController此控制器,我们将能利用脚手架可用的功能在更新中,ASP.NET MVC 3 的工具。设置添加控制器对话框中的选项,如下所示。

当您单击添加按钮时,您会看到 ASP.NET MVC 3 基架机制为您做了大量的工作:

  • 它与当地的实体框架变量创建新 StoreManagerController
  • 它将一个 StoreManager 文件夹添加到项目的视图文件夹
  • 它将添加 Create.cshtml、 Delete.cshtml、 Details.cshtml、 Edit.cshtml、 Index.cshtml 视图,强类型化为专辑类

新的 StoreManager 控制器类包括 CRUD (创建、 读取、 更新、 删除) 控制器操作,知道如何工作与册页类的模型和使用我们的实体框架上下文访问数据库。

修改基架的视图

它是重要的是要记住,虽然此代码为我们生成的它是 ASP.NET MVC 的标准代码,就像我们已经写了在本指南中。它的目的在于节约您在手动编写样板控制器代码以及创建强类型视图上花费的时间,但是所生成的代码并不会像您以前看到的那样在注释里显示一条严重警告,要求您不得更改代码。这是您的代码,你应该去改变它。

所以,让我们从开始到 StoreManager 索引视图快速编辑 (/ Views/StoreManager/Index.cshtml)。此视图将显示一个表,其中列出了在我们的商店专辑与编辑 / 详细信息 / 删除链接,并包括册页的公共属性。我们会删除 AlbumArtUrl 字段,因为它不是在此显示中非常有用。在 < 表 > 部分中查看代码,删除 < th > 和 < td > 元素周围 AlbumArtUrl 的引用,如下面突出显示的行所示:

<table>    <tr>        <th>            Genre        </th>        <th>            Artist        </th>        <th>            Title        </th>        <th>            Price        </th>        <th>            AlbumArtUrl        </th>        <th></th>    </tr>@foreach (var item in Model) {    <tr>        <td>            @Html.DisplayFor(modelItem => item.Genre.Name)        </td>        <td>            @Html.DisplayFor(modelItem => item.Artist.Name)        </td>        <td>            @Html.DisplayFor(modelItem => item.Title)        </td>        <td>            @Html.DisplayFor(modelItem => item.Price)        </td>        <td>            @Html.DisplayFor(modelItem => item.AlbumArtUrl)        </td>        <td>            @Html.ActionLink("Edit", "Edit", new { id=item.AlbumId }) |            @Html.ActionLink("Details", "Details", new { id=item.AlbumId }) |            @Html.ActionLink("Delete", "Delete", new { id=item.AlbumId })        </td>    </tr>}</table>

修改的视图代码将显示如下:

@model IEnumerable<MvcMusicStore.Models.Album>@{    ViewBag.Title = "Index";}<h2>Index</h2><p>    @Html.ActionLink("CreateNew", "Create")</p><table>    <tr>        <th>            Genre        </th>        <th>            Artist        </th>        <th>            Title        </th>        <th>            Price        </th>        <th></th>    </tr>@foreach (var item in Model) {    <tr>        <td>            @Html.DisplayFor(modelItem => item.Genre.Name)        </td>        <td>            @Html.DisplayFor(modelItem => item.Artist.Name)        </td>        <td>            @Html.DisplayFor(modelItem => item.Title)        </td>        <td>            @Html.DisplayFor(modelItem => item.Price)        </td>        <td>            @Html.ActionLink("Edit", "Edit", new { id=item.AlbumId }) |            @Html.ActionLink("Details", "Details", new { id=item.AlbumId }) |            @Html.ActionLink("Delete", "Delete", new { id=item.AlbumId })        </td>    </tr>}</table>

第一次看看店经理

现在运行该应用程序并浏览到/StoreManager /。这显示我们刚刚修改的链接,编辑的详细信息,和删除存储区中显示的相册列表存储管理器索引。

单击编辑链接显示的唱片集、 流派和艺术家包括下拉列表编辑窗体的字段。

单击"返回列表"链接在底部,然后单击一张专辑的详细信息链接。这将显示个人专辑的详细信息。

再次单击背对列表中的链接,然后单击删除链接上。这将显示一个确认对话框,显示唱片集详细资料和问我们是不我们想要删除它。

单击底部的删除按钮将删除相册并返回到索引页,该页显示已删除的相册。

我们还没有完成与存储管理器,但我们有控制器和视图的 CRUD 操作的代码从开始工作。

查看音乐商店管理器控制器代码

存储管理器控制器包含大量的代码。我们去通过这从顶部到底部。控制器包含一些标准的命名空间为 MVC 控制器,以及对我们的模型命名空间的引用。控制器有一个私人的 MusicStoreEntities,用于数据访问的每个控制器操作实例。

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Web; using System.Web.Mvc; using MvcMusicStore.Models; namespace MvcMusicStore.Controllers{     public class StoreManagerController : Controller    {        private MusicStoreEntities db = new MusicStoreEntities();

存储管理器的索引和详细信息操作

索引视图检索出唱片,包括每个专辑被引用的体裁和艺术家信息,正如我们先前看到的商店浏览方法工作时的列表。索引视图是后对所链接的对象的引用,这样它可以显示每个专辑流派名称和艺术家名称,所以控制器正在高效率和查询的原始请求中的此信息。

//// GET: /StoreManager/public ViewResult Index(){  var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist);  return View(albums.ToList());}

StoreManager 控制器的详细信息控制器操作的作品作为我们以前-写它查询为册页的存储控制器详细信息操作完全一样的使用 Find() 方法的 ID,然后将它返回到视图。

  //  // GET: /StoreManager/Details/5  public ViewResult Details(int id)  {    Album album = db.Albums.Find(id);    return View(album);  }

创建操作方法

创建操作方法是有点不同于那些到目前为止,我们已经看到的因为他们处理窗体的输入。当用户首次访问时 /StoreManager/创建/他们将显示一个空窗体。该 HTML 页面将包含一个包含下拉列表的 < 窗体 > 元素和他们可以在其中输入唱片集的详细信息的文本框中输入的元素。

用户填充专辑的窗体值后,他们可以按"保存"按钮以提交这些更改发回我们的应用程序保存在数据库中。当用户按下"保存"按钮时 < 窗体 > 将执行 HTTP POST 回 /StoreManager/创建的 URL 并将 < 窗体 > 值提交作为 HTTP POST 的一部分。

ASP.NET MVC 允许我们轻松地分手这两个 URL 调用方案的逻辑,使我们能够执行两个单独的"创建"操作方法内我们 StoreManagerController 类 — — 一个处理初始 HTTP 获取浏览到 /StoreManager/创建/URL 和其他处理 HTTP POST 的提交的更改。

将信息传递到视图中使用 ViewBag

我们较早前在本教程中,使用过 ViewBag,但还没谈了许多关于它。ViewBag 允许我们将信息传递给视图,而无需使用的强类型化的模型对象。在这种情况下,需要将这两个流派和艺术家的列表传递给该窗体以填充下拉列表,我们编辑的 HTTP GET 控制器操作和这样做的最简单方法是返回他们作为 ViewBag 项目。

ViewBag 是一个动态对象,这意味着您可以键入 ViewBag.Foo 或 ViewBag.YourNameHere,而无需编写代码来定义这些属性。在这种情况下,控制器代码使用 ViewBag.GenreId 和 ViewBag.ArtistId,以便通过该表单提交的下拉列表值将是 GenreId 和 ArtistId,这是它们将要设置的唱片专辑属性。

这些下拉列表值返回到窗体中使用的 SelectList 对象,只是为此目的生成。这是使用这样的代码:

ViewBag.GenreId = new SelectList(db.Genres, "GenreId","Name");

你可以看到从操作方法代码,正在使用三个参数来创建此对象:

  • 将显示下拉列表中的项的列表。请注意这并不是仅仅是一个字符串-我们路过的流派列表。
  • 下一个参数被传递到 SelectList 是所选值。此 SelectList 如何知道如何预先选择列表中的项。这将是容易理解当我们看编辑窗体,这是很相似的。
  • 最后一个参数是要显示的属性。在这种情况下,这表示的 Genre.Name 属性什么将显示给用户。

这一点,然后,HTTP GET 创建行动是相当简单-两个 SelectLists 添加到 ViewBag,并没有模型对象将被传递到窗体中 (因为它尚未创建)。

//// GET: /StoreManager/Createpublic ActionResult Create(){    ViewBag.GenreId = new SelectList(db.Genres, "GenreId","Name");    ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId","Name");    return View();} 

创建视图的下拉菜单中显示的HTML助手

既然我们已经讨论过值下拉传递到视图的方式,让我们看快速视图以查看这些值的显示方式。在视图的代码中 (/ Views/StoreManager/Create.cshtml),你就会看到下面的调用由以显示体裁滴下来。

@Html.DropDownList("GenreId",String.Empty) 

这被称为 HTML 帮助器-一种实用方法,执行视图的常见任务。HTML 帮助是非常有用的在保持我们的视图代码简洁和易读。Html.DropDownList 帮助器提供的 ASP.NET MVC 中,但后面我们会看到它是可能要创建我们自己的查看代码,我们就会在我们的应用程序中重用的佣工。

Html.DropDownList 调用只需要说两件事-凡到 get 列表中要显示,和什么值 (如果有) 应预先选定。第一个参数,GenreId,告诉下拉列表中查找一个名为 GenreId 的模型或 ViewBag 中值。第二个参数用于指示要显示的值作为最初在下拉列表中选定。由于此窗体创建窗体,没有值要预先选定和 String.Empty 传递。

处理发布的表单值

正如我们讨论之前,有两个与每个窗体关联的操作方法。第一次处理的 HTTP GET 请求并显示窗体。第二个处理 HTTP POST 请求,其中包含提交窗体值。请注意控制器操作有 [HttpPost] 属性中,它告诉 ASP.NET MVC 只应响应 HTTP POST 请求。

//// POST: /StoreManager/Create[HttpPost] public ActionResult Create(Album album) {    if (ModelState.IsValid)    {        db.Albums.Add(album);        db.SaveChanges();        return RedirectToAction("Index");      }    ViewBag.GenreId = new SelectList(db.Genres, "GenreId","Name", album.GenreId);    ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId","Name", album.ArtistId);    return View(album); }

这一行动具有四个职责:

  • 1.读取表单的值
  • 2.检查是否窗体值传递任何验证规则
  • 3.如果表单提交是有效的保存的数据和显示更新的列表
  • 4.如果表单提交不是有效的重新显示子窗体的验证错误

读窗体值与模型绑定

控制器中的操作处理表单提交,包括用于标题、 价格和 AlbumArtUrl GenreId 和 ArtistId (从下拉列表中) 的值和文本框中的值。虽然它也能直接访问的窗体值,更好的方法是使用内置的 ASP.NET MVC 中的模型绑定的功能。当控制器操作模型类型作为参数时,ASP.NET MVC 将尝试填充使用窗体输入 (以及工艺路线和查询字符串值) 该类型的对象。这是通过寻找其名称匹配的模型对象的属性,如值在设置时新专辑对象的 GenreId 值,它看起来与 GenreId 的名称输入。当您创建视图在 ASP.NET MVC 中使用的标准方法时,形式将始终呈现使用属性名称作为输入的字段名称,所以此字段名称将与只匹配。

验证模型

该模型是用一个简单的调用到 ModelState.IsValid 进行验证。我们还没到我们专辑类添加任何验证规则还-在位-所以,现在这种检查并不很多事要做,我们会。重要的是这种 ModelStat.IsValid 检查将适应我们穿我们的模型,所以,将来对验证规则的更改不会需要对控制器操作代码的任何更新的验证规则。

保存的提交的值

如果表单提交通过验证,它是将值保存到数据库的时间。与实体框架中,这只是需要将模型添加到相册集合并调用 SaveChanges。

db.Albums.Add(album); db.SaveChanges();

实体框架生成适当的 SQL 命令,保持值。保存数据之后, 我们重定向到的相册列表所以我们可以看到我们的更新。这是通过返回 RedirectToAction 与我们想要显示的控制器操作的名称。在这种情况下,是该索引方法。

显示带有验证错误无效表单提交

在无效表单输入下拉列表值添加到 ViewBag (如 HTTP GET 案) 和的绑定的模型值被传递回视图显示。使用 @Html.ValidationMessageFor 的 HTML 帮助器会自动显示验证错误。

测试创建窗体

对此进行测试了,运行应用程序并浏览到 /StoreManager/创建 /-这会显示你由 StoreController 创建 HTTP GET 方法返回的空白窗体。

填写某些值,请单击创建按钮以提交该表单。

处理编辑

编辑操作对 (HTTP GET 和 HTTP POST) 是与我们刚看的创建操作方法非常相似。通过路由,因为编辑方案中涉及使用现有的相册,编辑 HTTP-获取方法加载基于"id"参数,专辑中传递。此代码检索专辑由 AlbumId 是相同的我们以前已经看在控制器中的操作的详细信息。作为具有创建 / HTTP GET 方法,通过 ViewBag 返回值下拉。这使我们能够返回专辑作为我们的模型对象的视图 (这强类型的专辑类) 同时通过 ViewBag 传递额外的数据 (例如流派的列表)。

//// GET: /StoreManager/Edit/5public ActionResult Edit(int id) {    Album album = db.Albums.Find(id);    ViewBag.GenreId = new SelectList(db.Genres, "GenreId","Name", album.GenreId);    ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId","Name", album.ArtistId);    return View(album); }

编辑 HTTP POST 操作是非常类似于创建 HTTP POST 操作。唯一的区别是,而不是向数据库添加一张新的专辑。专辑集合中,我们发现当前实例的专辑使用 db。Entry(album) 并将其状态设置为已修改。这就告诉我们要修改现有的相册,而不是创建一个新实体框架。

//// POST: /StoreManager/Edit/5[HttpPost] public ActionResult Edit(Album album) {    if (ModelState.IsValid)    {        db.Entry(album).State = EntityState.Modified;        db.SaveChanges();        return RedirectToAction("Index");    }    ViewBag.GenreId = new SelectList(db.Genres, "GenreId","Name", album.GenreId);    ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId","Name", album.ArtistId);    return View(album); }

我们可以测试出由运行应用程序并浏览到/StoreManger/,然后单击一张专辑的编辑链接。

这将显示由编辑 HTTP GET 方法显示的编辑窗体。填写某些值,请单击保存按钮。

这将窗体发送、 保存的值,并返回我们到相册列表中,显示的值被更新。

处理删除

删除如下编辑和创建、 使用一个控制器的操作来显示确认窗体上和另一个控制器操作来处理表单提交相同的图案。

控制器中的 HTTP GET 删除操作正是我们先前存储管理器详细信息控制器中的操作相同。

//// GET: /StoreManager/Delete/5 public ActionResult Delete(int id) {    Album album = db.Albums.Find(id);    return View(album); }

我们为专辑类型时,使用删除视图内容模板显示的窗体,强类型的。

删除模板显示所有字段的模型中,但我们可以相当简化把它放下来。在 /Views/StoreManager/Delete.cshtml 中的视图代码更改为以下。

@model MvcMusicStore.Models.Album@{    ViewBag.Title = "Delete";}<h2>Delete Confirmation</h2><p>Are you sure you want to delete the album titled    <strong>@Model.Title</strong>?</p>@using (Html.BeginForm()) {    <p>        <input type="submit" value="Delete" />    </p>    <p>        @Html.ActionLink("Back toList", "Index")    </p>}

这将显示简化的删除确认。

单击删除按钮使窗体回发到服务器,执行 DeleteConfirmed 的操作。

//// POST: /StoreManager/Delete/5[HttpPost, ActionName("Delete")]public ActionResult DeleteConfirmed(int id) {                Album album = db.Albums.Find(id);    db.Albums.Remove(album);    db.SaveChanges();    return RedirectToAction("Index");}

我们的 HTTP POST 删除控制器操作会执行下列操作:

  • 1.加载由 ID 专辑
  • 2.将它删除相册并保存更改
  • 3.重定向到索引中,显示专辑已从列表中移除

对此进行测试,运行该应用程序并浏览到 /StoreManager。从列表中选择一个相册,并单击删除链接。

这将显示我们删除确认屏幕。

单击删除按钮删除相册并返回我们店经理索引页,其中显示相册已被删除。

使用自定义的 HTML 帮助器要截断文本

我们与我们的存储管理器索引页面有一个潜在的问题。我们相册标题和艺术家名称属性可以两者都是足够长的时间他们能摆脱我们的表格格式。我们将创建自定义的 HTML 帮助器,以使我们能够容易地截断这些属性和其他属性在我们的意见。

Razor 的 @helper 语法可以很容易地创建您自己的 helper 函数以用于您的视图。打开 /Views/StoreManager/Index.cshtml 视图,然后在 @model 行后直接添加以下代码。

@helper Truncate(stringinput, int length) {    if (input.Length <= length) {        @input    } else {        @input.Substring(0, length)<text>...</text>    }} 

此帮助器方法使用一个字符串和要允许的最大长度。如果提供的文本是比指定的长度短,佣工输出它作为-是。如果它的长度,然后截断文本,并呈现"..."剩余时间。

现在我们可以使用我们截断的帮助器,确保的相册标题和艺术家名称属性是少于 25 个字符。使用我们新的截断佣工的完整视图代码显示的下方。

@model IEnumerable<MvcMusicStore.Models.Album>@helper Truncate(string input, int length) {    if (input.Length <= length) {        @input    } else {        @input.Substring(0, length)<text>...</text>    }}@{    ViewBag.Title = "Index";}<h2>Index</h2><p>    @Html.ActionLink("CreateNew", "Create")</p><table>    <tr>        <th>            Genre        </th>        <th>            Artist        </th>        <th>            Title        </th>        <th>            Price        </th>        <th></th>    </tr>@foreach (var item in Model) {    <tr>        <td>            @Html.DisplayFor(modelItem => item.Genre.Name)        </td>        <td>            @Truncate(item.Artist.Name, 25)        </td>        <td>            @Truncate(item.Title, 25)        </td>        <td>            @Html.DisplayFor(modelItem => item.Price)        </td>        <td>            @Html.ActionLink("Edit", "Edit", new { id=item.AlbumId }) |            @Html.ActionLink("Details", "Details", new { id=item.AlbumId }) |            @Html.ActionLink("Delete", "Delete", new { id=item.AlbumId })        </td>    </tr>}</table>

现在当我们浏览 /StoreManager/ URL,专辑和标题都保持低于我们的最大长度。