博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

客户端和Web Api服务的交互

Posted on 2013-02-20 17:06  Leon zhang  阅读(1113)  评论(0编辑  收藏  举报

客户端(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; }