在这一章节中,我们将创建一个新的MoviesController类,写代码获取movie数据并用视图模板将它们显示到浏览器中。
在我们进行下一操作之前先Build the application。如果你没有编译该应用程序,我们添加一个controller时候编译器会报错。
在Solution Explorer,在Controllers文件夹上右击,点击Add, 然后选择Controller.
在Add Scaffold对话框中,选择MVC 5 Controller with views, using Entity Framework, 然后点击Add.
- 给Controller命名为 MoviesController.
- 给Model Class选择Movie(MvcMovie.Models).
- 给Data context类选择MovieDBContext(MvcMovie.Models).
完成后的对话框显示如下:
点击Add.(如果你得到错误,很有可能是在添加controller的时候没有编译.)到此,VS帮你创建了如下文件和文件夹:
- 在Controllers文件夹下创建了一个MovieController.cs文件。
- 创建了一个新的Views\Movies文件夹。
- 在Views\Movies文件夹下创建了Create.cshtml, Delete.cshtml, Details.cshtml, Edit.cshtml和Index.cshtml文件。
此时VS自动给你创建好了CRUD(Create, Read, Update and Delete)action方法和视图(这些自动创建号的CRUD action方法和视图就被作为是scaffolding).现在你已经有了一个能够让你添加,删除,修改,查看Movie实体的全功能Web应用程序了。
运行应用程序,点击MVC Movie链接(或者通过在你的浏览器地址栏里追加/Movies来浏览Movies控制器)。因为你的应用程序依赖于默认的路由配置(定义在App_Start\RouteConfig.cs文件里),浏览器向服务器请求http://localhost:xxxx/Movies,结果被路由到了Movies controller中默认的Index方法中。换句话说,浏览器请求的http://localhost:xxxx/Movies 和请求http://localhost:xxxx/Movies/Index 的效果是一样的。结果是一个空的Movies列表,因为你并没有添加任何Movie.
1. 创建一个Movie
选择Create New链接,输入给movie输入一些详细信息,然后点击Create按钮。
注意:
在Price字段,你也许没有输入小数点(‘.‘)或者逗号(‘,‘).为了给用逗号(‘,‘)替代小数点,用非美式的日期格式的非英语环境支持JQuery验证,你必须保护globalize.js和具体的cultures/globalize.culture.js文件(可以从https://github.com/jquery/globalize获得),并且在Javascript使用Globalize.parseFloat方法。在下面的章节中我将向你显示如何操作。至此,我们仅输入10。
点击Create按钮将导致该表单提交到服务器,也就是movie信息被保存进数据库的地方。然后你将被重定向到/Movies URL, 此时你就可以在列表中看到你新添加的movie了。
创建更多的movie实体,尝试Edit, Details, 和Delete的功能能不能起作用。
2. 检查产生的代码
打开Controller\MoviesController.cs文件,检查产生的Index方法。movie controller中的Index方法的部分代码显示如下:
1 public class MoviesController : Controller 2 { 3 private MovieDBContext db = new MovieDBContext(); 4 5 // GET: /Movies/ 6 public ActionResult Index() 7 { 8 return View(db.Movies.ToList()); 9 }
一个要求返回Movies数据表中的所有项,然后把结果传递给Index视图的请求发向Movies controller.下面的行来自于MoviesController类,作用是实例化一个movie数据上下文。在query,edit和delete Movies时你会用到这个数据上下文实例。
1 private MovieDBContext db = new MovieDBContext();
3. 强类型Models和@model关键字
在这本教程的早期,你看到我们如何使用ViewBag对象将数据从一个controller当中传递给视图模板。ViewBag是一个动态类型,能够提供一种方便后期邦定的方式将数据信息传递给视图。
MVC也有这种能力,就是将一个强类型对象传递给视图模板。强类型方式能够更好的在编译时检查你的代码,并在VS编译器中提供更丰富的智能感知能力。VS中的scaffolding机制当他在MoviesController类中创建方法和视图的时候也是使用这种方式。
在Controllers\MoviesController.cs文件检查Details方法,Details方法内容如下:
1 public ActionResult Details(int? id) 2 { 3 if (id == null) 4 { 5 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 6 } 7 Movie movie = db.Movies.Find(id); 8 if (movie == null) 9 { 10 return HttpNotFound(); 11 } 12 return View(movie); 13 }
id参数被作为路由数据来传递,例如:http://localhost:xxxx/movies/details/1 将设置controller为movie controller,阿action方法为details和id为‘1‘.你也可以使用如下的query string来传递:
http://localhost:xxxx/movies/details?id=1
如果一个movie被找到了, Movie模型的实例就会被传递给Details视图:
1 return View(movie);
检查Views\Movies\Details.cshtml文件中的内容:
1 @model MvcMovie.Models.Movie 2 3 @{ 4 ViewBag.Title = "Details"; 5 } 6 7 <h2>Details</h2> 8 9 <div> 10 <h4>Movie</h4> 11 <hr /> 12 <dl class="dl-horizontal"> 13 <dt> 14 @Html.DisplayNameFor(model => model.Title) 15 </dt> 16 @*Markup omitted for clarity.*@ 17 </dl> 18 </div> 19 <p> 20 @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) | 21 @Html.ActionLink("Back to List", "Index") 22 </p>
通过在视图文件顶部添加@model,你就可以给视图添加你所期望的对象类型。当你创建一个movie controller的时候,VS将自动把@model语句包含到Details.cshtml文件的顶部。
1 @model MvcMovie.Models.Movie
这@model能够使你将controller中的movie使用强类型的Model对象传递给视图。例如,在Details.cshtml模板中,通过强类型的Model对象给movie的每一个字段的值传入给DisplayNameFor和DisplayFor HTML Helpers。在Create和Edit方法与相应的视图模板也传递了一个强类型的movie model对象。
检查Index.cshtml视图模板和MoviesController.cs文件中的Index方法。注意:当在Index action方法中调用View的Helper方法时如何用代码创建一个List对象。这段代码能够将Movies列表从Index方法传递给视图。
1 public ActionResult Index() 2 { 3 return View(db.Movies.ToList()); 4 }
当你创建一个movie controller的时候,VS将自动的下面的@model语句包含到Index.cshtml文件顶部:
1 @model IEnumerable<MvcMovie.Models.Movie>
@model表明允许你能够访问通过使用Model对象(强类型)从Controller传递到View中的movies列表信息。例如:在Index.cshtml模板,通过对强类型的Model对象使用foreach语句,遍历movies。
1 @foreach (var item in Model) { 2 <tr> 3 <td> 4 @Html.DisplayFor(modelItem => item.Title) 5 </td> 6 <td> 7 @Html.DisplayFor(modelItem => item.ReleaseDate) 8 </td> 9 <td> 10 @Html.DisplayFor(modelItem => item.Genre) 11 </td> 12 <td> 13 @Html.DisplayFor(modelItem => item.Price) 14 </td> 15 <th> 16 @Html.DisplayFor(modelItem => item.Rating) 17 </th> 18 <td> 19 @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | 20 @Html.ActionLink("Details", "Details", { id=item.ID }) | 21 @Html.ActionLink("Delete", "Delete", { id=item.ID }) 22 </td> 23 </tr> 24 }
因为Model对象是强类型(实际上是IEumerable<Movie>对象),在循环中的每一个item对象就是一个Movie。另外几个好处是,意味着你可以编译时检查代码和在代码编译器中有富智能提示的支持。
4. 与SQL Server LocalDB的协同合作
EF框架中的Code First检测用来指示Movies DB的数据库连接串实际上并不存在,所以Code First自动创建了这个数据库。你可以验证一下该数据库在App_Data文件夹下并没有被创建。如果你没有看到Movies.mdf文件,可以在Solution Explorer工具栏上点击Show All Files, 再点击Refresh按钮,然后再打开App_Data文件夹。
双击Movies.mdf打开SERVER EXPLORER,然后打开Tables文件夹来查看Movies数据表。默认的情况下主键的图标临近ID,EF将是命名为ID的属性作为主键。如果想获得更多的关于EF和MVC的信息,请查看教程MVC and EF.
在Movies表上右击,选择Show Table Data来查看你所创建的数据。
在Movies表上右击,选择Open Table Definition来查看EF框架通过Code First给你创建好的表的结构。
注意:
Movies表的架构是如何印射到你刚才创建的Movie类的。EF框架将自动的根据你的Movie类创建者中架构。
当你完成这些操作的时候,通过在MovieDBContext上右击,选择Close Connection来关闭数据库的连接。(如果你没有关闭这个连接,当你下次再运行这个项目的时候程序会报错)
到此为止,你已经有了一个能够进行增、删、改查的数据库和页面了。在下面的教程中,我们将检查scaffolded代码并添加一个SearchIndex方法和SearchIndex视图以便能够让你在数据库中查询movies。想了解能够信息,请查看Creating an Entity Framework Data Model for an ASP.NET MVC Application