• C#中POST数据和接收的几种方式(抛砖引玉)


    POST方式提交数据,一种众所周知的方式:

    html页面中使用form表单提交,接收方式,使用Request.Form[""]或Request.QueryString[""]来获取。

    这里介绍另外一种POST方式和接收方式,就是将整个数据作为加入到数据流中提交和接收

    接收方式:

    Stream s = System.Web.HttpContext.Current.Request.InputStream;
    byte[] b = new byte[s.Length];
    s.Read(b, 0, (int)s.Length);
    return Encoding.UTF8.GetString(b);

    只需要从input Stream中读取byte数据,然后转为string,再解析即可。如果要回复响应消息只需要用:Response.Write()  输出即可(和普通的页面输出一样)。

    主动POST发送方式:

    复制代码
                HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(url);
                webrequest.Method = "post";
    
    
                byte[] postdatabyte = Encoding.UTF8.GetBytes(postData);
                webrequest.ContentLength = postdatabyte.Length;
                Stream stream;
                stream = webrequest.GetRequestStream();
                stream.Write(postdatabyte, 0, postdatabyte.Length);
                stream.Close();
    
    
    
                using (var httpWebResponse = webrequest.GetResponse())
                using (StreamReader responseStream = new StreamReader(httpWebResponse.GetResponseStream()))
                {
    
                    String ret = responseStream.ReadToEnd();
    
                    T result = XmlDeserialize<T>(ret);
    
                    return result;
                }
    复制代码

    使用HttpClient对象发送

    复制代码
     public static  string   PostXmlResponse(string url, string xmlString)
                 
            {
                HttpContent httpContent = new StringContent(xmlString);
                httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                HttpClient httpClient = new HttpClient();
    
               
    
                HttpResponseMessage response = httpClient.PostAsync(url, httpContent).Result;
    
                if (response.IsSuccessStatusCode)
                {
                    Task<string> t = response.Content.ReadAsStringAsync();
                    return t.Result;
                }
                return string.Empty;
            }
             
    复制代码

    从代码中可以看出仅仅是将字符串转为byte[] 类型,并加入到请求流中,进行请求即可达到POST效果,该种POST方式与上边所提到的接收方式相互配合使用。

    下面一种方式是以键值对的方式主动POST传输的。

    复制代码
         /// <summary>
            /// 发起httpPost 请求,可以上传文件
            /// </summary>
            /// <param name="url">请求的地址</param>
            /// <param name="files">文件</param>
            /// <param name="input">表单数据</param>
            /// <param name="endoding">编码</param>
            /// <returns></returns>
            public static string PostResponse(string url, UpLoadFile[] files, Dictionary<string, string> input, Encoding endoding)
            {
    
                string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.ContentType = "multipart/form-data; boundary=" + boundary;
                request.Method = "POST";
                request.KeepAlive = true;
                //request.Credentials = CredentialCache.DefaultCredentials;
                request.Expect = "";
    
                MemoryStream stream = new MemoryStream();
    
    
                byte[] line = Encoding.ASCII.GetBytes("--" + boundary + "
    ");
                byte[] enterER = Encoding.ASCII.GetBytes("
    ");
                ////提交文件
                if (files != null)
                {
                    string fformat = "Content-Disposition:form-data; name="{0}";filename="{1}"
    Content-Type:{2}
    
    ";
                    foreach (UpLoadFile file in files)
                    {
    
                        stream.Write(line, 0, line.Length);        //项目分隔符
                        string s = string.Format(fformat, file.Name, file.FileName, file.Content_Type);
                        byte[] data = Encoding.UTF8.GetBytes(s);
                        stream.Write(data, 0, data.Length);
                        stream.Write(file.Data, 0, file.Data.Length);
                        stream.Write(enterER, 0, enterER.Length);  //添加
    
                    }
                }
    
    
                //提交文本字段
                if (input != null)
                {
                    string format = "--" + boundary + "
    Content-Disposition:form-data;name="{0}"
    
    {1}
    ";    //自带项目分隔符
                    foreach (string key in input.Keys)
                    {
                        string s = string.Format(format, key, input[key]);
                        byte[] data = Encoding.UTF8.GetBytes(s);
                        stream.Write(data, 0, data.Length);
                    }
    
                }
    
                byte[] foot_data = Encoding.UTF8.GetBytes("--" + boundary + "--
    ");      //项目最后的分隔符字符串需要带上--  
                stream.Write(foot_data, 0, foot_data.Length);
    
    
    
                request.ContentLength = stream.Length;
                Stream requestStream = request.GetRequestStream(); //写入请求数据
                stream.Position = 0L;
                stream.CopyTo(requestStream); //
                stream.Close();
    
                requestStream.Close();
    
    
    
                try
                {
    
    
                    HttpWebResponse response;
                    try
                    {
                        response = (HttpWebResponse)request.GetResponse();
    
                        try
                        {
                            using (var responseStream = response.GetResponseStream())
                            using (var mstream = new MemoryStream())
                            {
                                responseStream.CopyTo(mstream);
                                string message = endoding.GetString(mstream.ToArray());
                                return message;
                            }
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        }
                    }
                    catch (WebException ex)
                    {
                        //response = (HttpWebResponse)ex.Response;
    
    
                        //if (response.StatusCode == HttpStatusCode.BadRequest)
                        //{
                        //    using (Stream data = response.GetResponseStream())
                        //    {
                        //        using (StreamReader reader = new StreamReader(data))
                        //        {
                        //            string text = reader.ReadToEnd();
                        //            Console.WriteLine(text);
                        //        }
                        //    }
                        //}
    
                        throw ex;
                    }
    
    
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    复制代码

    通过两种主动POST提交 的代码可以看出,其主要区别在于发送前的数据格式 ContentType 的值。

    下面列举几种常用的ContentType 值,并简述他们的区别

    Content-Type 被指定为 application/x-www-form-urlencoded 时候,传输的数据格式需要如  title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3 所示格式,才能正确解析

    Content-Type 被指定为 multipart/form-data 时候,所需格式如下面代码块中所示

    复制代码
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    Content-Disposition: form-data; name="text"
    
    title
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    Content-Disposition: form-data; name="file"; filename="chrome.png"
    
    Content-Type: image/png
    
    PNG ... content of chrome.png ...
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
    复制代码

    Content-Type 也可以被指定为 application/json ,最终传输格式为 {"title":"test","sub":[1,2,3]}  至于如何接收本人未经尝试,但是可以肯定的讲使用文章开头所说的接收方式接收后转为string类型再

    发序列化是可行的。

    Content-Type指定为 text/xml  ,传输的数据格式为

    复制代码
    复制代码
    <?xml version="1.0"?>
    <methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
            <param>
                <value><i4>41</i4></value>
            </param>
        </params>
    </methodCall>
    复制代码
    复制代码

    此种方式,本人亦未经尝试,接受方式可以参考上文中 application/json 的接收方式。

    由于xml的格式传输数据,使用相对较少,相信很多同学亦不知道如何将字符串解析为对象,下文将提供一种转换方式,供参考

    复制代码
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(weixin);//读取xml字符串
                XmlElement root = doc.DocumentElement;
    
                ExmlMsg xmlMsg = new ExmlMsg()
                {
                    FromUserName = root.SelectSingleNode("FromUserName").InnerText,
                    ToUserName = root.SelectSingleNode("ToUserName").InnerText,
                    CreateTime = root.SelectSingleNode("CreateTime").InnerText,
                    MsgType = root.SelectSingleNode("MsgType").InnerText,
                };
                if (xmlMsg.MsgType.Trim().ToLower() == "text")
                {
                    xmlMsg.Content = root.SelectSingleNode("Content").InnerText;
                }
                else if (xmlMsg.MsgType.Trim().ToLower() == "event")
                {
                    xmlMsg.EventName = root.SelectSingleNode("Event").InnerText;
                }
                return xmlMsg;
    复制代码
    复制代码
            private class ExmlMsg
            {
                /// <summary>
                /// 本公众账号
                /// </summary>
                public string ToUserName { get; set; }
                /// <summary>
                /// 用户账号
                /// </summary>
                public string FromUserName { get; set; }
                /// <summary>
                /// 发送时间戳
                /// </summary>
                public string CreateTime { get; set; }
                /// <summary>
                /// 发送的文本内容
                /// </summary>
                public string Content { get; set; }
                /// <summary>
                /// 消息的类型
                /// </summary>
                public string MsgType { get; set; }
                /// <summary>
                /// 事件名称
                /// </summary>
                public string EventName { get; set; }
    
            }
    复制代码

    至此,相信一部分同学能有所得。由于本人水平一般,文中所述可能有纰漏之处,还请路过高手指出,同时也欢迎在评论区贴出更好的 发送和接受方式,供大家学习和交流。

    本文有参考:https://imququ.com/post/four-ways-to-post-data-in-http.html  ,向原文作者致谢。

  • 相关阅读:
    percona-toolkit 之 【pt-heartbeat】说明
    sql-索引的作用(超详细)
    SqlServer2005 海量数据 数据表分区解决难题
    怎样玩转千万级别的数据(表分区)
    SQL数据缓存依赖总结
    关于缓存中Cookie,Session,Cache的使用
    Anti-Forgery Request Recipes For ASP.NET MVC And AJAX
    jquery 父、子页面之间页面元素的获取,方法的调用
    win7系统部分软件显示乱码怎么办
    转:mvc 当中 [ValidateAntiForgeryToken] 的作用
  • 原文地址:https://www.cnblogs.com/webenh/p/5775543.html
Copyright © 2020-2023  润新知