zoukankan      html  css  js  c++  java
  • 使用RestSharp 库消费Restful Service

    现在互联网上的服务接口都是Restful的,SOAP的Service已经不是主流。.NET/Mono下如何消费Restful Service呢,再也没有了方便的Visual Studio的方便生产代理的工具了,你还在用HttpWebRequest 自己封装吗?Restful Service还有授权问题,自己写出来的代码是不是很不优雅?通常Restful Service返回的数据格式是XML或者Json,还要设置服务的输入参数等等,使用起来很复杂。本文向你推荐一个开源的库RestSharp轻松消费Restful Service。RestSharp是一个开源的.NET平台下REST和Http API的客户端库,支持的平台有.NET 3.5/4、Mono、Mono for Android、MonoTouch、Windows Phone 7.1 Mango。他可以简化我们访问Restful服务,可以到这里下载代码 https://github.com/johnsheehan/RestSharp/archives/master 更简单的使用NuGet。RestSharp使用Json.Net处理 Json数据同Poco对象的序列化。

    下面分别从库的使用方式上进行介绍,使用的Restful Service是腾讯社区开放平台(http://opensns.qq.com/)。 
    1、服务认证,RestSharp定义了一个认证授权的接口 IAuthenticator ,有NtlmAuthenticator、HttpBasicAuthenticator、OAuth1Authenticator、OAuth2Authenticator几种,基本上可以满足要求了,腾讯社区开放平台使用OAuth2,腾讯社区开放平台额外增加了一个OpenId的参数,我们从OAuth2Authenticator的基类继承实现一个:

        public class OAuthUriQueryParameterAuthenticator : OAuth2Authenticator 
        { 
            private readonly string openId; 
            private readonly string consumerKey;

            public OAuthUriQueryParameterAuthenticator(string openId, string accessToken, string consumerkey) 
                :base(accessToken) 
            { 
                this.openId = openId; 
                this.consumerKey = consumerkey; 
            }

            public override void Authenticate(IRestClient client, IRestRequest request) 
            { 
                request.AddParameter("access_token", AccessToken, ParameterType.GetOrPost); 
                request.AddParameter("openid", openId, ParameterType.GetOrPost); 
                request.AddParameter("oauth_consumer_key", consumerKey, ParameterType.GetOrPost); 
            }

    2、Get请求方法,下面的例子是根据access_token获得对应用户身份的openid: https://graph.qq.com/oauth2.0/me?access_token=YOUR_ACCESS_TOKEN

         public string GetOpenId(string accessToken) 
          {

              RestClient  _restClient = new RestClient(Endpoints.ApiBaseUrl); 
              var request = _requestHelper.CreateOpenIDRequest(accessToken); 
              var response = Execute(request); 
              var openid = GetUserOpenId(response.Content); 
              return openid; 
          }

           private RestSharp.RestResponse Execute(RestRequest request) 
           {

           //返回的结果

               var response = _restClient.Execute(request);

               if (response.StatusCode != HttpStatusCode.OK) 
               { 
                   throw new QzoneException(response); 
               } 
               return response; 
           }

           internal RestRequest CreateOpenIDRequest(string accesstoken) 
           { 
               var request = new RestRequest(Method.GET); 
               request.Resource = "oauth2.0/me?access_token={accesstoken}"; 
               request.AddParameter("accesstoken", accesstoken, ParameterType.UrlSegment); 
               return request; 
           }

          上面代码里涉及到了服务的输入参数通过AddParameter方法很方便的处理,是不是很简单。

    3、POST请求服务,下面的例子是发表一条微博信息(纯文本)到腾讯微博平台上http://wiki.opensns.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91add_t

            /// <summary> 
            /// 发表一条微博信息(纯文本)到腾讯微博平台上 
            /// </summary> 
            /// <param name="content">表示要发表的微博内容。必须为UTF-8编码,最长为140个汉字,也就是420字节。 
            /// 如果微博内容中有URL,后台会自动将该URL转换为短URL,每个URL折算成11个字节。</param> 
            /// <param name="clientip">用户ip,以分析用户所在地</param> 
            /// <param name="jing">用户所在地理位置的经度。为实数,最多支持10位有效数字。有效范围:-180.0到+180.0,+表示东经,默认为0.0</param> 
            /// <param name="wei">用户所在地理位置的纬度。为实数,最多支持10位有效数字。有效范围:-90.0到+90.0,+表示北纬,默认为0.0。</param> 
            /// <param name="syncflag">标识是否将发布的微博同步到QQ空间(0:同步; 1:不同步;),默认为0.</param> 
            /// <returns></returns> 
            internal AddWeiboResult AddWeibo(string content, string clientip = "", string jing = "", string wei = "", int syncflag = 0) 
            {

            RestClient  _restClient = new RestClient(Endpoints.ApiBaseUrl);

                 _restClient.Authenticator = new OAuthUriQueryParameterAuthenticator(context.AccessToken.OpenId, context.AccessToken.AccessToken, context.Config.GetAppKey()); 
                var request = _requestHelper.CreateAddWeiboRequest(content, clientip,jing,wei,syncflag);

                var response = Execute(request);            
                var payload = Deserialize<AddWeiboResult>(response.Content); 
                return payload; 
            }

           internal RestRequest CreateAddWeiboRequest(string content, string clientip, string jing, string wei, int syncflag) 
            { 
                var request = new RestRequest(Method.POST); 
                request.RequestFormat = DataFormat.Json; 
                request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); 
                request.Resource = "t/add_t"; 
                request.AddParameter("content", content); 
                if (!string.IsNullOrEmpty(clientip)) 
                { 
                    request.AddParameter("clientip", clientip); 
                } 
                if (!string.IsNullOrEmpty(jing)) 
                { 
                    request.AddParameter("jing", jing); 
                } 
                if (!string.IsNullOrEmpty(wei)) 
                { 
                    request.AddParameter("wei", wei); 
                } 
                request.AddParameter("syncflag", syncflag); 
                return request; 
            }

       这个方法需要使用到OAuth2的认证和前面的不需要认证的接口比较起来并没有变复杂,代码很优雅。

    4、来点复杂的,发个图片微博,RestSharp对HttpFile的封装也很不错,使用起来一样很简单,看代码中的红色部分:

    internal RestRequest CreateAddPictureWeiboRequest(string content, string clientip, string jing, string wei, int syncflag, string fileName, byte[] bytes) 
           { 
               var request = new RestRequest(Method.POST); 
               request.RequestFormat = DataFormat.Json; 
               var boundary = string.Concat("--", Util.GenerateRndNonce()); 
               request.AddHeader("Content-Type", string.Concat("multipart/form-data; boundary=", boundary)); 
               request.Resource = "t/add_pic_t"; 
               request.AddParameter("content", content); 
               if (!string.IsNullOrEmpty(clientip)) 
               { 
                   request.AddParameter("clientip", clientip); 
               } 
               if (!string.IsNullOrEmpty(jing)) 
               { 
                   request.AddParameter("jing", jing); 
               } 
               if (!string.IsNullOrEmpty(wei)) 
               { 
                   request.AddParameter("wei", wei); 
               } 
               request.AddParameter("syncflag", syncflag); 
               request.AddFile("pic", bytes, fileName); 
               return request; 
           }

    上面这几个API的调用已经很具有代表性了,是不是可以很好的简化你使用Restful Service,记住DRY(don’t repeat yourself),可以很好的加速你的应用的开发。

    Quartz.NET的管理工具

    很多同学都在用Quartz.NET做任务调度,任务调度情况怎么样啊,需要暂停某个任务,运行下某个任务,需要有管理工具的支持,本篇文章是向你介绍Quartz.NET的管理工具方面的几个开源项目。工具有两类:完整的一个管理站点和嵌入你的项目里头的一个模块。

    1、quartznet-admin 是一个完整的asp.net mvc的Quartz.NET 管理应用,地址是 http://code.google.com/p/quartznet-admin/ ,这个项目目前也没有发布出来的版本,自己可以去下载代码下来编译,但是这个项目有好几个月都没有活动了,估计会有些问题,开源的项目自己搞定没问题。

    2、QuartzNetWebConsole 是一个可以插入你网站里头的一个模块 ,地址是https://github.com/mausch/QuartzNetWebConsole 。这个项目适合于在你的ASP.NET网站里面使用。如果你的任务是使用Windows服务方式承载的,那就得使用quartznet-admin或者是crystal-quartz

    3、crystal-quartz 也是一个模块,地址是http://code.google.com/p/crystal-quartz/,可以很方便的集成到的管理网站里头,它提供了2个提供者CrystalQuartz.Simple(和QuartzNetWebConsole一样在Web里头直接承载调度任务)和CrystalQuartz.Remote(用于使用Windows服务方式承载任务调度,远程管理方式)。

    4、QuartzNetManager 是一个完整Quartz.NET的WPF写的管理工具,地址是https://github.com/adometry/QuartzNetManager

    Protocol Buffers 是在一个很理想的结构化数据的语言中立的序列化格式。你可以考虑一下XML或JSON,但更轻,更小的协议缓冲区。 这种格式的广应用于谷歌不同的系统之间交换数据。

    由于其结构化数据的最佳表现,protocol buffers 是一个代表RESTful服务处理的数据很好的选择。要遵循REST的原则, protocol buffers 应作为一个新的超媒体类型的代表。 在当前版本(.NET 4) 的Windows通讯基础(WCF),包含一个新的媒体类型,需要相当数量的努力。 幸运的是,新版本的WCF HTTP堆栈,使媒体类型的WCF编程模型的一等公民,大家可以Glenn Block’s 博客去了解更详细的内容。推荐大家假期可以看下这本书《REST实战》http://book.douban.com/subject/6854551/

    下面我们来介绍如何使用Google Protocol Buffers,只定义一个超媒体类型 ProtoBufferFormatter:

    自定义超媒体类型是通过创建自定义的MediaTypeFormatter,实现OnWritetoStream() 和 OnReadFromStream() 方法进行序列化和反序列化处理。人们经常认为媒体类型只是在服务端使用,但是它用来在客户端控制序列化和反序列化的要求,下图显示了一个HTTP 请求/响应和媒体类型格式化扮演的角色:

    MediaTypeFormatterProcess

    这个例子我们使用入门:构建简单的Web API 的代码和WCF Web API Preview 6。使用的媒体类型是application/x-protobuf ,REST服务的核心原则就是服务器和客户端之间的松耦合性,客户端需要知道书签的URI,但不应该知道任何其他的URI的知识,但是客户端必须知道链接关系。

    image

    下面的代码是自定义的ProtoBufferFormatter,构造函数里指明了支持的媒体类型 application/x-protobuf。

    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Net.Http.Formatting; 
    using System.IO; 
    using ProtoBuf; 
    using ProtoBuf.Meta;

    namespace WcfWebFormat.Formatters 

        public class ProtoBufferFormatter : MediaTypeFormatter 
        { 
            public ProtoBufferFormatter() 
            { 
                this.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-protobuf")); 
            }

            protected override void OnWriteToStream(Type type, object value, Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, System.Net.TransportContext context) 
            { 
                Serializer.Serialize(stream, value);  
            }

            protected override object OnReadFromStream(Type type, Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders) 
            { 
                object obj = (RuntimeTypeModel.Default).Deserialize(stream, null, type); 
                return obj; 
            }

        } 
    }

    如上所示,我们在OnWriteToStream方法中将.NET对象序列化为ProtoBuf格式,在OnReadFromStream方法中将ProtoBuf格式饭序列化为.NET对象。

    现在需要给我们的.NET对象加入ProtoBuf 序列化的标签:

    using System.Collections.Generic; 
    using System.Xml.Serialization; 
    using ProtoBuf;

    namespace ContactManager.Resources 

        [ProtoContract] 
        public class Contact 
        { 
            [ProtoMember(1)] 
            public int ContactId { get; set; } 
            [ProtoMember(2)] 
            public string Name { get; set; } 
        } 
    }

    把ProtoBufferFormatter 加入到WCF运行时的超媒体类型集合里。

    using Microsoft.ApplicationServer.Http; 
    using WcfWebFormat.Formatters;

    namespace ContactManager 

        public class ContactManagerConfiguration : HttpConfiguration 
        { 
            public ContactManagerConfiguration() 
            { 
                this.Formatters.Add(new ProtoBufferFormatter()); 
            } 
        } 
    }

    修改服务配置,使用ContactManagerConfiguration:

    var config = new ContactManagerConfiguration() { EnableTestClient = true }; 
    routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory() { Configuration = config }, typeof(ContactsApi)));

    在客户端调用的代码如下:

               var serviceUri = new Uri("http://localhost:9000/api/contacts/"); 
                var httpClient = new HttpClient(); 
                httpClient.BaseAddress = serviceUri; 
                httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-protobuf"));

                var response = httpClient.GetAsync("1").Result; 
                Contact obj = (RuntimeTypeModel.Default).Deserialize(response.Content.ReadAsStreamAsync().Result, null, typeof(Contact)) as Contact;

                var formatters = new MediaTypeFormatterCollection() { new ProtoBufferFormatter() };
                var content = new ObjectContent<Contact>(obj, "application/x-protobuf",formatters);
                content.Headers.ContentType = new MediaTypeHeaderValue("application/x-protobuf");

                httpClient.PostAsync(serviceUri,content);

    即使目前来说Google Protocol Buffers没有XML/JSON那样普及,RESTful服务使用中ProtoBuf无疑是一个非常有效的超媒体类型。祝大家龙年新春愉快,吉祥如意!

    相关文章:

    • 软件系统开发中的数据交换协议
    • .net自带二进制序列化,XML序列化和ProtoBuf序列化的压缩对比
    • Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式而非XML
    • Leverage T4Scaffolding for WCF Web API
    • using-protocol-buffers-on-net-platform-part-i
    • using-protocol-buffers-on-net-platform-part-ii
    • Restful WCF / EF POCO / UnitOfWork / Repository / MEF : 1 of 2
    • 两种常见的分布式应用架构风格包括:DO(分布式对象)、RPC(远程过程调用)。这两种架构风格在企业应用中得到了广泛的应 
      用,然而,Web架构的设计者们却有意避免采用这两种架构风格。主要的原因是运行Web应用的互联网环境,与运行企业应用的企业内网环境有很大的差别。 
      那么,互联网环境有哪些独有的特点呢? 
      1. 可伸缩性要求难以预测和无法控制:一个Web应用的并发访问量,是开发者难以预测和无法控制的。 
      2. 安全性要求难以预测和无法控制:一个Web应用所接受的请求格式,是开发者难以预测和无法控制的,有可能出现大量恶意构造的请求格式。 
      3. 松耦合至关重要:因为存在着大量异构的系统,必须要追求最大限度的松耦合。 
      4. 简单性至关重要:不可引入复杂的编程模型,必须降低开发者开发Web应用的门槛。

      软件应用所处的运行环境会对其架构设计产生巨大影响。设计软件应用的架构,一定要深入考虑软件所处的运行环境。脱离开软件所处的运行环境,比较不同架构 
      之间的优劣是没有意义的。

      REST这种架构风格,正是为面向互联网的Web应用量身定制的。它由一组架构约束组成: 
      1. 客户-服务器 
      2. 无状态 
      3. 缓存 
      4. 统一接口 
      5. 分层系统 
      6. 按需代码(可选)

      上述内容来自《REST实战》译者序。.NET上的分布式应用架构风格从WCF开始统一了Remoting,SOAP,以及对REST的支持。现在我们来看下最新的.NET平台上都有哪些REST框架和工具库:

      1. WCF WebHttp Services in .NET 4 :WCF 3.5开始支持REST,实现方式上还是RPC 方式,Windows Communication Foundation (WCF)Web HTTP 编程模型可以向非 SOAP 终结点公开 WCF 服务操作。文档地址 http://msdn.microsoft.com/zh-cn/library/bb412169.aspx 

      2. WCF WebApi:这是完全按照HTTP模型实现的REST,目前还处于预览版,WCF Web API允许开发人员通过HTTP开放他们的应用程序、数据和服务。这允许开发人员可以充分利用HTTP作为应用程序的协议,应用程序可以和丰富的客户端进行交互,不仅仅是浏览器、移动设备、桌面应用还是其他的后端服务。文档地址:http://wcf.codeplex.com/documentation 

      3. Open Rasta:OpenRasta是一个基于MIT协议开源的支持.NET 2.0以上的Rest开发框架,重点围绕这资源和HTTP方法开发的REST框架。文档地址:https://github.com/openrasta/openrasta-stable/wiki 

      4. Service Stack :是一个高性能的开源 .NET/Mono  REST服务框架 地址:http://www.servicestack.net/

      5. RestSharp :这只是一个支持WindowsPhone,Mono for Android, MonoTouch跨平台的Rest 客户端开发库。地址:http://restsharp.org/

    作者: 自由、创新、研究、探索……
    出处:http://shanyou.cnblogs.com/
    版权:本文版权归作者和博客园共有
    转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
    要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任 
  • 相关阅读:
    单例模式
    HashSet、LinkedHashSet、SortedSet、TreeSet
    ArrayList、LinkedList、CopyOnWriteArrayList
    HashMap、Hashtable、LinkedHashMap
    andrew ng machine learning week8 非监督学习
    andrew ng machine learning week7 支持向量机
    andrew ng machine learning week6 机器学习算法理论
    andrew ng machine learning week5 神经网络
    andrew ng machine learning week4 神经网络
    vue组件监听属性变化watch方法报[Vue warn]: Method "watch" has type "object" in the component definition. Did you reference the function correctly?
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2330272.html
Copyright © 2011-2022 走看看