WCF 快速入门

定义服务契约

  构建HelloWCF应用的第一步是创建服务契约。契约式是表示消息应用外形的主要方式。对于外形,是指服务暴露的操作,使用的消息
schema和每个操作实现的消息交换模式(MEP)。总之,契约定义了我们消息应用生成和使用的东西。大多数契约是带有WCF
API定义的属性标记的类型定义。

  在下面的例子里,服务契约是一个带有System.ServiceModel.ServiceContractAttribute
和System.ServiceModel.OperationContractAttribute标记的接口,如下所示:




[ServiceContract]

public
interface IHelloWCF {

 [OperationContract]

 void
Say(String input);

}

  在高层次上,我们的服务契约表示我们接收消息的应用包含一个名字为Say的操作,并且这个操作接收一个String类型的参数和void返回类
型。发送消息的应用可以用它来构造和发送消息给接收程序。既然我们已经定义的服务契约,那就到了该定义接收程序侦听地址和如何与其它消息参与者交换消息的
时候了。

定义地址和绑定

  定义侦听请求消息的地址需要使用System.Uri类型,定义如何与其它消息参与者交换消息需要我们使用
System.ServiceModel.Channels.Binding类型。或者这些类型的继承类型。下面的代码说明了如何在我们的应用里使用
Uri和Binding类型。




static
void Main(){

 // define where to listen for messages定义侦听消息的地址

 Uri address = new
Uri("http://localhost:8000/IHelloWCF");

 

 // define how to exchange messages定义如何交换消息

 BasicHttpBinding binding = new
BasicHttpBinding();

}

  注意局部变量address使用的是HTTP格式的统一资源标识符(URI)。选择这个地址强制要求我们使用HTTP传输。更高层次上,绑定是
指定传输、消息编排和消息编码的主要方式。局部变量binding是BasicHttpBinding类型的实例。和你从名字看到的一
样,BasicHttpBinding创建的是一个用于HTTP传输的消息架构。

创建一个终结点并启动侦听

  接下来我们要使用地址(address)、绑定(binding)和契约(contract)来构建一个终结点(endpoint)并在此终结
点上侦听发送进来的消息。通常来说,一个WCF接受程序可以构建和使用多个终结点,并且每个终结点都需要一个地址、一个绑定和一个契约。
System.ServiceModel.ServiceHost类型构建和托管终结点,并管理接受应用底层结构的其他部分,比如线程和对象的生命周期。
下面代码块演示了如何实例化ServiceHost,如何添加终结点和如何开始侦听进入的消息:




static
void Main(){

   // define where to listen for messages定义侦听消息的地址

   Uri address = new
Uri("http://localhost:4000/IHelloWCF");

   // define how to exchange messages定义如何交换消息

   BasicHttpBinding binding = new
BasicHttpBinding();

   // instantiate a ServiceHost, passing the type to instantiate实例化ServiceHost,传递服务类型

   // when the application receives a message

   ServiceHost svc = new
ServiceHost(typeof(HelloWCF));

   // add an endpoint, passing the address, binding, and contract增加终结点、绑定和契约

   svc.AddServiceEndpoint(typeof(IHelloWCF), binding, address);

   // begin listening开始侦听

   svc.Open();

   // indicate that the receiving application is ready and指示应用准备接受消息

   // keep the application from exiting immediately保持应用程序不会立即退出

   Console.WriteLine("The HelloWCF receiving application is ready");

   Console.ReadLine();

   // close the service host关闭宿主

   svc.Close();

}

  上述代码里调用了svc.AddServiceEndpoint
和svc.Open。AddServiceEndpoint实例方法设置ServiceHost对象的属性,这样它将使用地址、绑定和契约参数执行的行为
来侦听消息。要着重指出的是AddServiceEndpoint方法没有开始循环侦听;它仅仅是简单地改变了ServiceHost对象的状态。
ServiceHost实例的Open方法构建了消息基础结构,并开始循环侦听。Open方法会验证ServiceHost对象的状态,从它的状态里构建
终结点,并且开始侦听。

