微冷的雨ASP.NET MVC之葵花宝典
By:微冷的雨
第一章 ASP.NET MVC的请求和处理机制.
在MVC中:
01.所有的请求都要归结到控制器(Controller)上.
02.约定优于配置
*:所有的控制器放到Controllers文件夹中
*:所有的视图放到Views文件夹对应的Controller类名的文件夹中
03.如何通过Session保存用户登录信息,以及通过Cookie记录用户名
Session和Cookie都属于系统对象
设置Cookie(jsp还是cshtml cookie都不是内置对象)
HttpCookie hcCookie = new HttpCookie(Cookie的名称, 变量值);
hcCookie.Expires = 过期时间;
Response.Cookies.Add(hcCookie);
//
读取Cookie
string 变量名 = Request.Cookies[Cookie的名称].Value;
如何从一个Action跳转到另外一个Action RedirectToAction(“action名称”,“Controller”)
04.GPR原则:用户先发一个get请求让客户看到登录界面,然后用户录入数据,通过表单的post提交方式提交.登录成功后要进行跳转
class="NewStyle17">05.内嵌语法
<%%>
<%=%>
<%:%>
<srcipt runat="server">
在aspx页面中定义方法
</script>
06.母版页
ContentPlaceHolder
第二章 基于三层架构搭建MVC系统
01.可选参数
Public void Test(string name,int age=20)
Var:隐式.类型推断 第一个=不能给null值,必须给一个确定的值,这样才能推断出=左侧变量的类型
Dynamic:动态类型 可以凭空的点出一个自身不存在方法,编译时不进行类型检查,在运行时会报错.
匿名.类中的属性是只读的.
Int? num=5;
Int result=Num??0;
依赖关系
DAL→Model
BLL→Model 和DAL
UI→BLL 和Model
06.会搭建分区项目,会在Areas文件夹下,创建出自己的一套MVC
第三章
01.路由
解析:路由的定义规则,URL规则
Routes.MapRoute(
Name:”Default”,
Url:blogs/{Controller}/{action}/{id},
Defaults:new{ Controller=”Home”,action=”Index”,id= UrlParameter.Optional },
Constraints:new{ id=@”\d{4}”},
Namespaces:new String[]{“BookShop.Controllers”}
)
*****引入了RouteDebug工具,通过在App_Start文件中的RouteConfig类中,添加一行代码
, //RouteDebug.RouteDebugger.RewriteRoutesForTesting(routes);
02.如何在Controller和View中共享数据
方案二:5种
ViewBag
TempData
上面三种的场景简单数据类型
ViewData.Model 4
View(Model) 5
强类型的复杂类型需要传递model使用方式4和5
3.通过看MVC源码剖析了一下为什么ViewData这个容器可以实现从Controller到View的数据共享.
解析:Controller →有一个Action→ 返回值类型ViewResult→继承自ViewResultBase
→ 里面有ViewData,和一个ExecuteResult()→ExecuteResult()参数是一个控制器对象,更精彩的是在ExecuteResult()方法中new出一个视图上下文,并且在构造中携带了控制器对象,和ViewData数据. →调用View.Render(viewContext)方法渲染视图, →由于View是一个接口类型,WebFormVIew视图引擎是View的一个实现类,WebFormView重写的Render方法又调用了RenderVIewPage方法,
第四章
00.自动绑定
路由数据,URL数据,表单数据
01.表单数据<URL数据以及路由数据都可以实现自动装配.如果是表单数据的简单类型要想实现自动装配,那么只需要保证表单元素的name名字必须和参数的名字相同.
02.通过EF来完成应用程序和数据库之间的数据传递.
BookShopEnties:DBContext(EF5.0)
EF4.0继承自ObjectContext
03.Business Model ViewModel
业务Model:10个字段
视图Model:3个字段
04.由于我们的验证标签直接打在生成的实体类的属性上可能造成验证特性标签的丢失(重新生成实体类)
考虑一下如何解决???
解析:助手类
步骤:
[MetaDataType(typeof(UserViewModel))]
Public partial class User
{
}
解析:在Edmx模型中,有一个名称为BookShopPlusEntities的类,这个类中会自动根据数据库中的表名生成一个DBSet<User> Users{get;set;}集合,然后在Controller中就可以通过db.Users.Add(entity)
.master不再有,推出了_Layout.cshtml
Bundle技术:牛X在可以将1000个css样式表文件合成一次
结论:如果您选取了Razor视图引擎,那么无论是否启用Layout视图,都要从_ViewStart.cshtml执行.
其实上前端校验还是交给了jquery-validate完成的.如果在页面中没有引入对应的js库,那么不会自动形成前端校验.
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Required();必填项
Compare()比较:确认密码
StringLength();限定字符格式
Range(这里课本上是错误的,不能通过它来验证日期范围)
RegularExpression(@”^$”)
ModelState.IsValid:true,表明后台所有的实体校验均通过
如何将错误信息扔到ValidationSummary中
ModelState.AddModelError(“和Index.chhtml中的表单元素name保持”,”用户名存在”)
补充远端校验:[Remote] System.web.MVC;
补充:通过隐式的ajax请求来实时校验用户名是否存在
核心就是每次产生校验的时候,调用Controller中的一个方法,只不过该方法返回的是
Json数据.
扩展方法三要素:
分页
Controller中内容:
public ActionResult PageData(int? pageSize, int? pageIndex)
{
pageSize = pageSize ?? 2;
pageIndex = pageIndex ?? 1;
ViewData["CurrentPage"] = pageIndex.Value;
ViewData["PageSize"] = pageSize.Value;
ViewData["TotalCount"] = db.Subjects.Count();
ViewData["PageNum"] = Math.Max((db.Subjects.Count() + pageSize.Value - 1) / pageSize.Value, 1);
var temp = db.Subjects
.OrderBy(c => c.SubjectId)
.Skip<Subject>(pageSize.Value * (pageIndex.Value - 1))
.Take<Subject>(pageSize.Value);
return View("Index",temp);
}
View中生成页码条
<div class="paginator">
@Html.ShowPageNavigate((int)ViewData["CurrentPage"],(int)ViewData["PageSize"],(int)ViewData["TotalCount"])
</div>
Day06次课程
01.日历控件引入
步骤:
01.直接在项目中添加下发的calendar文件夹,然后依次引入
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<link href="~/calendar/Css/calendar.css" rel="stylesheet" />
<script src="~/calendar/dt.js"></script>
<script type="text/javascript">
$(function () {
$("#tName").click(function () {
ShowCalendar(this);
});
})
</script>
02.可以手动修正dt.js文件,可以让日历控件同时显示日期和时间,要看业务场景,
如果只需要显示日期,那么可以将dt.js中第982行代码做一个修正,如下
function ShowCalendar(txt) {
displayCalendar(txt, 'yyyy-mm-dd hh:ii', txt,true);
}
同时显示日期和时间,如果仅仅显示日期,配置如下:
function ShowCalendar(txt) {
displayCalendar(txt2014-09-09 08:00, 'yyyy-mm-dd', txt,false);
}
02.文件上传
文件上传
步骤:01.构造上传文件的表单
@using(Html.BeginForm("Upload", "FileTest", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" name="upload" value="提交" />
}
02.在控制器中进行文件上传代码的处理
public ActionResult Upload()
{
return View();
}
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if (file!=null)//证明用户选择了一个文件
{
//在服务器上找一个文件夹来保存用户上传的文件
string path= Server.MapPath("~/files/" + file.FileName);
//就是将客户端用户上传的文件保存到该目录中.
file.SaveAs(path);
return RedirectToAction("Index");
}
return View();
}
5.通过jquery-ui进行文件上传
步骤1:01.构造上传文件的表单
@using(Html.BeginForm("Upload", "FileTest", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" name="upload" value="提交" />
}
*步骤一补充:在视图文件中,引入3个文件,顺序不能变
01.jquery文件
02.jquery-ui的样式文件
03.jquery-ui.js插件
<!--引入Jquery文件-->
<script src="~/Scripts/jquery-1.7.1.js"></script>
<!--引入Jquery-ui-css文件-->
<link href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" />
<!--引入Jquery-ui文件-->
<script src="~/Scripts/jquery-ui-1.8.20.js"></script>
04.要将Views文件夹下的_Layout.cshtml文件中的 @* @Scripts.Render("~/bundles/jquery")*@
注释,否则在Chrome中监视的时候,会发现以后一个错误,就是找不到jquery-ui插件的
dialog方法。
步骤2: *02. 在视图中用一个div将表单包裹起来,并且在div外定义一个a标签。达到的效果
就是默认情况下div隐藏的,只有a标签显示。起到作用的就是autoOpen属性。设置为false,就是
默认隐藏div。
<script type="text/javascript">
$(function () {
$("#dialog").dialog({
autoOpen: false,
show: "blind",
hide:"explode"
})
//写在此处的代码已经完成了当前页面中所有标签都加载(不包含图片和css),
//但是和Window.onload方法不同,保证所有的标签和图片都加载完成后再执行
$("#myupload").click(function () {
$("#dialog").dialog("open");
//原来a标签起到一个链接到另外一个目标页面的作用,通过return false可以取消标签的默认行为
return false;
})
})
</script>
<div id="dialog" title="文件上传">
@using (Html.BeginForm("Upload", "File", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" id="file1" />
<input type="submit" name="upload" value="提交" />
}
</div>
<a href="#" id="myupload">文件上传</a>
03. 富文本编辑器
补充下拉框双向绑定
04.综合案例
第八章 EF
1.EF体系结构
01.ORM的优势
快速开发
方便移植数据库
02.流行的ORM框架
Hibernate
MyBatis
TopLink
03..NET 世界的ORM框架
NHibernate
MyBatis.NET
LINQ to SQL
ADO.NET Entity Framework
04.在EF中,对数据对象的操作,实际是在操作EDM。在EDM抽象化的结构之下,
则是概念层(CSDL)、存储层(SSDL)和对应层(MSL)
CSDL定义了EDM的灵魂部分---概念模型。概念模型对应的是实体类,用实体类
表示数据库中的对象。
SSDL负责与数据库管理系统中的数据表做实体对应,描述了表、列、关系、主键
及索引等数据库中存在的概念。
05.关于Object Services:
from c in db.Student
where c.id>0
select c;
c=>c.id
参见msdn:http://msdn.microsoft.com/en-us/library/bb386871.aspx
Object Services is a component of the Entity Framework that enables you to query,
insert, update, and delete data, expressed as strongly typed CLR objects
that are instances of entity types. Object Services supports both
Language-Integrated Query (LINQ) and Entity SQL queries against types
that are defined in the conceptual model. Object Services materializes(成为现实)
returned data as objects, and propagates(传递) object changes back to
the data source. It also
1.T4模板下载地址
http://www.devart.com/t4-editor/download.html
DbSet 表示上下文中给定类型的所有实体的集合或可从数据库中查询的给定类型的所有实体的集合。
可以使用 DbContext.Set 方法从 DbContext 中创建 DbSet 对象。
2。延迟加载的本质
是IQueryable接口成就了延迟加载
解析:通过扩展IQueryable接口类型,在Queryable类中定义了一个名称为Where的扩展方法。
最本质的是通过DbQuery子类来进行延迟加载的。
3.延迟加载的目的不是为了延迟使用数据,而是为了延迟生成SQL语句,满足业务需求。
4.查询出来的对象都是以包装类的形式存在的。
5.Conceptual schema definition language (CSDL)
概念架构定义语言 (CSDL) 支持一组抽象基元数据类型(称为 EDMSimpleTypes),
这些类型在概念模型中定义属性。
Store schema definition language (SSDL) is an XML-based language
that describes the storage model of an Entity Framework application.
http://msdn.microsoft.com/zh-cn/library/cc982042.aspx
Mapping specification language (MSL) is an XML-based language
that describes the mapping between the conceptual model and
storage model of an Entity Framework application.
In an Entity Framework application, mapping metadata is loaded from
an .msl file (written in MSL) at build time.
The Entity Framework uses mapping metadata at runtime
to translate queries against the conceptual model to store-specific commands.
The Entity Framework Designer (EF Designer) stores mapping information
in an .edmx file at design time. At build time, the Entity Designer
uses information in an .edmx file to create the .msl file
that is needed by the Entity Framework at runtime
Names of all conceptual or storage model types that are referenced in MSL
must be qualified by their respective namespace names.
For information about the conceptual model namespace name,
see CSDL Specification. For information about the storage model namespace name,
see SSDL Specification. provides facilities(工具) for tracking(路线) changes,
binding objects to controls, and handling concurrency(并发性).
Object Services is implemented by classes in the System.Data.Objects
and System.Data.Objects.DataClasses namespaces.
Object Context
The ObjectContext class is the primary class for interacting with data in the form of objects that are instances of entity types that are defined in a conceptual model. An instance of the ObjectContext class encapsulates(囊括) the following:
A connection to the database, in the form of an EntityConnection object.
Metadata that describes the model, in the form of a MetadataWorkspace object.
An ObjectStateManager object that tracks objects during create, update, and delete operations.
06.白话理解Object Services ,Entity Client ,ADO.NET Provider 和EDM MetaData(CSDL,MSL和SSDL)
Object Services:就相当于封装增删改查的高级类。例如调用AddObject就可以实现新增操作。
Entity Client:相当于ADO.NET中的SqlClient Connection,Command
ADO.NET Provider:相当于数据库的驱动程序
EDM MetaData(CSDL,MSL和SSDL):XML文档,映射程序中对象和表中对象关系
07.IQueryable接口继承自IEnumerable接口
总结:
下次课程:
01.模型绑定特性
02.定制视图模板
03.Razor视图引擎 @
***重点一:webform :aspx
<% using (Html.BeginForm()) { %>
<% } %>
Razor :cshtml
@using (Html.BeginForm("提交到的action","提交的Controller",FormMethod.Post)) {
}
@{
//仅仅进行内存级别的操作,并不将结果打印到页面上
}
***重点二:母版页的概念存在于webform视图引擎下,在Razor视图引擎下,
没有母版页,只有布局页面(视图),_Layout.cshtml
ViewStart.cshtml :视图在渲染的时候第一个执行的页面。
LogIn.cshtml:
_Layout.cshtml:对页面的<html><title>以及样式和js都做了设置。
并且预留了子页面需要填补的内容RenderBody()
***重点三:http协议
关于HTTP协议:之前的http协议版本是1.0,短连接。也即是当客户端
向服务器发出一个请求后,服务器返回给客户端响应后,连接立即断开,
后来出现了长连接,也就是现在通用的1.1,将间隔时间很短的多次请求
合并,这样提升网站的性能。
***重点四:状态码
状态码:
200:OK ,服务器已经正确做出响应。
302:暂时重定向。
303:永久重定向
304: Not Modified(未修改)客户的缓存资源是最新的, 要客户端使用缓存
404:404 Not Found 未找到资源
500:服务器内部错误!
***重点五:压缩文件技术:Bundle技术:
问题:请求一个页面Index,页面上引用了10个外部CSS,需要发几次请求?
解析:发送11次请求,请求页面的文本一次请求。请求10个CSS需要10次请求。所以
总共是11次请求。
手动配置自己的Bundle。
//自己的css压缩名称
bundles.Add(new StyleBundle("~/Content/mine").Include("~/Content/mycolor.css","~/Content/myfont.css"));
***重点六:ModelState:
功能一:是拦截程序跨过验证的一种有效手段
--ASP.NET Page.IsValid
--ASP.NET MVC ModelState.IsValid:本质上可以对应用的前后台同时进行验证。
哪怕前端禁用了js,也无法跨过后台我们给对应标签设置的特性。
功能二:当action中某个分支语句有错误,需要从Controller传递到View视图的时候,
我们可以使用ModelState.AddModelError("key","错误信息字符串")
ModelState.AddModelError("key“,Exception对象)
在前台VIew中有一个ValidationSummary(true);
第九章 EF高级应用
01.如何从委托进化到Lambda
委托
匿名函数
Lambda
1.LINQ
LINQ(Language Integrated Query)语言集成查询
LINQ to Entities;主流,后台可以是任意数据库。
EF这个ORM矿建性能比较优良。!@
LINQ to Objects:(string,数组和集合)
Linq to xml
Linq to SQL:后台数据库只能是SQL server数据库,微软停止更新
2.
01.查询“北京大学出版社”
最早出版的3本书籍
var query= (from c in Books
where c.Publisher.Name.Equals("北京大学出版社")
orderby c.PublishDate descending
select c.Title).Take(3)
编译后,和如下SQL语句等价
select top 3 * from books,publishers
where books.publiserid=publishers.id
and publisers.name='北京大学出版社'
order by publisherdate
02.
查询分类为“C#” 、2003
年前出版的书籍,
包括书名、出版社名称
from c in Books
where c.Category.Name.Equals("C#") &&
c.PublishDate<Convert.ToDateTime("2003-01-01")
select new {c.Title,c.Publisher.Name}
03.查询出版书籍超过100本的出版社名称
var list = from c in db.Publishers
where c.Books.Count > 100
select c.Name;
重点:所有LINQ查询语句都可转换成查询方法
有的查询方法不能用LINQ查询表达式表示
3.FirstOrDefault()和SingleOrDefault()区别
解析:这里以First、FirstOrDefault进行说明,其他类似。
1、First:取序列中满足条件的第一个元素,如果没有元素满足条件,则抛出异常
2、FirstOrDefault:取序列中满足条件的第一个元素,如果没有元素满足条件,
则返回默认值(对于可以为null的对象,默认值为null,对于不能为null的对象,
如int,默认值为0)
区别:First,返回序列中的第一条记录,如果没有记录,则引发异常
FirstOrDefault,返回序列中的第一条记录,如果序列中不包含任何记录,则返回默认值。
Single,返回序列中的唯一一条记录,如果没有或返回多条,则引发异常。
SingleOrDefault,返回序列中的唯一一条记录,如果序列中不包含任何记录,则返回默认值,如果返回多条,则引发异常。
4.从LINQ to Objects到LINQ to Entities
解析:查询语法上LINQ to Objects是一致的。但是他们在执行上却存在本质的区别。Objects始终是一个CLR对象,LINQ to Objects始终
是在CLR中进行的运算和操作;而LINQ to Entities虽然在编码上操作集合对象,但最终会被框架转换为对具体数据库表的操作。简单的说,
在LINQ to Entities中,查询表达式最终会被转化成相应的SQL语句。在这个转化过程中,from,where,order by,select等部分会相应地
转化成SQL子句,用到的函数会转换成相应的SQL函数或运算符,如StartsWith("张"),在SQL Server数据库中会转换成Like N'张%'
5.查询多表数据
方式一:使用导航属性
方式二:join连接查询
方式三:嵌套查询子查询
6.上机练习一(获取好友分组信息)
(1)当前用户的所有分组信息
from c in PrivateGroups
where c.OwnerId==6
select c
PrivateGroups
.Where (c => (c.OwnerId == 6))
(2)当前用户的未分组好友总个数
(from c in FriendRelations
where c.UserId==6 && c.GroupId.HasValue==false
select c).Count()
FriendRelations
.Where (c => ((c.UserId == 6) && (c.GroupId.HasValue == false))).Count()
(3)当前用户的好友总个数
(from c in FriendRelations
where c.UserId==1
select c).Count()
FriendRelations
.Where (c => (c.UserId == 1)).Count()
上机练习二(获取分组下的好友)
01.分组编号对应的分组信息
(from c in PrivateGroups
where c.GroupId==4
select c)
PrivateGroups
.Where (c => (c.GroupId == 4))
02.分组编号下的所有好友信息
from c in FriendRelations
where c.UserId==6
&& c.GroupId==20
select c
FriendRelations
.Where (c => ((c.UserId == 6) && (c.GroupId == (Int32?)20)))
上机练习3(按组合条件搜索好友)
实现动作方法,按姓名、性别、城市和家乡组合条件搜索青鸟朋友网所有用户,要求
获取到姓名、编号、是否和当前用户是好友关系、所属分组等信息
,支持分页查询
第十章 Ajax
1.无刷新删除分组信息数据
核心:01.先通过EF给用户展现出一个列表页面
02.修改对应的View使用,将原有的超链接
改成一个<img>标签,并且img标签设置两个属性,
如下<img src="" class="del" delid="@item.GroupId">
03.通过$.post(请求的目标页面,{id:id},回调函数function(data){
});
04.db.PrivateGroup.Where().SingleOrDefault();
2.根据分组编号获取当前登录用户某个分组下所有的好友信息以及
未分组信息(PartialView实现)
实现步骤:01.我们都知道,MVC模式最终把所有的请求都归结到到控制的
某个Action上.这里我们点击页面左侧的一个table中某一个分组的名称时,
需要在右侧的div中展示该分组下的所有好友名称.
02.首先,在HomeController中书写一个GetFriendsByGroupId(int? id)
返回的视图类型不再是View(),而变成了PartialView().
03.再Index页面中,将分组名称从原来的默认形式设置成一个无刷新
超链接,@Ajax.ActionLink("热点文字","Action名称","Controller名称",
路由参数(new{id=@item.GroupId},new AjaxOptions(){
OnScuccess="服务器执行成功后要执行的Js函数",
HttpMethod="请求提交方式",
Confirm="提示是否进行操作的对话框",
UpdateTargetId="要更新的目标区域的id",
LoadingElementId="当网速慢的时候,或者并发量大的时候,用户
看到的正在加载./...图片效果.",
}))
LoadingElementId参数注意事项:设定的显示图片加载的标签如下:
<div id="load">
<img src="~/images/01.jpg"/>
</div>
01.先在样式表中让id="load"的div隐藏
display:none;
02.当图标在指定的时间内将数据加载完成后,会自动将div再次自动隐藏.
最后一项目:目标区域的代码
<div id="mytarget">
//如何调用分布视图
@Html.Partial("分布视图的名称",model数据)
</div>
如何加载未分组数据呢?
解析:其实上就是在table最后一个tr后面手动构造一个tr对象.
并且也使用无刷新超链接来进行分组名称的显示.其他内容同上.
3.Json实现某个分组下的好友信息
核心01:什么是Json?
解析:JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它相对于xml格式解析起来更加简便,比Serialize序列化的数据有更好的
展示效果.
解析:JSON 数据的书写格式是:名称/值对。
名称/值对组合中的名称写在前面(在双引号中),值对写在后面(同样在双引号中),中间用冒号隔开:
例如:"firstName":"John"
核心03.JSON 值
JSON 值可以是:
数字(整数或浮点数)
字符串(在双引号中)
逻辑值(true 或 false)
数组(在方括号中)
对象(在花括号中)
null
核心04.Json的各种形式
最简单的形式:{"name":"张靓颖"}
如果想让服务器打给浏览器Json数据, 那么返回类型要写成Json(携带数据,JsonRequestBehavior.AllowGet)
在使用Json方法的过程中,会出现循环引用的异常信息,我们可以通过
db.Configuration.ProxyCreationEnabled=false解决,或者是通过
db.Configuration.LazyLoadingEnabled=false解决,微软官方解决可以通过
blog上的方案,原理是重写了Json方法的执行流程.
json数据:
[{"UserId":5,"Mail":"yanyan@sina.com","RealName":"唐燕",
"Password":"123456","Gender":"女","Birthday":"\/Date(255110400000)\/","City":null,"HomeCity":null,"Situation":"教员","HeaderImage":"5.jpg","BloodStyle":null,"RegisterTime":"\/Date(1366732800000)\/","GenderPrivate":0,"BirthdayPrivate":0,"CityPrivate":0,"HomeCityPrivate":0,"SituationPrivate":0,"BloodStylePrivate":0,"InitialPrize":2345,"FriendRelation":[],"GroupFriend":[],"EntityState":2,"EntityKey":{"EntitySetName":"UserInfo","EntityContainerName":"FriendsEntities1","EntityKeyValues":[{"Key":"UserId","Value":5}],"IsTemporary":false}}]
解析服务器打到浏览器上的Json格式数据
$.each(data, function (i, object) {
$("#FriendList").text("");
$("#FriendList").append(
"<div>" + object.RealName + "</div>" + "<br/>");
});
注意点:当我们从GetFriendByGroupId转型成GetFriendByGroupIdJson的时候,一定
要注意AjaxOptions中不能再有UpdateTargetId的值.因为在OnSuccess中已经
指定了要更新的区域信息.
第11章 Forms身份校验 过滤器() 缓存 错误页
关于Session的配置
什么是进程内Session
解析:淘宝登陆:StateServer:
<sessionState mode="InProc" customProvider="DefaultSessionProvider" timeout="20">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
1.Forms验证方式
配置步骤:
01.在程序的web.config文件中,
配置如下节点
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />--注意这里超时的单位为分钟
</authentication>
02.登陆成功后向用户发放身份票据
通过用户名和密码判定
FormsAuthentication.SetAuthCookie(user.UserId.ToString(),false);
03.获取身份票据进行验证
if (this.User.Identity.IsAuthenticated)
//验证通过
{
//获取写入的userName
int userId = Convert.ToInt32( this.User.Identity.Name );
//具备权限后的操作代码...
}
Win7下Cookie的位置
C:\Users\Administrator\AppData\Local\Microsoft\Windows\Temporary Internet Files
Authorize 特性-方便的实现授权
其实Authorize内部也是通过03的步骤实现的
Authorize过滤器
2.过滤器
AOP+面向接口编程
service service.impl
dao dao.impl
过滤器的本质:本质就是一个实现了特定接口或者是父类的特殊类。
咱们自定义的过滤器必须满足两个条件:01.继承FilterAttribute抽象类
02.必须实现四个接口中的任何一个。
在ASP.NET MVC中,过滤器就是一个继承自FilterAttribute的类,并且实现了
IActionFilter、IResultFilter、IException或者是IAuthorizationFilter接口
中的任何一个接口。
两个Demo:如何记录网站的错误日志(不能记录404错误)。
如何记录网站的访问日志(浏览器,IP) 。
在FilterConfig文件中,注册全局过滤器。
注意FilterAttribute命名空间为mvc下
public class MYExceptionFilter:FilterAttribute,IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
//记录错误日志
//01.得讲错误日志记录到当前项目的某个文件中(erroglog.txt)
//02.在服务器上指定该文件的位置
string realpath=filterContext.HttpContext.Server.MapPath(@"~\errorlog.txt");
//03.通过IO流的方式写入错误信息
using (StreamWriter sw = File.AppendText(realpath))
{
sw.WriteLine("时间:{0}",DateTime.Now);
sw.WriteLine("ip地址:{0}",filterContext.HttpContext.Request.UserHostAddress);
sw.WriteLine("控制器:{0}",filterContext.RouteData.Values["Controller"]);
sw.WriteLine("动作方法:{0}",filterContext.RouteData.Values["Action"]);
sw.WriteLine("错误信息:{0}",filterContext.Exception.StackTrace);
sw.WriteLine("**********************************************************");
}
}
}
public class SystemOperationListFilter:FilterAttribute,IActionFilter,IResultFilter{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
//当action执行完后执行该方法
string realpath = filterContext.HttpContext.Server.MapPath(@"~\pageList.txt");
//写入IO流
using (StreamWriter sw=File.AppendText(realpath))
{
sw.WriteLine("时间:{0}",DateTime.Now);
sw.WriteLine("地址:{0}",filterContext.HttpContext.Request.Url);
sw.WriteLine("浏览器引擎:{0}", filterContext.HttpContext.Request.UserAgent);
sw.WriteLine("计算机名:{0}",filterContext.HttpContext.Request.UserHostName);
}
}
}
自定义过滤器特性可以打在三个地方
:
01.Action
02.控制器
03.路由中配置
第三方,api
咱们自己的接口
我们现在努力的学习英文,就是为了有一天所有外国人都学习中文。考试
IActionFilter,IResultFilter,IExceptionFilter,IAuthorizeFilter
3.谈一下设计模式(常见的总共有23种设计模式) AOP IOC
简单工厂模式(不属于)
工厂模式
抽象工厂
门面模式
适配器模式:可以使系统本来存在的两个毫不相干的类型可以协同工作。
GOF(设计模式的权威书籍)
大话设计模式
设计模式之禅(Java)
AOP(面向切面编程)
面向切面(AOP)编程,Adapter适配器模式
********************************************06.缓存********************************************
06.缓存
使用缓存的目的就是加快对某种资源的访问。
并发量比较大的时候:分布式
本质:SOA+集群
作用:缓存是一把双刃剑,优点:加快网站的访问速度。因为缓存的数据存在于
应用服务器的内存中,当缓存对象形成后,第二次访问的时候,不需要再从数据库
中将数据取到APP服务器上 。这样速度自然块。
缺点:01.占用了服务器的内存,服务器内存是很稀缺的资源。如果对页面的大量数据
启用缓存,那么可能造成服务器崩溃。
02.有一些网站不适合使用缓存技术, 例如股票,天气等需要实时更新数据的
网站,如果启用缓存,可能造成网站的数据有延迟不准确。
哪些网站适合缓存,比如当当网首页???
缓存分两种:
01.对集合的缓存
02.对整个页面的缓存
缓存一般有两种方式,如果我们需要进行更细粒度的控制,比如控制缓存数据(
例如,某个泛型集合,可以使用通过在Controller中定义一个属性来设置缓存数据。
可以通过如下方式,设置缓存。HttpContext.Cache["key"]=值;
上述方式无法进行缓存过期设置,所以我们引入了Add方法和Insert()方法。
Insert方法中可以设置缓存过期时间,真实开发中,一般使用绝对过期时间。
用法如下:
HttpContext.Cache.Insert(CACHEDUSERS, items, null,System.Web.Caching.Cache.NoAbsoluteExpiration,TimeSpan.FromSeconds(10));
HttpContext.Cache.Insert(CACHEDUSERS, items, null, DateTime.Now.AddSeconds(15),System.Web.Caching.Cache.NoSlidingExpiration);
参数一:key
参数二;value
参数三:缓存依赖,没有为null
参数四:过期时间
参数五:设置是绝对过去还是滑动过期。取值:如果是NoSlidingExpiration,证明是绝对过期,如果是
NoAbsoluteExpiration :滑动过期时间
)
//缓存登陆数据
public const string CHACHEDUSERS = "FriendsUsers";
public List<User> UserList
{
get
{
List<User> list= HttpContext.Cache[CHACHEDUSERS] as List<User>;
if (list==null)
{
list = db.Users.ToList();
HttpContext.Cache.Insert(CHACHEDUSERS, list, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(10));
}
return list;
}
}
缓存页面:
[OutputCache(Duration=15)] 设置的也是绝对过期时间
绝对过期时间和滑动过期时间:
刚才我们设置了15s后过期,那么从用户第一次开始访问,往后数15秒,
就会在15s之后过期
滑动过期时间:从用户最后一次访问页面的时间开始往后推15s。
07.ajax
08.Forms进行网站验证
09.安全相关
10.过滤器
在ASP.NET MVC中,过滤器就是一个继承自FilterAttribute的类,或者实现了
IActionFilter、IResultFilter、IException或者是IAuthorizationFilter。
AOP思想:
11.单元测试
****************************************错误页定制************************************************
12.错误页定制
第一种方式:
步骤一:就是在网站的web.config配置文件中,找到
<system.web>节点,在该节点中添加如下代码。
<customErrors defaultRedirect="~/ErrorPage.htm" mode="On">
<error statusCode="404" redirect="~/FileNotFound.htm"/>
</customErrors>
步骤二:在网站的根目录下创建对应的静态错误页
步骤三:重点,一定要对Views/Shared/Error.cshtml文件重新命名,否则自定义的错误页不会显示。
方式二:针对控制器或者控制器下的某个Action来构建错误页。
在Web.config文件中进行如下配置
<customErrors mode="On">
</customErrors>
** mode的取值:
On表示启用自定义错误
Off表示禁用自定义错误
RemoteOnly向远程客户端显示自定义错误,并且向本地主机显示 ASP.NET 错误
[HandleError(ExceptionType=Exception,View="Error")]
//默认ExceptionType取值为Exception,View取值为Error
public ActionResult Index()
{
//查询所有的出版社信息
var query = db.Publishers.Select(c=>c);
return View(query);
}
创建一个静态页面,位于对应的Controller所在的View文件夹中
************************************************************************************************
指定Order属性
**:01.如果某个Action设置了多个HandleErrorAttribute,Order属性可以用来确定使用哪个过滤器.
其值可以设置为从-1(最高优先级)到任何正整数之间的整数来标识其优先级,值越大,
优先级别越低.Order属性遵循以下规则:
*:01.应用到Controller上的过滤器将会自动应用到该Controller的所有Action上.
*:02.如果Controller和Action都应用了HandleErrorAttribute,那么只要Order属性值相同,
将会先执行Controller上的过滤器,而后才会执行Action上的过滤器.
*:03.对于相同Order属性的过滤器,其执行先后次序不定.
*:04.如果没有指定Order属性,则默认为-1,这意味着该过滤器将比其他的过滤器优先执行,
除非其他过滤器指定了Order为-1.
*:05.如果有多个过滤器可适用,那么第一个可以处理该异常的过滤器会被首先调用,
然后针对该异常的处理将会终结.
***********************************************************************************************
********************************在View中获取异常信息***************************************************************
ASP.NET MVC框架将异常信息存储在ViewDataDictionary中来传递给Error视图,
该ViewDataDictionary的Model属性即是ExceptionContext类的一个实例,
这个ViewData有下面几个键:
ActionName:目标Action方法的名称
ControllerName:目标Controller的名称
Exception:异常对象.
船停在港湾是很安全的,但那不是造船的目的!
IAuthorizeFilter
IActionFilter
IExceptionFilter
IResultFilter
系统默认过滤器:
[Authorize]
[HandleError]
[OutputCache]
同一个动作方法应用过滤器时,决定执行顺序的因素?
解析:01.类过滤器优先于Action
02.同一个Action上的多个过滤器有Order时,Order值越小,执行优先级越高,默认为-1最高 。
03.在当前的Controller重写OnActionExecuting时,优先级高于其他任何通过特性过滤的内容
***************************01.XSS,CSRF攻击************************************************************
**
问题一:ASP.NET MVC中常用的过滤器有哪些?
解析:Authorization Action Result Exception
问题二:应用程序缓存和输出缓存有什么区别?
解析:应用程序缓存是对集合数据的缓存,输出缓存是对整个页面的缓存。
问题三:同一个动作方法应用过滤器时,决定执行顺序的因素?
解析:按Order属性值从小到达执行。
问题五:解释CSRF的概念?
解析:CSRF全称是Cross Site Request Forgery,即跨站请求伪造。简单地说,就是假冒正常的http请求。
问题六:Moq 在单元测试中有什么用?
解析:模拟
1.
1.XSS漏洞和防御
XSS攻击原理:XSS英文全称Cross-site scripting,即跨站脚本。
首先是恶意用户向某个网站的页面植入破坏性代码,植入的方式,一般是通过表单提交。
授课步骤:通过一个评论Demo来用普通的文本框提交数据,这时候会出现“检测到存在危险的Request.Form”值。然后我们不检查输入,在Action中进行如下设置。
[ValidateInput(false)],然后我们换成了eckeditor,
假设登录页面有个输入用户名和密码的输入框,可以有很多Xss/csrf/注入钓鱼网站/SQL
输入用户名 : >"'><script>alert(1779)</script>
输入用户名: usera>"'><img src="javascript:alert(23664)">
输入用户名: "'><IMG SRC="/WF_XSRF.html--end_hig--begin_highlight_tag--hlight_tag--">
输入用户名: usera'"><iframe src=http://demo.testfire.net--en--begin_highlight_tag--d_highlight_tag-->
2.CSRF漏洞和防御
你在光大银行:可有可无
EMS:
[TestMethod]
public void TestListFriends_UnGrouped()
{
FriendController friendController = new FriendController();
var mock = new Mock<ControllerContext>();
mock.Setup(p => p.HttpContext.User.Identity.Name).Returns("1");
friendController.ControllerContext = mock.Object;
//执行
PartialViewResult result = (PartialViewResult)friendController.ListFriends(-1);
//断言
Assert.IsNotNull(result);
Assert.IsNotNull(result.ViewBag.Friends);
}
//单元测试
单元测试是由开发人员来测试,主要是对业务方法的测试。测试的核心就是断言类Assert,
他提供了一堆静态方法供程序员使用。
不需要提供上下文的:直接创建出一个单元测试项目,添加对被测项目Book的引用。
需要提供上下文的:利用第三方的Moq.dll框架实现
*01.引入被测项目
*02.在测试工程中,创建一个lib文件夹,放入Moq.dll文件,并且添加引用
*03.一定要在测试工程的App.config文件的ConnectionString节点中,添加连接字符串
(从被测项目的根目录的Web.config获取)
*04.在打有[TestMethod]
//XSS
CSRF:必须在用户正常登陆网站的前提下实施的。
本质上是在需要提交表单的页码隐藏了令牌XXXToken,在控制器的Post方法中,对令牌进行校验。
在IIS中发布MVC应用,和之前的ASP.NET方式一样