C# HTTP POST(System.Net.WebException:请求已中止:请求已被取消)

一.问题描述

最近在使用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;

相关推荐
威联通网络存储8 小时前
某大型制造企业基于威联通 NAS 的海量数据存储与容灾归档实践
网络·nas
二进制person11 小时前
JavaEE初阶 --网络编程
linux·服务器·网络
钛态11 小时前
Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos)
android·网络协议·flutter·http·华为·中间件·harmonyos
Oll Correct11 小时前
实验八:验证以太网交换机的生成树协议STP
网络·笔记
Irissgwe12 小时前
进程间通信
linux·服务器·网络·c++·进程间通信
IT小白314 小时前
windows的VMware虚拟机上的Linux系统(CentOS)配置永久ip(关机重启ip不变)
网络·网络协议·tcp/ip
喵叔哟14 小时前
29_内容生产质量网关Skill:草稿生成+事实校验+发布前检查
网络·人工智能
liulilittle15 小时前
LINUX RING BUFFER TUN/TAP 1
linux·服务器·网络·c++·信息与通信·通信
蛊明15 小时前
批量检测 IP 是否在线:CPing vs QuickPing
网络·网络协议·tcp/ip
路由侠内网穿透.16 小时前
本地部署开源书签管理工具 LinkAce 并实现外部访问( Linux 版本)
linux·运维·服务器·网络·网络协议·开源