·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 你不知道的 页面编码,浏览器选择编码,get,post各种乱码由来

你不知道的 页面编码,浏览器选择编码,get,post各种乱码由来

作者:佚名      ASP.NET网站开发编辑:admin      更新时间:2022-07-23

你不知道的 页面编码,浏览器选择编码,get,post各种乱码由来

asp.net页面编码和浏览器的选择编码

每个asp.net的朋友都知道,在新版本的visual studio,在没有任何设置的情况下,新建页面时的默认编码为utf-8

我们可以从两个地方可以看出:

第一:打开aspx页面,“文件”->“高级保存选项”,如下图,可以看出编码为:Unicode(UTF-8带签名)

第二:找到aspx存放路径,用系统自带的文本编辑器打开,然后“文件”->"另存为",如下图,可以看出编码为UTF-8

很多时候我们有些疑问,我们经常在aspx页面的<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />强制把carset改为gb2312

然后我们在“文件”->“高级保存选项”,可以看出编码为:GB2312(如果你前面把carset改为gb2312,vs会自动在高级保存选项中进行绑定改变),然后编译运行后,右击html“查看源”发现<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />没有变化,这时候一切正常

下面以IE为例:我们以为此时 “右击浏览器”->“编码” 看到的是 浏览器会选中简体中文(GB2312),但是事实上,你看到的还是选中的Unicode(UTF-8) (再勾选了‘自动选择’前提下)

现象已经很明显,但是需要验证浏览器为何会这样,F12调试浏览器(如下图),我们发现content-type竟然是“text/html;charset=utf-8”!

这个现象至少说了两个问题点:

1、asp.net机制至少在某个地方改变了response的ContentEncoding,导致虽然html页面代码上看到的设置<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />并没有生效

2、浏览器再自动选择编码方式的时候不会优先根据html源码中的所展示的<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />代码来决定选择什么编码方式,很明显,以上的现象证明浏览器是优先根据“响应标头-response header”中的键为“Content-Type”的值来自动选择判断,导致html中的所看到的<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />形同虚设。

以上两个问题点很快得到论证:

问题1、出现这个现象,我们知道<META http-equiv="content-type" content="text/html; charset=xxx"> 标签是设置页面编码的,meta标签是属于html的,https标头是服务器以HTTP协议传送HTML信息到浏览器前所送出的字串,所以header发送的内容先到达浏览器在任意新建一个测试页面,在第一个“}”处设置断点,然后命中断点后再“即时窗口”中写入“Response.ContentEncoding.EncodingName”,按enter执行,输出什么?没错:"Unicode (UTF-8)"

PRotected void Page_Load(object sender, EventArgs e){

}

如果了解asp.net生命机制的朋友知道,在执行到Page_Load之前已经执行了很多潜在的初始化事件,类似:Page_Init,LoadViewState,LoadPostData等等,可以想象一定是在某个地方系统为响应页面指定修改了ContentEncoding的值,也就是“响应标头-response header”中的键为“Content-Type”的值为“UTF-8”

我们不妨做一个测试,上面说过,我把<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />的carset改为gb2312,是没有效果的,那么我如果在Page_Load事件中如下写上代码:

protected void Page_Load(object sender, EventArgs e){ Encoding gb2312 = Encoding.GetEncoding("gb2312"); Response.ContentEncoding = gb2312;}

即我在load事件中再次强制性把响应标头中的“Content-Type”改为gb2312,那么浏览器表现如何呢?

这正是我们想看到的,我相信很多朋友有过中文乱码的情况,我先不说具体乱码的解决方案,但是至少搜索发现很多解决方案是在web.config下添加如下节点,即把网站内所有网页的请求编码和响应编码都改为utf-8

<system.web><globalization requestEncoding="utf-8" responseEncoding="utf-8" /></system.web>

其实,上面案例其实只是单个页面的修改response Encoding为gb2312,我们也可以在web.config中添加<globalization requestEncoding="gb2312" responseEncoding="gb2312" />,即整个网站有效

问题2、浏览器编码方式是根据“响应标头-response header”中的键为“Content-Type”的值来自动选择判断,而不会简单的根据你在html中看到的标签值<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />来判定,虽然这个标签一般情况下会写入header,但是有时候会被暗中修改掉,导致html中看到的和调试捕捉到的Content-Type不一致的情况

当然在老版本的ie中,有时候出现的页面全部为空白,右击ie浏览器编码发现没有勾选“自动选择”的情况下会出现这种白屏现象,那不是本文讨论的范围,但是简单的说下原因(拷贝):老版本的ie浏览器解析网页编码时以HTML内的标签优先,而后才是HTTP header内的讯息,而mozilla系列的浏览器则刚刚相反,由于UTF-8为3个字节表示一个汉字,而普通的GB2312或BIG5是两个。页面输出时,由于上述原因,使浏览器解析、输 出<title$amp;>amp;$lt;/title>的内容时,如果在</title>前有奇数个全角字符时,IE把UTF-8当作两 个字节解析时出现半个汉字的情况,这时该半个汉字会和</title>的<结合成一个乱码字,导致IE无法读 完<title>部分,使整个页面为空百输出。而这个时候如果察看源文件的话,会发现实际上整个叶面全部已经输出了

解决方法:将<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />放在<title>测试标题</title>之前(好像现在新建网页默认都在title之前)

asp.net URL参数编码