映射接收的消息到HelloWCF的成员

  在目前状态,我们编译程序,当程序试图构建一个终结点的时候,会出现一个异常:InvalidOperationException。原因一目
了然:在ServiceHost类型的构造函数里,我们传递了HelloWCF作为参数,因此,这就表示消息基础结构要分发消息给我们的HelloWCF
对象。因此,必然存在消息到服务成员的映射关系。最简单的创建映射的方式就是使HelloWCF服务类实现服务契约IHelloWCF。




using
System;

using
System.ServiceModel;

using
System.ServiceModel.Channels;

 

// implement the IHelloWCF service contract

sealed
class HelloWCF : IHelloWCF {

 // indicate when a HelloWCF object is created

 HelloWCF() { Console.WriteLine("HelloWCF object created"); }

 

 static
void Main(){

    // define where to listen for messages

    Uri address = new
Uri("http://localhost:4000/IHelloWCF");

    // define how to exchange messages

    BasicHttpBinding binding = new
BasicHttpBinding();

    // instantiate a ServiceHost, passing the type to instantiate

    // when the application receives a message

    ServiceHost svc = new
ServiceHost(typeof(HelloWCF));

    // add an endpoint, passing the address, binding, and contract

    svc.AddServiceEndpoint(typeof(IHelloWCF), binding, address);

    // begin listening

    svc.Open();

    // indicate that the receiving application is ready and

    // keep the application from exiting immediately

    Console.WriteLine("The HelloWCF receiving application is ready");

    // wait for incoming messages

    Console.ReadLine();

    // close the service host

    svc.Close();

 }

 

 // received messages are dispatched to this instance

 // method as per the service contract

 public
void Say(String input){

    Console.WriteLine("Message received, the body contains: {0}", input);

 }

}

 

[ServiceContract]

public
interface IHelloWCF {

 [OperationContract]

 void
Say(String input);

}

  改变HelloWCF的类型定义会使得消息的基础结构分发接受到的消息到服务实例的Say操作上,因此会在控制台界面上输出一个简单的语句。

编译、运行和检验接受者

  我们现在准备使用下面的命令行编译并运行这个应用:





C:\temp>csc /nologo /r:"c:\WINDOWS\Microsoft.Net\Framework\v3.0\Windows Communication

Foundation\System.ServiceModel.dll" HelloWCFApp.cs

 

C:\temp>HelloWCFApp.exe

The HelloWCF receiving application is
ready

  此时,接受消息的应用在被动地等待请求消息的到来。我们是用netstat.exe可以检查一下应用是否确实在侦听,如下所示:




c:\temp>netstat –a –b

TCP    kermit:4000            0.0.0.0:0              LISTENING       1104

[HelloWCFApp.exe]

向接受者发送消息

  发送消息的基础结构也需要依靠地址、绑定和契约,这与接收消息的基础结构类似。

  与接受者不同,绝大多数发送者放弃直接使用Uri类型,而是使用System.ServiceModel.EndpointAddress类型去表示消息发送的目标。

  EndpointAddress类型是WCF对于WS-Addressing
终结点参考的抽象。此外,发送者不使用ServiceHost类型,而是使用ChannelFactory<T>类型(T是服务契约类型)。
ChannelFactory<T>类型构建发送消息的基础结构和ServiceHost构建接受消息的基础结构类似。下面的代码演示了如何
使用EndpointAddress类型和ChannelFactory<T>构建发送基础结构。




using
System;

using
System.ServiceModel;

using
System.ServiceModel.Channels;

 

// implement the IHelloWCF service contract

sealed
class HelloWCF : IHelloWCF {

 // indicate when a HelloWCF object is created

 HelloWCF() { Console.WriteLine("HelloWCF object created"); }

