ASP.NET MVC 音乐商店 - 5 通过支架创建编辑表单 续

转自http://www.cnblogs.com/haogj/archive/2011/11/15/2249147.html

查看 StoreManager 控制器的代码

现在,Store Manager 控制器中已经包含了一定数量的代码,我们从头到尾重新过一下。

首先,在控制器中包含了标准的 MVC 控制器的代码,为了使用方便,还可以引用我们的模型类所在的命名空间 MvcMusicStore.Models。控制器还拥有了一个私有的 MusicStoreEntities 的私有成员,以方便控制器中的每个 Action 访问数据库。

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;

using MvcMusicStore.Models;

namespace MvcMusicStore.Controllers{public class StoreManagerController : Controller    {        MvcMusicStore.Models.MusicStoreEntities storeDB            = new MvcMusicStore.Models.MusicStoreEntities();

 

Index 和 Details Action

Index 视图获取专辑的列表,包含每一个专辑引用的流派和艺术家信息,向我们在前面 Store控制器的 Browse时候看到的,Index 视图中需要包含对于链接到的流派和艺术家对象来显示相关的信息,所以,在 Index 的 Action 方法中,需要包含这些数据。

//// GET: /StoreManager/

public ActionResult Index(){var albums = storeDB.Albums.Include("Genre").Include("Artist");return View(albums.ToList());}

 

在 Details 方法中,类似于 Store 控制器的 Details 方法,通过专辑的 Id 来获取专辑对象,这里使用 Find() 方法完成,最后,把这个对象传递给视图。

//// GET: /StoreManager/Details/5

public ViewResult Details(int id){    MvcMusicStore.Models.Album album = storeDB.Albums.Find(id);return View(album);}

 

创建方法 Create

与前面看到的不同,Create 方法需要处理表单,当用户第一次访问地址 /StoreManager/Create 的时候,用户将会看到一个空的表单,HTML 页面中包含一个 <form> 元素,其中包含了下拉列表和文本框等输入元素,用户可以借助他们输入专辑的详细信息。

当用户填写了专辑的信息之后,可以通过点击 “保存” 按钮来提交表单信息到服务器,我们de应用程序可以获取这些信息保存到数据库中。在用户点击 “保存” 的时候,浏览器发出一个 Http 的 Post 请求,到 /StoreManager/Create 地址,表单的内容作为这个 Post 请求的一部分发送回服务器。

ASP.NET MVC 允许我们容易地分割这两种同样对于 Create 方法的请求处理,通过提供两个同名的 Create 方法,一个用来处理 Http Get 请求,一个用来处理 Http Post 请求,区分的方式是在处理 Post 请求的方法前面增加一个 [HttpPost] 的标签。如果增加 [HttpGet] 标签,则表示这个方法仅仅处理 Http Get 请求。通常没有这个标签,则表示无论是 Get 请求还是 Post 请求都可以由这个 Action 方法处理。

使用 ViewBag 向视图传递信息

我们曾经在这个教程的开始使用过 ViewBag, 但是,没有深入讨论它,ViewBag 允许我们向视图传递信息而不需要首先定义强类型的 Model,在创建专辑的 Action 中,因为在表单中需要两个列表框,我们需要向视图传递列表所需要的数据,以便在视图中填充下拉列表框,最简单的方式就是通过 ViewBag 来实现。

ViewBag 是动态对象,这意味着你可以使用 ViewBag.Foo 或者 ViewBag.YourNameHere 形式的属性而不需要预先定义这些属性,控制器中的代码使用 ViewBag.GenreId 和 ViewBag.Artisid 传递流派和艺术家的信息以便生成表单中下拉列表的值,以后,用来在新创建的专辑中使用。

传递到视图的下拉列表的值使用 SelectList 对象表示,对于我们的要求,使用下面的代码。

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

 

方法中的三个参数被用于创建这个对象:

用来生成下拉列表中信息的集合,注意,不是一个字符串集合,我们这里是流派对象的集合。

方法的第二个参数提供下拉列表中的值,这是一个字符串,实际上是流派对象的一个属性 GenreId。

最后的参数提供下拉列表中显示出来的值,这里使用流派的 Name 属性。

理解了上面的内容,代码就很简单了,两个 SelectList 对象通过 ViewBag 传递给视图,没有使用模型对象,我们也没有创建这样用途的模型。

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

 

在 Create 视图中使用 HtmlHelper 来显示下拉列表

下拉列表的数据已经被传递到了视图中,现在,我们看一下视图如何使用这些数据显示一个下拉列表,在 Create 视图中,将原来显示流派标识的代码

@Html.LabelFor(model => model.GenreId)

 

修改为

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

 

这里使用了 HtmlHelper ,一个用于视图中生成 Html 的实用工具,使用 HtmlHelper 可以保持我们的视图清楚和易读。Html.DropDownList 助手方法由 ASP.NET MVC 提供,后面可以看到,我们也可以提供自己的助手方法进行扩展。 

Html.DropDownList 方法需要两个参数,从哪里获取显示用的列表,和哪一个值需要被预先选中,方法的第一个参数, GenreId,告诉DropDownList 从模型对象或者 ViewBag 对象中寻找名为 GenreId 的属性值,第二个参数用来指出下拉列表默认选中的值。这是创建专辑的表单,所以,没有需要预先选中的值,这里传递了一个 String.Empty 。

获取 Post 表单中的值

我们在前面讨论过,对于一个表单可以有两个对应的处理方法,一个处理 Http Get 请求显示表单,另外一个用于处理 Http Post 请求,用于处理提交的表单数据,注意,在控制器中,处理 Http Post 请求的方法需要通过标签 [HttpPost] 进行标注,这样,这个方法将会被 ASP。NET 仅仅用来处理 Post 请求。

//// POST: /StoreManager/Create

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

这个 Action 方法完成四个任务:

