WCF之一

  WCF(Windows Communication Foundation)的概念这里就不多说了,google一下就知道了。

  必须知道的是,WCF的服务是不能孤立的存在的,需寄宿于一个运行的的进程中(我们称之为宿主),为服务指定宿主的过程成为服务寄宿。服务寄宿有两种方式:一种是自我寄宿;另一种是通过IIS将服务寄宿于IIS进程中。

  接下来就先来看看第一种寄宿方式——自我寄宿。

  首先,新建一个空的解决方案,添加如图所示项目

  

每个项目的描述及项目之间的关系如下:

  • Contracts类库项目,定义服务契约(Service Contract),引用System.ServiceModel程序集;
  • Services类库项目,提供对WCF服务的实现。定义在该项目中的所有WCF服务实现了定义在Contracts中相应的服务契约,所以Services具有对Contracts项目的引用;
  • Hosting控制台应用程序(宿主),实现对定义在Services项目中的服务的寄宿,引用Contracts、Services和System.ServiceModel程序集;
  • Client控制台应用程序(客户端),引用System.ServiceModel程序集。

  Tag:有关更多System.ServiceModel,请点击http://msdn.microsoft.com/zh-cn/library/vstudio/system.servicemodel.aspx

  创建服务契约:一般地,通过接口的形式定义服务契约。通过下面的代码,将一个接口ITestWcf定义成服务契约。WCF广泛采用基于自定义特性(Custom Attribtue)的声明式编程模式,我们通过在接口上应用System.ServiceModel.ServiceContractAttribute特性将一个接口定义成服务契约

using System.ServiceModel;

namespace Contracts
{
    [ServiceContract]
    public interface ITestWcf
    {
        [OperationContract]
        string HelloWord();
    }
}

  创建服务:WCF服务TestWcfService定义在Services项目中,实现了服务契约接口ITestWcf,实现了所有的服务操作

using Contracts;
namespace Services
{
    public class TestWcfService : ITestWcf
    {
        public string HelloWord()
        {
            return "Hello Word";
        }
    }
}

  自我寄宿:在实现寄宿之前,先了解些关键概念。

   WCF服务需要依存一个运行着的进程(宿主),服务寄宿就是为服务指定一个宿主的过程。WCF是一个基于消息的通信框架,采用基于终结点(Endpoint)的通信手        段。终结点由地址(Address)、绑定(Binding)和契约(Contract)三要素组成。由于三要素应为首字母分别为ABC,所以就有了易于记忆的公式:Endpoint = ABC。一个终结包含了实现通信所必需的所有信息,我们可以这样认识终结点的ABC:

  地址(Address):地址决定了服务的位置,解决了服务寻址的问题,意味着标识服务在哪里

  绑定(Binding):绑定实现了通信的所有细节,包括网络传输、消息编码,以及其他为实现某种功能(比如安全、可靠传输、事务等)对消息进行的相应处理。WCF中具有一系列的系统定义绑定,比如BasicHttpBinding、WsHttpBinding、NetTcpBinding等,意味着信息如何传输

  契约(Contract):契约是对服务操作的抽象,也是对消息交换模式以及消息结构的定义。意味着信息具体是什么

  在了解了ABC后,再来看代码:

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Contracts;
using Services;

namespace Hosting
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(TestWcfService)))
            {
                host.AddServiceEndpoint(typeof(ITestWcf), new WSHttpBinding(), "http://127.0.0.1:9999/testwcfservice");
                if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
                {
                    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); ;
                    behavior.HttpGetEnabled = true;
                    behavior.HttpGetUrl = new Uri("http://127.0.0.1:9999/testwcfservice/metadata");
                    host.Description.Behaviors.Add(behavior);
                }
                host.Opened += delegate
                {
                    Console.WriteLine("TestWcfService已经启动,按任意键终止服务!");
                };
                host.Open();
                Console.Read();
            }
        }
    }
}

  松耦合是SOA的一个基本的特征,WCF应用中客户端和服务端的松耦合体现在客户端只须要了解WCF服务基本的描述,而无须知道具体的实现细节,就可以实现正常的服务调用。WCF服务的描述通过元数据(Metadata)的形式发布出来。WCF中元数据的发布通过一个特殊的服务行为ServiceMetadataBehavior实现。在上面提供的服务寄宿代码中,我们为创建的ServiceHost添加了ServiceMetadataBehavior,并采用了基于HTTP-GET的元数据获取方式,元数据的发布地址通过ServiceMetadataBehavior的HttpGetUrl指定。在调用ServiceHost的Open方法对服务成功寄宿后,我们可以通过该地址获取服务相关的元数据。在IE地址栏上键入http://127.0.0.1:9999/testwcfservice/metadata,你将会得到以WSDL形式体现的服务元数据,部分如图

  当然,一般不会直接通过编码的方式进行终结点的添加和服务行为的定义,而是通过配置的方式进行。上面的代码可以用如下的配置代替