 static
void Main(){

    // define where to listen for messages

    Uri address = new
Uri("http://localhost:4000/IHelloWCF");

    // define how to exchange messages

    BasicHttpBinding binding = new
BasicHttpBinding();

    // instantiate a ServiceHost, passing the type to instantiate

    // when the application receives a message

    ServiceHost svc = new
ServiceHost(typeof(HelloWCF));

    // add an endpoint, passing the address, binding, and contract

    svc.AddServiceEndpoint(typeof(IHelloWCF), binding, address);

    // begin listening

    svc.Open();

    // indicate that the receiving application is ready and

    // keep the application from exiting immediately

    Console.WriteLine("The HelloWCF receiving application is ready");

 

    // begin the sender code发送者代码开始

    // create a channelFactory<T> with binding and address

    ChannelFactory<IHelloWCF> factory =

      new
ChannelFactory<IHelloWCF>(binding,

                                    new
EndpointAddress(address));

    // use the factory to create a proxy使用工厂创建代理

    IHelloWCF proxy = factory.CreateChannel();

    // use the proxy to send a message to the receiver使用代理发送消息给接受者

    proxy.Say("Hi there WCF");

    // end the sender code发送者代码结束

 

    Console.ReadLine();

    // close the service host

    svc.Close();

 }

 

 // received messages are dispatched to this instance

 // method as per the service contract

 public
void Say(String input){

    Console.WriteLine("Message received, the body contains: {0}", input);

 }

}

 

[ServiceContract]

public
interface IHelloWCF {

 [OperationContract]

 void
Say(String input);

}

  更高层次上,ChannelFactory<T>对象是一个可以制造产生和发送消息给接受者(因此需要在构造函数里传递绑定和地
址)的基础结构的类型。ChannelFactory<T>实例的CreateChannel方法实际创建的是发送基础结构,并且通过实现服
务契约的一个对象返回这个基础结构的引用。

编译、运行和检验发送者

  既然我们已经完成了发送和接受基础结构代码,现在应该是编译和运行程序的时候了,如下所示:




c:\temp>csc /nologo /r:"c:\WINDOWS\Microsoft.Net\Framework\v3.0\Windows Communication

Foundation\System.ServiceModel.dll" HelloWCFApp.cs

 

c:\temp>HelloWCFApp.exe

The HelloWCF receiving application is
ready

HelloWCF object
created

Message received, the body contains: HelloWCF!

  如期望的一样,我们的程序执行步骤如下:

  1.    为接受来自http://localhost:4000/IHelloWCF的消息构建基础结构。

  2.    开始在http://localhost:4000/IHelloWCF上侦听消息。

  3.    构建发送到http://localhost:4000/IHelloWCF消息的基础结构。

  4.    生成和发送消息到http://localhost:4000/IHelloWCF。

  5.    接受消息,实例化一个HelloWCF对象,分发消息到服务实例的Say方法上。

看一下消息

  现在代码写完了,貌似没看到我们HelloWCF例子里哪里使用到了消息。对于开发者,一个WCF应用看起来和感觉都很像面向对象或者面向组件
的应用。在运行时,WCF应用要生成、发送和接受消息,同样也要处理消息。通过修改Say方法的实现我们能看到WCF接触结构的消息:




public
void Say(String input){

 Console.WriteLine("Message received, the body contains: {0}", input);

 // Show the contents of the received message显示接受消息内容

 Console.WriteLine(

    OperationContext.Current.RequestContext.RequestMessage.ToString());

}

  修改Say方法后的输出如下:




The HelloWCF receiving application is
ready

HelloWCF object
created

Message received, the body contains: HelloWCF!

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

 <s:Header>

    <To s:mustUnderstand="1"

        xmlns="http://schemas.microsoft.com/ws/2005/05/adessing/none">

      http://localhost:8000/IHelloWCF

    </To>

    <Action s:mustUnderstand="1"

            xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">

         http://tempuri.org/IHelloWCF/Say

     </Action>

 </s:Header>

 <s:Body>

    <Say xmlns="http://tempuri.org/">

      <input>HelloWCF!</input>

    </Say>

 </s:Body>

</s:Envelope>

  注意到打印的SOAP消息,消息的Body部分包含我们传递给局部变量的channel
