MVC建立 登录 详细步骤
0.新建文件夹,规划好代码摆放位置
1)根目录下新建一个 ViewModels文件夹。
Models文件夹里面存放对应于数据库表的实体。
View中需要显示的数据和Models中实体模型不一定能对应上, 因此需要专门给View使用的自定义数据模型,我们称之为ViewModel , 放在ViewModels文件夹里面。
2)根目录下新建一个DAL 文件夹。
DAL 放置数据访问相关类。 本文中放AccountContext.cs, AccountInitializer.cs
1.打开上次项目,新建两个Action
本系列文章知识点和演示代码都以前一篇文章为基础,有问题可以回上一篇进行查找。本次我们将会新建用户 注册/登录 的两个页面。
打开Controllersà AccountController.cs ,仿照已有的Index, 添加两个Action, 如下图。
NOTE: 添加这Action可以
a. 通过手打或粘贴复制,
b.右键,插入代码段(或ctrl k, x)→ASP.NET MVC4→mvcaction4(或mvcpostaction4), 如下面一组图。
2.添加Action相应的View
根据上一步中添加的Action, 添加相关View: Login.cshtml, Register.cshtml
添加方法详见上篇文章,不再重复讲解。
这里再说明下View的存放位置约定。记住下面三句话:
1)所有的View都放在Views文件夹
2)Views文件夹创建了一系列与Controller同名的子文件夹
3)各子文件夹内存放与Action同名的cshtml文件(对应的View文件)
3.完成登录界面UI
我们把Login.cshtml就当做一个静态html页面,完成登录界面的UI,大家可以把cshtml理解成原来的aspx和html的混合体:利用了aspx的优点,方便和后台交互;利用了html的优点,语法简洁(HtmlHelper)。
1)到bootstrap上复制个登录界面html
http://v3.bootcss.com/css/#forms
2)放到Login.cshtml 的body的div中
右键浏览器 View page source, 发现多了VS Browser Link废代码。
我们将它禁用掉。
打开web.config添加如下代码,再去浏览器查看源代码,可以看到纯净的html了。
4.完成注册界面UI(类似登录界面,步骤略)
5.添加EF引用
右击项目->管理Nuget 包。选择Entity Framework 并点击安装。
6.创建连接字符串(ConnectionString)
打开Web.Config 文件,在< Configuration >标签内添加以下代码:
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<addname="AccountContext"connectionString="user id=sa;password=sasa;initial catalog=MVC;data source=.\SQLexpress"providerName="System.Data.SqlClient" />
</connectionStrings>
。。。。
</configuration>
7. 创建Model 类
在Models文件夹下新建Account类,代码如下。
对于上面的类的约定和说明:EF生成数据库时,ID 属性将会成为主键。(约定:EF默认会将ID或classnameID生成主键, MSDN建议保持风格的一致性, 都用ID或classnameID, 我们这里都用ID)
8.创建 Database Context
前置条件:安装EF
从上图可以看出,EF框架在底层是通过调用ADO.NET来实现数据库操作的。
在DAL文件夹下创建类 AccountContext.cs , 让他继承自System.Data.Entity.DbContext, 我们用这个类完成EF的功能。
主要做下面三件事:
1)为每个entity set创建一个DbSet
在EF中,通常情况下一个entity set对应数据库中的一张表,一个entity对应表中的一行。
2)指定一个连接字符串
构造函数中的 base("AccountContext") 。
默认情况下和类名一样,即AccountContext,我们显式的给他指定出来。
3)指定单数形式的表名
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();默认情况下会生成复数形式的表,如SysUsers
此行代码,需引入命名空间:
using System.Data.Entity.ModelConfiguration.Conventions;
NOTE 表名用单复数形式看各自的习惯,没有明确的规定。有的公司表名全用单数,有的公司根据表的意思,有单数也有复数。
9.创建Initializer, 使用EF初始化数据库,插入示例数据
EF可以以多种方式建立数据库。
我们采用如下方式:
第一次运行程序时新建数据库,插入测试数据; model改变(和database不一致)时删除重建数据库,插入测试数据。目前在开发阶段,不用管数据丢失的问题,直接drop and re-create
1)下面我们就新建类AccountInitializer.cs来完成这个工作。
Seed方法用我们之前定义的database context(即AccountContext) 作为参数,通过这个context将entities添加到database中去。(就是我们前面说的桥梁作用)
从上面代码可以看出, Seed方法对每一个entity的类型(我们用了Account):
创建一个colletion → 添加到适当的 DbSet property →保存到数据库。
NOTE 不一定要在每个entity组后面都调用SaveChanges方法,可以在所有组结束后调用一次也可以。这样做是因为如果写入数据库代码出错,比较容易定位代码的错误位置。
2)修改web.config, 通知EF使用我们刚刚写好的initializer类。
找到entityFramework配置节,添加下图方框处内容。
context 配置节中, type 的值对应 (context class的完整描述,程序集)
databaseInitializer 配置节中 , type 的值对应 (initializer class 的完整描述,程序集)
如果你不想EF使用某个context, 可以将下面方框处设置为true.
10.连接数据库
打开Controllers à AccountController.cs
Instantiate 一个database context 对象
11.打开Login.cshtml, 修改form,为后端接收数据做准备。
1)先在form标签内增加两个属性action, method。
对于form中的method(默认是get),通常情况下, get用于简单的读取数据操作,post用于写数据操作。
2)在input元素下添加name属性
设置成和models下的类的字段名一致。NOTE: 服务器端需要通过name来取值。
3)前台加个登陆状态文字标识。
12.首先我们先去AccountController.cs中创建一个Login同名的Action来接受表单提交的数据。
注意新添加的Action中增加了一个[HttpPost] ,表示这个Action只会接受http post请求。ASP.NET MVC提供了Action Method Selector, HttpPost就是其中之一。
HttpPost属性典型的应用场景:
涉及到需要接受客户端窗口数据的时候,创建一个用于接收HTTP Get请求的Action, 用于显示界面, 提供给用户填写数据;
另一个同名Action则应用[HttpPost]属性,用于接收用户发来的数据,完成对应的功能。
13.打开AccountController.cs,修改[HttpPost]的Login Action,查询数据库进行比对,查看邮箱、密码是否正确。
14.运行程序
打开数据库,发现MVC这个数据库已经新建,示例数据已经插入。
知识点:
1)Controller与 View之间的值传递---ViewBag
控制器Controller里定义:
ViewBag.LoginState = "成功";
View Login.cshtml里输出:
@ViewBag.LoginState
注:LoginState是自定义的名字,可随意,但要前后匹配
2)页面跳转
常用的两种方法
RedirectToAction(“ActionName”);
RedirectToAction(“ActionName”, "ControllerName");
注意对应的Controller、Action要存在。
3)EF的数据查询
EF数据查询用LINQ实现(LINQ to Entities),通常有表达式和函数式两种方式。建议用函数式方式,比较简单。
假设我们已经定义好了context
private AccountContext db = new AccountContext();
[基本查询] 查询所有的SysUser
var users = db.Accounts; //函数式方式
[条件查询] 加入查询条件
var users = db.Accounts.Where(u => u.Email == "[email protected]"); //函数式方式
NOTE 注意这边等号是C#写法 : " == "
[排序和分页查询]
var users = db.Accounts.OrderBy(u => u.Email).Skip(0).Take(5); //函数式方式
NOTE 只有排序了才能分页
[聚合查询]
//查总数
var num = db.Accounts.Count();
//查最小ID
var minId = db.Accounts.Min(u => u.ID);
NOTE 聚合查询只能通过函数式查询
4)View的值是如何传到controller的?
Controller里的login方法的参数account的字段会与 View里的input控件的name名进行匹配,获取值。