WCF 4.0 如何编程修改wcf配置,不使用web.config静态配置
How to programmatically modify WCF without web.config setting
WCF 4.0 如何编程修改wcf配置,不使用web.config静态配置
接上一篇
WCF4.0安装 NET.TCP启用及常见问题
的例子,继续
在IIS中要实现定义的ServiceHost,需要以下步骤:
1)引入Dll: System.ServiceModel.Activation
2) 修改 svc文件的头部:
<%@ ServiceHost Language="C#" Debug="true" Service="WcfServiceOfMyTest.Service_Test_NetTcp" Factory="CustomServiceHost.SelfDescribingServiceHostFactory" CodeBehind="Service1.svc.cs" %>
加入 Factory,每一个svc文件的头部都要做修改,都需要添加。
3)实现自己的ServiceHost:
我参考了微软的例子,融入了自己修改:
代码:
SelfDescribingServiceHostFactory.cs
using System; using System.ServiceModel; using System.ServiceModel.Activation; namespace CustomServiceHost { public class SelfDescribingServiceHostFactory : ServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { //All the custom factory does is return a new instance //of our custom host class. The bulk of the custom logic should //live in the custom host (as opposed to the factory) for maximum //reuse value. var host = new SelfDescribingServiceHost(serviceType, baseAddresses); return host; } } }
通常,如果我们使用自定义的ServiceHost,最后一句话基本上都是 host.Open(),而在IIS中,我们直接继承 ServiceHostFactory,实现CreateServiceHost函数,并Return host,而不是 直接Open。
SelfDescribingServiceHost.cs
using System; using System.Net.Security; using System.ServiceModel; using System.ServiceModel.Description; using System.Xml; using WcfServiceOfMyTest; namespace CustomServiceHost { //This class is a custom derivative of ServiceHost //that can automatically enabled metadata generation //for any service it hosts. class SelfDescribingServiceHost : ServiceHost { public SelfDescribingServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { } //Overriding ApplyConfiguration() allows us to //alter the ServiceDescription prior to opening //the service host. protected override void ApplyConfiguration() { //First, we call base.ApplyConfiguration() //to read any configuration that was provided for //the service we're hosting. After this call, //this.ServiceDescription describes the service //as it was configured. base.ApplyConfiguration(); //Now that we've populated the ServiceDescription, we can reach into it //and do interesting things (in this case, we'll add an instance of //ServiceMetadataBehavior if it's not already there. ServiceMetadataBehavior smb = this.Description.Behaviors.Find<ServiceMetadataBehavior>(); if (smb == null) { smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = false; this.Description.Behaviors.Add(smb); } else { ////Metadata behavior has already been configured, ////so we don't have any work to do. //return; } ServiceDebugBehavior sdb = this.Description.Behaviors.Find<ServiceDebugBehavior>(); if (sdb == null) { sdb = new ServiceDebugBehavior(); this.Description.Behaviors.Add(sdb); } sdb.IncludeExceptionDetailInFaults = true; ServiceBehaviorAttribute sba = this.Description.Behaviors.Find<ServiceBehaviorAttribute>(); if (sba == null) { sba = new ServiceBehaviorAttribute(); this.Description.Behaviors.Add(sba); } sba.IncludeExceptionDetailInFaults = true; sba.MaxItemsInObjectGraph = int.MaxValue; ServiceThrottlingBehavior stb = this.Description.Behaviors.Find<ServiceThrottlingBehavior>(); if (stb == null) { stb = new ServiceThrottlingBehavior(); stb.MaxConcurrentCalls = int.MaxValue; //stb.MaxConcurrentSessions = int.MaxValue; this.Description.Behaviors.Add(stb); } var items = this.Description.Endpoints; //这个东西无法在代码中修改,只能在web.config 中修改 //ServiceHostingEnvironment.MultipleSiteBindingsEnabled = true; //Add a metadata endpoint at each base address //using the "/mex" addressing convention foreach (Uri baseAddress in this.BaseAddresses) { if (baseAddress.Scheme == Uri.UriSchemeHttp) { /* svcutil.exe http: //localhost/WcfServiceOfMyTest/Service1.svc?wsdl */ smb.HttpGetEnabled = true; this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); } else if (baseAddress.Scheme == Uri.UriSchemeHttps) { smb.HttpsGetEnabled = true; this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpsBinding(), "mex"); } else if (baseAddress.Scheme == Uri.UriSchemeNetPipe) { this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexNamedPipeBinding(), "mex"); } else if (baseAddress.Scheme == Uri.UriSchemeNetTcp) { //这里只暴露了NET.TCP的协议 var tcpBinding = new NetTcpBinding() { Name = "CacheSrvNetTcpBindConfig", ReaderQuotas = XmlDictionaryReaderQuotas.Max, ListenBacklog = int.MaxValue, MaxBufferPoolSize = long.MaxValue, MaxConnections = int.MaxValue, MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue, PortSharingEnabled = true, CloseTimeout = TimeSpan.FromMinutes(30), OpenTimeout = TimeSpan.FromMinutes(30), ReceiveTimeout = TimeSpan.FromMinutes(30), SendTimeout = TimeSpan.FromMinutes(30), TransactionFlow = false, TransferMode = TransferMode.Buffered, TransactionProtocol = TransactionProtocol.OleTransactions, HostNameComparisonMode = HostNameComparisonMode.StrongWildcard, ReliableSession = new OptionalReliableSession { Enabled = false, Ordered = true, InactivityTimeout = TimeSpan.FromMinutes(1) }, Security = new NetTcpSecurity { Mode = SecurityMode.None, Message = new MessageSecurityOverTcp { ClientCredentialType = MessageCredentialType.None }, Transport = new TcpTransportSecurity { ClientCredentialType = TcpClientCredentialType.None, ProtectionLevel = ProtectionLevel.None } } }; /* svcutil.exe net.tcp://dst52382.cn1.global.ctrip.com/WcfServiceOfMyTest/Service1.svc/mex */ this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, tcpBinding,//MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); this.AddServiceEndpoint(typeof(IJustAnInterface), tcpBinding, ""); } } } } }
Web.config
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer> </configuration>