【WCF Restful】C# HTTP请求示范及踩坑问题
1、Post Body传多个参数
接口定义:(ResponseFormat与RequestFormat分别将相应参数序列化、请求参数反序列化)
[OperationContract] [WebInvoke(UriTemplate = "api/fun2", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] string TestFun2(string p1,string p2);
实现:
public string TestFun2(string p1, string p2) { return p1+p2; }
调用:
private void button1_Click(object sender, EventArgs e) { try { string sUrl3 = "http://localhost:10086/api/fun2"; string sBody2 = JsonConvert.SerializeObject(new { p1 = "1", p2 = "2" }); string sBack = HttpHelper.HttpPost(sUrl3, sBody2); } catch (Exception ex) {} }
2、Post Body传对象
接口定义:
[OperationContract] [WebInvoke(UriTemplate = "api/fun", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, Method = "POST", BodyStyle = WebMessageBodyStyle.Bare)] string TestFun(TestModel data);
实现:
public string TestFun(TestModel pars) { try { return pars.Test1 + pars.Test2; } catch (Exception ex) {} }
调用:
private void button1_Click(object sender, EventArgs e) { try { string sUrl = "http://localhost:10086/api/fun"; TestModel model = new TestModel(); model.Test1 = "1"; model.Test2 = "2"; string sBody = JsonConvert.SerializeObject(model); string sBack = HttpHelper.HttpPost(sUrl, sBody); } catch (Exception ex) { } }
3、Post Header传参
定义:
[OperationContract] [WebInvoke(Method = "POST", UriTemplate = "/api/Test/GetData2", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] string GetData2();
实现:
public string GetData2()
{ WebHeaderCollection headerCollection = WebOperationContext.Current.IncomingRequest.Headers; string code = headerCollection.Get("code"); string token = headerCollection.Get("token"); // todo return "200"; }
调用:
private void btnTest2_Click(object sender, EventArgs e) { try { string sUrl = "http://localhost:10086/api/Test/GetData2"; Dictionary<string, string> header = new Dictionary<string, string>(); header.Add("code", "cccccc"); header.Add("token", "tttttt"); string sBack = HttpHelper.Post(sUrl, header, ""); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
4、Get请求方式(ps:header传参方式与POST异曲同工)
定义:
[OperationContract] [WebGet(UriTemplate = "/api/Test/GetFun/{par1}/{par2}?code={code}&token={token}", ResponseFormat = WebMessageFormat.Json)] string GetFunction(string par1, string par2, int code, string token);
实现:
public string GetFunction(string par1, string par2, int code, string token) { return $"{par1},{par2},{code},{token}"; }
调用:
private void button1_Click(object sender, EventArgs e) { try { string sUrl = string.Format("http://localhost:6323/api/Test/GetFun/{0}/{1}?code={2}&token={3}", "par111", "par222", "ccccc", "ttttt"); string sBack = HttpHelper.Get(sUrl, null, null); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
“踩坑集合”:
1、MVC,HttpPost,请求传多个参数时,被请求的方法不支持类似 string sUser, string sPwd 的传参方式(接收值都为null),要用模型、dynmic或HttpContext.Current.Request.Form["par1"]接收参数!!!
2、请求参数中,参数数据类型不能为:DateTime(用string代替)、枚举(用int代替)、byte[],否则请求返回400错误。
3、请求参数中,Dictionary<T,V> 类型用 List<KeyValuePair<T,V>> 代替;在接口声明的入参中,应使用 Dictionary<T,V> 才能接到。
HttpHelper.cs
public class HttpHelper { static HttpHelper() { ServicePointManager.MaxServicePoints = 4; ServicePointManager.MaxServicePointIdleTime = 10000; ServicePointManager.UseNagleAlgorithm = true; ServicePointManager.Expect100Continue = true; ServicePointManager.CheckCertificateRevocationList = true; ServicePointManager.DefaultConnectionLimit = 512; //默认2,ServicePointManager.DefaultPersistentConnectionLimit } /// <summary> /// Post /// </summary> /// <param name="url"></param> /// <param name="body"></param> /// <param name="contentType"></param> /// <returns></returns> public static string Post(string url, string body, string contentType = "application/json") { return HttpMethod("POST", url, body, contentType); } public static string Post(string url, Dictionary<string, string> headers, string body, string contentType = "application/json") { return HttpMethod("POST", url, body, contentType, headers); } /// <summary> /// Put /// </summary> /// <param name="url"></param> /// <param name="body"></param> /// <param name="contentType"></param> /// <returns></returns> public static string Put(string url, string body, string contentType = "application/json") { return HttpMethod("PUT", url, body, contentType); } /// <summary> /// Get /// </summary> /// <param name="url"></param> /// <param name="contentType"></param> /// <returns></returns> public static string Get(string url, string contentType = "application/json") { return HttpMethod("GET", url, "", contentType); } /// <summary> /// Get /// </summary> /// <param name="url"></param> /// <param name="headers"></param> /// <param name="contentType"></param> /// <returns></returns> public static string Get(string url, Dictionary<string, string> headers, string contentType = "application/json") { return HttpMethod("GET", url, null, contentType, headers); } /// <summary> /// Get获取Image /// </summary> /// <param name="url"></param> /// <param name="contentType"></param> /// <returns></returns> public static Image Get_Image(string url, string contentType = "application/json") { return HttpMethod((stream) => Image.FromStream(stream), "GET", url, "", contentType, null); } /// <summary> /// Get获取byte[] /// </summary> /// <param name="url"></param> /// <param name="contentType"></param> /// <returns></returns> public static byte[] Get_byte(string url, string contentType = "application/json") { return HttpMethod((stream) => { using (var ms = new MemoryStream()) { stream.CopyTo(ms); using (stream) return ms.ToArray(); } } , "GET", url, "", contentType, null); } /// <summary> /// Delete操作 /// </summary> /// <param name="url">url地址</param> /// <param name="body">内容</param> /// <param name="contentType">要求内容,默认application/json</param> /// <returns>返回值</returns> public static string Delete(string url, string body = "", string contentType = "application/json") { return HttpMethod("DELETE", url, body, contentType); } private static string HttpMethod(string method, string url, string body, string contentType = "application/json", Dictionary<string, string> headers = null) { return HttpMethod((stream) => { using (StreamReader streamReader = new StreamReader(stream)) { return streamReader.ReadToEnd(); } }, method, url, body, contentType, headers); } private static T HttpMethod<T>(Func<Stream, T> func, string method, string url, string body, string contentType = "application/json", Dictionary<string, string> headers = null) { if (string.IsNullOrEmpty(contentType)) contentType = "application/json"; string responseContent = string.Empty; HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url); httpWebRequest.Method = method; //httpWebRequest.Accept = "text/html, application/xhtml+xml, */*"; httpWebRequest.Timeout = 600000; // 10分钟,10*60*1000=600000 //httpWebRequest.KeepAlive = true; // 获取或设置一个值,该值指示是否与 Internet 资源建立持久性连接默认为true。 httpWebRequest.ReadWriteTimeout = 600000; // 10分钟,10*60*1000=600000 httpWebRequest.ContentType = contentType; // 内容类型 httpWebRequest.MaximumResponseHeadersLength = 40000; httpWebRequest.ContentLength = 0; if (headers != null) { FormatRequestHeaders(headers, httpWebRequest); } if (!string.IsNullOrEmpty(body)) { byte[] btBodys = Encoding.UTF8.GetBytes(body); httpWebRequest.ContentLength = btBodys.Length; using (Stream writeStream = httpWebRequest.GetRequestStream()) { writeStream.Write(btBodys, 0, btBodys.Length); writeStream.Flush(); } } T t; using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse()) { using (Stream stream = httpWebResponse.GetResponseStream()) { t = func(stream); } } return t; } /// <summary> /// 格式化请求头信息 /// </summary> /// <param name="headers"></param> /// <param name="request"></param> private static void FormatRequestHeaders(Dictionary<string, string> headers, HttpWebRequest request) { foreach (var hd in headers) { //因为HttpWebRequest中很多标准标头都被封装成只能通过属性设置,添加的话会抛出异常 switch (hd.Key.ToLower()) { case "connection": request.KeepAlive = false; break; case "content-type": request.ContentType = hd.Value; break; case "transfer-enconding": request.TransferEncoding = hd.Value; break; default: request.Headers.Add(hd.Key, hd.Value); break; } } } }