WCF 4 Cookbook 系列(三) 寄宿和配置

在这篇文章中,将会包括:

  • 在控制台程序中寄宿服务
  • 在Windows服务(Windows Service)中寄宿服务
  • 使用兼容ASP.NET的上下文寄宿HTTP服务
  • 在IIS 7中寄宿非HTTP服务
  • 通过ServiceHostFactory定制IIS ServiceHost
  • 为单例服务指定专用的服务实例
  • 在WSS 3.0中寄宿服务

简介

对于构建WCF服务来说,服务的寄宿和配置是非常重要的,特别是在服务部署阶段。在开发人员完成服务开发之后,我们需要部署服务以便提供给所有客户端消费者使用。在现实环境中,有各种服务部署方案可供选择,这将导致在服务配置或寄宿环境中不同的部署和配置要求。

作为一个增强的服务开发平台,WCF在服务寄宿和配置上提供了丰富的内置的支持,能够满足大部分已经存在的部署需求和要求。例如,最流行的IIS寄宿方式可以为本地局域网或基于公网部署的情况提供高可用性和稳定的服务。Windows服务寄宿方式使得WCF服务寄宿更容易和现有的后台计划任务集成,并且自寄宿的方式在生产环境中提供最灵活的服务部署和定制点。

在这一章中,我们将着眼于各种WCF托管和配置方案的7个食谱。食谱开始于4个典型的寄宿案例——自寄宿,Windows服务寄宿,基于IIS的HTTP寄宿和基于IIS的非HTTP寄宿。接下来是两个定制服务寄宿案例——包括一个自定义ServiceHostFactory和一个专用单例寄宿。最后演示一个更高级的WCF服务寄宿场景——Windows SharePoint服务寄宿。

在控制台程序中寄宿服务

当在.NET框架下建立一个简单的演示程序时,通常选择一个控制台应用程序。同样,当讨论WCF服务寄宿是,控制台寄宿方案是最方便的一种,当我们想做一些快速演示或者测试一些WCF功能时,控制台是特别方便并且有用的。

怎么做…

  1. 在Visual Studio中创建一个控制台项目。
    Console Host App
  2. 向项目中添加一个新的WCF服务。
    在Visual Studio中可以很简单完成这一步。使用新建项功能,在Visual Studio添加新项界面选择WCF服务
    image
  3. 在Main方法中添加启动WCF服务的代码。下面的代码展示了在控制台程序的典型Main方法中启动WCF服务。
    static void Main(string[] args)
    {
        using (ServiceHost consoleHost = new ServiceHost(typeof(TestService)))
        {
            consoleHost.Open();
            Console.WriteLine("press any key to stop service host...");
            Console.ReadLine();
        }
    }

原理…

当在Visual Studio中添加一个新的WCF服务项,IDE其实帮你完成了下面3件事:

  • 创建一个ServiceContract接口;
  • 创建一个实现了ServiceContract接口的服务类;
    下面的代码展示ServiceContract示例及在这一食谱中使用的实现类
    [ServiceContract]
    public interface ITestService
    {
        [OperationContract]
        void DoWork();
    }
    public class TestService : ITestService
    {
        public void DoWork()
        {
        }
    }
  • 在 App.config文件中添加服务终结点和绑定配置。

除了契约和服务类型之外,IDE将插入一个默认的可以通过服务暴露终结点的配置设置。下面的截图展示了包含一个使用WSHttpBinding的单一终结点示例服务配置节。

image

用先前定义的代码和配置项,我们可以通过在ServiceHost类的构造函数中提供的服务类型来启动服务宿主。

using (ServiceHost consoleHost = new ServiceHost(typeof(TestService)))

运行时将会检查配置文件,并加载与构造函数中具有相同名称的指定类型的<service>项,然后启动已定义的服务和终结点。

在Windows服务(Windows Service)中寄宿服务

Windows服务被广泛应用于Windows操作系统上托管的将在后台执行一些长期或预定任务的应用程序。通过Windows服务寄宿的应用程序可以在一个特定的用户账户下运行,并能选择启动模式(手动或自动)。作为一个流行的服务-应用程序-寄宿场景,也是相当普遍的方式来部署WCF服务作为一个Windows服务。

怎么做…