上Say方法的字符串。宏观上讲,我们的应用程序使用这个字符来构建一个SOAP消息,然后发送这个SOAP消息到我们程序的接受部分。接受部分,换句话
说,它要接受SOAP消息,创建一个HelloWCF实例,提取SOAP Body的内容,调用HelloWCF
实例的Say方法,传递字符串参数。

暴露元数据

  我们的Hello
WCF程序使用一个相当简单的方法就实现了接收者和发送者之间的兼容性。因为接收者和发送者驻留在同一个AppDomain里,并且接收者使用的对象对于
发送者来说是可见的,我们在发送者代码里简单地重用了地址、绑定和契约。在发部分消息应用里,这个方法是可行的。绝大多数情况,我们希望发送者和接收者去
驻留在不同的机器上的AppDomains里。在这些场景里,接收者显示指定消息需求,发送者遵守这些需求。

  WS-
MetadataExchange规范规定了发送者和接收者在平台无关时如何交换这些数据信息。在更多的条款里,WS-MetadataExchange
规范限定了方便终结点之间进行消息交换的schema和编排。在大部分现实世界的应用系统里,有一个暴露信息方式的需求,这个方式就是发送者询问接收者的
终结点去提取元数据,并使用这些元数据构建能发送给接收终结点消息的基础结构。

  WCF缺省的情况下不会暴露元数据,这些原因都是因为对安全的考虑。元数据暴露的信息包含应用系统的安全需求。以保护秘密的名义,这个团队选择
缺省情况下关闭这个特性。如果决定暴露系统的元数据,我们可以构建一个暴露元数据的终结点。构建元数据终结点的方式和其它终结点非常相似:使用地址、绑定
和契约。但是目前为止你看到的终结点不太一样,就是服务契约已经定义到WCF的API里了。

  构建元数据终结点的第一步是修改ServiceHost到可以托管元数据的状态。我们可以通过System.ServiceModel.
Description.ServiceMetadataBehavior对象增加到ServiceHost行为集合里。行为是WCF基础结构用来改变本
地消息处理的特定信息。下面代码演示了如何增加ServiceMetadataBehavior对象到活动的ServiceHost对象:




// instantiate a ServiceHost, passing the type to instantiate

// when the application receives a

messageServiceHost svc = new
ServiceHost(typeof(HelloWCF), address);

// BEGIN NEW METADATA CODE

// create a ServiceMetadataBehavior创建服务元数据行为

ServiceMetadataBehavior metadata = new
ServiceMetadataBehavior();

metadata.HttpGetEnabled = true;

// add it to the servicehost description

svc.Description.Behaviors.Add(metadata);

  下一步就是为元数据终结点定义Binding。元数据绑定的对象模型与其它绑定区别很大,我们通过调用工厂方法上的System.ServiceModel.Description.MetadataExchangeBindings的类型创建元数据绑定,如下所示:




// instantiate a ServiceHost, passing the type to instantiate

// when the application receives a message

ServiceHost svc = new
ServiceHost(typeof(HelloWCF));

 

// BEGIN NEW METADATA CODE

// create a ServiceMetadataBehavior创建服务元数据行为

ServiceMetadataBehavior metadata = new
ServiceMetadataBehavior();

// add it to the servicehost description

svc.Description.Behaviors.Add(metadata);

// create a TCP metadata binding创建TCP元数据绑定

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();

由 于ASMX(ASP.NET Web Service)的影响,你也许会认为元数据只能通过HTTP传输呈现。事实上,元数据可以通过多种传输协议传递,并且WS- MetadataExchange说明了这个灵活性。在我们的例子里,我们调用CreateMexTcpBinding方法,它返回了一个继承自 Binding类型的TCP 传输绑定。因为我们使用的是TCP传输,所以我们必须确保元数据地址使用了TCP地址格式,如下所示:

// instantiate a ServiceHost, passing the type to instantiate

// when the application receives a message

ServiceHost svc = new
ServiceHost(typeof(HelloWCF));

 

// BEGIN NEW METADATA CODE

// create a ServiceMetadataBehavior

ServiceMetadataBehavior metadata = new
ServiceMetadataBehavior();

// add it to the servicehost description

svc.Description.Behaviors.Add(metadata);

