MVC模型
一、构建基架。
MVC中的基架可以为应用程序提供CURD各种功能生成所需要的样板代码。在添加控制器的时候可以选择相应的模板以及实体对象来生成相应的模板代码。
首先定义一个模型类如下所示:
namespace LYG.HelloWorld.Models { public class Album { public virtual int AlbumId { get; set; } public virtual string Title { get; set; } public virtual decimal Price { get; set; } public virtual Artist Artist { get; set; } } public class Artist { public virtual int ArtistId { get; set; } public virtual string Name { get; set; } } }
然后选择添加控制器,选择相应的基架,这里列出来的有好多种不同的基架。
再点下一步选择相应的模型和数据上下文,如下图所示,然后点添加按钮。
这样在生成的控制器中会生成CURD的各种操作代码以及视图文件也会同时生成,大大简化了工作量,提高了工作效率。这里因为刚接触基架还不明白各种基架的优缺点,后续将单独进行学习比较,选择适合自己项目的基架。
二、基架和实体框架。
1、代码优先约定;
开发变得更轻松,通过代码的方式来产生需要存储的数据结构。
2、DbContext类;
当使用代码优先开发方式时,需要使用EF的DbContext类派生出一个类来访问数据库。这个类有一个或多个DbSet<T>的属性。每一个T表示要持久的对象。如:
public class MusicStoreDB:DbContext { public MusicStoreDB():base("DefaultConnection") { } public DbSet<Album> albums { get; set; } public DbSet<Artist> artists { get; set; } 然后控制器如下所示访问数据库: var db = new MusicStoreDB(); var allAlbums = from album in db.albums orderby album.Title ascending select album; return View(allAlbums.ToList()); }
最后视图读取数据:
@model IEnumerable<LYG.HelloWorld.Models.Album> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table class="table"> <tr> <th> @Html.DisplayNameFor(model => model.Title) </th> <th> @Html.DisplayNameFor(model => model.Price) </th> <th></th> </tr> @foreach (var item in Model) { <tr> <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>
三、初始化数据库
在开发过程中经常变更数据结构,如果想要重新生成新的数据结构字段,需要初始化数据库,可以在Global.asax.cs文件中增加如下代码:
Database.SetInitializer(new DropCreateDatabaseAlways<MusicStoreDB>());
这样每次启动应用程序时都会重新构建数据,但这样会存在一个问题,有部分初始化的基础数据都会清空,因此便于测试,需要进行数据库播种。如下代码所示:
public class MusicStoreDBInitializer: DropCreateDatabaseAlways<MusicStoreDB> { protected override void Seed(MusicStoreDB context) { context.artists.Add(new Artist { Name="李小卫"}); context.albums.Add(new Album { Title="汪峰2018演唱会", Price=, Artist= new Artist { Name = "李小卫" } }); base.Seed(context); } }
Global.asax.cs中增加如下代码:
Database.SetInitializer(new MusicStoreDBInitializer());
注意这里本人测试结果是执行到删除数据库的时候提示数据库正在使用,然后删除异常,还未找到原因。这是程序抛出的异常:Cannot drop database "MusicStoreDB" because it is currently in use.
四、模型绑定
以前asp.net webform的通用写法是通过Request.Form[“Title”]类似这样获取传输过来的参数值。如果表单字段类型过多,感觉就会变得冗长泛味。Asp.net MVC可以通过表单元素的命名与模型实体的名称相同,这样就可以通过一个实体参数来获取所传输过来的所有字段类型。
1、默认模型绑定DefaultModelBinder,代码如下:
[HttpPost] //注意这里的参数是通过album中的属性与视图表单中的元素命名一致的控件传输过来的参数值。 public ActionResult Edit(Album album) { if (ModelState.IsValid) { musicDB.Entry(album).State = EntityState.Modified; musicDB.SaveChanges(); return RedirectToAction("Index"); } return View(album); }
注意通过这种模型绑定器会绑定所有album中的参数,这样会增加“重复提交”攻击的风险,可以设置一两个属性不使用模型绑定器来设置,将在后面的学习中学习到,需要牢记这个威胁。
2、显示模型绑定UpdateModel,如果模型无效UpdateModel会抛出一个异常来,代码如下:
[HttpPost] public ActionResult Edit() { var album = new Album(); //注意声明一个实例 try { UpdateModel(album); //显示模型绑定 musicDB.Entry(album).State = EntityState.Modified; musicDB.SaveChanges(); return RedirectToAction("Index"); } catch { return View(album); } }
3、显示模型绑定TryUpdateModel,如果模型无效UpdateModel不会抛出一个异常来,但会返回true或false来表示模型是否有效,代码如下:
[HttpPost] public ActionResult Edit() { var album = new Album();//注意声明一个实例 If(TryUpdateModel(album)) //显示模型绑定 { musicDB.Entry(album).State = EntityState.Modified; musicDB.SaveChanges(); return RedirectToAction("Index"); } else { return View(album); } }
模型绑定的副产品就是模型状态,因此也可以这样写:
[HttpPost] public ActionResult Edit() { var album = new Album();//注意声明一个实例 TryUpdateModel(album) If(ModelState.IsValid) //显示模型绑定 { musicDB.Entry(album).State = EntityState.Modified; musicDB.SaveChanges(); return RedirectToAction("Index"); } else { return View(album); } }
模型知识到此就学习完了,接下来学习模型状态如何使用HTML辅助方法、MVC验证特性和模型绑定一起工作。