<?xml version='1.0' encoding='utf-8'?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:9999/testwcfservice/metadata" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="Services.TestWcfService" behaviorConfiguration="metadataBehavior">
        <endpoint address="http://127.0.0.1:9999/testwcfservice" binding="wsHttpBinding" contract="Contracts.ITestWcf" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

而在Hosting宿主内的代码就精简了许多

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Contracts;
using Services;

namespace Hosting
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(TestWcfService)))
            {
                //host.AddServiceEndpoint(typeof(ITestWcf), new WSHttpBinding(), "http://127.0.0.1:9999/testwcfservice");
                //if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
                //{
                //    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); ;
                //    behavior.HttpGetEnabled = true;
                //    behavior.HttpGetUrl = new Uri("http://127.0.0.1:9999/testwcfservice/metadata");
                //    host.Description.Behaviors.Add(behavior);
                //}
                host.Opened += delegate
                {
                    Console.WriteLine("CalculaorService已经启动,按任意键终止服务!");
                };
                host.Open();
                Console.Read();
            }
        }
    }
}

  一般对于初学者来说,WCF的配置显得过于复杂,直接对配置文件进行手工编辑不太现实。可以通过VS的工具(Tools)菜单,选择“WCF Service Configuration Editor”子项,开启这样的一个配置编辑器

  客户端调用:在运行服务寄宿程序(Hosting.exe)的情况下,右键点击Client项目,在弹出的上下文菜单中选择“添加服务引用(Add Service References)”,如图6所示的添加服务引用的对话会显示出来。在地址栏上键入服务元数据发布的源地址:http://127.0.0.1:9999/testwcfservice/metadata,并指定一个命名空间,点击OK按钮,VS为为你生成一系列用于服务调用的代码和配置。

客户端代码如下:

using System;
using Client.WcfTest;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            using (TestWcfClient hw=new TestWcfClient())
            {
                Console.WriteLine(hw.HelloWord());
            }
        }
    }
}

当然输出结果就不用贴出来了。

接下来看第二种方式——IIS进程寄宿

在原有项目的基础上,添加一个wcf应用程序项目

打开TestWcfService.svc添加

然后生成运行TestWcfService,生成部署包后发布IIS

Tag:这里的配置文件基本和上面的一样,但这里不需要配置终结点地址

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="metadataBehavior" name="Services.TestWcfService">
        <endpoint  binding="wsHttpBinding" contract="Contracts.ITestWcf" />
      </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  
</configuration>

通过访问http://192.168.0.1/TestWcfService.svc

如图

然后在客户端添加服务引用

客户端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Client.TestWcf;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            using (TestWcfClient test = new TestWcfClient())
            {
                Console.WriteLine(test.HelloWord());
            }
        }
    }
}

在发布IIS时,可能会遇到


这样的问题,解决方法:找到配置文件所在文件夹,单击右键属性,切换到“安全”选项卡,将 IIS-IUSRS 用户组添加到安全列表中,并按需求赋予其权限(我赋予了修改的权限),更改后如下图:

查看 web.config 的安全权限,如果有此用户组的权限则说明成功,否则退回到根文件夹,打开“安全”选项卡,选中 IIS-IUSRS 用户组,点“高级”打开高级安全设置对话框,选中 IIS-IUSRS 用户组,点击“更改权限”,打开可编辑的高级安全设置对话框,把下图红色区域的复选按钮选上,

 

完成以上步骤,如果还不能解决问题,就在 IIS 中选中应用程序,修改应用程序域。(如果没有4.0相应的应用程序域,在vs2010命令提示符下运行aspnet_regiis.exe –i)

posted on 2013-05-25 23:13  DonnyPeng  阅读(194)  评论(0编辑  收藏  举报