客户端(windows应用程序和Web)和Web Api交互的核心代码提炼
//★HTTP请求对象。 HttpRequestMessage requestMsg = new HttpRequestMessage(); //设置HTTP接收请求的数据类型为JSON requestMsg.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //请求数据的链接(Uri)例如:"http://10.186.3.xx/zl_server/api/[Controller]/[id]?XXX=XXX&..." requestMsg.RequestUri = new Uri(strToRequest); //★HTTP的内容对象 HttpContent content = null; if(objToSend!=null) //StringContent():转换成基于字符串的HTTP内容。 //JsonConvert.SerializeObject(objToSend):将实体对象序列化成JSON content = new StringContent(JsonConvert.SerializeObject(objToSend), Encoding.UTF8, "application/json"); requestMsg.Method = HttpMethod.Get;//用于获取数据 requestMsg.Content = content; //★HTTP客户端对象(用于发送HTTP请求和接收HTTP响应) static readonly HttpClient s_httpClient = new HttpClient(); //s_httpClient是HttpClient的对象:用于发送HTTP请求和接收HTTP响应 //s_httpClient.SendAsync:发送一个HTTP请求一个异步操作,并返回响应结果。 Task<HttpResponseMessage> rtnAll = s_httpClient.SendAsync(requestMsg);//这一步是核心,正式发出请求并获取响应的结果。 //★HTTP的响应对象(这一步是核心,正式发出请求并获取响应的结果) HttpResponseMessage resultMessage =rtnAll.Result; /* ★这一步非常关键,是将服务器端响应的数据赋值给本地的过程。 * resultMessage.Content.ReadAsAsync<NjtHttpInfo>(s_formatters)如何理解? * 解释:从响应的内容里异步读取,并赋值给指定的Model对象 * new MediaTypeFormatter[] { new JsonMediaTypeFormatter() } 指定数据以Json格式化 */ Task<T> rtnFinal = resultMessage.Content.ReadAsAsync<T>(new MediaTypeFormatter[] { new JsonMediaTypeFormatter() }); //如果HttpMethod.Get时 rtnFinal.Result这个就是Get获取的数据 return rtnFinal.Result; //如果是HttpMethod.Post\HttpMethod.Put\HttpMethod.Delete的时候是不需要返回值的 return default(T);//default(T):返回 NULL
客户端(windows应用程序和Web)和Web Api交互的完成的代码
//Get调用方法(集合列表)获取单条数据只需要后面加上“/id” WebApiClientHelper.DoJsonRequest<SimUser_API_Get>("http://10.186.3.21/zl_server/api/entrance", EnuHttpMethod.Get); //Post调用方法(新增) WebApiClientHelper.DoJsonRequest<UsbDisk_API_Post>("http://10.186.3.21/zl_server/api/entrance", EnuHttpMethod.Post, objToSend: objToPost); //Put调用方法(变更) WebApiClientHelper.DoJsonRequest<User_API_Put>("http://10.186.3.21/zl_server/api/entrance/2", EnuHttpMethod.Put, objToSend: userPut, tick: userVm.UpdateTicks);
/// <summary> /// 客户端与API服务的交互函数 /// </summary> /// <typeparam name="T">T DoJsonRequest<T>中“T”是代表可变的参数,是根据传入的类型而定的可以是model类或是IEnumerable<T></typeparam> /// <param name="strUri">请求地址</param> /// <param name="method">请求类型(Get,Put,Post,Delete)</param> /// <param name="queryCondition">分页参数</param> /// <param name="objToSend">对象参数(一般用于Update的时候)</param> /// <param name="tick">变更时间</param> /// <returns></returns> public static T DoJsonRequest<T>(string strUri, EnuHttpMethod method, IUriConvertable queryCondition = null, Object objToSend = null, long tick = 0) { string strToRequest = strUri; if (tick != 0 && (method == EnuHttpMethod.Put || method == EnuHttpMethod.Delete)) strToRequest += "?UpdateTicks=" + tick.ToString(CultureInfo.InvariantCulture);//CultureInfo.InvariantCulture的作用是为了固定格式 if (queryCondition != null && method == EnuHttpMethod.Get) strToRequest += queryCondition.QueryString; //表示一个HTTP请求消息。 HttpRequestMessage requestMsg = new HttpRequestMessage(); //这一步是非对称的加密 MakePrincipleHeader(requestMsg, strToRequest); //设置HTTP接收请求的数据类型为JSON requestMsg.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //请求数据的链接(Uri) requestMsg.RequestUri = new Uri(strToRequest); HttpContent content = null; if(objToSend!=null) //StringContent():转换成基于字符串的HTTP内容。 //JsonConvert.SerializeObject(objToSend):将实体对象序列化成JSON content = new StringContent(JsonConvert.SerializeObject(objToSend), Encoding.UTF8, "application/json"); switch (method) { case EnuHttpMethod.Post: requestMsg.Method = HttpMethod.Post;//Post用于新增 requestMsg.Content = content; break; case EnuHttpMethod.Put: requestMsg.Method = HttpMethod.Put;//Put用于修改 requestMsg.Content = content; break; case EnuHttpMethod.Delete: requestMsg.Method = HttpMethod.Delete; break; default: //EnuHttpMethod.Get: requestMsg.Method = HttpMethod.Get;//Get用于获取 break; } //s_httpClient是HttpClient的对象:用于发送HTTP请求和接收HTTP响应 //s_httpClient.SendAsync:发送一个HTTP请求一个异步操作,并返回响应结果。 Task<HttpResponseMessage> rtnAll = s_httpClient.SendAsync(requestMsg); #region 执行 HttpResponseMessage resultMessage = null; Task<T> rtnFinal; try { try {
//这一步是关键提交请求的过程,rtnAll.Result这里其实是一个多线程的处理,是.Net Framework 4.0的新特性之一 resultMessage = rtnAll.Result; } catch (AggregateException ae) { foreach (var ex in ae.InnerExceptions) { if (ex is HttpRequestException) { throw new NjtCsException("发送网络请求失败", ex); } } } if (!resultMessage.IsSuccessStatusCode)//判断响应是否成功? { Task<NjtHttpInfo> error; try { /* * resultMessage.Content.ReadAsAsync<NjtHttpInfo>(s_formatters)如何理解? * 解释:从响应的内容里异步读取,并赋值给指定的Model对象 * s_formatters:就是new MediaTypeFormatter[] { new JsonMediaTypeFormatter() } 指定数据以Json格式化 */ error = resultMessage.Content.ReadAsAsync<NjtHttpInfo>(s_formatters); } catch (Exception ex) { throw new NjtCsException("服务器意外错误", ex); } throw new NjtCsException(error.Result.Message); } if (method!=EnuHttpMethod.Get) { return default(T);//default(T):返回 NULL(除了Get方式是需要获取值的,其他方式都不需要返回响应结果) } try { /* ★这一步非常关键,是将服务器端响应的数据赋值给本地的过程。 * resultMessage.Content.ReadAsAsync<NjtHttpInfo>(s_formatters)如何理解? * 解释:从响应的内容里异步读取,并赋值给指定的Model对象 * s_formatters:就是new MediaTypeFormatter[] { new JsonMediaTypeFormatter() } 指定数据以Json格式化 */ rtnFinal = resultMessage.Content.ReadAsAsync<T>(s_formatters); } catch (Exception ex) { throw new NjtCsException("服务器返回与请求不匹配", ex); } } catch (NjtCsException njtex) { njtex.ParameterObject = new { Uri = strUri, Method = method, Data = objToSend, Tick = tick }; throw; } #endregion return rtnFinal.Result; }