【第二篇】ASP.NET MVC快速入门之数据注解(MVC5+EF6)
目录
【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)
【第二篇】ASP.NET MVC快速入门之数据注解(MVC5+EF6)
【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)
【第四篇】ASP.NET MVC快速入门之完整示例(MVC5+EF6)
【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
请关注三石的博客:http://cnblogs.com/sanshi
数据库连接字符串
上一篇文章中,我们使用MVC的模板自动生成了CRUD的全部操作,但是没有配置数据库连接字符串,那么数据存到什么地方了?
打开项目的App_Data目录,你可以发现数据库原来在这里:
我们通过VS自带的数据库访问工具,来看下表结构和其中的数据,首先找到[服务器资源管理器]面板,新增数据库连接:
在添加连接向导对话框中,输入服务器名:(LocalDb)\MSSQLLocalDB,这个是VS2015自带的LocalDb的服务器实例名称(如果你使用VS2013,这个名称可能是:(LocalDB)\v11.0)。数据库选择我们刚刚创建的StudentDbContext。
原来如果没有显式的指定数据库连接字符串,VS会使用默认的LocalDb实例,这个对应关系在Web.config中有定义:
<entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="mssqllocaldb" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework>
当然我们也可以明确指定数据库连接字符串:
<connectionStrings> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\AspNetMvc.QuickStart.Models.StudentDbContext.mdf;Initial Catalog=AspNetMvc.QuickStart.Models.StudentDbContext;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings>
然后在代码中引用这个数据库连接字符串:
public class StudentDbContext : DbContext { public StudentDbContext() : base("DefaultConnection") { } public DbSet<Student> Students { get; set; } }
注意:如果使用的VS2013,Data Source应该是(LocalDb)\v11.0,而VS2015对应的是(LocalDb)\MSSQLLocalDB。
经过这个改变,在真正部署到MSSQL服务器时,简单修改数据库连接字符串就可以了。
数据库表结构
打开Students的表定义:
可以看下EF是怎么将Student模型映射到数据库表结构的:
1. 模型中ID属性的数据映射为表的主键。
2. 模型中的string类型映射为表的nvarchar(MAX)。
3. 模型中的int和DateTime分别映射为表的int和datetime类型。
再来看下上一篇文章中添加到表中的数据:
如果你之前有数据库设计的经验,会很容易发现这个表结构的问题:
1. Name和Major存储字符串,一般需要限制最大长度,比如nvarchar(200)。
2. Name和Major列应该不允许为空。
那么怎么来实现这两个需求呢?直接修改数据库肯定是不行的!
数据注解
我们应该从模型入手,还记得我们在上一篇文章结尾说的那句话吗,数据模型不仅会影响数据库的表结构,还会控制MVC视图层的客户端验证和控制器层的服务器端验证。
修改Student模型类,添加适当的数据注解:
public class Student { public int ID { get; set; } [Required] [StringLength()] public string Name { get; set; } public int Gender { get; set; } [Required] [StringLength()] public string Major { get; set; } public DateTime EntranceDate { get; set; } }
如果输入[Required]时没有智能感知,很可能是没有引用相应的命名空间,VS可以很方便的协助我们添加:
这样就会在文件头部添加如下引用:
using System.ComponentModel.DataAnnotations;
直接运行项目(Ctrl+F5),此时我们会看到如下的错误页面:
相信使用EF的同学都会遇到这个页面,上面的提示也很明确,包含两个层次的信息:
1. 数据库创建之后模型改变了。
2. 可以使用数据迁移来更新数据库。
数据迁移(Migrations)
从VS的[工具]菜单中,找到Nuget包管理器控制台:
启用数据迁移
在控制台中输入如下命令:Enable-Migrations
这时会在项目目录中增加一个Migrations文件夹,里面放置了两个文件:
EF会通过C#代码的方式将每一次对模型的修改保存到这个文件夹中,现在来看下生成的文件内容:
每个迁移文件,都包含Up和Down两个重写函数,分别对应于更新和回退。上面的代码也很直白,Up函数中创建一个Students表,定义表结构并指定ID主键(PrimaryKey),Down函数用来回退操作,里面简单的删除了Students表。
可以看到,这里的创建表操作并没有使用最新的模型(Name列没有nullable的设置),因为这是初始模型对应的表结构,EF会在数据库中自动生成一个名为__MigrationHistory表来跟踪数据库的状态。
增加迁移项
增加迁移项需要我们手工来进行,在程序包管理器控制台中,输入如下命令:
Add-Migration Add_Annotation_Name_Major
这时会在Migrations目录下生成迁移文件,文件是以[时间+迁移名]命名的,方便查找:
201612160406415_Add_Annotation_Name_Major.cs
更新到数据库
此时,数据库尚未改变,我们还需要手工命令来更新数据库:
Update-Database
此时,再来查看数据库中Students的表结构:
Name列的数据类型和是否允许Null都已经改变了。
在真实的项目中,数据库可能部署在远程服务器中,这时我们就不能直接在VS中通过Update-Database来更新数据库了。
不过我们可以生成更新SQL脚本,然后拿到数据库服务器上执行。生成这个SQL脚本的方法:
Update-Database -Script
-SourceMigration: InitialCreate
-TargetMigration: Add_Annotation_Name_Major
来看下生成的SQL更新脚本:
有了这个SQL更新脚本,我们就可以方便的更新远程数据库了。
视图的客户端验证
现在运行项目,转到创建页面:
可以看到,如果Name为空则会有错误提示信息,而Major输入字符串过多,也会有提示信息,而这些设置是来自模型的数据注解。
这个客户端验证是有jQuery的validation插件提供的:
http://bassistance.de/jquery-plugins/jquery-plugin-validation/
如果你查看页面源代码,会发现Major输入框的input标签上有相应的自定义属性data-val-length-max=200和data-val-length,而这些属性值正是来自于模型的数据注解。
控制器的服务器端验证
在启用JavaScript的情况下,由于所有的错误输入在客户端就会被拦截,所以根本到达不了服务器,不过这并不表示恶意用户无法提交错误的输入,有很多种方法可以做到:
禁用JavaScript
不同浏览器禁用JavaScript的方法不同,在Chrome中,F12打开开发工具,然后找到设置对话框:
此时提交页面,你会看到和前面完全相同的页面,由于本地运行速度很快,你甚至可能没意识已经发起了一次HTTP POST请求,而显示错误提示的页面来自服务器,而不是客户端:
响应正文包含如下内容,其中错误信息是服务器端生成的:
<div class="form-group"> <label class="control-label col-md-2" for="Name">Name</label> <div class="col-md-10"> <input class="input-validation-error form-control text-box single-line" data-val="true" data-val-length="字段 Name 必须是最大长度为 200 的字符串。" data-val-length-max="200" data-val-required="Name 字段是必需的。" id="Name" name="Name" type="text" value="" /> <span class="field-validation-error text-danger" data-valmsg-for="Name" data-valmsg-replace="true">Name 字段是必需的。</span>
</div> </div>
此时再回过头来看下Students控制器中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); }
如果验证失败,则不更新数据库,并返回带Student模型的视图。
模拟POST请求
有很多工具可以模拟POST,这里我们讲解如果使用Fiddler来模拟项服务器提交POST请求。
打开Fiddler,就开始自动监测所有的HTTP请求,这时我们刷新Create页面,并在JavaScript禁用的情况下,提交表单,这时会有两个请求:
首先选中左侧的第二个请求,右侧面板中选择Inspectors->WebForms,下面会显示三个窗格:
1. QueryString:当前请求的URL查询字符串。
2. Body:POST请求的表单参数。
3. 第三部分:响应正文,我们可以看到服务器端返回的错误信息。
现在切换到Composer选项卡,我们可以在这里面模拟POST请求:
上面有一段提示信息:使用这个页面创建一个请求。你可以通过拖拽的方式从左侧会话列表中拷贝一个之前的请求。
这就方便多了,我们从左侧选中第二个请求并拖拽到本页面:
这时页面背景变成明显的绿色以作提示,拖拽结束:
这时,Fiddler自动帮我们设置了模拟POST请求的参数,拷贝自之前的某个请求,这时的[Request Body]是经过URL编码的,我们可以方便的进行解码:
我们把这段代码修改成:
__RequestVerificationToken=wwoxICDootbixw8YMiFIOU1WW95QSCicREsWLeewlSAE28sdyEA0ZChlY0nfuOlxu2WDIjcrx086GYkaBOAtewyARWbeRZp0kD6tRt-hyAs1&Name=张三石&Gender=1&Major=&EntranceDate=2000-09-01
把这段字符串拷贝到Fiddler中的[Request Body],并点击[Execute]按钮,这时会发起一个新的模拟请求:
注意这个请求并不是从页面发出的,而是通过工具模拟的HTTP POST请求,并且我们还修改了其中的表单参数(Name=张三石,Major=空字符串),这样当然也就会躲开浏览器端的JavaScript验证规则,但是还是无法穿透服务器端的验证。
这也正是MVC中数据注解带来的便利,一个地方定义,三个地方使用(数据库表结构、客户端验证,服务器端验证)。
小结
本章我们首先查看了EF自动生成的数据库结构,然后为数据模型添加数据注解,继而介绍了数据迁移的工作过程。数据注解不仅对数据库表结构产生影响,而且会应用到前台的客户端验证和服务器端验证,接下来我们详细讲解了两则躲避客户端验证的手段,分别为禁用JavaScript和模拟POST请求。从而更加深刻的认识到数据注解给我们提供的便利:一个地方定义,三个地方使用(数据库表结构、客户端验证,服务器端验证)
在创建新用户页面,我们可以看到两个安全相关的代码(ValidateAntiForgeryToken和Bind),它们分别用于阻止CSRF跨站请求伪造和Over-Posting过多提交攻击,下一篇文章我们会详细介绍。
【第二篇】ASP.NET MVC快速入门之数据注解(MVC5+EF6)的更多相关文章
- 【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 【第四篇】ASP.NET MVC快速入门之完整示例(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- ASP.NET Core 快速入门(Razor Pages + Entity Framework Core)
引子 自从 2009 年开始在博客园写文章,这是目前我写的最长的一篇文章了. 前前后后,我总共花了 5 天的时间,每天超过 3 小时不间断写作和代码调试.总共有 8 篇文章,每篇 5~6 个小结,总截 ...
- ASP.NET MVC 5 入门指南汇总
经过前一段时间的翻译和编辑,我们陆续发出12篇ASP.NET MVC 5的入门文章.其中大部分翻译自ASP.NET MVC 5 官方教程,由于本系列文章言简意赅,篇幅适中,从一个web网站示例开始讲解 ...
- ASP.NET MVC 5 入门教程 (3) 路由route
文章来源: Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc-5-get-started-route.html 上一节:ASP.NET MVC 5 入门 ...
- ASP.NET MVC 5 入门摘要
翻译和编辑的第一阶段后,.我们已经发出12片ASP.NET MVC 5入门文章. 他们中的大多数来自翻译ASP.NET MVC 5 官方教程,因为本系列文章言简意赅,篇幅适中,从一个web站点演示样例 ...
- ASP.NET Core快速入门--学习笔记系列文章索引目录
课程链接:http://video.jessetalk.cn/course/explore 良心课程,大家一起来学习哈! 抓住国庆假期的尾巴完成了此系列课程的学习笔记输出! ASP.NET Core快 ...
随机推荐
- Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...
- 痞子衡嵌入式:ARM Cortex-M文件那些事(1)- 源文件(.c/.h/.s)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的source文件. 众所周知,嵌入式开发属于偏底层的开发,主要编程语言是C和汇编.所以本文要讲的source文件主要指的就是 ...
- 基于Dockerfile镜像制作的基本操作
一.使用Dockerfile制作镜像 前面的博客中已经介绍了如何基于容器制作镜像,此方法的原理是使用一个正在运行的容器,根据生产所需进行配置更改等操作后,使其满足生产环境,再将这个容器打包制作为镜像, ...
- Spring Cloud Alibaba基础教程:Nacos配置的多环境管理
前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式> ...
- 使用微软PinYinConverter查询汉字拼音
通过汉字,如何查询拼音? 微软有相应的DLL可直接使用 引用方式 Nuget包管理安装 DLL下载后,引用 可以从微软的网站上下载相关文字处理的类库,下载地址如下: http://download.m ...
- 第六讲 smart qq C#开发总结
smart qqC#开发总结: 整个开发下来其实一点都不是很难,从一开始二维码 获取到最终的收发消息,基本上都是模拟浏览器的操作.都是基于http通讯.一下就是 本次新手学习http协议的最关键的一个 ...
- Android安全–Dex文件格式详解
Dex文件是手机上类似Windows上的EXE文件,dex文件是可以直接在Dalvik虚拟机中加载运行的文件. 首先我们来生成一个Dex文件. 新建文件Hello.java内容如下: class He ...
- 微信小程序域名配置问题
最主要的:不能用ip地址,不能用localhost,域名要经过备案等 这些在 https://developers.weixin.qq.com/miniprogram/dev/framework/ab ...
- 浏览器登录Dynamics 365 CE没毛病,程序连接却报错。
摘要: 微软动态CRM专家罗勇 ,回复308或者20190308可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 今天我做实验 ...
- 小程序实践(十一):showModal的使用
显示模态对话框,确定和取消两个选择+标题+内容的对话框 . // 编辑用户性别 tapSex:function(res){ var that = this wx.showModal({ title: ...