在这个食谱中,我们使用一个典型的基于.NET的Windows服务来演示如何在一个Windows服务应用程序中寄宿WCF服务。通过具体的步骤来看看:

  1. 创建一个Windows服务项目。
    第一步是通过 Visual Studio IDE建立一个新的Windows服务项目。当项目创建时,我们简单地选择Windows服务项目类型。下面截图展示了怎么在 Visual Studio 新建项目向导中选择Windows服务项目。
    image
  2. 添加一个新的WCF服务项目。
    作为一个WCF服务寄宿程序,肯定需要在这里有一个WCF服务定义。创建WCF服务的步骤和已经讨论过的在控制台应用程序寄宿服务是一样。
  3. 向服务启动和关闭事件中添加服务寄宿代码。
    关于在Windows服务中服务寄宿代码,需要把代码放在正确的地方,因为基于.NET的Windows服务类型不直接暴露Main方法。下面的代码展示了WCF服务的启动和关闭的代码是怎样定义的:
    public partial class Service1 : ServiceBase
    {
        ServiceHost _svcHost = null;
        protected override void OnStart(string[] args)
        {
            // Start the service host here
            _svcHost = new ServiceHost(typeof(TestService));
            _svcHost.Open();
        }
        protected override void OnStop()
        {
            // Close the service host
            _svcHost.Close();
        }
    }
  4. 为Windows Service添加安装程序。
    现在Windows Service和WCF服务类型已经定义好了。然而,我们仍需要添加另一个组件——为了在目标操作系统上部署Windows Service到Windows Service集合的安装程序类。在Visual Studio IDE中,我们可以简单地通过组件设计器上的上下文菜单为Windows Service添加一个安装程序。下图展示了为Windows Service创建安装器的上下文菜单项。
    image
    IDE帮忙创建了两个辅助类——一个是ServiceProcessInstaller类型,另一个是ServiceInstaller类型。我们可以在这两个类的属性面板中指定许多Windows Service的部署参数。下图展示了示例serviceProcessInstaller1类的属性:
    image
    下图展示了示例serviceInstaller1类的属性:
    image
    正如截图所展示的,Visual Studio使用标准的属性窗口来展示和配置Windows Service类的个别属性。
  5. 通过Installutil.exe安装Windows Service。
    最后一步是安装我们创建的Windows Service到操作系统。这一步可以通过使用.NET framework提供的Installutil.exe工具来完成。你可以直接在Visual Studio命令行提示窗口执行Installutil.exe命令,或者可以选择通过.NET framework文件夹的物理路径来运行工具,如C:\Windows\Microsoft.NET\Framework\v4.0.30319。

下面的语句展示了使用Installutil.exe工具安装和卸载一个基于.NET的Windows Service应用程序的完整命令。

安装Windows Service:
InstallUtil.exe WCFNTService.exe
卸载Windows Service:
Install Util.exe /u WCFNTService.exe
上面提及的WCFNTService.exe是示例Windows Service项目的生成的编译名。

原理…

当Windows Service启动的时候会触发OnStart事件,而Windows Service关闭时则触发OnStop事件。因此,它们是我们把寄宿WCF服务代码最好的地方。

有时,我们可能需要访问一些远程或受保护的Windows Service寄宿程序的资源,在这种情况下,最重要的是要指定一个特有的服务账户,而这可以在开发时指定也可在Windows Service配置管理器中指定。下图展示的服务列表中,就包含了在Windows Service配置管理器中已经安装的Windows Service示例。

image

使用兼容ASP.NET的上下文寄宿HTTP服务

ASP.NET为开发基于.NET框架的web应用程序提供一个强大的平台。ASP.NET web应用程序也是为应用了web HTTP协议的WCF服务提供了固有的寄宿环境,这意味着开发人员可以部署WCF服务时,可以与ASP.NET网页一起部署在相同的Web应用程序中而不需要任何特别的配置。

然而,默认情况下,一些ASP.NET运行时特性或状态对象不适用于WCF服务代码,虽然他们是在相同的web应用程序中。限制特性包括:

  • 当访问来自一个WCF服务时,HttpContext一直为null;
  • 基于配置的URL验证(使用了 <authorization>配置节) 不适用于WCF的.svc文件。如果服务驻留在一个通过ASP.NET的URL授权规则来获得URL空间,这些设置将忽略掉WCF请求;
  • 用于截获请求而注入到ASP.NET应用程序的自定义HttpModule,在请求管道的后期不会截获WCF请求;
  • 特定的ASP.NET状态,比如Session状态和应用程序缓存不适用于WCF服务代码。

