一.问题描述
最近在使用c# http post请求时,遇见了这种异常,大概异常提示如下
System.Net.WebException:请求已中止:请求已被取消,在数据写入前关闭了数据流
错误代码如下:
cs
/// <summary>
/// 向指定URL发送POST请求
/// </summary>
/// <param name="url">发送请求的URL</param>
/// <param name="jsonData">请求参数,请求参数应该是Json格式字符串的形式</param>
/// <param name="contenType"><设置响应信息的编码格式,如utf-8/param>
/// <param name="header">请求头</param>
/// <returns>所代表远程资源的响应结果</returns>
public static string SendPost(string url,string jsonData,Encoding encoding,string contenType="application/json",Dictionary<string,string>header=null)
{
string result =string.Empty;
try
{
CookieContainer cookie = new CookieContainer();
HttpWebRequest request= (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
if(null != header && 0 < header.Count())
{
foreach(var item in header.Keys)
{
request.Headers.Add(item, header[item]);
}
}
request.ServicePoint.Expect100Continue = false;
request.ContentType = contenType;
request.ContentLength = Encoding.UTF8.GetByteCount(jsonData);
request.CookieContainer = cookie;
using (StreamWriter writer = new StreamWriter(request.GetRequestStream(), encoding))
{
writer.Write(jsonData);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
response.Cookies = cookie.GetCookies(response.ResponseUri);
using (Stream responseStream=response.GetResponseStream())
{
using(StreamReader reader= new StreamReader(responseStream,encoding))
{
result = reader.ReadToEnd();
reader.Close();
}
responseStream.Close();
}
response.Close();
response = null;
request = null;
}
catch (Exception ex)
{
string msg = ex.Message;
}
return result;
}
通过代码调试,出问题的大致位置在这里:
cs
using (StreamWriter writer = new StreamWriter(request.GetRequestStream(), encoding))
{
writer.Write(jsonData);
}
二.问题分析
在Write时,数据流意外关闭了,触发了http数据传输异常,为什么会出现这种情况,使用其它接口时不会出现这种问题,通过分析代码以及查阅资料发现了出问题的原因,我在调用接口函数时是这样的:
cs
SendPost(url, jsonData, Encoding.Default, contenType, header);
这里我指定了编码格式为Encoding.Default, 在函数内部计算request.ContentLength 长度的时候却指定了UTF8编码,如下:
cs
request.ContentLength = Encoding.UTF8.GetByteCount(jsonData);
这种情况如果当前默认刚好是UTF8编码,则不会出问题,如果是其它编码,则数据流读取时会出问题(编码解析规则),导致意外结束,分析问题大概是这样
三.问题修改
修改后的代码如下,使用前后一致的编码格式
cs
/// <summary>
/// 向指定URL发送POST请求
/// </summary>
/// <param name="url">发送请求的URL</param>
/// <param name="jsonData">请求参数,请求参数应该是Json格式字符串的形式</param>
/// <param name="contenType"><设置响应信息的编码格式,如utf-8/param>
/// <param name="header">请求头</param>
/// <returns>所代表远程资源的响应结果</returns>
public static string SendPost(string url,string jsonData,Encoding encoding,string contenType="application/json",Dictionary<string,string>header=null)
{
string result =string.Empty;
try
{
CookieContainer cookie = new CookieContainer();
HttpWebRequest request= (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
if(null != header && 0 < header.Count())
{
foreach(var item in header.Keys)
{
request.Headers.Add(item, header[item]);
}
}
request.ServicePoint.Expect100Continue = false;
request.ContentType = contenType;
request.ContentLength = encoding.GetByteCount(jsonData);
request.CookieContainer = cookie;
using (StreamWriter writer = new StreamWriter(request.GetRequestStream(), encoding))
{
writer.Write(jsonData);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
response.Cookies = cookie.GetCookies(response.ResponseUri);
using (Stream responseStream=response.GetResponseStream())
{
using(StreamReader reader= new StreamReader(responseStream,encoding))
{
result = reader.ReadToEnd();
reader.Close();
}
responseStream.Close();
}
response.Close();
response = null;
request = null;
}
catch (Exception ex)
{
string msg = ex.Message;
}
return result;
}
四.其它解决该异常的方法
这种异常问题触发原因估计有很多,这里收集一些其它的解决方法
1.添加:request.KeepAlive = false
2.注释掉:request.ContentLength = data.Length;