一、画好用户登录界面
同时换下请求的地址。
获取用户信息及判断代码插入位置:
一、画好用户登录界面
同时换下请求的地址。
获取用户信息及判断代码插入位置:
<%@ WebHandler Language="C#" Class="_06_login" %> using System;
using System.Web; public class _06_login : IHttpHandler { public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
//在服务其上获取用户输入的用户名和密码判断是否正确。
string name=context.Request.Form["name"];
string pwd=context.Request.Form["pwd"]; if (name=="admin"&&pwd=="admin")
{
context.Response.Write("登录成功");
}
else
{
context.Response.Write("登录失败");
}
} public bool IsReusable {
get {
return false;
}
} }
二、登录演示
如果用户登录失败了,用户想重新登录,为什么要把判断写到服务器上面呢?JS判断没法判断数据库去,所以只能放到服务器上面。
还想在用户登录失败之后,返回登录页面怎么做呢?
第一种解决办法拼html。
登录失败显示登录界面代码插入位置:
<%@ WebHandler Language="C#" Class="_06_login" %> using System;
using System.Web;
using System.Text; public class _06_login : IHttpHandler { public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/html";
//拼html
StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.Append("<body>");
//action就是提交给自己
sb.Append("<form action='06-login.ashx' method='post'>");
//双引号改成单引号
sb.Append("用户名:<input type='text' name='name' />r/>");
sb.Append("密码:<input type='text' name='pwd'/><br/>");
sb.Append("<input type='submit' value='login'/>");
sb.Append("</form>");
sb.Append("</body>");
sb.Append("</html>"); //在服务其上获取用户输入的用户名和密码判断是否正确。
string name=context.Request.Form["name"];
string pwd=context.Request.Form["pwd"]; if (name=="admin"&&pwd=="admin")
{
context.Response.Write("登录成功");
}
else
{
context.Response.Write("登录失败");
}
//输出登录
context.Response.Write(sb.ToString());
} public bool IsReusable {
get {
return false;
}
} }
三、登录失败提示用户演示
想下登录失败之后怎么就更省事儿,更方便?
登录失败之后就把用户输入的用户名和密码清空了,这样不好,用户就不知道自己输入的是什么了。
我们做个把用户名显示出来的界面。
刚才登录之后,为什么输入的信息都没了呢?
四、为什么文本框里面没有值
四、为什么文本框里面没有值
五、给文本框返回值的写法
六、返回值的演示
我们都是运行html,要是直接运行一般处理程序会直接显示登录失败。
这样写特别的不舒服,得不停的拼html字符串。
七、不拼html,直接运行一般处理程序
八、再改下html页
运行html和一般处理程序,我们发现都有问题,先看下运行html。只有第一次运行的时候有问题,怎么解决呢?
只能再ashx里面来完成,第一次的时候替换成空,什么时候是第一次呢?
以表单的方式,读取的时候是空,说明是第一次。第一次请求时get请求。
九、帮我们判断是第几次
十、判断页面是否是首次加载
写完之后,运行一般处理程序就行了。
十一、最终效果演示
十二、登录过程图
为什么用隐藏域呢?如果这不放占位符,通过JavaScript的方式呢?演示原理的,演示webform里面的一个内容,这个内容就叫做隐藏域。
十三、第一次是get请求
十四、post请求
现在我们再按F5
十五、提示信息
十六、这是怎么回事儿
这样会给我们带来什么不方便的地方呢?交易的时候post会带来错误的,点击重试又买了一次。添加的时候,点击F5提交到数据库,点击F5又提交到数据库一次。怎么解决呢?跳转到成功页面。跳转的时候是get请求,再按F5就不会出这个问题了。
下面我们看下做什么事情的时候用get请求,做什么事情的时候用post请求。
还可以设定<form>的method属性指定表单提交方式,get(默认值)是通过URL传递表单值,post传递的表单值是隐藏到http报文体中,url中看到不。
get和post的区别(常考):get是通过url传递表单值,post通过url看不到表单域的值;get传递的数据量是有限的,如果要传递大数据量不能用get,比如type=“file”上传文章、type=“password”传递密码或者<textarea>发表大段文章,post则没有这个限制;post会有浏览器提示重新提交表单的问题,get则没有(加分的回答)。对于Post的表单重新敲地址栏再刷新就不会提示重新提交了,因为重新敲地址就没有偷偷提交的数据了。Post方式的正确的地址很难直接发给别人。
Get方式URL数据格式。服务端文件名后跟着“?”,由于客户端可能向服务器端提交多个键值对,键值对之间用“&”进行分割,如果URL中有汉字、特殊符号等,则需要对URL进行编码。
表单域只有设定了name的才会被提交给服务器(用get方式看的清楚)。如果给submit按钮设定name,那么按钮的value也会被提交给服务器
【刷新】。
十七、对URL进行编码
下面我们做个数字自增的练习:
要求:页面上放一个文本框,一个按钮,文本框默认是0,点一次按钮文本框加1.
写好的html页面插入位置:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<form action="07-数值自增.ashx" method="post">
<input type="text" value="@name" />
<input type="submit" value="click" />
</form>
</body>
</html>
初步写好的ashx插入位置:
<%@ WebHandler Language="C#" Class="_07_数值自增" %> using System;
using System.Web; public class _07_数值自增 : IHttpHandler {
//1.定义一个变量
int n = ;
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
//3.把页面输出出来
string path = context.Request.MapPath("07-数值自增.htm");
string html=System.IO.File.ReadAllText(path);
//2.输出
n++;
context.Response.Write(n);
context.Response.Write(html);
} public bool IsReusable {
get {
return false;
}
} }
这个时候写成这个样子,数值不会自增,这是什么原因呢?第一次请求是一,服务器不会把值存起来的.怎么解决呢?
初始化的时候,让文本框的值等于0,再点按钮的时候,post回来了,把文本框的值取出来,进行++,重新放回去。每一次执行完成之后,都把上一次的值重新放到文本框里面来,下一次请求的时候会把值post给服务器,服务器读取完++再重新放回来。什么时候给它的值付成0呢?第一次的时候,点按钮的时候++。所以用到隐藏域。
十八、放个隐藏域
读取隐藏域并判断是否是第一次加载
<%@ WebHandler Language="C#" Class="_07_数值自增" %> using System;
using System.Web; public class _07_数值自增 : IHttpHandler { public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/html";
//1.定义一个变量
int n = ;
//3.把页面输出出来
string path = context.Request.MapPath("07-数值自增.htm");
string html=System.IO.File.ReadAllText(path);
//读取隐藏域,判断是否是第一次加载
string viewstate=context.Request.Form["_viewstate"];
if (!string.IsNullOrEmpty(viewstate))
{
//post
string txt=context.Request.Form["txtNum"];
n = int.Parse(txt);
n++; }
//给文本框赋值
html = html.Replace("@num", n.ToString());
//2.输出
context.Response.Write(html);
} public bool IsReusable {
get {
return false;
}
} }
十九、同时,我还修改了一下html代码。
二十、数值自增演示
现在我们做的这个是刷新页面的数值自增,后面我们还要带领大家做无刷新。
下面我们再做几个练习:
练习:用ashx实现加法计算器。常见错误:type=submit才会自动提交表单,type=button不会自动提交。从ashx启动和从html启动的区别
二十一、做好准备工作
计算加法的一般处理程序代码插入位置:
<%@ WebHandler Language="C#" Class="_08_add" %> using System;
using System.Web; public class _08_add : IHttpHandler { public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/html";
//1.读取静态模板
string path = context.Request.MapPath("08-add.htm");
string html = System.IO.File.ReadAllText(path); //2.判断页面是否是首次加载
string viewstate=context.Request.Form["_viewstate"];
if (!string.IsNullOrEmpty(viewstate))
{
string num1=context.Request.Form["txtNum1"];
string num2=context.Request.Form["txtNum2"]; int num3 = int.Parse(num1) + int.Parse(num2); //把两个文本框的值重新替换回去,还有计算之后的值也返回去。
html = html.Replace("@num1", num1).Replace("@num2", num2).Replace("@num3", num3.ToString());
}
//如果是第一次加载的时候把文本框的值付成空。
else
{
html = html.Replace("@num1", "").Replace("@num2", "").Replace("@num3", "");
}
//3.输出
context.Response.Write(html);
} public bool IsReusable {
get {
return false;
}
} }
二十二、加法计算演示
如果出问题了,而且在代码里面一眼看不出来,这个时候要设个断点调试.一般处理程序怎么进行调试呢?
二十三、这样调试进不去断点
二十四、调试过程
练习:实现div内文本的自增。因为服务器不记得上次给浏览器的值是什么,而且不像input那样会将上次的值重新提交回来,因此浏览器需要用一个隐藏字段将上一次的值保存下来。代码见备注
二十五、写好html页
二十六、实现div内文本的自增代码
二十七、div内文本自增演示
http无状态,每次请求都是由一个新的页面对象来处理请求。如果把value搞成static可以实现,但是两个用户访问的话就会串了。而用Input方式的话两个人各自点各自的,不会互相影响。
非表单元素无法将客户端的元素值传递给服务器端,即使是表单元素也只能传递value值,对于其他属性值比如背景颜色、大小等也是无法传递的,因此对于这些值都要存在隐藏字段中。
下面我们通过之前我们讲解的三层,做个照片列表。
二十八、新建解决方案
这样做方便管理三层里面的几个项目。
二十九、对应生成文件夹
下面创建三层那几个项目,从下往上创建。
三十、model
三十一、再创建DAL
再创建BLL
三十二、新建网站
这块在浏览的时候要找对文件夹
三十三、找对文件夹
这个命名空间不好看,中间加个点。这里学习微软起个*的命名空间。
三十四、属性
这样再添加一个model类的时候就有点了。
三十五、把没用的类都删掉
下面我们添加引用:
三十六、添加引用一
三十七、添加引用二
三十八、添加引用三
建好之后先写model,我们这里就不写了,直接把以前写好的拷贝过来。
三十九、直接拷贝过来
检查下命名空间就行了。
先写dal写个SQLHelper。这里我们用什么写什么,就去做那个照片列表。
四十、别忘了添加引用
建个配置文件,建到UI,运行谁,配置文件就放到哪个里面。我们发现配置文件有了,打开它。
四十一、忘了的话打开这儿
四十二、写好配置文件
四十三、写好SqlHelper
下面我们操作那个photos表,把表中所有的数据查询出来,生成一个照片列表。
四十四、再创建一个类操作photo表
拿数据的DAL代码插入位置:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Data;
using MyPhotos.Model; namespace MyPhoto.DAL
{
public class PhotosDAL
{
//1.拿到照片数据
public List<Photos> GetAllPhotos()
{
List<Photos> list = new List<Photos>();
string sql = "select*from photos";
//2.执行
SQLHelper helper = new SQLHelper();
DataTable dt = helper.GetTable(sql);
//把关系转换成对象
foreach (DataRow dr in dt.Rows)
{
Photos p = RowToPhotos(dr);
list.Add(p);
}
return list;
}
//3.写个方法
private Photos RowToPhotos(DataRow dr)
{
Photos p = new Photos();
p.PClicks = Convert.ToInt32(dr["PClicks"]);
p.PDes = dr["PDes"].ToString();
p.PDown = Convert.ToInt32(dr["PDown"]);
p.PId = Convert.ToInt32(dr["PId"]);
p.PTime = Convert.ToDateTime(dr["PTime"]);
p.PTitle = dr["PTitle"].ToString();
p.PTypeId = Convert.ToInt32(dr["PTypeId"]);
p.PUp = Convert.ToInt32(dr["PUp"]);
p.PUrl = dr["purl"].ToString();
p.PUserId = Convert.ToInt32(dr["PUserId"]);
return p;
}
}
}
一句话写完BLL层。
四十五、写好BLL
我们底层的代码就写完了,大家可以参考我们之前的关于三层的知识进行复习。
我们主要的任务就是写UI层的代码。
添加个一般处理程序:
为了好看一点再建个模板。
四十六、做好静态页
写好一般处理程序后我们运行一下,发现报错了。
四十七、常见的报错一
编译一下,就是重新生成解决方案。
四十八、常见的报错二
四十九、看到照片列表
给表格加个边框。
五十、加个边框
在数据库建题目中表的SQL:
create database MyPhotos
go
use MyPhotos
go
create table PhotoType --相册
(
TypeId int identity(,) primary key,
TypeName nvarchar() not null,
TypeDes nvarchar()
)
go
create table Photos
(
PId int identity(,) primary key,
PTypeId int not null,
PUserId int not null, --User表的主键
PTitle nvarchar() not null,
PUrl nvarchar() not null, --图片的名称
PDes nvarchar(), --描述
PClicks int, --点击次数
PTime datetime, --录入时间
PUp int, --支持
PDown int --反对
)
go
create table Comments
(
CId int identity(,) primary key,
CPhotoId int not null, --照片的id
CText nvarchar(), --评论内容
CTime datetime, --评论时间
CUp int,
CDown int
)
go
create table [User]
(
UId int identity(,) primary key,
UName varchar(),
UPwd varchar()
)
go create view v_Photo
as
SELECT dbo.Photos.PId, dbo.Photos.PTypeId, dbo.Photos.PUserId, dbo.Photos.PTitle, dbo.Photos.PUrl, dbo.Photos.PDes, dbo.Photos.PClicks,
dbo.Photos.PTime, dbo.Photos.PUp, dbo.Photos.PDown, dbo.PhotoType.TypeId, dbo.PhotoType.TypeName, dbo.PhotoType.TypeDes
FROM dbo.Photos INNER JOIN
dbo.PhotoType ON dbo.Photos.PTypeId = dbo.PhotoType.TypeId
go
alter table Photos
add constraint DF_pClicks default() for pClicks
alter table Photos
add constraint DF_PUp default() for PUp
alter table Photos
add constraint DF_PDown default() for PDown alter table Photos
add constraint DF_pTime default(getdate()) for pTime alter table Comments
add constraint DF_cTime default(getdate()) for cTime
alter table Comments
add constraint DF_CUp default() for CUp
alter table Comments
add constraint DF_CDown default() for CDown alter table Photos
add constraint FK_PTypeId
foreign key(PTypeId) references PhotoType(TypeId) alter table Comments
add constraint FK_CPhotoId
foreign key(CPhotoId) references Photos(PId) use MyPhotos
insert into phototype values('人物','人物')
insert into phototype values('风景','风景')
insert into phototype values('卡通','卡通')
insert into phototype values('家庭','家庭')
insert into phototype values('自拍','自拍') insert into [user] values('admin','admin')
insert into [user] values('zs','')
insert into [user] values('ls','')
insert into [user] values('ww','') insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(,,'图片1','01.jpg','图片one')
insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(,,'图片2','02.jpg','图片two')
insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(,,'图片3','03.jpg','图片three')
insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(,,'图片4','04.jpg','图片four')
insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(,,'图片5','05.jpg','图片five')
insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(,,'图片6','06.jpg','图片six')
insert into photos(PTypeId,PUserId,ptitle,purl,pdes) values(,,'图片7','07.jpg','图片seven')
五十一、表格样式
五十二、最终美图
我们可以用之前学过的东西加个隔行变色,加个高亮显示。