为什么使用验证控件
当需要让用户输入数据时,用户有可能输入不符合我们程序逻辑要求的信息,所以我们要对输入进行验证。 客户端验证(用户体验,减少服务器端压力) 服务器端验证(防止恶意攻击,客户端js很容易就可以被绕过) 必须要对用户输入的数据进行合法性校验,这些校验逻辑很多是重复的,比如字段不能为空、必须为日期格式、数字不能大于100等,而且要同时在客户端和服务器端校验。
验证控件
ASP.Net提供了如下的控件: RequiredFieldValidator:字段必填; RangeValidator:值在给定的最大值、最小值之间; CompareValidator:用于比较两个值的关系是否满足要求或者是否是指定类型的数据; RegularExpressionValidator:校验数据满足正则表达式; CustomValidator:自定义验证。 ASP.NET提供了验证控件 轻松实现用户输入的验证,且与用户浏览器无关 由在客户端或服务器中运行的验证代码执行 多种验证控件,验证数据更加简单方便
RequiredFieldValidator
作用:非空验证控件,要求必须输入内容 ControlToValidate:设定要验证的控件。该 ID 必须引用与验证控件相同的容器中的控件,该控件必须在同一页或同一用户控件中,或必须在模板化控件的同一模板中。 如不设置此属性,会引会异常。 要对输入控件进行验证,必须将 System.Web.UI.ValidationPropertyAttribute 属性应用于该控件。 System.Web.UI.WebControls.DropDownList System.Web.UI.WebControls.FileUpload System.Web.UI.WebControls.ListBox System.Web.UI.WebControls.RadioButtonList System.Web.UI.WebControls.TextBox System.Web.UI.HtmlControls.HtmlInputFile System.Web.UI.HtmlControls.HtmlInputPassword System.Web.UI.HtmlControls.HtmlInputText System.Web.UI.HtmlControls.HtmlSelect System.Web.UI.HtmlControls.HtmlTextArea
RequiredFieldValidator
Text属性:当验证控件为空的时候,显示的错误消息。消息可以设置文本也可以设置Html代码和js代码 ErrorMessage:提供给ValidationSummary控件,如果Text属性为空,也会取ErrorMessage的值。 Display属性,用来决定如何显示错误信息。三个值:Static:没有错误信息的时候控件的visiblity样式为hidden来实现隐藏;Dynamic:没有错误信息的时候控件的display样式为none来实现隐藏。这两者的区别是display:none和visiblity:hidden隐藏的区别是visiblity:hidden隐藏控件仍然会占据空间,而display:none隐藏则不会占空间。Display属性还可以设置为None(用来配合后面讲的ValidationSummary) SetFocusOnError:当验证不通过时,是否让该控件获得焦点 InitialValue:设置验证控件的默认值 当客户端禁用js时,点击按钮发生回传,客户端验证没有触发。 Page.IsValid指示页面验证是否成功 用于客户端验证失败情况下 更加安全 服务器端的验证事件发生在Page_Load事件之后
CompareValidator
Operator属性,比较操作符,可选值DataTypeCheck、Equal、GreaterThan、GreaterThanEqul、LessThan、LessThanEqual、NotEqual。 ValueToCompare,所比较的运算符右边的值。ControlToCompare,设定与另外一个控件进行比较。 Type属性为数据类型(String、Integer、Double、Date、Currency等)。 用法一 两个控件比较 (Demo:比较两次输入的密码是否相同) ControlToValidate (符号左边的) ControlToCompare 待比较的控件(符号右边的) Operator 比较操作 Type属性 用法二 与一个定值进行比较(Demo:年龄必须大于18岁) ValueToCompare Operator 比较操作 Type属性
CompareValidator
用法三 类型检查 (Demo 年龄必须为数字) ControlToVlidate 待检查类型的控件id Operator DataTypeCheck Type 当验证控件所指定的控件内容为空时,除了RequiredFieldValidator会触发验证,其他验证控件都不会。因为我们有这样的需求,在填写一张表的时候,有必填项有非必填项,非必填项可以不填写值,但如果填写,就一定要正确。所以除非空验证控件之外的其他验证控件所验证的控件,如果为空,则不会被查检,反之只要填写内容,为了保证正确,就要检查。所以对于年龄大于18岁并且又要求年龄必须填写这一需求,我们要使用非空和比较两个验证控件来实现。
RangeValidator
RegularExpressionValidator
RangeValidator 范围验证控件(Demo:订10天以内的火车票) MinimumValue、MaximumValue属性:为最大、最小值 Type属性同ComareValidator RegularExpressionValidator 正则表达式验证控件 ValidationExpression 正则表达式 Vs提供常用的正则表达式 Demo:身份证 QQ号 Email地址 用户名在3-10位之间 CustomValidator,自定义验证控件。当ASP.Net内置的验证控件无法满足要求的时候可以使用CustomValidator。 其他: CausesValidation: 指明该按钮提交是否触发验证 验证控件的分组
ValidationSummary
使用Validator错误消息会显示在放置的位置,这样做因为有两个可能的问题:如果表单非常大,用户看不到全部的错误消息,希望把错误消息集中显示在提交按钮旁边;如果错误信息非常多错误信息会散落各地,希望能集中显示。 ValidationSummary控件用来集中显示错误消息。每个验证控件都有ErrorMessage、Text两个属性,ErrorMessage是用来显示到ValidationSummary中的值,Text是用来显示到Validator位置的值,如果Text为空,则ErrorMessage会同时显示到ValidationSummary和控件的位置。一般Text的值要简短,因为直接显示到控件的位置,能知道指的是哪个控件;ErrorMessage要详细一些,这样才能从ValidationSummary每条错误信息中读取值出来。 ValidationSummary的属性:DiplayMode,显示模式,ShowMessageBox显示警告对话框。 ShowSummary显示错误汇总 验证控件的Display:none时,只在汇总控件中显示错误消息
练习
练习:实现注册页面(写校验逻辑就行):用户名(必填,长度必须在3—10之间),密码(必填,长度在3—9之间),再次输入密码(必须和密码一样),邮箱(选填,必须符合邮箱格式),入学日期,毕业日期(必填,用TextBox,毕业日期要大于入学日期,小于当前日期),性别(用DropDownList,必选,选择项:“请选择性别”、”男”、”女”、”保密”),生日月份(必填,TextBox)、日(必填,TextBox,校验日期中日的数值在合法范围内,{1,3,5,7,8,10,12}是31天,{4,6,9,11}是30天,2月假设最大固定是29天不考虑闰年平年。,CustomValidator)。 共性问题? Ajax中如何使用验证控件? 非空验证控件的触发 RangeValidator 与 长度 待验证的控件和验证控件一定要放在同一个模板中
Page_ClientValidate //使页面上的所有验证控件执行客户端验证 ValidatorValidate //执行某一个验证控件的验证方法 Page_IsValid属性 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG 全局的配置文件 machine.config web.config 如果一个页面上有验证控件,当点提交按钮时,执行过程如下:(在客户端不禁用js脚本的情况下) 1)在客户端,依次调用页面上每一个验证控件的验证方法 2)如果页面上的所有验证控件在客户端的验证都成功之后,才把数据提交到服务器. 3)在服务器端先执行Page_Load方法,再执行所有验证控件的服务器端的验证方法,再执行提交按钮的click事件 ControlToValidator > ControToCompare
导航控件和母版
导航控件:
给用户一个能够指示自己目前位置的一个地图 方便用户跳转 传统的实现方式: 包含文件 用户控件 硬编码 在asp.net中提供了面包屑导航控件 SiteMapPath需要提供站点地图 站点地图是基于xml格式的 站点地图的文件名必须为:Web.sitemap TreeView一般用于左侧的树型菜单导航 可以基于一个xml文件 也可以通过写代码来操作 Menu一般用菜单导航
为什么需要模板
网站的布局通常是统一的,上面是Logo、菜单条、下面是公司地址、版权声明等。如果每个页面都重复做这些功能的话:重复性劳动、一旦修改那么每个页面都要修改。可以使用FrameSet(框架集)技术来解决,但是FrameSet技术不灵活,而且很难进行SEO,所以只有部分内网系统还在用FrameSet,.Net中一般用母版(MasterPage)技术来解决这个问题。 MasterPage是这样一种技术,把页面布局画好,在变化的内容部分“留空”,留空的部分由子页面填充内容,这样子页面只要填空就行,不用重复设计页面结构,一旦要修改页面结构修改母版页就可以,这样所有页面都会变化。母版页“挖坑”,具体页面“填坑”。母版页、具体页面中几乎可以使用所有的普通WebForm页面能够使用的技术。
添加一个“母版页”,使用<asp:ContentPlaceHolder>挖坑,新建的母版页已经自动设置了两个ContentPlaceHolder,还可以添加更多的ContentPlaceHolder。在id="head"前面后面都加入一些script,在id="ContentPlaceHolder1"前后也加入一些内容。 创建使用母版页的具体页面,WebSite是新建“Web窗体”的时候勾选“选择模板页”,WebApplication是新建“Web内容窗体”,然后选择页面使用的母版页(一个项目内可以创建多个母版页,比如新闻频道用一个母版页,视频频道用另外一个母版页)。 使用母版的具体页面和普通aspx页面的不同是:@Page区域用MasterPageFile属性表示页面使用哪个母版页,页面不包含html等内容,只定义了<asp:Content这些填坑的内容。<asp:Content>就是用来在具体页面中对母版页进行填坑的,ContentPlaceHolderID为这个Content要填母版页中的哪个坑,对应母版页中ContentPlaceHolder的Id
具体页面可以对母版页填坑也可以不填坑,如果不填坑则显示<asp:ContentPlaceHolder>中定义的默认内容。 案例:实现上导航菜单、下版权声明,左侧功能面板,右侧为具体的内容的模板,然后分别实现关于我们和登录界面。 在母版页中使用超链接、图片地址等的时候需要注意路径问题,在母版页中的runat=server控件的链接地址、图片地址等会被解析为相对于母版页的地址,而客户端HTML控件ASP.Net引擎是直接输出的,因此是解析为相对于具体页面的地址。建议使用服务端控件,如果不能使用服务器控件,那么可以在aspx页面中调用ResolveClientUrl 、ResolveUrl进行虚拟路径的转换 每个具体页设置不同的标题,只要在具体页面的@page中设置Title属性即可。可以在具体页中通过Master.FindControl来定位母版页中的控件然后对母版页中的控件进行操作,比如在一个具体页面中将母版页中的一个控件隐藏。
三层架构(3-tier application)
三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。 1、表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得。 2、业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。 3、数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找等。 宠物商店(Pet Shop) 微软展示.NET企业开发的范例 与Sun的PetStore的商业竞争 一个小型的电子商务案例 体现了微软推广的开发思想和设计理念 分22个项目,经典的系统,从设计的思想到最好的编码,学习参考价值很高
优点 1、开发人员可以只关注整个结构中的其中某一层; 2、可以很容易的用新的实现来替换原有层次的实现; 3、有利于标准化; 4、利于各层逻辑的复用。 5、更加安全 缺点 1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。 2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码,因为UI层是不允许直接访问DAL层的。 3、增加了开发成本
三层架构创建
创建四个项目,表现层项目类型为WebApplication,业务逻辑层、数据访问层、模型层均为类库。 添加引用:表现层引用业务逻辑层。业务逻辑层引用数据访问层。由于模型层负责在三层之间传递数据,所以每一层都要引用模型层。有时候还会有一个公共项目,每一层都会引用。 模型层(ORM):数据库中每一个表都在模型层创建一个类,一般情况类的名称和数据表名相同,如果数据库中表名为复数型式,一般模型层类名为单数。表中的字段在类中建成属性。 数据库访问层:每一个模型层的类,都在数据库访问层对应一个类,该类的命名一般为模型层中的类名+Services,此类中仅包含对该表的CRUD的方法。 业务逻辑层:业务逻辑层中的类名由业务决定,一般情况下也可以与数据访问层的类相对应,类名一般由表名+Manager命名。 表现层:由需求网页构成,调用业务逻辑层的方法。该层一般不出现SQL语句相关的内容,就算出现,也不能出现能执行的SQL语句。
根据需求设计表
某酒店为提高管理效率,采用全新的计算机网络和信息管理系统,对基础设施和业务流程进行智能化控制。“基础设施”用于对客房类型、客房价格、客房信息等进行初始化设置 1、“客房类型设置”用于设置客房的分类信息,包括分类名称、分类价格、是否加床、加床价格、备注等 2、“客房信息设置”用于设置客房的初始信息,包括房间号、房间所属类型、房间状态、床数、客人数、描述等
模型层中外键的处理
两种方式: 为实体类添加状态id属性,存储状态id 为实体类添加状态属性,存储状态对象 Demo:演示如何创建三层结构的项目 Demo:用动软创建三层结构项目
GridView、DataList、DetailsView
两种数据绑定方法
方法一:得到数据后,赋给DataSource属性,然后执行控件的DataBind()方法。Demo:DropDownList的数据绑定 方法二:使用数据源控件,赋给数据绑定控件的DataSourceId。 DataSource属性和DataSourceId不能同时使用。如果先用数据源控件获得数据并绑定显示,在程序中又需要改用手动绑定的方法显示数据,要先给DataSourceId赋null
GridView的使用1
AllowPaging属性:是否自动分页 AutoGenerateColumns属性:是否自动生成列 PageIndex属性:当前页 PageSize属性:页大小 Rows属性:所显示数据行的集合 EditIndex 属性:指用户正在编辑的行,如果没有编辑任何行,设置为-1 列设置中可选字段的用法: BoundField:显示要绑定的数据 CheckBoxField:以CheckBox显示,一般与数据库中bit类型绑定 HyperLinkField:以超链接形式显示,一般链接地址与绑定数据有关系 ImageField:以图片形式显示,一般图片地址与绑定数据有关系 ButtonField:以按钮形式显示 CommandField:包含能够触发增删改事件的按钮,其实就是一个普通按钮,不同的是CommandName的设置。
CommandName为Update触发更新事件RowUpdating和RowUpdated事件,要在此事件中设置EditIndex CommandName为Cancel触发点编辑后的取消事件RowCancelingEdit事件,要在此事件中设置EditIndex=-1 CommandName为Delete触发删除事件RowDeleting和RowDeleted事件 如果启用了自动分页功能,AllowPaging=true,当点击上一页和下一页时,当触发PageIndexChanging事件,要在此事件中设置PageIndex
如果使用手动绑定的方法,更新和删除的操作要写在其触发的ing事件内。 如果使用了数据源控件来绑定,那么在更新和删除的ing事件触发后,数据源控件会自动调用其指定的更新和删除方法,然后再触发ed事件。可以根据ed事件中e.Exception属性,来判断是否在更新和删除的过程中有错误产生。 GridView的高效分页,其实这个功能是数据源控件提供的,设置以下属性: EnablePaging=true; 启用数据源分页 MaximumRowsParameterName StartRowIndexParameterName SelectCountMethod SelectMethod 删除自动生成的SelectParameters的两个参数
DataList和DetailsView
DataList:一般只用于展示数据,他只能通过设置模板来实现数据绑定。DataList不支持排序和分页功能,实现分页和排序方法见后面案例。 DetailsView:一般用于展示一条数据,同时也可以实现更新和插入操作。经常用于主细表当中。 各数据源控件之间的比较: 效率:GridView<DataList<Reapter GridView一般用于以网格(表的)形式显示数据。 DataList用于以Html自定义(模板)来显示数据 Reapter数据绑定后不产生任何模板中没有的代码,所以常用于div+Css的网页布局或绑定生成xml文件 FormView和DetailsView类似,前者要自定义布局,后者一般用于固定布局
缓存
整页缓存 1)浏览频繁 2)短时间内不会更新的网页 浏览时需要大量计算的网页 根据控件缓存: VaryByControl 根据参数缓存:VaryByParam 局部缓存 整页缓存后替换 应用程序级缓存: 依赖于数据库的缓存。 基于轮洵和通知 测试:单元测试 WEB测试 负载测试
网站发布
数据库
附加 分离 备份 为每个应用创建一个用户 修改连接字符串 c/s app.config
配置文件
ASP.NET的两种配置文件 machine.config:提供整个机器的默认配置,对该文件的修改将影响所有本机的站点 web.config:一般用于应用程序级别的配置文件,对其修改不影响其他站点,也可以用于站点下的子目录 配置文件 基于XML,配置节元素区分大小写 可读可写(相比二进制的配置方便) 修改配置后,ASP.NET自动检测变化,不需要手动重启服务器或IIS
配置文件(就近原则
安全验证
安全控制 身份验证,验证用户是否拥有相应的身份 权限控制,控制各种身份的用户所拥有的权限 身份验证方式 Windows身份验证 Passport身份验证 Forms身份验证 <system.web> <authentication mode="Forms"> <forms name="AdminUser" loginUrl="~/Admin/AdminLogin.aspx" timeout="60"> </forms> </authentication> </system.web>
授权与拒绝
授权 allow,允许 deny,拒绝 特殊符号:“ * ”代表所有用户,“ ? ” 代表匿名用户 <system.web> <authorization> <deny users="?"/> <allow roles="admin"> <deny users="*"/> </authorization> </system.web>
配置文件
自定义错误页面: <customErrors mode="RemoteOnly" defaultRedirect="ErrorPage.htm"> <error statusCode="404" redirect="FileNotFound.htm" /> </customErrors> 允许调试 <compilation debug="true"/> 应用程序运行时配置 <httpRuntime enable="true" executionTimeout="90" maxRequestLength=“4096” /> 单位KB
服务器配置
先装IIS,后安装dotnetframework Aspnet_regiis ftp serv-u
发布网站
编译生成Release版 发布网站 修改Web.config中配置: compilation设为false 修改连接字符串 customErrors 申请域名和购买服务器或虚拟主机 将域名解析到服务器,注意:解析不是立即生效的,也不是同步的。 在服务器上绑定网站域名 将网站上传到服务器上 附加数据库
发布网站
如果你的是服务器,还要注意下面的问题: 上传文件夹不给执行权限: 在iis管理器中找到上传文件夹,选择属性--执行权限,设置为“无”。这样哪怕利用漏洞上传了可执行代码到上传文件夹,也无法执行。 取消所有文件夹的浏览权限,防止用户查看网站的文件列表,在iis管理器中找到主站节点→属性→主目录→取消“目录浏览”。 后台文件夹只允许管理员的IP访问,文件夹→属性 IIS管理中,Web服务器扩展,只允许asp.net那几个,其他的CGI、ASP等全部禁止。
缓存依赖
依赖于文件内容CacheDependency cDep = new CacheDependency(filePath); 依赖于数据库内容(轮询机制/通知机制)一:轮询机制 1.在数据库新建版本表。2.在数据库新建触发器(比如在新闻表上新建)。3.使用C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727中的aspnet_regsql.exe:注册:aspnet_regsql -S . -E -ed -d 数据库名 -et -t 版本表名删除:aspnet_regsql -S . -E -d 数据库名 -dt -t 版本表名取消数据库缓存依赖: aspnet_regsql -S . -E -dd 数据库名数据库名 列出已注册表:aspnet_regsql -S . -E -d 数据库名 –lt4.配置web.config(见备注)5.数据库依赖对象SqlCacheDependency cDep = new SqlCacheDependency("GSSMS", "CacheDep");