热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ASP.NET项目中出现乱码如何解决

ASP.NET项目中出现乱码如何解决?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习

ASP.NET项目中出现乱码如何解决?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

页面显示乱码问题

在一个网站中,有些页面会正常显示,然而,有些页面会显示成乱码。 如果发生这种情况,可以检查一下web.config和文件编码。

如果web.config是这样配置的:

而文件的编码不是UTF-8:

ASP.NET项目中出现乱码如何解决

那么就会有乱码问题。

注意:反之是不是会出现乱码的。

1. 不设置fileEncoding,此时不会有乱码现象。

2. fileEncoding="gb2312",文件以utf-8编码,此时也不会有乱码现象。

因此,我建议最好让所有文件都以UTF-8编码保存,从而解决这类乱码问题。

AJAX提交的数据乱码问题

AJAX技术流行了这么多年了,我想现在没有几个网站不使用这种技术的。 然而,有些人在使用AJAX时,遇到了乱码问题。

通过分析这类乱码案例中,我发现几乎都是采用这种方式向服务端提交数据: “key1=” + escape(value1) +“&key2=” + escape(value2)

这种方法在多数情况下,的确能够正常工作,然而遇到一些特殊字符,就行不通了。原因我后面再来解释。

我为这类不正确的方法准备了一个示例 (为了保持示例简单,我演示一个拼接URL),

页面代码如下:

escape

服务端的代码就是从QueryString读取那些参数值,然后输出。由于代码实在太简单,就不贴出了。(可下载示例代码)

当我点击链接时,服务端返回了这样的结果:

ASP.NET项目中出现乱码如何解决

注意:"fish li + is me." 中间的加号没有了。

解决这个问题有个简单的方法,那就是使用JQuery的$.param()方法,修改后的代码如下:

另外,我非常反感拼接这种提交数据:“key1=” + escape(value1) +“&key2=” + escape(value2)

因为这种代码的可读性太差了,在此,我建议在AJAX调用时,最好直接使用JQuery的$.ajax方法向服务端提交数据。

请看下面的示例代码(注意我为data属性赋值的方式):

Click me! 【点击我】

运行结果:

ASP.NET项目中出现乱码如何解决

Javascript中正确的URL编码方式

看过前面的示例,您有没有想过:为什么escape不能解决的问题,JQuery就能解决呢?

对于这个问题,我想还是先来看看MSDN中关于escape的说明(截图):

ASP.NET项目中出现乱码如何解决

MSDN说的很清楚,我也没有必要再做解释。

不过,我想有人可能会问:我用POST提交数据呢?那可是不经过URL的。

是的,POST数据时,参数没有放在URL中,但是,仍然采用URL编码。

POST数据也采用URL编码,是因为:表单可以采用GET方式提交,那么数据将通过URL提交给服务器。

所以提交的数据都要经过URL编码。

我们再来看一下$.ajax是如何处理数据的提交过程的:

ajax: function( origSettings ) {
  var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
  
  // ............... 去掉一些无关的代码

  // convert data if not already a string
  if (s.data && s.processData && typeof s.data !== "string") {
    // 注意下面这个调用
    s.data = jQuery.param( s.data, s.traditional );
  }

再来看jQuery.param的实现过程:

// Serialize an array of form elements or a set of
// key/values into a query string
param: function( a, traditional ) {
  var s = [];
  // ............... 去掉一些无关的代码
  
  // If an array was passed in, assume that it is an array of form elements.
  if ( jQuery.isArray(a) || a.jquery ) {
    // Serialize the form elements
    jQuery.each( a, function() {
      add( this.name, this.value );
    });
    
  } else {
    // ............... 去掉一些非重点代码
  }

  // Return the resulting serialization
  return s.join("&").replace(r20, "+");

  function add( key, value ) {
    // If value is a function, invoke it and return its value
    value = jQuery.isFunction(value) ? value() : value;
    s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
  }
}

这段代码的核心就是add函数的实现了,它在内部调用了encodeURIComponent()函数。

我们应该注意JQuery对数据的处理方式:encodeURIComponent(key) + "=" + encodeURIComponent(value);

JQuery在最后还把%20还替换成 + 号了。

在WEB开发领域,我想大家对JQuery的权威应该不用怀疑吧? 所以我认为JQuery的方法肯定是正确的。

从JQuery的实现方式也可以看出:encodeURI()其实也是不推荐在编码URL数据时使用的。

说到这里,我要说说为什么不推荐使用encodeURI。

encodeURI用于对整个URL字符串进行编码,如果某个参数值本身包含一些特殊字符。

例如:key = "x?x/x&x", value = "aa=2&bb=3&cc=汉字。",这个函数的结果将会不正确。

它通常用于编码URL路径中包含有类似汉字这种场合,不适合处理URL参数。

但是,URL路径中的目录名与文件名,我们可以选择英文字符,所以encodeURI通常没有机会使用。

ASP.NET中正确的URL编码方式

前面介绍了Javascript中三种URL的编码方式,在服务端,ASP.NET有更多的URL编码方法,今天我也把服务端的编码也做了个总结,因为我发现网上有些资料也是错误的。

在ASP.NET中提供三个URL编码方法:HttpUtility.UrlPathEncode、HttpUtility.UrlEncode、Server.UrlEncode
 .NET framework还提供了System.Uri这个类,它也有一些用于URL处理的方法。 比如EscapeUriString,EscapeDataString这二个方法,可用于URL路径与参数的编码任务。

面对这些方法,我该选择哪个?

我建议在 ASP.NET 中,编码查询参数 时选择HttpUtility.UrlEncode(str) ,并且在拼接URL时,采用 HttpUtility.UrlEncode(key) + "=" + HttpUtility.UrlEncode(value) 的方法。如果要 编码URL中的路径,请使用HttpUtility.UrlPathEncode()

下面我来解释前面不建议使用的另外的一些方法的原因:

1. Server.UrlEncode: 这个方法其实也是调用HttpUtility.UrlEncode,只是它会尽量使用Response.ContentEncoding所表示的编码格式, 然而HttpUtility.UrlEncode(str)总是会使用UTF-8编码,如果你不希望被字符编码纠缠,那就应该放弃Server.UrlEncode , 毕竟UTF-8编码才是更好的选择。

2. 虽然System.Uri的那二个编码方法,也能实现我们需要的URL编码任务, 但是,当ASP.NET在填充Request.QueryString, Request.Form时,使用的解码方法是HttpUtility.UrlDecode, 因此,如果你执意选择使用System.Uri的相关的编码方法,显然就不能与解码方法匹配,后果如何就难说了。

正确的URL编码方式的总结

由于编码函数(方法)较多,而且又比较重要,我认为有必要再做个总结。

一个完整的URL可以简单地认为包含二个部分:文件路径(含目录) 和 查询参数(QueryString)
在编码时,一定要分开处理。

编码文件路径时,应该选择 encodeURI,HttpUtility.UrlPathEncode 。

编码查询参数时,应该选择 encodeURIComponent,HttpUtility.UrlEncode,而且拼接方式应该是:Encode(key) + "=" + Encode(value)

绝对不能先把整个URL(包含查询参数)拼接起来了,再来考虑该选择哪个编码方法。

再说一遍:在Javascript中使用escape肯定是错误的。

彻底解决encodeURIComponent()与GB2312乱码问题

前面我建议在Javascript中使用encodeURIComponent()来处理提交数据, 然而encodeURIComponent()在编码字符时,使用的是UTF-8编码。 也正因为这个原因,有人可能会说:我的网站使用的编码方式是gb2312 !

对于这个回答,我有时实在不想再说下去了:你就不能把网站的编码改成UTF-8吗?

现在好了,我设计了一种方法,可以解决在GB1212编码的网站中使用encodeURIComponent(), 这个方法的设计思路比较直接:既然encodeURIComponent()是使用UTF-8编码, 那么,我们是不是只要告诉服务端,客户端提交的数据是UTF-8编码的,此时服务端只要识别后,按照UTF-8编码来解码,问题就解决了。

理清了思路,代码其实很简单。首先来看客户端的代码。

$.ajax({
  // 注意下面这行代码,它为请求添加一个自定义请求头
  beforeSend: function(xhr) {  xhr.setRequestHeader("x-charset", "utf-8"); },
  
  url: "/TestParam.ashx", type: "GET", cache: false,
  data: { id: 2,
    name: "fish li + is me.",
    tel: "~!@#$%^&*()_+-=<>?|",          
    "x?x!x&x": "aa=2&bb=3&cc=汉字。", // 特殊的键名,值内容也特殊。
    encoding: "见鬼去吧。?& :)",
    中文键名: "大明王朝1368"
  },
  success: function(responseText) {
    $("#divResult").html(responseText);
  }
});

注意:在原来的基础上,我只加了一行代码:

beforeSend: function(xhr) {  xhr.setRequestHeader("x-charset", "utf-8"); },

再来看服务端代码。我写了一个HttpModule来统一处理这个问题。

public class ContentEncodingModule : IHttpModule
{
  public void Init(HttpApplication app)
  {
    app.BeginRequest += new EventHandler(app_BeginRequest);
  }

  void app_BeginRequest(object sender, EventArgs e)
  {
    HttpApplication app = (HttpApplication)sender;
    HttpWorkerRequest request = (((IServiceProvider)app.Context)
              .GetService(typeof(HttpWorkerRequest)) as HttpWorkerRequest);

    // 注意:我并没有使用 app.Request.Headers["x-charset"]
    // 因为:绝大部分程序不访问它,它将一直保持是 null,
    // 如果我此时该问这个集合,会导致填充它。
    // 我认为填充Headers集合比我下面的调用的成本要高很多,
    // 所以,直接通过HttpWorkerRequest读取请求头对性能的损耗会最小。
    
    string charset = request.GetUnknownRequestHeader("x-charset");
    if( string.Compare(charset, "utf-8", StringComparison.OrdinalIgnoreCase) == 0 )

      // ASP.NET在填充QueryString,Form时,会访问Request.ContentEncoding做为解码时使用的字符编码
      app.Request.ContentEncoding = System.Text.Encoding.UTF8;
  }

改造后的结果是:除非客户端明确添加"x-charset"请求头,否则还是按原来的方式处理,对于服务端代码来说,完全不用修改。

说明:

1. 如果网站的提交全部采用JQuery,也可以统一设置,这是JQuery支持的功能。

2. 如果使用JQuery1.5以上版本,也可以写成:headers: {"x-charset" : "utf-8"} 

3. 就算以后网站使用UTF-8编码,所有代码不需要做任何修改。

COOKIE乱码问题

前段时间,有人在博客的评论中问我:asp.net服务器端写中文COOKIE,js客户端读取时乱码。

其实这个问题还是比较好解决的,方法是:写COOKIE时用HttpUtility.UrlEncode编码,然后在客户端使用decodeURIComponent把内容转回来就可以了。 在此,我推荐使用jquery.COOKIE.js这个插件来读写COOKIE。 示例代码如下(前端):

$(function() {
  var COOKIE = $.COOKIE("TestJsRead");
  $("#COOKIEValue").text(COOKIE);
});

服务端代码:

COOKIE = new HttpCOOKIE("TestJsRead", HttpUtility.UrlEncode("大明王朝1368"));
Response.COOKIEs.Add(COOKIE);

下载文件名乱码问题

有时我们需要在程序运行时动态的创建文件,并让用户下载这个在运行时产生的文件, 然而,有时候用户会要求程序能生成一个默认的文件名,方便他们保存。 此时,我们只需要设置Content-Disposition这个响应头,并给一个默认的文件名就可以了。

一般说来,我们只要让默认的下载文件名是英文及数字,问题永远不会出现, 但是,有时候用户可能要求默认的文件中包含汉字, 最终,问题也随之发生了。 请看下面的代码:

public void ProcessRequest(HttpContext context)
{
  byte[] fileContent = GetFileContent();
  context.Response.ContentType = "application/octet-stream";

  string downloadName = "ClownFish性能测试结果.xlsx";
  string headerValue = string.Format("attachment; filename=\"{0}\"", downloadName);
  context.Response.AddHeader("Content-Disposition", headerValue);

  context.Response.OutputStream.Write(fileContent, 0, fileContent.Length);
}

这段代码在我的FireFox, Opera, Safari, Chrome都能正常运行,其中FireFox显示的下载对话框也是我期待的样子:

ASP.NET项目中出现乱码如何解决

遗憾的是,在我的IE8中是这样的:

ASP.NET项目中出现乱码如何解决

对于这个乱码问题,我们需要把代码做一点修改:

string downloadName = "ClownFish性能测试结果.xlsx";
if( context.Request.Browser.Browser == "IE" )
  downloadName = HttpUtility.UrlPathEncode(downloadName);

此时IE显示的文件名就不是乱码了。

说明:我的机器环境是 Windows Server 2003 SP2, 用于测试的浏览器版本分别为:

ASP.NET项目中出现乱码如何解决

多语言数据的乱码问题

现在还有一种乱码问题是:同一个程序供多种不同字符集(语言)的用户在使用。
 例如:程序是简体中文的,此时,繁体中文的用户无法保存繁体汉字(就算简体汉字能正常显示)。

当发现这种现象时,需要检查一下数据库的字段类型,是否是Unicode或者UTF-8, 因为当数据字段的字符集不支持多种语言时,乱码问题必定产生。

我建议在使用SQL SERVER时,保存文字的字段都使用N开头的类型, 如:nvarchar, nchar,除非明确知道要保存邮政编码或者md5值,才有必要使用char(xxx)这种数据类型。 类似的,在MySQL中,我建议使用UTF-8

 乱码问题的总结

ASP.NET的乱码问题一般与二个因素有关:

1. 选择了不恰当的字符编码,如:gb2312 

2. 选择了不正确的URL编码方法,如:escape()

因此,解决方案其实也不难:

1. 字符编码选择 utf-8 ,包含文件编码,请求/响应编码,数据库字段类型。

2. URL编码方法选择encodeURIComponent,再次强烈推荐直接使用JQuery

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程笔记行业资讯频道,感谢您对编程笔记的支持。


推荐阅读
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
author-avatar
书友54330525
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有