  1. 读取表单的数据
  2. 检查表单的数据是否通过了验证规则
  3. 如果表单通过了验证,保存数据,然后显示更新之后的专辑列表
  4. 如果表单没有通过验证,重新显示带有验证提示信息的表单。 

通过模型绑定获取表单数据

控制器处理的表单提交中包含了流派的标识 GenreId 和 艺术家标识 ArtistId,这些来自下拉列表框,以及通过文本框输入的 Title,Price 等等数据,虽然可以直接通过 FormCollection 来访问表单数据,但是,更好的做法是使用 ASP.NET MVC 内置提供的模型绑定。

当 Action 方法的参数是模型类型的时候,ASP.NET MVC 将会试图使用表单中的数据来填充对象的属性,它通过检查表单参数的名字是否匹配模型对象的属性来进行,例如,对于专辑对象的 GenreId 属性来说,它将会在表单数据中查找名为 GenreId 的值赋予它。当使用标准的模型方式生成视图的时候,表单会使用模型对象的属性名称来生成表单输入项目的名称,这样,在发出表单的时候,请求参数就会正好匹 配模型的属性了。

验证模型

通过访问 ModelState 的 IsValid 属性就可以检查模型是否通过验证。这里我们还没有为 Album 提供任何的验证规则,后面我们就会提供,所以,这里的验证并没有实际的作用。验证的重要性取决于我们定义的在模型上的验证规则,如果我们已经提供了对于 ModelState 的 IsValid 检查的话,以后增加验证规则就不需要修改这里的代码。

保存提交的数据

如果提交的数据通过了验证,下一步就可以保存到数据库中,使用 EF,仅仅需要将模型对象加入到 Albums 的集合中,然后调用 SaveChanges 方法就可以了。

db.Albums.Add(album);

db.SaveChanges();

 

EF 将会生成适当的 SQL 命令来持久化对象,保存数据之后,我们重定向到专辑列表的页面,以便看到更新之后的内容。这可以通过调用 RedirectToAction 方法,并提供 Action 方法的名称来完成。在这里,我们使用 Index 。 

显示带有验证提示信息的表单

如果没有通过验证,与 GET 处理的时候相同,我们通过 ViewBag 传递下拉列表的值,通过模型传递其他的数据,验证的提示信息由 @HtmlValidationMessageFor 助手方法自动显示在页面上。

测试创建表单

测试一下,运行程序,访问 /StoreManager/Create,你将会看到一个由 StoreManagerController 的 Create 方法处理  Http Get 请求生成的空白表单。

填写一些内容,然后点击创建按钮提交表单。

可以看到内容已经被添加。                       

 

处理编辑

编辑处理的一对 Action 方法非常类似我们刚刚看到的 Create 处理。由于编辑的情况需要对已经存在的唱片进行处理,在编辑的 Get 方法中,我们使用唱片的 Id 来加载原有的唱片,这个参数通过路由传递过来,实际的代码类似在 Details 中看到的处理。除了专辑对象,同时还有处理下拉列表,所以,这里也通过 ViewBag 来处理,这样就允许我们在传递一个 Model 的同时还通过 ViewBag 传递了两个额外的 SelectList。

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

 

处理 Post 请求的 Edit 方法也非常类似于 Create 的 Post 处理方法,仅有的不同就是不用创建一个新的专辑对象加入到集合中,而是将现有的专辑对象,注意已经通过模型绑定获取了请求参数,将这个对象的状态属性 State 修改为 Modified ,这就回告诉 EF 我们正在修改一个存在的专辑对象,而不是创建一个新的。

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

 

注意,这个时候,编译器会提示一个错误:

类型“System.Data.EntityState”在未被引用的程序集中定义。必须添加对程序集“System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”的引用。         F:\Lesson\MVC\MvcMusicStore\MvcMusicStore\Controllers\StoreManagerController.cs 76     17     MvcMusicStore 

添加这个程序集的引用。

 

 

下面我们运行程序测试一下,浏览/StoreManager,然后点击 Edit 链接。

点击 Save, 回到专辑列表,可以看到值已经被更新了。

 

处理删除

删除的处理模式与 Edit 和 Create 一样,使用一个控制器的 Action 显示确认信息,使用另外一个 Action 来处理提交。

删除的 Get 处理非常类似于前面的 Details 处理。

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

 

使用 Delete 视图模板显示强类型的 Album 表单。

默认的 Delete 视图使用模型来显示信息,但是,我们仅仅需要简单地显示确认信息就可以了,把这个视图修改一下,变成下面的样子。

@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 to List", "Index")    </p>}

 

这样,确认页面就成了下面的样子。

点击 Delete 按钮之后,将导致表单发送到服务器,执行 DeleteConfirmed 的 Action 处理方法。

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

 

在我们的 Post 处理中,完成了下面的任务

