上一篇VS帮我们创建了简单的操作页面,实现了CRUD功能,但是具体是怎样实现的,本篇试着分析一下。
1.视图(以Create视图为例):
class="code_img_closed" src="/Upload/Images/2014110510/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('829b731a-e566-4702-85ce-e43e507f2581',event)" src="/Upload/Images/2014110510/2B1B950FA3DF188F.gif" alt="" />1 @* 说明:此段话左右两端括起来的部分表示注释 *@ 2 3 @* 下面的@model表示利用强类型的方法来将数据或对象传递到视图模板中 *@ 4 5 @* @前缀表示HTML与代码之间的转换 *@ 6 7 @model Guestbook.Models.GuestbookEntry 8 9 @{ 10 ViewBag.Title = "Create"; 11 } 12 13 <h2>Create</h2> 14 15 @*Html.BeginForm 用来构建表单*@ 16 17 @using (Html.BeginForm()) 18 { 19 @Html.AntiForgeryToken() @*@Html.AntiForgeryToken 防止跨站请求伪造*@ 20 21 <div class="form-horizontal"> 22 <h4>GuestbookEntry</h4> 23 <hr /> 24 @Html.ValidationSummary(true) @*@Html.ValidationSummary 显示验证消息*@ 25 26 <div class="form-group"> 27 @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" }) @*创建一个Label*@ 28 <div class="col-md-10"> 29 @Html.EditorFor(model => model.Name) @* 创建一个编辑框 此编辑框输入的内容即是GuestbookEntry中Name字段对应的值 *@ 30 @Html.ValidationMessageFor(model => model.Name) @* Name字段的验证 *@ 31 </div> 32 </div> 33 34 <div class="form-group"> 35 @Html.LabelFor(model => model.Message, new { @class = "control-label col-md-2" }) 36 <div class="col-md-10"> 37 @Html.EditorFor(model => model.Message) 38 @Html.ValidationMessageFor(model => model.Message) 39 </div> 40 </div> 41 42 <div class="form-group"> 43 @Html.LabelFor(model => model.DateAdded, new { @class = "control-label col-md-2" }) 44 <div class="col-md-10"> 45 @Html.EditorFor(model => model.DateAdded) 46 @Html.ValidationMessageFor(model => model.DateAdded) 47 </div> 48 </div> 49 50 <div class="form-group"> 51 <div class="col-md-offset-2 col-md-10"> 52 <input type="submit" value="Create" class="btn btn-default" /> 53 </div> 54 </div> 55 </div> 56 } 57 58 <div> 59 @Html.ActionLink("Back to List", "Index") 60 </div> 61 62 @section Scripts { 63 @Scripts.Render("~/bundles/jqueryval") 64 }View Code
2.控制器:
1 namespace Guestbook.Controllers 2 { 3 public class GuestbookController : Controller 4 { 5 private GuestbookContext db = new GuestbookContext(); 6 7 // GET: /Guestbook/ 8 public ActionResult Index() 9 { 10 return View(db.Entries.ToList()); 11 } 12 13 // GET: /Guestbook/Details/5 14 public ActionResult Details(int? id) 15 { 16 if (id == null) 17 { 18 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 19 } 20 GuestbookEntry guestbookentry = db.Entries.Find(id); 21 if (guestbookentry == null) 22 { 23 return HttpNotFound(); 24 } 25 return View(guestbookentry); 26 } 27 28 // GET: /Guestbook/Create 29 public ActionResult Create() 30 { 31 return View(); 32 } 33 34 // POST: /Guestbook/Create 35 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 36 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 37 [HttpPost] 38 [ValidateAntiForgeryToken] 39 public ActionResult Create([Bind(Include="Id,Name,Message,DateAdded")] GuestbookEntry guestbookentry) 40 { 41 if (ModelState.IsValid) 42 { 43 db.Entries.Add(guestbookentry); 44 db.SaveChanges(); 45 return RedirectToAction("Index"); 46 } 47 48 return View(guestbookentry); 49 } 50 51 // GET: /Guestbook/Edit/5 52 public ActionResult Edit(int? id) 53 { 54 if (id == null) 55 { 56 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 57 } 58 GuestbookEntry guestbookentry = db.Entries.Find(id); 59 if (guestbookentry == null) 60 { 61 return HttpNotFound(); 62 } 63 return View(guestbookentry); 64 } 65 66 // POST: /Guestbook/Edit/5 67 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 68 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 69 [HttpPost] 70 [ValidateAntiForgeryToken] 71 public ActionResult Edit([Bind(Include="Id,Name,Message,DateAdded")] GuestbookEntry guestbookentry) 72 { 73 if (ModelState.IsValid) 74 { 75 db.Entry(guestbookentry).State = EntityState.Modified; 76 db.SaveChanges(); 77 return RedirectToAction("Index"); 78 } 79 return View(guestbookentry); 80 } 81 82 // GET: /Guestbook/Delete/5 83 public ActionResult Delete(int? id) 84 { 85 if (id == null) 86 { 87 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 88 } 89 GuestbookEntry guestbookentry = db.Entries.Find(id); 90 if (guestbookentry == null) 91 { 92 return HttpNotFound(); 93 } 94 return View(guestbookentry); 95 } 96 97 // POST: /Guestbook/Delete/5 98 [HttpPost, ActionName("Delete")] 99 [ValidateAntiForgeryToken] 100 public ActionResult DeleteConfirmed(int id) 101 { 102 GuestbookEntry guestbookentry = db.Entries.Find(id); 103 db.Entries.Remove(guestbookentry); 104 db.SaveChanges(); 105 return RedirectToAction("Index"); 106 } 107 108 protected override void Dispose(bool disposing) 109 { 110 if (disposing) 111 { 112 db.Dispose(); 113 } 114 base.Dispose(disposing); 115 } 116 } 117 }View Code
从上面的代码中我们可以看到Create和Edit方法均有两个重载[其实Delete方法也有两个重载,只是由于这两个方法具有类型和个数相同的参数另一个被命名为DeleteConfirmed,然后添加ActionName("Delete")注解表示负责处理Delete视图的动作]。两个同名的方法一个在加载时渲染视图,另一个处理视图的动作(用HttpPost注解属性修饰)。
3.布局:
有没有感觉我们的CRUD页面使用了Master Page之类的东西,是的,默认布局为Views\Shared\_Layout.cshtml,代码如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>@ViewBag.Title - My ASP.NET Application</title> 7 @Styles.Render("~/Content/css") 8 @Scripts.Render("~/bundles/modernizr") 9 10 </head> 11 <body> 12 <div class="navbar navbar-inverse navbar-fixed-top"> 13 <div class="container"> 14 <div class="navbar-header"> 15 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> 16 <span class="icon-bar"></span> 17 <span class="icon-bar"></span> 18 <span class="icon-bar"></span> 19 </button> 20 @Html.ActionLink("Application name", "Index", "Home", null, new { @class = "navbar-brand" }) 21 </div> 22 <div class="navbar-collapse collapse"> 23 <ul class="nav navbar-nav"> 24 <li>@Html.ActionLink("Home", "Index", "Home")</li> 25 <li>@Html.ActionLink("About", "About", "Home")</li> 26 <li>@Html.ActionLink("Contact", "Contact", "Home")</li> 27 </ul> 28 @Html.Partial("_LoginPartial") @*渲染一个部分视图*@ 29 </div> 30 </div> 31 </div> 32 <div class="container body-content"> 33 @RenderBody() @*待渲染的页面内容*@ 34 <hr /> 35 <footer> 36 <p>© @DateTime.Now.Year - My ASP.NET Application</p> 37 </footer> 38 </div> 39 40 @Scripts.Render("~/bundles/jquery") 41 @Scripts.Render("~/bundles/bootstrap") 42 @RenderSection("scripts", required: false) 43 </body> 44 </html>View Code
那么视图和默认布局是怎样关联起来的呢,答案就在Views\_ViewStart.cshtml中:
1 @{ 2 Layout = "~/Views/Shared/_Layout.cshtml"; 3 }View Code
_ViewStart会在所有视图被执行之前执行,它设定了默认的布局,如果视图没有特别指定Layout的话,就会使用这个预设布局。