• wcf 服务创建,配置,测试


    一.WCF创建:

        常规的创建WCF服务是通过SOAP传输的,很多网站开发人员想放弃使用XML而使用JSON,这个时候可以参照:http://www.cnblogs.com/zhili/p/WCFRestService.html?utm_source=tuicool&utm_medium=referral

        WCF 3.5中对Rest服务做了支持。WCF在System.ServiceModel.Web组件中新增了ResT编程,Rest编程有两个主要的新属性: WebGetAttribute 和 WebInvokeAttribute ,还有一个URI模板机制,帮助你声明每种方法响应使用的URI和动词。.NET Framework还提供了一个新的绑定(WebHttpBinding)和新的行为(WebHttpBehavior),此外,还提供了WebServiceHost和WebServiceHostFactory类来对Rest服务进行支持。

        以前我们都是把WCF服务抽象为操作的概念,而Rest最早是由Roy Thomas Fielding 在他的博士论文( “体系结构风格和基于网络软件体系的设计 ”)中提出的。Rest服务是将服务抽象为资源,每个资源都有一个唯一的统一资源标识符(URI),我们不再是通过调用操作的方式与服务进行交互了,而是通过HTTP标准动词(GET、POST、PUT和DELETE)的统一接口来完成。总之一句话概括,Rest服务换了一种思维方式,把服务也当成一种资源,通过Get、Post、Put和Delete这些HTTP动词来进行交互。这样,问题就来了,Rest服务具有什么好处呢?即我们为什么要去关注Rest和实现它呢?

       Rest优势就在于其使用极其简单,Rest服务要求很少的编码工作量,可以减少很多不必要的工作。Rest服务主要有以下优点:

    • 无需引入SOAP消息传输层,轻量级和高效率的HTTP格式可直接被应用。
    • 可以轻易地在任何编程语言中实现,尤其是在JS中。使用SOAP的服务与JS交互非常繁琐,而使用Rest服务与JS交互非常简单。
    • 可以不使用任何编程语言就能访问服务,而只需要使用Web浏览器即可。
    • 更好的性能和缓存支持。使用Rest服务可以改善响应时间和改善用户体验。
    • 可扩展性和无状态性。Rest服务基于HTTP协议,每个请求都是独立的,一旦被调用,服务器不保留任何会话,这样可以更具响应性,通过减少通讯状态的维护工作来提供服务的可扩展性。

    Rest和SOAP比较:

    REST目前只基于HTTP和HTTPS协议,而SOAP可支持任何传输协议,包括HTTP/HTTPS、TCP、SMTP等协议。另外Rest服务除了能使用XML作为数据承载外,还有JSON,RSS和 ATOM 形式。

    Rest与SOAP对应的比较如下所示:

    1. SOAP是一种工业标准,面对的应用需求时RPC(远程过程调用),而Rest面对的应用需求是分布式Web系统。
    2. Rest服务强调数据,请求和响应消息都是数据的封装,而SOAP服务更强调接口,SOAP消息封装的是过程调用。Rest是面向资源的,而SOAP是面向接口的。
    3. Rest架构下,HTTP是承载协议,也是应用协议,而SOAP架构下,HTTP只是承载协议,SOAP才是应用协议。

    那在什么情况下使用Rest,什么情况下使用SOAP呢?这要看具体的实际情况。具体应用场景如下所示:

    • 远程调用用SOAP。如果服务是作为一种功能提供,客户端调用服务是为了执行一个功能,用SOAP,比如常见的需求是认证授权。而数据服务用Rest。
    • 要更多的考虑非功能需求时使用SOAP,如需考虑安全、传输和协议等需求的情况下。
    • 低带宽、客户端的处理能力受限的场合可以考虑使用Rest。如在PDA或手机上消费服务。

    第一步:创建Rest服务接口和实现。

    [ServiceContract(Namespace ="http://www.cnblogs.com/zhili/")]//也可以不加直接通过服务url作为地址
        public interface IEmployees
        {
            // 契约操作不再使用操作契约的方式来标识,而是使用WebGetAttribute特性来标识,从而表明该服务是Rest服务
            //[OperationContract]//Rest可以不适用OperactionContract标识
            [WebGet(UriTemplate = "all")] 
            //[WebGet(UriTemplate = "all", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] 
            IEnumerable<Employee> GetAll();
    
            [WebGet(UriTemplate = "{id}")]
            ////[WebGet(UriTemplate = "MySplit/{id}", Method = "POST" ,ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] 
            Employee Get(string id);
            
            [WebInvoke(UriTemplate="/", Method="PUT")]
            void Create(Employee employee);
    
            [WebInvoke(UriTemplate = "/", Method = "POST")]
            void Update(Employee employee);
    
            [WebInvoke(UriTemplate = "/", Method = "DELETE")]
            void Delete(string id);
        }
        //[Serializable],如果不是使用SOAP协议,可以不加
        [DataContract(Namespace = "http://www.cnblogs.com.zhili/")]
        public class Employee
        {
            //注意:对外访问的数据属性必须保证其get和set都是public,不然,数据传输不了的
            [DataMember]
            public string Id { get; set; }
    
            [DataMember]
            public string Name { get; set; }
    
            [DataMember]
            public string Department { get; set; }
        }

    从上面代码可以看出,Rest服务不再使用OperactionContract的方式来标识操作了,此时在Rest架构下,每个操作都被当做一种资源对待,所以这里的操作使用了WebGetAttribute特性和WebInvokeAttribute来标识。下面具体看看契约的具体实现,即Rest服务的实现代码。实现服务的代码就不加了。

    第二步:实现Rest服务宿主。这里还是使用控制台程序来作为宿主程序

    namespace RestServiceHost
    {
        class Program
        {
            static void Main(string[] args)
            {
                // Rest服务使用WebServiceHost类来为服务提供宿主
                using (WebServiceHost webHost = new WebServiceHost(typeof(EmployeesService)))
                {
                    webHost.Opened += delegate
                    {
                        Console.WriteLine("Rest Employee Service 开启成功!");
                    };
    
                    webHost.Open();
                    Console.Read();
                }
            }
        }
    }

    对应的配置文件内容如下所示:

    <configuration>
      <system.serviceModel>
        <services>
          <service name="WCFContractAndService.EmployeesService">
            <!--这里Rest服务只能使用WebHttpBinding来作为绑定-->
            <endpoint address="http://localhost:9003/employeeService"
                      binding="webHttpBinding" contract="RestContract.IEmployees"/>
          </service>
        </services>
      </system.serviceModel>
    </configuration>

    第三步:实现Rest服务调用客户端。这里通过通道工厂的方式来创建代理对象的

    namespace WCFClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (ChannelFactory<IEmployees> channelFactory = new ChannelFactory<IEmployees>("employeeService"))
                {
                    // 创建代理类
                    IEmployees proxy = channelFactory.CreateChannel();
    
                    Console.WriteLine("所有员工信息:");
    
                    // 通过代理类来对Rest服务进行操作
                    Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString()));
    
                    Console.WriteLine("
    添加一个新员工{0003}:");
                    proxy.Create(new Employee
                    {
                        Id = "0003", Name="李四", Department="财务部"
                    });
    
                    Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString()));
    
                    Console.WriteLine("
    修改员工(0003)信息:");
                    proxy.Update(new Employee 
                    {
                        Id = "0003", Name="李四", Department = "销售部"
                    });
                    Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString()));
                    Console.WriteLine("
    删除员工(0002)信息:");
                    proxy.Delete("0002");
                    Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString()));
    
                    Console.Read();
                }
            }
        }
    }

    客户端对应的配置文件内容如下所示:

    <configuration>
      <system.serviceModel>
        <behaviors>
          <endpointBehaviors>
            <behavior name="webBehavior">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <client>
          <endpoint name="employeeService" address="http://localhost:9003/employeeService"  binding="webHttpBinding" behaviorConfiguration="webBehavior"  contract="RestContract.IEmployees">
            
          </endpoint>
        </client>
      </system.serviceModel>
    </configuration>

    二.WCF配置文件

    配置也是WCF编程中的主要组成部分。在以往的.net应用程序中,我们会把DBConn和一些动态加载类及变量写在配置文件里。但WCF有所不同。他指定向客户端公开的服务,包括服务的地址、服务用于发送和接收消息的传输和消息编码,以及服务需要的安全类型等。

    <?xml version="1.0" encoding="utf-8"?>
     <configuration>
       <system.serviceModel>
     
         <!--配置服务和终结点开始-->
         <services>
           <service>
             <endpoint></endpoint>
           </service>
         </services>
         <!--配置服务和终结点结束-->
     
         <!--配置绑定开始-->
         <bindings>
           <netTcpBinding>
             <binding>
             </binding>
           </netTcpBinding>
         </bindings>
         <!--配置绑定结束-->
     
         <!--配置行为开始-->
         <behaviors>
            <!--endpointBehaviors在Rest时候用,也可以不配置,可以加入一些自定义的,自由发挥-->
            <endpointBehaviors>
             <behavior name="WebBehavior">
               <webHttp />
             </behavior>
           </endpointBehaviors>
           <serviceBehaviors>
             <behavior>
             </behavior>
           </serviceBehaviors>
         </behaviors>
         <!--配置行为结束-->
     
       </system.serviceModel>
     </configuration>

         Service配置节[必须有]:配置服务、接口和终结点。每个Service都会有以下两个属性。name:名称空间.类名[服务的具体实现类]。behaviorConfiguration:一个在behaviors节点中找到的名称。

      Binding配置节[可有可无]:配置绑定,如http,tcp等

      Behavior配置节[可有可无]:配置行为,如认证等。

    //附一个各种自定义配置的,英文基本代表了各个意思
    <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding0" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
              <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                  maxBytesPerRead="4096" maxNameTableCharCount="16384" />
              <security mode="None">
                <transport clientCredentialType="None" proxyCredentialType="None"
                    realm="" />
                <message clientCredentialType="UserName" algorithmSuite="Default" />
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>

    三.WCF测试:

    调试:将Web.config中的 <webHttp /> 修改为 <webHttp helpEnabled="true" />,将可以在浏览器页面中列举出可用接口,并提供提交的数据样例。打开IE浏览器,在地址栏输入:http://localhost:3000/MyService.svc/help 即可。

    1) 使用微软VisualStuio的wcf测试客户端(Common7IDEWcfTestClient.exe):

    双击接口方法名,输入参数,测试。

    2) 借用chrome扩展工具PostMan测试(Rest方式,也可以直接在地址栏输入地址)

  • 相关阅读:
    QlikView TEXT控件固定显示图片
    Qlikview List控件
    如何实现Qlikview的增量数据加载
    SQL Server开启READ_COMMITTED_SNAPSHOT
    AX函数,将EXCEL列号转为列名
    C# 中DataGridView 绑定List<T>做数据源的操作问题
    Could not resolve this reference. Could not locate the assembly
    WinForm程序用使用List对象绑定DataGridView数据源
    C#WebBrowser控件使用教程与技巧收集
    python局部变量、全局变量,global、nolocal的区别
  • 原文地址:https://www.cnblogs.com/lcawen/p/6862940.html
Copyright © 2020-2023  润新知