// create a TCP metadata binding

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();

// create an address to listen on WS-Metadata exchange traffic

//创建元数据交换侦听地址

Uri mexAddress = new
Uri("net.tcp://localhost:5000/IHelloWCF/Mex");

  既然我们定义了元数据终结点需要的地址和绑定,我们要添加终结点到ServiceHost上,方式很像我们定义的第一个消息终结点。当添加元数
据终结点时,我们要使用WCF
API定义的名为System.ServiceModel.Description.IMetadataExchange的服务契约。下面代码演示了如何
添加一个元数据终结点到ServiceHost上,使用适当的地址、绑定和契约。




// instantiate a ServiceHost, passing the type to instantiate

// when the application receives a message

ServiceHost svc = new
ServiceHost(typeof(HelloWCF));

 

// BEGIN NEW METADATA CODE

// create a ServiceMetadataBehavior

ServiceMetadataBehavior metadata = new
ServiceMetadataBehavior();

// add it to the servicehost description

svc.Description.Behaviors.Add(metadata);

// create a TCP metadata binding

Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();

// create an address to listen on WS-Metadata exchange traffic

Uri mexAddress = new
Uri("net.tcp://localhost:5000/IHelloWCF/Mex");

// add the metadata endpoint添加元数据终结点

svc.AddServiceEndpoint(typeof(IMetadataExchange),

                       mexBinding,

                       mexAddress);

// END METADATA CODE

使用元数据

  Microsoft .NET Framework
SDK安装了一个功能强大的工具名字是svcutil.exe,它的一个功能就是询问一个运行的消息应用并基于获得的信息生成代理。从内部来
说,svcutil.exe使用的是WS-MetadataExchange协议,像与ASMX一起普及的WSDL里的“get”语义一样。因为我们的接
收程序暴露了一个元数据终结点,我们可以把svcutil.exe指向这个运行的终结点,svcutil.exe会自动生成一个代理类型和与服务终结点兼
容的配置信息,这些信息都是参考元数据生成。当使用这种方式的时候,svcutil.exe
依照WS-MetadataExchange的方式发送消息给接收程序,并转化这些消息为.NET
Framework的类型以方便发送消息程序的开发。

使用Svcutil.exe生成代理

  在你运行svcutil.exe以前,检查一下HelloWCFApp.exe正常运行并侦听请求消息。下一步就是打开一个新的Windows
SDK命令行窗口,输入下面的命令:




C:\temp>svcutil /target:code net.tcp://localhost:5000/IHelloWCF/Mex

  Svcutil.exe会创建2个文件:HelloWCFProxy.cs
和output.config。如果你检查一下HelloWCFProxy.cs文件,你就会看到svcutil.exe产生了一个包含
IHelloWCF、IHelloWCFChannel,和HelloWCFClient的代码文件。合起来看,这些类型定义就是帮助我们创建于接受程序
兼容的发送代码。

http://www.cnblogs.com/tianzhiliang/archive/2011/08/09/2132532.html

时间: 2024-08-26 21:42:47

WCF 快速入门的相关文章

快速入门系列--MVC--01概述

虽然使用MVC已经不少年,相关技术的学习进行了多次,但是很多技术思路的理解其实都不够深入.其实就在MVC框架中有很多设计模式和设计思路的体现,例如DependencyResolver类就包含我们常见的DI依赖注入概念和注册表模式(GetService)等内容,ExceptionFilter等过滤器就体现AOP的概念,整个MVC内置了一个IOC容器,基本上所有的框架类的对象都是通过这种方式来创建的.此外,一直觉得很j2ee的spring很棒,其实如果大家很熟悉EHAB(微软企业开发库)的话,就会发

C# WCF简单入门图文教程(VS2010版)

C# WCF简单入门图文教程(VS2010版) 作者:丶一二丶 字体:[增加 减小] 类型:转载 时间:2016-03-17我要评论 这篇文章主要介绍了WCF简单入门图文教程,版本是VS2010版,帮助大家轻松学习了解DataContract.ServiceContract等特性,感兴趣的小伙伴们可以参考一下 在这个例子中我们将使用VS2010创建一个WCF服务,其中会了解[DataContract][ServiceContract]等特性. 内置的WCFSVCHost,并使用“WCF测试客户端