那么,怎么才能使这些特性也适用于WCF服务呢?答案就是,WCF服务寄宿基础架构已经提供了调用ASP.NET的兼容模型,它可以帮助解决这些问题。这个特性默认是不可用的,在这个部分,我们将演示如何使用这个特性,以便WCF服务可以继续享用ASP.NET运行时。

怎么做…

  1. 首先,我们需要有一个ASP.NET web应用程序,然后在这个web应用程序中添加一个新的WCF服务。对于示例,我们使用一个空的有两个ASPX页面的ASP.NET网站作为寄宿的网站。然后添加名为EchoService.svc的WCF服务,以便那两个ASPX页面可以与EchoService.svc同时运行。下图展示了在Visual Studio解决方案资源管理器中web应用程序的结构。
    image
    EchoService有一个非常简单的ServiceContract,包含一个返回string类型的Echo操作。
    [ServiceContract]
    public interface IEchoService
    {
        [OperationContract]
        string Echo();
    }
  2. 现在我们将ASP.NET web页面和WCF服务寄宿在一起了。然而,WCF服务代码仍不能访问特定的ASP.NET运行时对象。我们需要做的是向web应用程序和WCF服务中应用ASP.NET兼容的方式部署。
    为了使ASP.NET兼容模式可用,我们只需简单的设置WCF配置节<serviceHostingEnvironment>中的aspNetCompatibilityEnabled属性。下图展示了使ASP.NET兼容模式可用的配置片段。
    image
    在WCF服务的实现类上,我们需要应用System.ServiceModel.Activation.AspNetCompatibilityRequirements特性(attribute),并设置RequirementsMode的属性(property)为AspNetCompatibilityRequirementsMode.Allowed。这是非常有用的,因为有时我们可能不想某些WCF服务获取访问那些ASP.NET运行时的上下文对象,即使寄宿的web应用程序已经启用了ASP.NET兼容模式。下面的代码片段展示了示例EchoService的实现类,它已经应用了特有的AspNetCompatibilityRequirements设置。
    using System.ServiceModel.Activation;
    
    [AspNetCompatibilityRequirements(
    RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed
    )]
    public class EchoService : IEchoService
    {
         …
    }
  3. 拥有了所有的服务并应用了适当的配置,现在我们可以开始在WCF服务中使用ASP.NET上下文对象了。 下面的代码片段展示了示例Echo操作代码,它使用了ASP.NET请求上文中的数个运行时属性,并且返回他们给服务的调用者:
    public class EchoService : IEchoService
    {
        public string Echo()
        {
            var approot = HttpContext.Current.Server.MapPath("~/");
            var data = HttpContext.Current.Cache["key1"];
            var url = HttpContext.Current.Request.RawUrl;
            return string.Format("{0}, {1}, {2}", approot, data, url);
        }
    }
    通过在WCF客户端测试工具上执行一个快速测试,我们可以得到预期的所有返回ASP.NET上下文属性的相应,如下图所示:image

原理…

WCF HTTP服务寄宿在ASP.NET web应用程序中可以运行在两种不同的模式中——默认模式和ASP.NET兼容模式。

在默认模式中,ASP.NET运行时可以在请求管道的早期拦截WCF请求:BeginRequest (ASP.NET HttpModule的其中一个拦截点),因此大部分ASP.NET运行时信息不适用于WCF服务代码。当启用了ASP.NET兼容模式,WCF服务运行时通过用于HTTP传输的模块和处理程序挂接到ASP.NET HTTP管道,这样那些ASP.NET特定的上下文数据就又可以用了。

更多…

关于更多用于WCF服务寄宿的ASP.NET兼容模式详细信息,可以参考Wenlong Dong的博客:

ASP.NET Compatibility Mode :http://blogs.msdn.com/b/wenlong/archive/2006/01/23/516041.aspx

posted @ 2012-04-01 21:01  brycezhang  阅读(710)  评论(0编辑  收藏  举报