WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)
九、 无svc文件服务激活的原理:
在WCF4.0里,通过提供一种虚拟的服务类型映射机制来实现WCF服务的激活。我们可以在配置文件里指定服务类型和相对地址之间的映射关系。这就使得我们可以在不是要.svc文件的情况下,在WAS/IIS里托管WCF服务程序。
1) 关于服务激活,这里一个重要的配置元素就是serviceActivation。我们可以定义服务类型和相对地址之间的映射关系。在配置文件里serviceActivations节点属于serviceHostingEnvironment>。一个简单的服务类型和相对地址之间的映射如下:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <directoryBrowse enabled="false" /> </system.webServer> <system.serviceModel> <serviceHostingEnvironment> <serviceActivations> <add relativeAddress="BookService.svc" service="WcfServiceLib.BookService"/> </serviceActivations> </serviceHostingEnvironment> </system.serviceModel> <system.web> <compilation defaultLanguage="c#" /> </system.web> </configuration>
使用这个配置,我们就可以在WCF4.0里,使用http的方式,无svc文件激活BookService。注意<serviceHostingEnvironment>属于一个应用程序级别的配置。我们必须把它放置在<system.serviceModel>
节点下。此外,serviceHostingEnvironment继承自machinetoApplication。如果我们在machine注册单个服务,程序里的每个服务必须继承该服务。
这种通过配置设置的激活映射,支持http和非http协议。我们需要在相对地址relatativeAddress 里扩展文件名,例如.svc、.xoml 或.xamlx。我们也可以定义自己的处理扩展组件,然后在这里配置,那么WCF也会做类似的映射。为了避免冲突,我们在配置文件里定义的<serviceActivations>会代替svc的内容。也就是配置文件的设置优先级会比较高。
2) IIS部署:部署方式同本文WCF服务部署到IIS7.5。
- 指定网站的ASP.NET的版本,这里注意版本为4.0,默认的版本是2.0。
网站ASP.NET的版本配置如图所示:
3) 这里直接启动浏览器,可以在浏览器里查看到服务的信息。如果启用服务元数据页面,可以查看到服务的WSDL信息。页面如下:
十、批量寄宿
(1) 在解决方案下新建控制台输出项目 BatHosting。
(2)添加 System.ServiceModel.dll 的引用。
(3)添加 WCF 服务类库(WcfServiceLib)的项目引用。
(4) 创建配置文件,在配置文件中添加两个配置项
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> <system.serviceModel> <bindings> <webHttpBinding> <binding name="RestWebBinding"> </binding> </webHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="metadataBehavior"> <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8888/BookService/metadata" /> <serviceDebug includeExceptionDetailInFaults="True" /> </behavior> <behavior name="RestServiceBehavior"> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="RestWebBehavior"> <!--这里必须设置--> <webHttp /> </behavior> </endpointBehaviors> </behaviors> <services> <service behaviorConfiguration="metadataBehavior" name=" WcfServiceLib.BookService"> <endpoint address="http://127.0.0.1:8888/BookService" binding="wsHttpBinding" contract=" WcfServiceLib.IBookService" /> </service> <service name=" WcfServiceLib.BookRestService" behaviorConfiguration="RestServiceBehavior"> <endpoint address="http://127.0.0.1:8888/" behaviorConfiguration="RestWebBehavior" binding="webHttpBinding" bindingConfiguration="RestWebBinding" contract=" WcfServiceLib.IBookRestService"> </endpoint> </service> </services> </system.serviceModel> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <connectionStrings> <add name="Entities" connectionString="metadata=res://*/BookModel.csdl|res://*/BookModel.ssdl|res://*/BookModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.\SQLEXPRESS;initial catalog=Test;integrated security=SSPI;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration>
(5)创建宿主程序,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.ServiceModel.Description; using System.Text; using System.Threading.Tasks; using WcfServiceLib; namespace BatHosting { class Program { /// <summary> /// 批量寄宿 /// </summary> /// <param name="args"></param> static void Main(string[] args) { try { Configuration conf = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location); ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel"); foreach (ServiceElement el in svcmod.Services.Services) { Type svcType = Type.GetType(el.Name + "," + "SCF.WcfService"); if (svcType == null) Console.WriteLine("WCF Service Type " + el.Name + " 在配置文件中的名称."); ServiceHost host = new ServiceHost(svcType); host.Opened += delegate { Console.WriteLine(string.Format("{0},使用配置文件,批量寄宿!",svcType.ToString())); }; host.Open(); Console.ForegroundColor = ConsoleColor.Yellow; foreach (ServiceEndpoint se in host.Description.Endpoints) { Console.WriteLine("[终结点]: {0}\r\n\t[A-地址]: {1} \r\n\t [B-绑定]: {2} \r\n\t [C-协定]: {3}", se.Name, se.Address, se.Binding.Name, se.Contract.Name); } } Console.Read(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }
(5)运行宿主程序,在运行客户端进行调用之前,需要先运行宿主程序。如下图所示,则说明宿主建立成功。
十一、总结
通过上面的几个例子,我们实现了控制台宿主、Form宿主、IIS寄宿、WAS宿主(基于TCP协议)、批量寄宿等的实现。在实际的开发过程中,我们大部份都使用IIS做宿主,方便、快捷;有时候我们还会用到基于Windows服务的宿主。