快速入门系列--WebAPI--03框架你值得拥有

接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI,其核心概念就是构建REST风格的Web服务,把一起数据视为资源,无论是服务请求或者是数据操作,与以前的SOAP和XML-RPC架构风格有很大不同.说道这,很多读者可能想到WCF中不是早都有了REST风格的服务么,为什么还需要这个WebAPI?确实如此,不过WCF中的该类型服务显得比较复杂,因为其通

快速入门系列--WebAPI--01基础

ASP.NET MVC和WebAPI已经是.NET Web部分的主流,刚开始时两个公用同一个管道,之后为了更加的轻量化(WebAPI是对WCF Restful的轻量化),WebAPI使用了新的管道,因此两者相关类的命名空间有细微差异,在使用时需要注意. WebAPI学习系列目录如下,欢迎您的阅读! 快速入门系列--WebAPI--01基础 快速入门系列--WebAPI--02进阶 快速入门系列--WebAPI--03框架你值得拥有 快速入门系列--WebAPI--04在老版本MVC4下的调整 W

C#面向服务编程技术WCF从入门到实战演练

一.WCF课程介绍 1.1.Web Service会被WCF取代吗? 对于这个问题阿笨的回答是:两者在功能特性上却是有新旧之分,但是对于特定的系统,适合自己的就是最好的.不能哪一个技术框架和行业标准作比较,任何对于二者的比较都是错误的,因为两者根不不在同一个范畴里.就好比不能拿个汽车和交通法规比较一样,这是个误区. 阿笨的宗旨就是学完此<C#面向服务编程技术WCF从入门到实战演练>课程,让您从零基础上手后直接将学习的成果运用到实际项目中去.阿笨本次分享的WCF技术是完全来源于切身实际项目中,如

Expression Blend实例中文教程(2) - 界面快速入门

上一篇主要介绍Expression系列产品,另外概述了Blend的强大功能,本篇将用Blend 3创建一个新Silverlight项目,通过创建的过程,对Blend进行快速入门学习. 在开始使用Blend前,首先需要进行Silverlight的开发环境搭建,在银光中国网(SilverlightChina.Net)有篇"轻松建立Silverlight开发环境",其中列出了建立Silverlight开发环境的几个步骤,另外,我在过去发布过一篇"Silverlight开发工具集合&

.Net Core 3.0 IdentityServer4 快速入门

原文:.Net Core 3.0 IdentityServer4 快速入门 .Net Core 3.0 IdentityServer4 快速入门 一.简介 IdentityServer4是用于ASP.NET Core的OpenID Connect和OAuth 2.0框架. 将IdentityServer4部署到您的应用中具备如下特点: 1).认证服务 2).单点登陆 3).API访问控制 4).联合网关 5).专注于定制 6).成熟的开源系统 7).免费和商业支持 二.整体部署 目前大多数的应用

笔记:Spring Cloud Zuul 快速入门

Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了所有其他微服务的实例信息,这样的设计非常巧妙的将服务治理体系中维护的实例信息利用起来,使得维护服务实例的工作交给了服务治理框架自动完成,而对路由规则的维护,默认会将通过以服务名作为 ContextPath 的方式来创建路由映射,也可以做一些特别的配置,对于签名校验.登录校验等在微服务架构中的冗余问题

javaweb-html快速入门

本文主要是进行HTML简单介绍(详细的属性查帮助文档就行了,这里主要为快速入门,赶时间,在最短的时间中看明白一个html文件的代码(如果能称之为代码的话)详细的样式表,布局啥的有时间再研究吧) HTML 1.html的简介 1.1,html的全称:HyperText Mark-up Language ,超文本标记型语言,是网页的语言. 超文本:比文本更加强大(后面还会讲到XML,可扩展标记性语言) 标记:就是标签,html所有操作都是通过标签直接或间接的操作(把需要操作的数据通过标签封装起来)