  1. 通过专辑的 Id 加载专辑对象
  2. 删除专辑,然后保存所做的修改
  3. 重新定向到 Index, 显示删除专缉之后的列表。 

测试一下这些工作,运行程序,选择一个专辑,然后删除它。

 

点击删除之后,显示了第一张专辑的删除确认页面。

 

点击删除之后,原来的专辑已经消失了。

 

使用自定义的 HtmlHelper 截断文本内容

我们的管理首页存在一个潜在的问题,我们的专辑名称和艺术家名称可能比较长,这会影响到我们的页面。下面我们创建一个自定义的 HtmlHelper 扩展来使得我们可以轻易地截断比较长的字符串。在视图中显示成这样的效果

 

Rozor 的 @helper 可以使这个工作变得很容易实现,打开 /View/StoreManager/Index.cshtml视图,直接在 @model 的下面增加下面的代码。

@helper Truncate(string input, 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("Create New", "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>

 

注意,这里展示了简单地在一个视图中使用 HtmlHelper 的方式,关于更多的信息,请参考:

http://bit.ly/mvc3-helper-options 

如果希望在多个视图中使用这个扩展的助手方法,可以如下进行。

using System.Web.Mvc;

namespace MvcMusicStore.Helpers{public static class HtmlHelpers    {public static string Truncate(this HtmlHelper helper, string input, int length)        {if (input.Length <= length)            {return input;            }else            {return input.Substring(0, length) + "...";            }        }    }}

 

注意,使用扩展方法必须 using 其命名空间

@{ViewBag.Title = "Home Page";}@using RazorHelpers.Helpers

<h2>@Html.Truncate(ViewBag.Message as string, 8)</h2>

 

你也可以在配置文件 web.config 中统一定义。

<system.web.webPages.razor>

<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<pages pageBaseType="System.Web.Mvc.WebViewPage">

<namespaces>

<add namespace="System.Web.Mvc"/>

<add namespace="System.Web.Mvc.Ajax"/>

<add namespace="System.Web.Mvc.Html"/>

<add namespace="System.Web.Routing"/>

<add namespace="RazorHelpers.Helpers"/>

</namespaces>

</pages>

</system.web.webPages.razor>

 

时间: 2025-01-30 06:35:11

ASP.NET MVC 音乐商店 - 5 通过支架创建编辑表单 续的相关文章

ASP.NET MVC 音乐商店 - 5. 通过支架创建编辑表单

转自 http://www.cnblogs.com/haogj/archive/2011/11/15/2249143.html 在上一章,我们已经从数据库获取数据,然后显示出来,这一章,我们将允许编辑数据.  创建 StoreManagerController 控制器 我们将要创建称为 StoreManager 的控制器,对于这个控制器,我们将通过使用 ASP.NET MVC3 中提供的脚手架功能来实现.在添加控制器的窗口中,注意需要选中 为"创建"."更新".&q

ASP.NET MVC Music Store教程(5):编辑表单和模板

转自http://firechun.blog.163.com/blog/static/3180452220110303730942/ 在上一章,我们加载并显示了数据,这一章中,我们将对数据进行编辑. 我们创建一个新的控制器--StoreManagerController,这个控制器支持Create和Update操作,创建控制器时,把"为Create.Update.Delete和Details方案添加操作方法"勾选上: 这将生成一个包括通用的"增删改查"方法存根的类,

ASP.NET MVC 音乐商店 - 3. 视图与模型

转自http://www.cnblogs.com/haogj/archive/2011/11/11/2244895.html 上一篇中有同学提到为什么不使用视图,而使用字符串,这一篇我们就开始使用视图来处理. 我们已经可以从控制器的 Action 中返回一个字符串,这可以帮助我们更好地理解 Controller 是如何工作的.但是对于创建一个 Web 程序来说还是不够的.下面我们使用更好的方法来生成 HTML,主要是通过模板来生成需要的 HTML,这就是视图所要做的.  增加视图模板 为了使用视

ASP.NET MVC 音乐商店 - 6. 使用 DataAnnotations 进行模型验证

转自http://www.cnblogs.com/haogj/archive/2011/11/16/2251920.html 在前面的创建专辑与编辑专辑的表单中存在一个问题:我们没有进行任何验证.字段的内容可以不输入,或者在价格的字段中输入一些字符,在执行程序的时候,这些错误会导致数据库保存过程中出现错误,我们将会看到来自数据库的错误信息. 通过为模型类增加数据描述的 DataAnnotations ,我们可以容易地为应用程序增加验证的功能.DataAnnotations  允许我们描述希望应用

ASP.NET MVC 音乐商店 - 0 概览

转自http://www.cnblogs.com/haogj/archive/2011/11/08/2241710.html 这是一个系列文章,原文内容出自微软的 MusicStore. 首先对原文内容进行了简单的翻译,以方便大家参考,另外对于其中的部分内容,也进行了简单的分析,使用的 Visual Studio 也换成了中文版,这样大家看起来也更亲切一些. 下载地址:http://mvcmusicstore.codeplex.com/   MVC 音乐店是用来介绍和展示使用 ASP.NETMV

ASP.NET MVC 音乐商店 - 10. 完成导航和站点的设计

转自 http://www.cnblogs.com/haogj/archive/2011/11/20/2255680.html 我们已经完成了网站的大部分工作,但是,还有一些添加到站点的导航功能,主页,以及商店的浏览页面. 创建购物车汇总部分视图 我们希望在整个站点的页面上都可以看到购物车中的数量.                         通过创建一个部分视图,然后添加到网站的布局中就可以容易地完成, 前面看到,在 ShoppingCart 控制器中包含了一个名为 CartSummary

ASP.NET MVC 音乐商店 - 2.控制器

转自http://www.cnblogs.com/haogj/archive/2011/11/10/2241824.html 在典型的 Web 应用中,用户请求的 URL 地址通常映射到保存在网站中的文件上,例如,当用户请求 /Products.aspx 的时候,或者 /Products.php 的时候,很可能是在通过处理 Products.aspx 或者 Products.php 文件来完成任务. ASP.NET MVC 的处理方式则不同,它没有映射到文件上,相反,将这些 URL 地址映射到类

ASP.NET MVC 音乐商店简单应用实例

我们的项目从在 Visual Studio 中的文件菜单中选择"新建",选择"项目"开始.   然后,选择 C# 中的 Web 模板组,在右边的项目模板中选择 ASP.NET MVC3 Web 应用程序,在项目的名称输入框中,输入 MvcMusicStore ,点击确定.   这时,你会到第二个对话框,允许我们设置这个项目关于 MVC 的一些设置,确认选中了"空"项目模板,视图引擎选中 Razor ,点击确定.   这样我们的项目就创建成功了!

ASP.NET MVC 音乐商店 - 7.成员管理和授权

转自http://www.cnblogs.com/haogj/archive/2011/11/18/2253140.html   目前,我们的 Store Manager 可以被任何人访问,让我们限制一下对站点管理的访问. 增加 AccountController 和 相应的视图 在全功能的 ASP.NET MVC3 Wb 应用程序与空的 ASP.NET MVC3 应用程序模板之间的区别在于,空的应用程序模板中没有包含账号控制器,我们可以从新创建的全功能的 ASP.NET MVC 应用程序中复制