我开始选择了System.Net.WebClient的UploadValues来实现,后来发现银行那边用的编码是GB2312,而WebClient似乎是不能指定编码的(.Net1.1和.2.0似乎都是这样),所以通讯是字母和数字的话没有问题,如果通讯是中文的话就出现乱码,导致银行验证数字证书的时候出错。
走头无路的时候发现.Net2.0还有更低级的HTTP通讯类:WebResponse和WebRequest,所以用这两个类来实现我的目的。结果让我很失望,竟然数字和字母也不能正确发送了。没办法,我自己做了一个调试页面,其实就是把一个空页面设置成<%@ Page ... Trace="true"%>,让我的接口发送数据到这个空页面上,这样可以方便的看到每个Get和Post的字段。
这个时候看到中文是正常的(也就是说我发送和接受的数据是一致的),英文和数字也都正常,但是“+”传递过程中变成了空格。
为了这个问题郁闷了很久也没有解决,这时我突然想起来既然WebResponse和WebRequest比WebClient更低级,那么WebResponse会不会是用WebResponse和HttpWebRequest来实现的呢?
我找来.Net Reflector查看.Net的System.Net.WebClient.UploadValues()源代码如下:
1public byte[] UploadValues(string address, string method, NameValueCollection data)
2{
3 byte[] buffer1;
4 try
5 {
6 this.m_responseHeaders = null;
7 if (this.m_headers == null)
8 {
9 this.m_headers = new WebHeaderCollection();
10 }
11 string text1 = this.m_headers["Content-Type"];
12 if ((text1 != null) && (string.Compare(text1, "application/x-www-form-urlencoded", true, CultureInfo.InvariantCulture) != 0))
13 {
14 throw new WebException(SR.GetString("net_webclient_ContentType"));
15 }
16 this.m_headers["Content-Type"] = "application/x-www-form-urlencoded";
17 WebRequest request1 = WebRequest.Create(this.GetUri(address));
18 request1.Credentials = this.Credentials;
19 this.CopyHeadersTo(request1);
20 request1.Method = method;
21 using (Stream stream1 = request1.GetRequestStream())
22 {
23 using (StreamWriter writer1 = new StreamWriter(stream1, Encoding.ASCII))
24 {
25 string text2 = string.Empty;
26 foreach (string text3 in data.AllKeys)
27 {
28 string text4 = text2 + WebClient.UrlEncode(text3) + "=" + WebClient.UrlEncode(data[text3]);
29 writer1.Write(text4);
30 text2 = "&";
31 }
32 writer1.Write("\r\n");
33 }
34 }
35 WebResponse response1 = request1.GetResponse();
36 this.m_responseHeaders = response1.Headers;
37 buffer1 = this.ResponseAsBytes(response1);
38 }
39 catch (Exception exception1)
40 {
41 if (!(exception1 is WebException) && !(exception1 is SecurityException))
42 {
43 throw new WebException(SR.GetString("net_webclient"), exception1);
44 }
45 throw;
46 }
47 return buffer1;
48}
比较我的代码后发现错误在2{
3 byte[] buffer1;
4 try
5 {
6 this.m_responseHeaders = null;
7 if (this.m_headers == null)
8 {
9 this.m_headers = new WebHeaderCollection();
10 }
11 string text1 = this.m_headers["Content-Type"];
12 if ((text1 != null) && (string.Compare(text1, "application/x-www-form-urlencoded", true, CultureInfo.InvariantCulture) != 0))
13 {
14 throw new WebException(SR.GetString("net_webclient_ContentType"));
15 }
16 this.m_headers["Content-Type"] = "application/x-www-form-urlencoded";
17 WebRequest request1 = WebRequest.Create(this.GetUri(address));
18 request1.Credentials = this.Credentials;
19 this.CopyHeadersTo(request1);
20 request1.Method = method;
21 using (Stream stream1 = request1.GetRequestStream())
22 {
23 using (StreamWriter writer1 = new StreamWriter(stream1, Encoding.ASCII))
24 {
25 string text2 = string.Empty;
26 foreach (string text3 in data.AllKeys)
27 {
28 string text4 = text2 + WebClient.UrlEncode(text3) + "=" + WebClient.UrlEncode(data[text3]);
29 writer1.Write(text4);
30 text2 = "&";
31 }
32 writer1.Write("\r\n");
33 }
34 }
35 WebResponse response1 = request1.GetResponse();
36 this.m_responseHeaders = response1.Headers;
37 buffer1 = this.ResponseAsBytes(response1);
38 }
39 catch (Exception exception1)
40 {
41 if (!(exception1 is WebException) && !(exception1 is SecurityException))
42 {
43 throw new WebException(SR.GetString("net_webclient"), exception1);
44 }
45 throw;
46 }
47 return buffer1;
48}
string text4 = text2 + WebClient.UrlEncode(text3) + "=" + WebClient.UrlEncode(data[text3]);
我没有用UrlEncode编码 所以导致加号不能正常传输,所以问题解决。另外我想我也找到了为什么System.Net.WebClient.UploadValues()不能指定编码
很可能跟这个语句有关系
StreamWriter writer1 = new StreamWriter(stream1, Encoding.ASCII)
微软在代码里边把编码写死了,这个算不算MS的Bug呢?