【第一篇】ASP.NET MVC快速入门之数据库操做(MVC5+EF6)php
【第二篇】ASP.NET MVC快速入门之数据注解(MVC5+EF6)css
【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)html
【第四篇】ASP.NET MVC快速入门之完整示例(MVC5+EF6)前端
【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)jquery
请关注三石的博客:http://cnblogs.com/sanshi数据库
打开VS2015,找到菜单项[文件->新建->项目],打开向导对话框:bootstrap
注意咱们的选择项:浏览器
1. 运行平台:.NET FrameWork 4.5安全
2. 项目模板:ASP.NET Web Application (.NET Framework)app
3. 项目名称:AspNetMvc.QuickStart,若是你在跟着本教程练习,建议起相同的项目名称,方便直接拷贝代码到你的项目中。
点击[肯定]按钮,向导会带咱们到另外一个选择对话框:
因为本教程是快速入门,因此咱们从最简单的入手,只勾选必需的选项:
1. 不进行身份验证。ASP.NET MVC提供了完善的身份验证方案,咱们会有单独的文章讲解。
2. 仅勾选 MVC 引用。
点击[肯定],VS2015会建立一个可直接运行的项目,按下快捷键[Ctrl+F5],不调试直接运行:
默认的目录结构以下:
若是你以前在WebForms下进行开发,对其中的一些文件夹和文件应该很熟悉了:
1. Web.config:项目配置文件,里面保存项目配置参数以及数据库链接字符串。
2. packages.config:Nuget配置文件
3. Global.asax:全局代码文件,提供应用程序级别以及会话级别的事件处理函数,能够在Application_Start中注册全局变量。
4. favicon.ico:浏览器地址栏图标,在HTML的head标签中引用。
5. App_Data:放置本地数据库文件,好比LocalDB生成的数据库文件。
下面几个文件夹,用来放置静态文件,从名称就能够方便的猜出其用途:
1. Scripts:放置静态脚本文件,好比jQuery等。
2. fonts:放置图标字体文件,好比流行的FontAwesome字体等。
3. Content:放置静态文件,好比xml文件、Bootstrap的CSS库。
下面几个文件是ASP.NET MVC新引入的:
1. App_Start:用来放置应用初始化类,这个是MVC4引入的一个命名约定,其实这就是一个普通的文件夹,没有特殊的含义。
2. Controllers:控制器类。
3. Models:模型类,好比EF CodeFirst的模型定义。
4. Views:视图文件,最初的视图引擎是WebForms View Engine,使用和ASPX文件相同的语法,而如今用的Razor视图引擎是MVC3引入的,以cshtml为后缀。
首先看下 [About]页面:
这个页面之因此可以呈如今咱们眼前,经历了三个主要流程:
1. MVC的路由引擎根据URL查找相应的控制器(HomeController.cs)。
2. 控制器的操做方法About准备数据,而后传入视图Home/About.cshtml。
3. 视图准备HTML片断,放入布局页面并返回浏览器。
一切还得从Global.asax中提及,在其中的应用程序启用事件中,咱们须要注册路由处理器:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); }
RouteConfig.cs类位于App_Start文件夹中,咱们来看下内容:
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
这里注册一个名为Default的路由规则,对应的URL是{controller}/{action}/{id},这里三个占位符分别表示:
1. {controller}:控制器,默认是Home,对应的控制器类是HomeController.cs。
2. {action}:控制器里面的方法,默认是Index。因此若是用户直接经过http://localhost/访问系统时,默认调用Home控制器中的Index方法处理。
3. {id}:参数ID,可选项,这个参数对应于操做方法中的id参数。
经过上面的介绍,咱们就知道了http://localhost:55654/Home/About网址对应于Home控制器的About方法。
咱们在Controllers/HomeController.cs中找到相应的方法:
public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); }
ViewBag是一个动态对象(dynamic),能够用来存储任意参数,用来从控制器向视图传递数据。
从控制器向视图传递数据通常有两种方法:
1. 传入模型,而后在视图中经过Model对象访问,这是一种强类型的方式,也是推荐的作法。其局限性就是只能传入一个模型,若是须要传入多个模型对象,就须要自定义类来包含多个模型,另外一种方法就是ViewBag。
2. ViewBag,视图包传递数据很是方便,可是在视图中可能须要进行强制类型转换。在常见的传入一个主模型和多个次模型时,能够把屡次模型放到ViewBag中,从而避免自定义类的麻烦。
做为命名约定,这个操做方法会自动调用相应名称的视图文件About.cshtml。
下面来看About.cshtml视图文件:
@{ ViewBag.Title = "About"; } <h2>@ViewBag.Title.</h2> <h3>@ViewBag.Message</h3> <p>Use this area to provide additional information.</p>
以@开头用来输出C#代码的运行结果,MVC会自动判断于何处结束C#代码,并转入HTML代码。
须要注意,页面第一行的@{ }用来执行一段C#代码,不会输出内容,这里定义了一个ViewBag.Title的变量,并在下面的代码中使用@ViewBag.Title输出到页面中。
不少初学者可能有些疑惑,为啥控制器中定义了ViewBag.Message,而在视图中定义了ViewBag.Title,这二者有啥区别?
通常来讲是没有功能的区别,仅仅是语义的区别。在视图中定义的变量仅在视图中使用,好比这里定义的ViewBag.Title不只在About.cshtml中使用,并且在布局视图Shared/_Layout.cshtml中也用到了。
布局视图相似于WebForms中的母版页,具体的视图页面会做为一部分嵌入到布局视图中,而后返回到浏览器造成一个完整的页面。
每个视图页面默认会使用Views/_ViewStart.cshtml中的定义的内容:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
这里面指定了布局视图的位置,咱们来简单看下布局视图的内容:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Contact", "Contact", "Home")</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
其中head标签下面的title中使用了在About视图中定义的ViewBag.Title属性。
这个布局视图使用Bootstrap库定义的CSS样式来完成,包含标题栏,导航菜单,以及页脚的定义,具体的内容会嵌入@RenderBody()的地方,最终造成完整的HTML页面返回。
上面从控制器传入视图的数据是硬编码的一个字符串,实际项目中则常常须要从数据库中读取数据,咱们使用微软推荐的Entity Framework CodeFirst开发模式来建立和使用数据库。
首先须要安装EF,在VS2015中找到[工具]菜单,而后找到NuGet包管理器:
转到[浏览]选项卡,能够搜索Entity Framework,安装其最新稳定版到项目中:
安装后,会自动更改Web.config添加相应的配置信息。
咱们计划完成一个简单的学生管理系统,包含基本的增删改查(CRUD)。
首先在Models文件,建立学生(Student)的模型类:
public class Student { public int ID { get; set; } public string Name { get; set; } public int Gender { get; set; } public string Major { get; set; } public DateTime EntranceDate { get; set; } }
而后建立数据库操做上下文,EF须要这个文件来建立和访问数据库:
public class StudentDbContext : DbContext { public DbSet<Student> Students { get; set; } }
因为这个类继承自EF的DbContext基类,所以须要在文件头部添加以下引用:
using System.Data.Entity;
建立完这两个文件,须要从新编译项目(快捷键Ctrl+Shift+B),不然下面添加控制器时会出错。
在Controllers目录上点击右键,添加控制器,弹出向导对话框:
这里选择 MVC 5 Controller with views, using Entity Framework,而后进入设置对话框:
在这个对话框中,咱们须要指定刚才建立的模型类(Student)和数据访问上下文类(StudentDbContext),而后VS不只能够自动建立视图,并且使用EF自动建立CRUD的所有代码,是否是很酷!
是否是很惊奇,咱们甚至没来得及写视图代码,没有配置数据库,没有写CRUD的逻辑代码,VS模板帮咱们生成了一切,如今运行一下(Ctrl+F5),并在浏览器中输入/Students:
表格页面对应于Students控制器下的Index操做方法:
public class StudentsController : Controller { private StudentDbContext db = new StudentDbContext(); // GET: Students public ActionResult Index() { return View(db.Students.ToList()); } }
首先,咱们看到控制器内部定义了一个私有变量db,并进行初始化。这是数据库操做上下文实例,全部的CRUD操做都讲依赖于这个实例。
在Index方法中,经过向View方法传递学生列表的方式,把模型数据传递到了视图,在Views/Students/Index.cshtml视图文件中,咱们声明了传入模型的类型:
@model IEnumerable<AspNetMvc.QuickStart.Models.Student>
在视图中,Model属性的类型就肯定为强类型IEnumrable<Student>,配合VS提供的智能感知,不只能够快速编写代码,而且在编译时还检查代码的有效性。
完整的Index.cshtml代码:
@model IEnumerable<AspNetMvc.QuickStart.Models.Student> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table class="table"> <tr> <th> @Html.DisplayNameFor(model => model.Name) </th> <th> @Html.DisplayNameFor(model => model.Gender) </th> <th> @Html.DisplayNameFor(model => model.Major) </th> <th> @Html.DisplayNameFor(model => model.EntranceDate) </th> <th></th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.Gender) </td> <td> @Html.DisplayFor(modelItem => item.Major) </td> <td> @Html.DisplayFor(modelItem => item.EntranceDate) </td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | @Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) </td> </tr> } </table>
看着颇有古老的ASP的感受吧,不过这里的Model属性是强类型的,所以在foreach循环中,VS明确知道item类型是Student,从而方便代码编写:
@Html里面都是MVC提供的辅助方法,用来辅助生成HTML代码:
1. ActionLink:用来生成超连接,连接到本控制器内的某个操做方法(也能够是其余控制器的方法,有重载函数),能够指定路由参数,经过对象初始化语法来建立,好比new {id=item.ID}。
2. DisplayNameFor:显示模型属性的名称。强类型辅助方法,容许咱们使用一个lambda表达式来指定某个模型属性,而不用写字符串。好处不只有智能感知,编译时检查,并且也方便代码重构,好比咱们在更改模型的属性名称时,视图中的相应代码也会改变。
3. DisplayFor:显示模型属性的值。
新增页面对应于Students控制器下的Create操做方法:
// GET: Students/Create public ActionResult Create() { return View(); }
对应的视图文件:
@model AspNetMvc.QuickStart.Models.Student @{ ViewBag.Title = "Create"; } <h2>Create</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Student</h4> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) </div> </div> @* 省略 Gender Major EntranceDate *@ <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" /> </div> </div> </div> } <div> @Html.ActionLink("Back to List", "Index") </div> @section Scripts { @Scripts.Render("~/bundles/jqueryval") }
首先定义了视图中使用的模型类型是Student,这样LabelFor强类型辅助方法就能够从模型元数据中获取须要显示的文本。
页面打开时,因为并未传入任何模型对象,因此Model为空对象,以下所示:
因此页面上默认的输入框都是空的,截图中是做者输入值后的效果。
Html.BeginForm()会在页面上生成一个form标签,默认的提交地址仍是当前页面(action=/Students/Create),默认的请求方法是post,以下所示:
所以,点击[Create]按钮时,会发出一个POST请求到后台,对应于Students控制器的Create方法。
下面咱们来看下拥有[HttpPost]元数据的Create方法:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "ID,Name,Gender,Major,EntranceDate")] Student student) { if (ModelState.IsValid) { db.Students.Add(student); db.SaveChanges(); return RedirectToAction("Index"); } return View(student); }
这里面有两个安全措施:
1. ValidateAntiForgeryToken:用来阻止CSRF(跨站请求伪造)。
2. Bind:用来阻止Over-Posting(过多提交攻击)。
这两个安全手段咱们会在之后的文章中详细介绍,这里就先略过。
咱们先看下本次请求的POST参数:
可是Create方法中只有一个Student对象参数,是否是很神奇,其实这是一个重要的概念模型绑定。
若是在WebForms中,咱们能够会写一堆代码来从Request.Form中获取参数,并重建Student对象,相似以下代码:
Student student = new Student(); student.Name = Request.Form["Name"]; student.Gender = Convert.ToInt32(Request.Form["Gender"]); ....
在MVC中,这一过程是自动完成,简单来讲这就是模型绑定。
可是实际的模型绑定过程,不只在请求的表单数据中查找,还会在路由参数,URL查询字符串,以及Cookie中查找。
若是模型绑定失败(好比模型参数不符合验证规则),则ModelState.IsValid就为false,这时会直接返回页面内容,此时模型对象student中保存的是用户输入的值,前端也会有错误提示,这个过程咱们会在下一篇文章中讲解。
若是模型绑定成功,则保存新增数据,而后经过RedirectToAction来重定向到表格页面:
这篇文章首先介绍了VS2015下MVC项目的建立过程;而后简要概述页面执行的流程,从路由引擎到控制器,再由控制器到视图,最后由视图返回到浏览器,而模型是做为控制器传入视图的参数,这样清晰明了;最后使用VS提供的模板,建立了一个带CRUD操做的数据访问实例。
EF CodeFirst让咱们的关注点从数据库转移到了模型,而模型又是MVC的核心所在,对模型进行恰当的数据注解,不只会影响数据库的表结构,并且会影响浏览器端的数据验证和服务端的数据验证,所以下一篇文章咱们会详细介绍一下数据注解。