几乎所有的朋友都会遇到中文情况下乱码的问题,其原因到底是为何?

我先不说乱码问题,先说get和post的区别,几乎没有人不知道

我们在新建asp.net页面时,是很少去对form进行修改的,即保持默认的<form id="form1" runat="server">,可是编译运行后查看代码发现变成<form method="post" action="Default2.aspx" id="form1">

很显然,asp.net默认会为form的method写上post,但是需要注意的是如果仅仅是单纯的html页面,form默认的method是get

我这边可以举一个例子诠释一些无关紧要但是又比较重要的东西:

情况1(post):

浏览器选择编码 :utf-8

编译前的aspx : <form id="form1" runat="server">

运行后的html : <form id="form1" action="Default2.aspx" method="post">

点击服务器按钮(按钮文本:阿道夫):F12在请求正文中有如下图内容

情况2(get):

浏览器选择编码 :utf-8

编译前的aspx : <form id="form1" runat="server" method="get">

运行后的html : <form id="form1" action="Default2.aspx" method="get">

点击服务器按钮(按钮文本:阿道夫):F12在请求正文中有如下图内容

其实,情况1和情况2的对比,并不是我今天想说的意图,但是我还是要稍微顺带说下:

1、我们可以看到get方式的提交,参数仅仅是拼接在url后面,然后直接向web服务器请求,所以我们图中“请求标头-request header”中就可以看到参数的值,而post可以从图中看到,在“请求标头”中并看不到值,而在“请求正文”中看到值,说明post提交时值是包装在请求的body中,发送给服务器,然后向服务器请求数据

2、在asp.net中,图中可以看到不管是get还是post,提交形式不一样,内容确是一样的,本文仅为测试,所以内容相对较少,但是看起来也非常的长了,如果用get提交方式,这就带来隐患,浏览器到底支持多长的uri,web服务器到底支持多长的uri,反正是有限制的(具体长度见:http://www.cnblogs.com/henryhappier/archive/2010/10/09/1846554.html),不仅仅是长度,数据量也是有限制,get数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,web服务器载体例如iis应该会有限制,比如IIS5的post最大传输量为100kb等

3、安全性,get更加容易暴露参数,而且会被保存在浏览器的历史记录中,但是对于稍微专业点的人来说,post请求传送的数据也是可以被捕捉到的

4、缓存和SEO优化等就不提了

5、编码问题!!!(这边上面说这么多,就是为了最后一个“编码问题”)

我将着重讲解编码问题:

在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型。 一般是下面几种类型: application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。 multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。 text/plain: 窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。

假设此时使用get提交form方式:

浏览器则会用x-www-form-urlencoded的数据格式,虽然在F12浏览器调试或者cs代码中的Request.ContentType都看不出来。注意如下是我的get提交的url:

GET /Default2.aspx?__VIEWSTATE=MGASeC9kBMq4iDCI2YLRzkZYqkKYhDhWH2jlP5mpv7idP8gAoNcy0T0y6g6wRvccP%2BFz%2FVx4HdMGwLLW%2BYPbJsMEOTMi5PjS7Ea66DmHQJc%3D&__VIEWSTATEGENERATOR=9BD98A7D&__EVENTVALIDATION=BFMAr0Q6mSwngMhaCLeScGaXywIIRlFClDYAnVhHprxOeifBIGWKNbsunWO9yVOAV6jWHW%2FJ4g2laHQpTvJe%2Fc7X8vralK3hyO5Y0nuiJkT%2FdfxEj9NnCb8S5BfNvZKXVJA%2FOy8yH4Bf9K5DN%2FRI9aDR3EFR86Zm6fN4iEkvJfc%3D&Button2=%E9%98%BF%E9%81%93%E5%A4%AB

我只看最后部分“Button2=%E9%98%BF%E9%81%93%E5%A4%AB”,这是我的服务器按钮“阿道夫”,这一串“%E9%98%BF%E9%81%93%E5%A4%AB”是“阿道夫”三个汉字编码后的,究竟这个编码方式到底是什么?又是如何经常引起乱码问题的呢?

首先:get只能向服务器发送ASCII字符,这是W3C组织规定的,所以任何参数最后都要以ASCII码的形式传递,例如“Button2=%E9%98%BF%E9%81%93%E5%A4%AB”都是ASCII码中的英文字符和符号等字符,没有任何中文字符,其次编码方式是根据当前网页采用选择的编码来编码,例如asp.net网页使用的是utf-8码,那么“阿道夫”用utf-8的编码后的十六进制字符串就是“E9-98-BF-E9-81-93-E5-A4-AB”,和上面提到的“%E9%98%BF%E9%81%93%E5%A4%AB”是不是非常的类似,只是多了百分号

如何查看中文字符的十六进制字符串?方法:BitConverter.ToString(System.Text.Encoding.UTF8.GetBytes("阿道夫"));

如果用本文一开始介绍的方法,在Page_Load中加上

Encoding gb2312 = Encoding.GetEncoding("gb2312");Response.ContentEncoding = gb2312;

强制把当前页面编码改为gb2312,然后点击按钮,那么我们猜测在F12浏览器调试时,get提交的url的最后部分一定不再是“%E9%98%BF%E9%81%93%E5%A4%AB”,

调试后发现是:“%B0%A2%B5%C0%B7%F2”

那么用BitConverter.ToString(System.Text.E