浏览器向服务器发送请求,服务器响应.
报错
HTTP Error 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容。
解决:
每当用户请求访问ashx页面的时候,ProcessRequest方 法就会被调用,在这里通过访问context.Request获得访问者的请求参数等。然后在ProcessRequest中通过context.Response向浏览器发回数据给浏览器。
调试形式启动项目(默认请求报错的问题),修改地址栏访问ashx。选择浏览器:选择浏览器安装目录;更方便的改代码测试:哪怕停止调试,只要web服务器还在运行,那么修改CS代码之后只要点击“生成”
Html表单可以自动给服务器提交参数(get是 通过url,post是通过报文体,后面会讲区别),不用用户自己拼url。action指定把表单内容提交给谁。
浏览器向服务器端提交数据,被提交数据的表单(input. selecttextarea等)放到form中,form中 通过action属性设定表单被提交给哪个页面,为了在服务端取出表单项的值,需要在HTML中为表单元素设定name属性
注意id是给JS操作Dom用的,name才是提交给服务器用的。id不能重复,name可以重复,重复的name的值都会被提交给服务器。
服务器端用context. Request[“username”]来根据表单项的name 来获得提交的属性值。
checkbox没选中为null,选中为"on"。
补充:
当我们点击[登录]按钮以后是浏览器将用户填写的文本框等控件中的值“提取”出来发送给服务器,而不是服务器来读取用户填写的这个页面。
哪些标签的哪些值会被提交给服务器呢?将用户填写的内容提交到服务器有如下几个条件[使用浏览器监视网络请求验证) :
只能为input. textarea. select三种类型的标签。
只有三种标签的value属性的值才会提交给服务器。标签必须设定name属性。如果要将标签的value属性值提交到服务器,则必须为标签设定name属性,提交到服务器的时候将会以“name= =value"的键值对的方式提交给服务器。name是给服务器用的,id是给Dom用的。
对于RadioButton, 同name的为一组,违中的RadioButton的value被提交到服务器
当input= submit的时候,只有被点击的按钮(要有name)的value才会被提交。
放到form标签内。只有放到form标签内的标签才可能会被提交到服务器,form之外的input等标签被 忽略。
请求
GET / HTTP/1. 1表示向服务器用GET方式请求首页,使用HIIP/1. 1协议
User- Agent (简称UA)为浏览器的版本信息。通过这个信息可以读取浏览器是IE还是FireFox.支持的插件、. Net版本等。看看IE和Chrome的UserAgent不-样
Referer:来源页面、所属页面
Accept- Encoding:服务器支持什么压缩算法。Accept-Language: 浏览器支持什么语言。
请求是可以伪造的。
响应:
响应码:“200” : OK:“302” : Found 暂时转移,用于重定向,Response. Redirect0会让浏览器再请求一次重定向的地址,重定向的请求是Get方式:;
"404” : Not Found未找到。
500 服务器错误(一般服务器出现异常),通过调试方式自动跳转到出异常的点。304(ctrl+f5)
Content-Type: texthtml; charset=utf-8表示返回数据的类型中服务器通过Content-Type告诉客户端响应的数据的类型,这样浏览器就根据返回数据的类型来进行不同的处理,如果是图片类型就显示,如果是文本类型就直接显示内容,如果用html类型就用浏览器显示内容.常用Content-Type: texthtml. image/gif、image/jpeg. text/plain. textjavascript。 这是为什么要的ashx中设置contenttype的原因,试着改成text/plain
context. Request (HttpRequest类型),请求相关信息。
context.Request.Form[“username”]获取Post请求中的值
context.Request.QueryString[“username”]获取Get请求中的值。
context. Request[" username "]顺序从QueryString .Form. Cookies. ServerVariables中 找,第一个找到的就是(反编译验证).
'name=rupeng&age=8” 叫做QueryString请求参数获取的都是String类型数据,因为Http协议就是文本。
UrlReferrer; UserAgent; UserHostAddress客 户端IP地址
// text/plain 指示响应的内容是纯文本数据,text/html 指的是html代码
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
// context. Request [" name"]无论是Get还是Post都能获得
// string name = context. Request [" name"]://[""]索引器
// string age = context. Request[" age"]:
// 浏览器类型
context.Response.Write("" + context.Request.Browser.Browser + "\n");
// 操作系统类型
context.Response.Write("" + context.Request.Browser.Platform + "\n");
// 浏览器版本
context.Response.Write("" + context.Request.Browser.Version + "\n");
context.Response.Write("------------------\n");
// 浏览器发送的请求头的信息的种类
for (int i = 0; i < context.Request.Headers.AllKeys.Length; i++)
{
String key = context.Request.Headers.AllKeys[i];
String value = context.Request.Headers[key];
context.Response.Write(key + " \n");
}
// 请求方法
context.Response.Write(context.Request.HttpMethod + "\n");
// context.Response.Write(context.Request.InputStream)//请求报文体的流
// 请求路径
context.Response.Write(context.Request.Path + "\n");
// get请求时表单提交信息信息将拼接到url上
context.Response.Write(context.Request.QueryString + "\n");
//被请求的文件的服务器上的物理路径
context.Response.Write(context.Request.PhysicalPath + "\n");
// 浏览器,操作系统的详细信息
context.Response.Write(context.Request.UserAgent + "\n");
//客户端的IP地址
context.Response.Write(context.Request.UserHostAddress + "\n");
// refer 请求的refer
context.Response.Write(context.Request.UrlReferrer + "\n");
//浏览器支持什么语言
context.Response.Write(String.Join(", ", context.Request.UserLanguages) + "\n");
响应浏览器的请求信息。提供最基本的write等方法,将字符串信息返回给浏览器。
context. Response响应相关信息. ContentType; OutputStream输出流; End()将当前所有缓冲的输出发送到客户端,停止该页的执行。通过对End(进行try,发现是是抛出了异常。所以 End()之后的代码就不会执行了。 Redirect()重定向;
Server是一个HttpServerUtility类型的对象,不是一个类名
MapPath: MapPath("~/a.htm")将 虚拟路径(~代表项目根目录)转换为磁盘上的绝对路径,操作项目中的文件使 用。
HtmlEncode. HtmlDecode: HTML编码解码。Encode 为的是把特殊字符转义显示,如<>等
UrlEncode、UrlDecode: url编码解码。汉字、特殊字符(空格、尖括号)等通过Url传递的时候要编码,举例子“1 '<如鹏+网rupeng.com>
Transfer()
context.Response.ContentType = "text/html";
//得到文件在服务器磁盘上的绝对路径。~表示网站根目录
string filepath = context.Server.MapPath(" ~/t1.html");
FileInfo fi = new FileInfo (filepath);
context.Response.Write(fi. Length);
// 注意规范,对于响应的html代码,应构成完整的html结构
context.Response.Write("<html><head></head><body>");
/*
string cscode = "hello List<T> list = new List<T>();";
//HtmlEncode:把<>等特殊字符转换为htm1中的转义字符
string enCodeCSCode = context.Server.HtmlEncode(cscode);
// context.Response.Write(cscode);
context.Response.Write(enCodeCSCode);
context.Response.Write("</body></html>")*/
/*
string s = "hello List<:T>: list = new List<:T>:();";
string s1 = context.Server.HtmlDecode(s);//HtmlEncode的反过程
context.Response.Write(s1);*/
string s = "hello 如.鹏.网<>
// 对url进行编码解码,对其中的汉字,特殊符号等进行编码解码
string s1 = context.Server.Ur1Encode(s);
context.Response.Write(s1);
// 需要注意contenttype的类型
context.Response.ContentType = "image/jpeg";
//String name = context.Request["name"];
String name = "sb";
String imgfullpath = context.Server.MapPath("~/test.jpg");
using (Image bmp = Image.FromFile(imgfullpath))
using (Graphics g = Graphics.FromImage(bmp))
using (Font f1 = new Font(FontFamily.GenericSansSerif, 12))
{
g.DrawString(name, f1, Brushes.Red, 0, 0);
bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
ashx的代码
context.Response.ContentType = "text/plain";
// 告诉浏览器,返回的内容是以附件形式需要用户保存
context.Response.AddHeader("Content-Disposition", "attachment;filename=" + context.Server.UrlEncode("test.txt"));
DataTable dt = SqlHelper.ExecuteQuery("select * from work_guangzhou limit 10");
foreach (DataRow item in dt.Rows)
{
context.Response.Write(item["number"]+" "+ item["jobname"]+" "+item["salary"] + "\n");
}
在html中有一个a链接,链接到ashx,点击即可下载。
html中需要注意必须要post提交,一般文件数据较大,不适合报文头提交数据。enctype必须要设置multipart/form-data
<form action="handle_upload_file.ashx" method="post" enctype="multipart/form-data">
<input type="file" name="file1" value="选择文件" />
<input type="text" name="text1" value="" />
<input type="submit" name="sub1" value="上传" />
</form>
c#代码中使用HttpPostedFile类获取对应文件控件的相关内容,并且保存。
context.Response.ContentType = "text/plain";
// context.Response.Write("Hello World");
HttpPostedFile file1 = context.Request.Files["file1"];
file1.SaveAs(context.Server.MapPath("~\\upload" + "\\" + file1.FileName)) ;
对于一般的js代码,服务器而言只是一串字符串,对于客户端而言是需要执行js代码,需要按照语言规范来执行。所以服务器而言,只会对服务器的代码严格的执行。js的代码只会执行在浏览器。
服务器端的数据检查是必不可少的,客户端的数据不能保证真实性!!!
客户端提交的数据都可以进行造假。
协议是无状态的,浏览器每一次请求服务器,对于服务器而言根本不会认识这个浏览器,权当一样的请求处理。
代码中,浏览器的每一次请求但会生成一个新的IhttpHandle对象解析请求。
因为HTTP协议是无状态的,所以为了记录用户登录状态等目的,cookie就因此诞生。
Cookie是和站点相关的,并且每次向服务器请求的时候除了发送表单参数外,还会将和站点相关的所有Cookie都提交给服务器。Cookie也是保存在浏览器端的,而且浏览器会在每次请求的时候都会把和这个站点的相关的Cookie提交到服务器,并且将服务端返回的Cookie更新回数据库,因此可以将信息保存在Cookie中,然后在服务器端读取、修改(看报文)。
在服务器端控制Cookie案例,实现记住用户名的功能,设置值的页面: Responsea SetCookie(new HttpCookie(’ UserName’,username)); 读取值的页面: username= Reauest. Cookies[’ UserName’ ]. Value;
如果不设定Expires那么生命周期则是关闭浏览器则终止,否则“最多”到Expires的时候终止。保存7天”。 Cookie的缺点:还不能存储过多信息,机密信息不能存。Cookie:是可以被清除不能把不能丢的数据存到Cookie中; Cookie尺寸有限制,一般就是几K,几百K,Cookie无法跨不同的浏览器;浏览器的“隐私模式/小号模式
cookie不能跨浏览器,同时浏览器的隐藏模式,无痕模式,都会又不同的cookie
当一个新的浏览器请求服务器,服务器会返回一个cookie信息,浏览器接受到将保存至本地,在之后的每次请求服务器都会将cookie信息携带上发送给服务器。
HttpCookie cookie = new HttpCookie("test");
cookie.Value = "zhushaonb";
context.Response.SetCookie(cookie);
以这种形式赋值cookie,cookie的生存期只会保持到浏览器关闭前。
cookie.Expires = DateTime.Now.AddSeconds(10);
设置expires属性,自定义cookie的生存时间。
可以通过设设置cookie的path属性,指定某个页面可以读取这个cookie
以及指定domain属性,控制可以读取cookie信息的域名范围。
session 可以近似得看成是服务器端的cookie,因为对与浏览器端提交的cookie信息,本质上可以通过造假来欺骗服务器,对此只能将信息存储在cookie并且保存在浏览器中就存在极大的弊端,为此,服务器需要有自己得独立得一套记录浏览器情况的 “cookie”,这就可以看成是session。
session的类型基本上可以是任意类型的值,cookie只能赋值字符串。
代码中对session的处理,只有当httphandle实现IRequiresSessionState接口,这是标记接口,asp.net引擎才会处理session。session具有自动销毁机制,如果在一段时间内浏览器没有和服务器发生交互,服务器则会销毁session,对于此时的浏览器而言则会需要进行重新登录等操作。在web.config文件中,在system.web节点下配置sessionState节点的timeout属性,单位是分钟,默认是20,可以手工设置。
使用Abandon()方法可以直接销毁服务器的session
// 生成随机数
Random rand = new Random();
int num = rand.Next(1000,10000);// 左闭右开的区间
String code = num.ToString();
// 存储在session中,用于服务器判断浏览器输入的验证码是否正确
content.Session[""] = code;
// 70X25大小的画板
using(Bitmap bmp = new Bitmap(70, 25))
{
// 创建画笔
using(Graphics g = Graphics.FromImage(bmp))
// 创建字体样式
using(Font font = new Font(FontFamily.GenericSerif, 15))
{
g.DrawString(code, font, Brushes.Red, new PointF(0, 0));
}
// 保存在输出流中
bmp.Save(content.Response.OutputStream, ImageFormat.Jpeg);
}
session和cookie的关系,cookie中存放了一个sessionid,服务器中保存sessionid和数据的对应关系.
简单的借助Guid算法生成session
public class TestSesssion
{
private const String TestSessionId = "test";
private String sessionid;
private HttpContext context;
public TestSesssion(HttpContext context)
{
this.context = context;
HttpCookie cookie = this.context.Request.Cookies[TestSessionId];
if (cookie == null)
{
CreateGuidSession();
}
else
{
this.sessionid = cookie.Value;
}
}
public void CreateGuidSession()
{
Guid guidt = Guid.NewGuid();
this.sessionid = guidt.ToString();
HttpCookie cookie = new HttpCookie(TestSessionId);
cookie.Value = this.sessionid;
this.context.Response.SetCookie(cookie);
}
public bool HasSessionId()
{
HttpCookie cookie = this.context.Request.Cookies[TestSessionId];
return cookie != null;
}
public void SetValue(String value)
{
String fullpath = this.context.Server.MapPath("~/MySession/" + TestSessionId);
File.WriteAllText(fullpath, value);
}
public String GetValue()
{
String fullpath = this.context.Server.MapPath("~/MySession/" + TestSessionId);
return File.ReadAllText(fullpath);
}
}
因为,一般情况下session默认保存在iis服务器的内存中,所以在iis重启后session信息会丢失,所以将session存储在数据库中,这样在web服务器重启后依然能保持session信息.
1、Session保存在SQLServer中配置方法 1)运行.NetFramework安装目录下对应版本的aspnet_regsql.exe 来创建相关的数据库、表和存储过程等,比如: C:\Windows\Microsoft.NET\Framework\v4.0.30319> aspnet_regsql.exe -ssadd -sstype p -S 127.0.0.1 -U sa -P 123456
其中-sstype p表示数据库名固定为ASPState,-S(大写)为数据库服务器地址,-U和-P分别为数据库的用户名和密码,参数详细解释见 http://blog.csdn.net/yuanzhuohang/article/details/6758304 2)修改web.config中sessionState节点的配置:
<sessionState mode="SQLServer" timeout="20" sqlConnectionString="server=.;uid=sa;password=123456;" ></sessionState>
服务器端常见基本控件:
5.viewstate;
aspx文件(新建项→Web窗体)。在aspx中可以使用<%=表达式%>的方式在页面的当前位置输出表达式(表达式至少要用protected级别,后面会讲为什么,如果自动提示出不来,则重新生成项目)或者局部变量,表达式也可以是一个方法、属性、字段。不要忘了写=。
其实=就是相当于R.esponse.Write(),直接写Response.Write()也可以。
语法:
基本原理:本质上就是占位符替换内容。
aspx.和ashx.关系: aspx就是一个特殊的lHttpHandler.,aspx.对应的类是Page,它是实现了IHttpHandler接口,所以可以说aspx是高级的HttpHandler。
ashx(handler), aspx(page)
aspx标签runat属性设置为server,可以实现后台控制该标签。对于没有设置runat=“server”属性的标签aspx引擎会将该标签当成普通字符串处理返回给浏览器。
<input type="text" id="txt1" runat=server/>
<!-- 加完runat=server后可以,在c#里面操作这些标签 -->
Button控件。OnClientClick属性,设置成onclientclick=“return confirm(‘真的要删除吗’)”后,可以弹窗询问
现在在A.aspx,这个页面上,点击页面上的按钮把数据提交到A.aspx,处理,这个过程可以看做是“从客户端浏览器把之前的状态数据提交回来(Post Back)”
**IsPostBack:**是否是第一次加载
aspx中<% %>可以编写c#;webstorm做了解就行,尽量不使用,最多轻量版。
Repeater相当于一个高级的foreach,每一项的显示用ItemTemplate格式去显示。
if (!IsPostBack)
{
Repeater1.DataSource = SqlHelper.ExecuteQuery("select * from T_Persons");
Repeater1.DataBind();
}
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<%#Eval("Name") %><br />
</ItemTemplate>
</asp:Repeater>
ViewState就是一个隐藏字段,服务器把需要浏览器去记忆的值,放到<input type=“hidden” name=”__VIEWSTATE“ 每次表单提交的时候都把__VIEWSTATE提交服务器,服务器再根据__VIEWSTATE还原ViewrState
通过代码进行赋值的属性的值都会放到ViewState中。而aspx中的初始值则不会
禁用ViewState(设置:EnableViewState=“false”),客户端只会保留基本的__VIEWSTATE
异步的js和XML。用于网页的局部刷新。前端通过Ajax请求后台数据,刷新局部页面。
jQuery对Ajax的封装,并使用
<script type="text/javascript">
$(function () {
//$.ajax()方法中传入字典,键值对之间用:冒号分隔...
$("#imgValidCode").click(function () {
$("#imgValidCode").attr("src", "validCode.ashx?" + new Date());
})
// 在自己需要触发的事件上设置Ajax请求,定义需要完成的动作(函数)
$("#loginBtn").click(function () {
$.ajax({
// 定义什么方式去请求url
type: "post",
// 需要去请求的url
url: "Login.ashx",
// 是否将返回的数据转换成json
dataType:"json",//返回类型序列化成json格式,如果返回对象不能转换成json格式,则会执行error中的方法.
// 需要将什么数据提交给url
data: { userId: $("#userId").val(), password: $("#password").val(), inputValidCode: $("#inputValidCode").val() },
// 请求成功,并且返回数据正确
success: function (response) { alert(response.Msg) },
error: function () { alert("error...") }
})
})
})
</script>
使用JavaScriptSerializer对.net对象序列化或反序列化
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
String[] strs = { "t1", "t2", "t3"};
JavaScriptSerializer jss = new JavaScriptSerializer();
// Serialize 将对象转换成json字符串
String json = jss.Serialize(strs);
// Deserialize 可以将json字符串反序列化字符串
String[] s = jss.Deserialize<String[]>(json);
context.Response.Write(json);
context.Response.Write(s[0]);
context.Response.Write(s[1]);
context.Response.Write(s[2]);
}
应用场景:显示隐藏加载进度条…
body标签下的任何元素发送ajax请求时都会触发该事件。
因为HTTP协议的特性,使用HTTP协议传输的浏览器和服务器之间只能先由浏览器端先发起请求,服务器只能被动接受请求。响应浏览器的请求。然后关闭连接。一般而言,http协议有一次性连接的特点,每次连接只能处理一个请求,下一个请求需要再次建立连接才能处理。同时http协议没有记忆性,不会记录上一次与该客户端连接时状态,这些都保证了服务器能购高效率的运行。
因此,如果需要服务器先向浏览器发送数据,从http协议的层面上讲是不能实现的。
在视频的案例中,服务器的代码中对每次读取数据的请求进行while无限循环,直至读取到所需的数据,同时使用sleep来减轻服务求压力,这样不会立即响应请求并关闭连接。一定意义上,浏览器没有再次主动请求服务器,但服务器主动向浏览器返回数据。所以从http的一次连接只能处理一次请求来讲serverpush就是保持这一次的连接(即长连接),对此时的浏览器而言完全可以去请求其他的web服务器,就好像在被动等待服务器先发送数据。
全局应用程序类,在这个类中可以定义当一些事件触发时需要执行的方法。同时这是全局应用。
Application_Start:网站第一次被访问时执行 Session_Start:Session启动时 (*)Session_End:Seesion过期(只有进程内的Session,也就是InProc过期的时候才会调用Session_End) Application_BeginRequest:当一个请求过来的时候html等静态文件是iis直接把文件给到浏览器,不经过asp.net引擎的处理。所以不会调用Application_BeginRequest方法;即使访问不存在的页面也会被调用(用法:可以判断客户端输入的网址,然后转到另一个网址) Application_Error:程序中发生未处理异常
Application是应用全局对象,被全体共享(任何电脑,任何浏览器),操作之前先Application.Lock(),操作完成后Application.Unblock()
HttpRuntime.Cache.Insert(CacheKey, objObject.null, absoluteExpiration, slidingExpiration),
DataTable dt = (DataTable)HttpRuntime.Cache["person"]; // 从缓存中读取
if(dt == null) // 缓存中没有则从数据库中查询
{
dt = SqlHelper.ExecuteQuery("select * from T_Persons");
// 放入缓存,这里是30s过期
HttpRuntime.Cache.Insert("person", dt, null, DateTime.Now.AddSeconds(30), TimeSpan.Zero);
}
三个文件:1.shtml,head.html,foot.html
最后效果是三个文件拼接成一个页面显示
1.shtml的内容示例
<!-- #include file="head.html" -->
2222中间部分
<!-- #include file="foot.html" -->