1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
5 namespace System.ServiceModel
8 using System.Collections.Generic;
9 using System.Collections.ObjectModel;
10 using System.ComponentModel;
11 using System.Diagnostics;
12 using System.Globalization;
15 using System.Security;
16 using System.ServiceModel.Administration;
17 using System.ServiceModel.Channels;
18 using System.ServiceModel.Configuration;
19 using System.ServiceModel.Description;
20 using System.ServiceModel.Diagnostics;
21 using System.ServiceModel.Dispatcher;
23 using System.Runtime.Diagnostics;
24 using System.Threading;
25 using System.ServiceModel.Activation;
26 using System.ServiceModel.Diagnostics.Application;
27 using System.Reflection;
28 using System.Linq.Expressions;
30 public abstract class ServiceHostBase : CommunicationObject, IExtensibleObject<ServiceHostBase>, IDisposable
32 internal static readonly Uri EmptyUri = new Uri(string.Empty, UriKind.RelativeOrAbsolute);
34 bool initializeDescriptionHasFinished;
35 UriSchemeKeyedCollection baseAddresses;
36 ChannelDispatcherCollection channelDispatchers;
37 TimeSpan closeTimeout = ServiceDefaults.ServiceHostCloseTimeout;
38 ServiceDescription description;
39 ExtensionCollection<ServiceHostBase> extensions;
40 ReadOnlyCollection<Uri> externalBaseAddresses;
41 IDictionary<string, ContractDescription> implementedContracts;
42 IInstanceContextManager instances;
43 TimeSpan openTimeout = ServiceDefaults.OpenTimeout;
44 ServicePerformanceCountersBase servicePerformanceCounters;
45 DefaultPerformanceCounters defaultPerformanceCounters;
46 ServiceThrottle serviceThrottle;
47 ServiceCredentials readOnlyCredentials;
48 ServiceAuthorizationBehavior readOnlyAuthorization;
49 ServiceAuthenticationBehavior readOnlyAuthentication;
50 Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> endpointsByListenUriInfo;
52 EventTraceActivity eventTraceActivity;
54 internal event EventHandler BusyCountIncremented;
56 public event EventHandler<UnknownMessageReceivedEventArgs> UnknownMessageReceived;
58 protected ServiceHostBase()
60 TraceUtility.SetEtwProviderId();
61 this.baseAddresses = new UriSchemeKeyedCollection(this.ThisLock);
62 this.channelDispatchers = new ChannelDispatcherCollection(this, this.ThisLock);
63 this.extensions = new ExtensionCollection<ServiceHostBase>(this, this.ThisLock);
64 this.instances = new InstanceContextManager(this.ThisLock);
65 this.serviceThrottle = new ServiceThrottle(this);
66 this.TraceOpenAndClose = true;
67 this.Faulted += new EventHandler(OnServiceHostFaulted);
71 internal EventTraceActivity EventTraceActivity
75 if (this.eventTraceActivity == null)
77 this.eventTraceActivity = new EventTraceActivity();
80 return eventTraceActivity;
84 public ServiceAuthorizationBehavior Authorization
88 if (this.Description == null)
92 else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening)
94 return EnsureAuthorization(this.Description);
98 return this.readOnlyAuthorization;
103 public ServiceAuthenticationBehavior Authentication
107 if (this.Description == null)
111 else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening)
113 return EnsureAuthentication(this.Description);
117 return this.readOnlyAuthentication;
122 public ReadOnlyCollection<Uri> BaseAddresses
126 externalBaseAddresses = new ReadOnlyCollection<Uri>(new List<Uri>(this.baseAddresses));
127 return externalBaseAddresses;
131 public ChannelDispatcherCollection ChannelDispatchers
133 get { return this.channelDispatchers; }
136 public TimeSpan CloseTimeout
138 get { return this.closeTimeout; }
141 if (value < TimeSpan.Zero)
143 string message = SR.GetString(SR.SFxTimeoutOutOfRange0);
144 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", message));
146 if (TimeoutHelper.IsTooLarge(value))
148 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
153 this.ThrowIfClosedOrOpened();
154 this.closeTimeout = value;
159 internal ServicePerformanceCountersBase Counters
163 return this.servicePerformanceCounters;
167 this.servicePerformanceCounters = value;
168 this.serviceThrottle.SetServicePerformanceCounters(this.servicePerformanceCounters);
172 internal DefaultPerformanceCounters DefaultCounters
176 return this.defaultPerformanceCounters;
180 this.defaultPerformanceCounters = value;
184 public ServiceCredentials Credentials
188 if (this.Description == null)
192 else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening)
194 return EnsureCredentials(this.Description);
198 return this.readOnlyCredentials;
203 protected override TimeSpan DefaultCloseTimeout
205 get { return this.CloseTimeout; }
208 protected override TimeSpan DefaultOpenTimeout
210 get { return this.OpenTimeout; }
213 public ServiceDescription Description
215 get { return this.description; }
218 public IExtensionCollection<ServiceHostBase> Extensions
220 get { return this.extensions; }
223 protected internal IDictionary<string, ContractDescription> ImplementedContracts
225 get { return this.implementedContracts; }
228 internal UriSchemeKeyedCollection InternalBaseAddresses
230 get { return this.baseAddresses; }
233 public int ManualFlowControlLimit
235 get { return this.ServiceThrottle.ManualFlowControlLimit; }
236 set { this.ServiceThrottle.ManualFlowControlLimit = value; }
239 public TimeSpan OpenTimeout
241 get { return this.openTimeout; }
244 if (value < TimeSpan.Zero)
246 string message = SR.GetString(SR.SFxTimeoutOutOfRange0);
247 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", message));
249 if (TimeoutHelper.IsTooLarge(value))
251 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
256 this.ThrowIfClosedOrOpened();
257 this.openTimeout = value;
262 internal ServiceThrottle ServiceThrottle
266 return this.serviceThrottle;
270 internal virtual object DisposableInstance
278 internal Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> EndpointsByListenUriInfo
282 if (this.endpointsByListenUriInfo == null)
284 this.endpointsByListenUriInfo = this.GetEndpointsByListenUriInfo();
286 return this.endpointsByListenUriInfo;
290 Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> GetEndpointsByListenUriInfo()
292 Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> endpointDictionary = new Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>>();
293 foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
295 DispatcherBuilder.ListenUriInfo listenUriInfo = DispatcherBuilder.GetListenUriInfoForEndpoint(this, endpoint);
296 if (!endpointDictionary.ContainsKey(listenUriInfo))
298 endpointDictionary.Add(listenUriInfo, new Collection<ServiceEndpoint>());
300 endpointDictionary[listenUriInfo].Add(endpoint);
302 return endpointDictionary;
305 protected void AddBaseAddress(Uri baseAddress)
307 if (this.initializeDescriptionHasFinished)
309 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
310 SR.GetString(SR.SFxCannotCallAddBaseAddress)));
312 this.baseAddresses.Add(baseAddress);
315 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address)
317 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null);
320 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri)
324 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address"));
327 ServiceEndpoint endpoint = this.AddServiceEndpoint(implementedContract, binding, new Uri(address, UriKind.RelativeOrAbsolute));
328 if (listenUri != null)
330 endpoint.UnresolvedListenUri = listenUri;
331 listenUri = MakeAbsoluteUri(listenUri, binding);
332 endpoint.ListenUri = listenUri;
337 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address)
339 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null);
342 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri)
346 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address"));
351 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binding"));
354 if (implementedContract == null)
356 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("implementedContract"));
359 if (this.State != CommunicationState.Created && this.State != CommunicationState.Opening)
361 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointAfterOpen)));
364 if (this.Description == null)
366 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointWithoutDescription)));
369 Uri via = this.MakeAbsoluteUri(address, binding);
371 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.implementedContracts));
372 ContractDescription contract = configLoader.LookupContract(implementedContract, this.Description.Name);
374 ServiceEndpoint serviceEndpoint = new ServiceEndpoint(contract, binding, new EndpointAddress(via));
375 this.Description.Endpoints.Add(serviceEndpoint);
376 serviceEndpoint.UnresolvedAddress = address;
378 if (listenUri != null)
380 serviceEndpoint.UnresolvedListenUri = listenUri;
381 listenUri = MakeAbsoluteUri(listenUri, binding);
382 serviceEndpoint.ListenUri = listenUri;
384 return serviceEndpoint;
387 public virtual void AddServiceEndpoint(ServiceEndpoint endpoint)
389 if (endpoint == null)
391 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
393 if (this.State != CommunicationState.Created && this.State != CommunicationState.Opening)
395 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointAfterOpen)));
397 if (this.Description == null)
399 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointWithoutDescription)));
401 if (endpoint.Address == null)
403 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointAddressNotSpecified));
405 if (endpoint.Contract == null)
407 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointContractNotSpecified));
409 if (endpoint.Binding == null)
411 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointBindingNotSpecified));
413 if (!endpoint.IsSystemEndpoint || endpoint.Contract.ContractType == typeof(IMetadataExchange))
415 ConfigLoader loader = new ConfigLoader(GetContractResolver(this.implementedContracts));
416 loader.LookupContract(endpoint.Contract.ConfigurationName, this.Description.Name);
418 this.Description.Endpoints.Add(endpoint);
421 public void SetEndpointAddress(ServiceEndpoint endpoint, string relativeAddress)
423 if (endpoint == null)
425 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
427 if (relativeAddress == null)
429 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("relativeAddress");
431 if (endpoint.Binding == null)
433 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointBindingNotSpecified));
435 Uri absoluteUri = MakeAbsoluteUri(new Uri(relativeAddress, UriKind.Relative), endpoint.Binding);
436 endpoint.Address = new EndpointAddress(absoluteUri);
439 internal Uri MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding)
441 return MakeAbsoluteUri(relativeOrAbsoluteUri, binding, this.InternalBaseAddresses);
444 internal static Uri MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding, UriSchemeKeyedCollection baseAddresses)
446 Uri result = relativeOrAbsoluteUri;
447 if (!result.IsAbsoluteUri)
449 if (binding.Scheme == string.Empty)
451 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCustomBindingWithoutTransport)));
453 result = GetVia(binding.Scheme, result, baseAddresses);
456 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxEndpointNoMatchingScheme, binding.Scheme, binding.Name, GetBaseAddressSchemes(baseAddresses))));
462 protected virtual void ApplyConfiguration()
464 if (this.Description == null)
466 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription)));
469 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(implementedContracts));
471 // Call the overload of LoadConfigurationSectionInternal which looks up the serviceElement from ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
472 LoadConfigurationSectionInternal(configLoader, this.Description, this.Description.ConfigurationName);
474 EnsureAuthenticationAuthorizationDebug(this.Description);
477 internal void EnsureAuthenticationAuthorizationDebug(ServiceDescription description)
479 EnsureAuthentication(description);
480 EnsureAuthorization(description);
481 EnsureDebug(description);
484 public virtual ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints()
486 List<ServiceEndpoint> defaultEndpoints = new List<ServiceEndpoint>();
487 foreach (Uri baseAddress in this.InternalBaseAddresses)
489 ProtocolMappingItem protocolMappingItem = ConfigLoader.LookupProtocolMapping(baseAddress.Scheme);
490 if (protocolMappingItem != null)
492 Binding defaultBinding = ConfigLoader.LookupBinding(protocolMappingItem.Binding, protocolMappingItem.BindingConfiguration);
493 if (defaultBinding != null)
495 AddDefaultEndpoints(defaultBinding, defaultEndpoints);
499 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Exception(SR.GetString(SR.BindingProtocolMappingNotDefined, baseAddress.Scheme)));
503 if (DiagnosticUtility.ShouldTraceInformation && defaultEndpoints.Count > 0)
505 Dictionary<string, string> dictionary = new Dictionary<string, string>();
506 dictionary["ServiceConfigurationName"] = this.description.ConfigurationName;
507 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.DefaultEndpointsAdded, SR.GetString(SR.TraceCodeDefaultEndpointsAdded), new DictionaryTraceRecord(dictionary));
509 return new ReadOnlyCollection<ServiceEndpoint>(defaultEndpoints);
512 internal virtual void AddDefaultEndpoints(Binding defaultBinding, List<ServiceEndpoint> defaultEndpoints)
516 internal virtual void BindInstance(InstanceContext instance)
518 this.instances.Add(instance);
519 if (null != this.servicePerformanceCounters)
523 if (null != this.servicePerformanceCounters)
525 this.servicePerformanceCounters.ServiceInstanceCreated();
531 void IDisposable.Dispose()
536 protected abstract ServiceDescription CreateDescription(out IDictionary<string, ContractDescription> implementedContracts);
538 protected virtual void InitializeRuntime()
540 if (this.Description == null)
542 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotInitializeRuntimeWithoutDescription)));
545 if (this.Description.Endpoints.Count == 0)
547 this.AddDefaultEndpoints();
550 this.EnsureAuthenticationSchemes();
552 DispatcherBuilder dispatcherBuilder = new DispatcherBuilder();
553 dispatcherBuilder.InitializeServiceHost(description, this);
555 SecurityValidationBehavior.Instance.AfterBuildTimeValidation(description);
558 internal virtual void AfterInitializeRuntime(TimeSpan timeout)
562 internal virtual IAsyncResult BeginAfterInitializeRuntime(TimeSpan timeout, AsyncCallback callback, object state)
564 return new CompletedAsyncResult(callback, state);
567 internal virtual void EndAfterInitializeRuntime(IAsyncResult result)
569 CompletedAsyncResult.End(result);
572 ServiceAuthorizationBehavior EnsureAuthorization(ServiceDescription description)
574 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, "");
575 ServiceAuthorizationBehavior a = description.Behaviors.Find<ServiceAuthorizationBehavior>();
579 a = new ServiceAuthorizationBehavior();
580 description.Behaviors.Add(a);
586 ServiceAuthenticationBehavior EnsureAuthentication(ServiceDescription description)
588 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, "");
589 ServiceAuthenticationBehavior a = description.Behaviors.Find<ServiceAuthenticationBehavior>();
593 a = new ServiceAuthenticationBehavior();
594 description.Behaviors.Add(a);
599 ServiceDebugBehavior EnsureDebug(ServiceDescription description)
601 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, "");
602 ServiceDebugBehavior m = description.Behaviors.Find<ServiceDebugBehavior>();
606 m = new ServiceDebugBehavior();
607 description.Behaviors.Add(m);
613 ServiceCredentials EnsureCredentials(ServiceDescription description)
615 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, "");
616 ServiceCredentials c = description.Behaviors.Find<ServiceCredentials>();
620 c = new ServiceCredentials();
621 description.Behaviors.Add(c);
627 internal void FaultInternal()
632 internal string GetBaseAddressSchemes()
634 return GetBaseAddressSchemes(baseAddresses);
637 internal static String GetBaseAddressSchemes(UriSchemeKeyedCollection uriSchemeKeyedCollection)
639 StringBuilder buffer = new StringBuilder();
640 bool firstScheme = true;
641 foreach (Uri address in uriSchemeKeyedCollection)
645 buffer.Append(address.Scheme);
650 buffer.Append(CultureInfo.CurrentCulture.TextInfo.ListSeparator).Append(address.Scheme);
653 return buffer.ToString();
656 internal BindingParameterCollection GetBindingParameters()
658 return DispatcherBuilder.GetBindingParameters(this, new Collection<ServiceEndpoint>());
661 internal BindingParameterCollection GetBindingParameters(ServiceEndpoint inputEndpoint)
663 Collection<ServiceEndpoint> endpoints;
664 if (inputEndpoint == null)
666 endpoints = new Collection<ServiceEndpoint>();
668 else if (!this.EndpointsByListenUriInfo.TryGetValue(DispatcherBuilder.GetListenUriInfoForEndpoint(this, inputEndpoint), out endpoints) || !endpoints.Contains(inputEndpoint))
670 endpoints = new Collection<ServiceEndpoint>();
671 endpoints.Add(inputEndpoint);
674 return DispatcherBuilder.GetBindingParameters(this, endpoints);
677 internal BindingParameterCollection GetBindingParameters(Collection<ServiceEndpoint> endpoints)
679 return DispatcherBuilder.GetBindingParameters(this, endpoints);
682 internal ReadOnlyCollection<InstanceContext> GetInstanceContexts()
684 return Array.AsReadOnly<InstanceContext>(this.instances.ToArray());
687 internal virtual IContractResolver GetContractResolver(IDictionary<string, ContractDescription> implementedContracts)
689 ServiceAndBehaviorsContractResolver resolver = new ServiceAndBehaviorsContractResolver(new ImplementedContractsContractResolver(implementedContracts));
690 resolver.AddBehaviorContractsToResolver(this.description == null ? null : this.description.Behaviors);
694 internal static Uri GetUri(Uri baseUri, Uri relativeUri)
696 return GetUri(baseUri, relativeUri.OriginalString);
699 internal static Uri GetUri(Uri baseUri, string path)
701 if (path.StartsWith("/", StringComparison.Ordinal) || path.StartsWith("\\", StringComparison.Ordinal))
704 for (; i < path.Length; ++i)
706 if (path[i] != '/' && path[i] != '\\')
711 path = path.Substring(i);
714 // VSWhidbey#541152: new Uri(Uri, string.Empty) is broken
715 if (path.Length == 0)
718 if (!baseUri.AbsoluteUri.EndsWith("/", StringComparison.Ordinal))
720 baseUri = new Uri(baseUri.AbsoluteUri + "/");
722 return new Uri(baseUri, path);
725 internal Uri GetVia(string scheme, Uri address)
727 return ServiceHost.GetVia(scheme, address, InternalBaseAddresses);
730 internal static Uri GetVia(string scheme, Uri address, UriSchemeKeyedCollection baseAddresses)
733 if (!via.IsAbsoluteUri)
735 if (!baseAddresses.Contains(scheme))
740 via = GetUri(baseAddresses[scheme], address);
745 public int IncrementManualFlowControlLimit(int incrementBy)
747 return this.ServiceThrottle.IncrementManualFlowControlLimit(incrementBy);
750 protected void InitializeDescription(UriSchemeKeyedCollection baseAddresses)
752 foreach (Uri baseAddress in baseAddresses)
754 this.baseAddresses.Add(baseAddress);
756 IDictionary<string, ContractDescription> implementedContracts = null;
757 ServiceDescription description = CreateDescription(out implementedContracts);
758 this.description = description;
759 this.implementedContracts = implementedContracts;
761 ApplyConfiguration();
762 this.initializeDescriptionHasFinished = true;
765 protected void LoadConfigurationSection(ServiceElement serviceSection)
767 if (serviceSection == null)
769 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceSection");
771 if (this.Description == null)
773 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotLoadConfigurationSectionWithoutDescription)));
776 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts));
777 LoadConfigurationSectionInternal(configLoader, this.Description, serviceSection);
780 internal void LoadConfigurationSectionHelper(Uri baseAddress)
782 this.AddBaseAddress(baseAddress);
785 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.",
786 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")]
787 [SecuritySafeCritical]
788 void LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)
790 ServiceElement serviceSection = configLoader.LookupService(configurationName);
791 LoadConfigurationSectionInternal(configLoader, description, serviceSection);
794 [Fx.Tag.SecurityNote(Critical = "Handles a ServiceElement, which should not be leaked out of SecurityCritical code.",
795 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")]
796 [SecuritySafeCritical]
797 void LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, ServiceElement serviceSection)
799 // caller must validate arguments before calling
800 configLoader.LoadServiceDescription(this, description, serviceSection, this.LoadConfigurationSectionHelper);
803 protected override void OnAbort()
805 this.instances.Abort();
807 foreach (ChannelDispatcherBase dispatcher in this.ChannelDispatchers)
809 if (dispatcher.Listener != null)
811 dispatcher.Listener.Abort();
815 ThreadTrace.StopTracing();
818 internal void OnAddChannelDispatcher(ChannelDispatcherBase channelDispatcher)
822 this.ThrowIfClosedOrOpened();
823 channelDispatcher.AttachInternal(this);
824 channelDispatcher.Faulted += new EventHandler(OnChannelDispatcherFaulted);
828 protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
830 return new CloseAsyncResult(timeout, callback, state, this);
835 this.TraceServiceHostOpenStart();
836 this.TraceBaseAddresses();
837 MessageLogger.EnsureInitialized(); //force config validation instead of waiting for the first message exchange
841 protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
844 return new OpenAsyncResult(this, timeout, callback, state);
847 IAsyncResult BeginOpenChannelDispatchers(TimeSpan timeout, AsyncCallback callback, object state)
849 return new OpenCollectionAsyncResult(timeout, callback, state, this.SnapshotChannelDispatchers());
852 protected override void OnClose(TimeSpan timeout)
856 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
858 if (ManagementExtension.IsEnabled && null != this.Description)
860 ManagementExtension.OnServiceClosing(this);
863 for (int i = 0; i < this.ChannelDispatchers.Count; i++)
865 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i];
866 if (dispatcher.Listener != null)
868 dispatcher.Listener.Close(timeoutHelper.RemainingTime());
872 for (int i = 0; i < this.ChannelDispatchers.Count; i++)
874 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i];
875 dispatcher.CloseInput(timeoutHelper.RemainingTime());
878 // Wait for existing work to complete
879 this.instances.CloseInput(timeoutHelper.RemainingTime());
881 // Close instances (closes contexts/channels)
882 this.instances.Close(timeoutHelper.RemainingTime());
885 for (int i = 0; i < this.ChannelDispatchers.Count; i++)
887 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i];
888 dispatcher.Close(timeoutHelper.RemainingTime());
891 this.ReleasePerformanceCounters();
893 this.TraceBaseAddresses();
894 ThreadTrace.StopTracing();
896 catch (TimeoutException e)
898 if (TD.CloseTimeoutIsEnabled())
900 TD.CloseTimeout(SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose));
902 if (DiagnosticUtility.ShouldTraceWarning)
904 TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostTimeoutOnClose, SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose), this, e);
911 protected override void OnClosed()
915 for (int i = 0; i < this.ChannelDispatchers.Count; i++)
917 ChannelDispatcher dispatcher = this.ChannelDispatchers[i] as ChannelDispatcher;
918 if (dispatcher != null)
920 dispatcher.ReleasePerformanceCounters();
930 void TraceBaseAddresses()
932 if (DiagnosticUtility.ShouldTraceInformation && this.baseAddresses != null
933 && this.baseAddresses.Count > 0)
935 TraceUtility.TraceEvent(TraceEventType.Information,
936 TraceCode.ServiceHostBaseAddresses,
937 SR.GetString(SR.TraceCodeServiceHostBaseAddresses),
938 new CollectionTraceRecord("BaseAddresses", "Address", this.baseAddresses),
943 void TraceServiceHostOpenStart()
945 if (TD.ServiceHostOpenStartIsEnabled())
947 TD.ServiceHostOpenStart(this.EventTraceActivity);
951 protected override void OnEndClose(IAsyncResult result)
955 CloseAsyncResult.End(result);
956 this.TraceBaseAddresses();
957 ThreadTrace.StopTracing();
959 catch (TimeoutException e)
961 if (TD.CloseTimeoutIsEnabled())
963 TD.CloseTimeout(SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose));
965 if (DiagnosticUtility.ShouldTraceWarning)
967 TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostTimeoutOnClose,
968 SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose), this, e);
974 protected override void OnEndOpen(IAsyncResult result)
976 OpenAsyncResult.End(result);
979 void EndOpenChannelDispatchers(IAsyncResult result)
981 OpenCollectionAsyncResult.End(result);
984 void EnsureAuthenticationSchemes()
986 if (this.Authentication == null)
991 //Exit immediately when not hosted in IIS or if VirtualPathExtension is not set. VirtualPathExtension is used as a flag to indicate whether a ServiceHost
992 // is webhosted (WsDualHttpBinding-ChannelFactory is using HttpListener instead of IIS even when running in IIS)
993 if (!AspNetEnvironment.Enabled ||
994 this.Extensions.Find<VirtualPathExtension>() == null)
999 foreach (ServiceEndpoint serviceEndpoint in this.Description.Endpoints)
1001 if (serviceEndpoint.Binding != null &&
1002 serviceEndpoint.ListenUri != null &&
1003 ("http".Equals(serviceEndpoint.ListenUri.Scheme, StringComparison.OrdinalIgnoreCase) || "https".Equals(serviceEndpoint.ListenUri.Scheme, StringComparison.OrdinalIgnoreCase)) &&
1004 this.baseAddresses.Contains(serviceEndpoint.ListenUri.Scheme))
1006 HttpTransportBindingElement httpTransportBindingElement = serviceEndpoint.Binding.CreateBindingElements().Find<HttpTransportBindingElement>();
1008 if (httpTransportBindingElement != null)
1010 AuthenticationSchemes hostSupportedAuthenticationSchemes = AspNetEnvironment.Current.GetAuthenticationSchemes(this.baseAddresses[serviceEndpoint.ListenUri.Scheme]);
1012 if (hostSupportedAuthenticationSchemes != AuthenticationSchemes.None)
1014 //If no authentication schemes are explicitly defined for the ServiceHost...
1015 if (this.Authentication.AuthenticationSchemes == AuthenticationSchemes.None)
1017 //Inherit authentication schemes from IIS
1018 this.Authentication.AuthenticationSchemes = hostSupportedAuthenticationSchemes;
1022 // Build intersection between authenticationSchemes on the ServiceHost and in IIS
1023 this.Authentication.AuthenticationSchemes &= hostSupportedAuthenticationSchemes;
1033 protected override void OnOpen(TimeSpan timeout)
1035 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
1038 AfterInitializeRuntime(timeoutHelper.RemainingTime());
1040 for (int i = 0; i < this.ChannelDispatchers.Count; i++)
1042 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i];
1043 dispatcher.Open(timeoutHelper.RemainingTime());
1047 protected override void OnOpened()
1049 if (this.Description != null)
1051 ServiceCredentials c = description.Behaviors.Find<ServiceCredentials>();
1054 ServiceCredentials credentialsCopy = c.Clone();
1055 credentialsCopy.MakeReadOnly();
1056 this.readOnlyCredentials = credentialsCopy;
1059 ServiceAuthorizationBehavior authorization = description.Behaviors.Find<ServiceAuthorizationBehavior>();
1060 if (authorization != null)
1062 ServiceAuthorizationBehavior authorizationCopy = authorization.Clone();
1063 authorizationCopy.MakeReadOnly();
1064 this.readOnlyAuthorization = authorizationCopy;
1067 ServiceAuthenticationBehavior authentication = description.Behaviors.Find<ServiceAuthenticationBehavior>();
1068 if (authentication != null)
1070 ServiceAuthenticationBehavior authenticationCopy = authentication.Clone();
1071 authentication.MakeReadOnly();
1072 this.readOnlyAuthentication = authenticationCopy;
1075 if (ManagementExtension.IsEnabled)
1077 ManagementExtension.OnServiceOpened(this);
1080 // log telemetry data for the current WCF service.
1081 TelemetryTraceLogging.LogSeriveKPIData(this.Description);
1085 if (TD.ServiceHostOpenStopIsEnabled())
1087 TD.ServiceHostOpenStop(this.EventTraceActivity);
1091 internal void OnRemoveChannelDispatcher(ChannelDispatcherBase channelDispatcher)
1093 lock (this.ThisLock)
1095 this.ThrowIfClosedOrOpened();
1096 channelDispatcher.DetachInternal(this);
1100 void OnChannelDispatcherFaulted(object sender, EventArgs e)
1105 void OnServiceHostFaulted(object sender, EventArgs args)
1107 if (TD.ServiceHostFaultedIsEnabled())
1109 TD.ServiceHostFaulted(this.EventTraceActivity, this);
1112 if (DiagnosticUtility.ShouldTraceWarning)
1114 TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostFaulted,
1115 SR.GetString(SR.TraceCodeServiceHostFaulted), this);
1118 foreach (ICommunicationObject channelDispatcher in this.SnapshotChannelDispatchers())
1120 if (channelDispatcher.State == CommunicationState.Opened)
1122 channelDispatcher.Abort();
1127 internal void RaiseUnknownMessageReceived(Message message)
1131 EventHandler<UnknownMessageReceivedEventArgs> handler = UnknownMessageReceived;
1132 if (handler != null)
1134 handler(this, new UnknownMessageReceivedEventArgs(message));
1142 throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
1146 protected void ReleasePerformanceCounters()
1148 if (this.servicePerformanceCounters != null)
1150 lock (this.ThisLock)
1152 if (this.servicePerformanceCounters != null)
1154 this.servicePerformanceCounters.Dispose();
1155 this.servicePerformanceCounters = null;
1159 if (this.defaultPerformanceCounters != null)
1161 lock (this.ThisLock)
1163 if (this.defaultPerformanceCounters != null)
1165 this.defaultPerformanceCounters.Dispose();
1166 this.defaultPerformanceCounters = null;
1172 ICommunicationObject[] SnapshotChannelDispatchers()
1174 lock (this.ThisLock)
1176 ICommunicationObject[] array = new ICommunicationObject[this.ChannelDispatchers.Count];
1177 for (int i = 0; i < array.Length; i++)
1179 array[i] = this.ChannelDispatchers[i];
1185 internal virtual void UnbindInstance(InstanceContext instance)
1187 this.instances.Remove(instance);
1188 if (null != this.servicePerformanceCounters)
1190 lock (this.ThisLock)
1192 if (null != this.servicePerformanceCounters)
1194 this.servicePerformanceCounters.ServiceInstanceRemoved();
1200 internal void IncrementBusyCount()
1202 if (AspNetEnvironment.Enabled)
1204 AspNetEnvironment.Current.IncrementBusyCount();
1205 Interlocked.Increment(ref this.busyCount);
1208 EventHandler handler = this.BusyCountIncremented;
1209 if (handler != null)
1213 handler(this, EventArgs.Empty);
1215 catch (Exception exception)
1217 if (Fx.IsFatal(exception))
1220 throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(exception);
1225 internal void DecrementBusyCount()
1227 if (AspNetEnvironment.Enabled)
1229 Interlocked.Decrement(ref this.busyCount);
1230 AspNetEnvironment.Current.DecrementBusyCount();
1234 internal int BusyCount
1238 return this.busyCount;
1242 class OpenAsyncResult : AsyncResult
1244 static AsyncCompletion handleEndAfterInitializeRuntime = new AsyncCompletion(HandleEndAfterInitializeRuntime);
1245 static AsyncCompletion handleEndOpenChannelDispatchers = new AsyncCompletion(HandleEndOpenChannelDispatchers);
1247 TimeoutHelper timeoutHelper;
1248 ServiceHostBase host;
1250 public OpenAsyncResult(ServiceHostBase host, TimeSpan timeout, AsyncCallback callback, object state)
1251 : base(callback, state)
1253 this.timeoutHelper = new TimeoutHelper(timeout);
1256 if (ProcessAfterInitializeRuntime())
1262 bool ProcessAfterInitializeRuntime()
1264 IAsyncResult result = this.host.BeginAfterInitializeRuntime(
1265 this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(handleEndAfterInitializeRuntime), this);
1267 return SyncContinue(result);
1270 static bool HandleEndAfterInitializeRuntime(IAsyncResult result)
1272 OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState;
1273 thisPtr.host.EndAfterInitializeRuntime(result);
1275 return thisPtr.ProcessOpenChannelDispatchers();
1278 bool ProcessOpenChannelDispatchers()
1280 IAsyncResult result = this.host.BeginOpenChannelDispatchers(
1281 this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(handleEndOpenChannelDispatchers), this);
1283 return SyncContinue(result);
1286 static bool HandleEndOpenChannelDispatchers(IAsyncResult result)
1288 OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState;
1289 thisPtr.host.EndOpenChannelDispatchers(result);
1294 public static void End(IAsyncResult result)
1296 AsyncResult.End<OpenAsyncResult>(result);
1300 class CloseAsyncResult : AsyncResult
1302 ServiceHostBase serviceHost;
1303 TimeoutHelper timeoutHelper;
1305 public CloseAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ServiceHostBase serviceHost)
1306 : base(callback, state)
1308 this.timeoutHelper = new TimeoutHelper(timeout);
1309 this.serviceHost = serviceHost;
1311 if (ManagementExtension.IsEnabled && null != serviceHost.Description)
1313 ManagementExtension.OnServiceClosing(serviceHost);
1316 this.CloseListeners(true);
1319 void CloseListeners(bool completedSynchronously)
1321 List<ICommunicationObject> listeners = new List<ICommunicationObject>();
1322 for (int i = 0; i < this.serviceHost.ChannelDispatchers.Count; i++)
1324 if (this.serviceHost.ChannelDispatchers[i].Listener != null)
1326 listeners.Add(this.serviceHost.ChannelDispatchers[i].Listener);
1330 AsyncCallback callback = Fx.ThunkCallback(this.CloseListenersCallback);
1331 TimeSpan timeout = this.timeoutHelper.RemainingTime();
1332 Exception exception = null;
1333 IAsyncResult result = null;
1336 result = new CloseCollectionAsyncResult(timeout, callback, this, listeners);
1340 if (Fx.IsFatal(e) || completedSynchronously)
1347 if (exception != null)
1349 this.CallComplete(completedSynchronously, exception);
1351 else if (result.CompletedSynchronously)
1353 this.FinishCloseListeners(result, completedSynchronously);
1357 void CloseListenersCallback(IAsyncResult result)
1359 if (!result.CompletedSynchronously)
1361 ((CloseAsyncResult)result.AsyncState).FinishCloseListeners(result, false);
1365 void FinishCloseListeners(IAsyncResult result, bool completedSynchronously)
1367 Exception exception = null;
1370 CloseCollectionAsyncResult.End(result);
1374 if (Fx.IsFatal(e) || completedSynchronously)
1381 if (exception != null)
1383 this.CallComplete(completedSynchronously, exception);
1387 this.CloseInput(completedSynchronously);
1391 // Wait for existing work to complete
1392 void CloseInput(bool completedSynchronously)
1394 AsyncCallback callback = Fx.ThunkCallback(this.CloseInputCallback);
1395 Exception exception = null;
1396 IAsyncResult result = null;
1400 for (int i = 0; i < this.serviceHost.ChannelDispatchers.Count; i++)
1402 ChannelDispatcherBase dispatcher = this.serviceHost.ChannelDispatchers[i];
1403 dispatcher.CloseInput(this.timeoutHelper.RemainingTime());
1406 result = this.serviceHost.instances.BeginCloseInput(this.timeoutHelper.RemainingTime(), callback, this);
1410 if (Fx.IsFatal(e) || completedSynchronously)
1418 if (exception != null)
1420 // Any exception during async processing causes this
1421 // async callback to report the error and then relies on
1422 // Abort to cleanup any unclosed channels or instance contexts.
1423 FxTrace.Exception.AsWarning(exception);
1424 this.CallComplete(completedSynchronously, exception);
1426 else if (result.CompletedSynchronously)
1428 this.FinishCloseInput(result, completedSynchronously);
1432 void CloseInputCallback(IAsyncResult result)
1434 if (!result.CompletedSynchronously)
1436 ((CloseAsyncResult)result.AsyncState).FinishCloseInput(result, false);
1440 void FinishCloseInput(IAsyncResult result, bool completedSynchronously)
1442 Exception exception = null;
1445 serviceHost.instances.EndCloseInput(result);
1449 if (Fx.IsFatal(e) || completedSynchronously)
1456 if (exception != null)
1458 this.CallComplete(completedSynchronously, exception);
1462 this.CloseInstances(completedSynchronously);
1466 // Close instances (closes contexts/channels)
1467 void CloseInstances(bool completedSynchronously)
1469 AsyncCallback callback = Fx.ThunkCallback(this.CloseInstancesCallback);
1470 TimeSpan timeout = this.timeoutHelper.RemainingTime();
1471 Exception exception = null;
1472 IAsyncResult result = null;
1476 result = this.serviceHost.instances.BeginClose(timeout, callback, this);
1480 if (Fx.IsFatal(e) || completedSynchronously)
1487 if (exception != null)
1489 this.CallComplete(completedSynchronously, exception);
1491 else if (result.CompletedSynchronously)
1493 this.FinishCloseInstances(result, completedSynchronously);
1497 void CloseInstancesCallback(IAsyncResult result)
1499 if (!result.CompletedSynchronously)
1501 ((CloseAsyncResult)result.AsyncState).FinishCloseInstances(result, false);
1505 void FinishCloseInstances(IAsyncResult result, bool completedSynchronously)
1507 Exception exception = null;
1510 this.serviceHost.instances.EndClose(result);
1514 if (Fx.IsFatal(e) || completedSynchronously)
1521 if (exception != null)
1523 this.CallComplete(completedSynchronously, exception);
1527 this.CloseChannelDispatchers(completedSynchronously);
1531 void CloseChannelDispatchers(bool completedSynchronously)
1533 IList<ICommunicationObject> channelDispatchers = this.serviceHost.SnapshotChannelDispatchers();
1534 AsyncCallback callback = Fx.ThunkCallback(this.CloseChannelDispatchersCallback);
1535 TimeSpan timeout = this.timeoutHelper.RemainingTime();
1536 Exception exception = null;
1537 IAsyncResult result = null;
1540 result = new CloseCollectionAsyncResult(timeout, callback, this, channelDispatchers);
1544 if (Fx.IsFatal(e) || completedSynchronously)
1551 if (exception != null)
1553 this.CallComplete(completedSynchronously, exception);
1555 else if (result.CompletedSynchronously)
1557 this.FinishCloseChannelDispatchers(result, completedSynchronously);
1561 void CloseChannelDispatchersCallback(IAsyncResult result)
1563 if (!result.CompletedSynchronously)
1565 ((CloseAsyncResult)result.AsyncState).FinishCloseChannelDispatchers(result, false);
1569 void FinishCloseChannelDispatchers(IAsyncResult result, bool completedSynchronously)
1571 Exception exception = null;
1574 CloseCollectionAsyncResult.End(result);
1578 if (Fx.IsFatal(e) || completedSynchronously)
1585 this.CallComplete(completedSynchronously, exception);
1588 void CallComplete(bool completedSynchronously, Exception exception)
1590 this.Complete(completedSynchronously, exception);
1593 public static void End(IAsyncResult result)
1595 AsyncResult.End<CloseAsyncResult>(result);
1599 class ImplementedContractsContractResolver : IContractResolver
1601 IDictionary<string, ContractDescription> implementedContracts;
1603 public ImplementedContractsContractResolver(IDictionary<string, ContractDescription> implementedContracts)
1605 this.implementedContracts = implementedContracts;
1608 public ContractDescription ResolveContract(string contractName)
1610 return this.implementedContracts != null && this.implementedContracts.ContainsKey(contractName) ? this.implementedContracts[contractName] : null;
1614 internal class ServiceAndBehaviorsContractResolver : IContractResolver
1616 IContractResolver serviceResolver;
1617 Dictionary<string, ContractDescription> behaviorContracts;
1619 public Dictionary<string, ContractDescription> BehaviorContracts
1621 get { return behaviorContracts; }
1624 public ServiceAndBehaviorsContractResolver(IContractResolver serviceResolver)
1626 this.serviceResolver = serviceResolver;
1627 behaviorContracts = new Dictionary<string, ContractDescription>();
1630 public ContractDescription ResolveContract(string contractName)
1632 ContractDescription contract = serviceResolver.ResolveContract(contractName);
1634 if (contract == null)
1636 contract = this.behaviorContracts.ContainsKey(contractName) ? this.behaviorContracts[contractName] : null;
1642 public void AddBehaviorContractsToResolver(KeyedByTypeCollection<IServiceBehavior> behaviors)
1644 // It would be nice to make this loop over all Behaviors... someday.
1645 if (behaviors != null && behaviors.Contains(typeof(ServiceMetadataBehavior)))
1647 behaviors.Find<ServiceMetadataBehavior>().AddImplementedContracts(this);
1653 public class ServiceHost : ServiceHostBase
1655 object singletonInstance;
1657 ReflectedContractCollection reflectedContracts;
1658 IDisposable disposableInstance;
1660 protected ServiceHost()
1664 public ServiceHost(Type serviceType, params Uri[] baseAddresses)
1666 if (serviceType == null)
1668 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType"));
1671 this.serviceType = serviceType;
1672 using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
1674 if (DiagnosticUtility.ShouldUseActivity)
1676 ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct);
1679 InitializeDescription(serviceType, new UriSchemeKeyedCollection(baseAddresses));
1683 public ServiceHost(object singletonInstance, params Uri[] baseAddresses)
1685 if (singletonInstance == null)
1687 throw new ArgumentNullException("singletonInstance");
1690 this.singletonInstance = singletonInstance;
1691 this.serviceType = singletonInstance.GetType();
1692 using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
1694 if (DiagnosticUtility.ShouldUseActivity)
1696 ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct);
1699 InitializeDescription(singletonInstance, new UriSchemeKeyedCollection(baseAddresses));
1703 public object SingletonInstance
1707 return this.singletonInstance;
1711 internal override object DisposableInstance
1715 return this.disposableInstance;
1719 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address)
1721 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null);
1724 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri)
1726 if (address == null)
1728 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address"));
1731 ServiceEndpoint endpoint = this.AddServiceEndpoint(implementedContract, binding, new Uri(address, UriKind.RelativeOrAbsolute));
1732 if (listenUri != null)
1734 listenUri = MakeAbsoluteUri(listenUri, binding);
1735 endpoint.ListenUri = listenUri;
1740 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address)
1742 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null);
1745 void ValidateContractType(Type implementedContract, ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts)
1747 if (!implementedContract.IsDefined(typeof(ServiceContractAttribute), false))
1749 #pragma warning suppress 56506 // implementedContract is never null at this point
1750 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxServiceContractAttributeNotFound, implementedContract.FullName)));
1752 if (!reflectedAndBehaviorContracts.Contains(implementedContract))
1754 if (implementedContract == typeof(IMetadataExchange))
1755 #pragma warning suppress 56506 // ServiceType is never null at this point
1756 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFoundIMetadataExchange, this.serviceType.FullName)));
1758 #pragma warning suppress 56506 // implementedContract and ServiceType are never null at this point
1759 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, this.serviceType.FullName)));
1763 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri)
1765 if (implementedContract == null)
1767 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("implementedContract"));
1769 if (this.reflectedContracts == null)
1771 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractsNotInitialized1, implementedContract.FullName)));
1773 ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts = new ReflectedAndBehaviorContractCollection(this.reflectedContracts, this.Description.Behaviors);
1774 ValidateContractType(implementedContract, reflectedAndBehaviorContracts);
1775 ServiceEndpoint endpoint = AddServiceEndpoint(reflectedAndBehaviorContracts.GetConfigKey(implementedContract), binding, address);
1776 if (listenUri != null)
1778 listenUri = MakeAbsoluteUri(listenUri, binding);
1779 endpoint.ListenUri = listenUri;
1784 internal override void AddDefaultEndpoints(Binding defaultBinding, List<ServiceEndpoint> defaultEndpoints)
1786 // don't generate endpoints for contracts that serve as the base type for other reflected contracts
1787 List<ContractDescription> mostSpecificContracts = new List<ContractDescription>();
1788 for (int i = 0; i < this.reflectedContracts.Count; i++)
1790 bool addContractEndpoint = true;
1791 ContractDescription contract = this.reflectedContracts[i];
1792 Type contractType = contract.ContractType;
1793 if (contractType != null)
1795 for (int j = 0; j < this.reflectedContracts.Count; j++)
1797 ContractDescription otherContract = this.reflectedContracts[j];
1798 Type otherContractType = otherContract.ContractType;
1799 if (i == j || otherContractType == null)
1803 if (contractType.IsAssignableFrom(otherContractType))
1805 addContractEndpoint = false;
1810 if (addContractEndpoint)
1812 mostSpecificContracts.Add(contract);
1816 foreach (ContractDescription contract in mostSpecificContracts)
1818 ServiceEndpoint endpoint = AddServiceEndpoint(contract.ConfigurationName, defaultBinding, string.Empty);
1819 ConfigLoader.LoadDefaultEndpointBehaviors(endpoint);
1820 defaultEndpoints.Add(endpoint);
1824 // Run static Configure method on service type if it exists, else load configuration from Web.config/App.config
1825 protected override void ApplyConfiguration()
1827 // Load from static Configure method if it exists with the right signature
1828 Type serviceType = this.Description.ServiceType;
1829 if (serviceType != null)
1831 MethodInfo configure = GetConfigureMethod(serviceType);
1832 if (configure != null)
1834 // load <host> config
1835 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts));
1836 LoadHostConfigurationInternal(configLoader, this.Description, this.Description.ConfigurationName);
1838 // Invoke configure method for service
1839 ServiceConfiguration configuration = new ServiceConfiguration(this);
1840 InvokeConfigure(configure, configuration);
1846 // else just load from Web.config/App.config
1847 base.ApplyConfiguration();
1850 // Find the Configure method with the required signature, closest to serviceType in the type hierarchy
1851 static MethodInfo GetConfigureMethod(Type serviceType)
1853 // Use recursion instead of BindingFlags.FlattenHierarchy because we require return type to be void
1855 // base case: all Types are rooted in object eventually
1856 if (serviceType == typeof(object))
1861 // signature: "public static void Configure(ServiceConfiguration)"
1862 MethodInfo configure = serviceType.GetMethod("Configure", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(ServiceConfiguration) }, null);
1864 if (configure != null && configure.ReturnType == typeof(void))
1870 return GetConfigureMethod(serviceType.BaseType);
1874 static void InvokeConfigure(MethodInfo configureMethod, ServiceConfiguration configuration)
1876 Action<ServiceConfiguration> call = Delegate.CreateDelegate(typeof(Action<ServiceConfiguration>), configureMethod) as Action<ServiceConfiguration>;
1877 call(configuration);
1880 // called from ServiceConfiguration.LoadFromConfiguration()
1881 internal void LoadFromConfiguration()
1883 if (this.Description == null)
1885 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription)));
1888 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts));
1890 // Call the overload of LoadConfigurationSectionInternal which looks up the serviceElement from ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
1891 LoadConfigurationSectionExceptHostInternal(configLoader, this.Description, this.Description.ConfigurationName);
1892 EnsureAuthenticationAuthorizationDebug(this.Description);
1895 // called from ServiceConfiguration.LoadFromConfiguration(configuration)
1896 internal void LoadFromConfiguration(System.Configuration.Configuration configuration)
1898 if (this.Description == null)
1900 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription)));
1903 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts));
1905 // Look up the serviceElement explicitly on configuration, then call the overload of LoadConfigurationSectionInternal that loads the rest of the config from the same configuration as serviceElement
1906 ServicesSection servicesSection = (ServicesSection)configuration.GetSection(ConfigurationStrings.ServicesSectionPath);
1907 ServiceElement serviceElement = configLoader.LookupService(this.Description.ConfigurationName, servicesSection);
1908 configLoader.LoadServiceDescription(this, this.Description, serviceElement, this.LoadConfigurationSectionHelper, skipHost: true);
1910 EnsureAuthenticationAuthorizationDebug(this.Description);
1913 // Load only "host" section within "service" tag
1914 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.",
1915 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")]
1916 [SecuritySafeCritical]
1917 void LoadHostConfigurationInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)
1919 ServiceElement serviceSection = configLoader.LookupService(configurationName);
1920 if (serviceSection != null)
1922 configLoader.LoadHostConfig(serviceSection, this, (addr => this.InternalBaseAddresses.Add(addr)));
1926 // Load service description for service from config, but skip "host" section within "service" tag
1927 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.",
1928 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")]
1929 [SecuritySafeCritical]
1930 void LoadConfigurationSectionExceptHostInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)
1932 ServiceElement serviceSection = configLoader.LookupService(configurationName);
1933 configLoader.LoadServiceDescription(this, description, serviceSection, this.LoadConfigurationSectionHelper, skipHost: true);
1936 internal override string CloseActivityName
1938 get { return SR.GetString(SR.ActivityCloseServiceHost, this.serviceType.FullName); }
1941 internal override string OpenActivityName
1943 get { return SR.GetString(SR.ActivityOpenServiceHost, this.serviceType.FullName); }
1946 protected override ServiceDescription CreateDescription(out IDictionary<string, ContractDescription> implementedContracts)
1948 if (this.serviceType == null)
1950 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostCannotCreateDescriptionWithoutServiceType)));
1953 ServiceDescription description;
1954 if (this.SingletonInstance != null)
1956 description = ServiceDescription.GetService(this.SingletonInstance);
1960 description = ServiceDescription.GetService(this.serviceType);
1962 ServiceBehaviorAttribute serviceBehavior = description.Behaviors.Find<ServiceBehaviorAttribute>();
1963 object serviceInstanceUsedAsABehavior = serviceBehavior.GetWellKnownSingleton();
1964 if (serviceInstanceUsedAsABehavior == null)
1966 serviceInstanceUsedAsABehavior = serviceBehavior.GetHiddenSingleton();
1967 this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable;
1970 if ((typeof(IServiceBehavior).IsAssignableFrom(this.serviceType) || typeof(IContractBehavior).IsAssignableFrom(this.serviceType))
1971 && serviceInstanceUsedAsABehavior == null)
1973 serviceInstanceUsedAsABehavior = ServiceDescription.CreateImplementation(this.serviceType);
1974 this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable;
1977 if (this.SingletonInstance == null)
1979 if (serviceInstanceUsedAsABehavior is IServiceBehavior)
1981 description.Behaviors.Add((IServiceBehavior)serviceInstanceUsedAsABehavior);
1985 ReflectedContractCollection reflectedContracts = new ReflectedContractCollection();
1986 List<Type> interfaces = ServiceReflector.GetInterfaces(this.serviceType);
1987 for (int i = 0; i < interfaces.Count; i++)
1989 Type contractType = interfaces[i];
1990 if (!reflectedContracts.Contains(contractType))
1992 ContractDescription contract = null;
1993 if (serviceInstanceUsedAsABehavior != null)
1995 contract = ContractDescription.GetContract(contractType, serviceInstanceUsedAsABehavior);
1999 contract = ContractDescription.GetContract(contractType, this.serviceType);
2002 reflectedContracts.Add(contract);
2003 Collection<ContractDescription> inheritedContracts = contract.GetInheritedContracts();
2004 for (int j = 0; j < inheritedContracts.Count; j++)
2006 ContractDescription inheritedContract = inheritedContracts[j];
2007 if (!reflectedContracts.Contains(inheritedContract.ContractType))
2009 reflectedContracts.Add(inheritedContract);
2014 this.reflectedContracts = reflectedContracts;
2016 implementedContracts = reflectedContracts.ToImplementedContracts();
2020 protected void InitializeDescription(object singletonInstance, UriSchemeKeyedCollection baseAddresses)
2022 if (singletonInstance == null)
2024 throw new ArgumentNullException("singletonInstance");
2027 this.singletonInstance = singletonInstance;
2028 InitializeDescription(singletonInstance.GetType(), baseAddresses);
2031 protected void InitializeDescription(Type serviceType, UriSchemeKeyedCollection baseAddresses)
2033 if (serviceType == null)
2035 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType"));
2038 this.serviceType = serviceType;
2040 base.InitializeDescription(baseAddresses);
2043 protected override void OnClosed()
2046 if (this.disposableInstance != null)
2048 this.disposableInstance.Dispose();
2052 class ReflectedContractCollection : KeyedCollection<Type, ContractDescription>
2054 public ReflectedContractCollection()
2059 protected override Type GetKeyForItem(ContractDescription item)
2062 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("item");
2064 return item.ContractType;
2067 public IDictionary<string, ContractDescription> ToImplementedContracts()
2069 Dictionary<string, ContractDescription> implementedContracts = new Dictionary<string, ContractDescription>();
2070 foreach (ContractDescription contract in this.Items)
2072 implementedContracts.Add(GetConfigKey(contract), contract);
2074 return implementedContracts;
2077 internal static string GetConfigKey(ContractDescription contract)
2079 return contract.ConfigurationName;
2083 class ReflectedAndBehaviorContractCollection
2085 ReflectedContractCollection reflectedContracts;
2086 KeyedByTypeCollection<IServiceBehavior> behaviors;
2087 public ReflectedAndBehaviorContractCollection(ReflectedContractCollection reflectedContracts, KeyedByTypeCollection<IServiceBehavior> behaviors)
2089 this.reflectedContracts = reflectedContracts;
2090 this.behaviors = behaviors;
2093 internal bool Contains(Type implementedContract)
2095 if (this.reflectedContracts.Contains(implementedContract))
2100 if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract))
2108 internal string GetConfigKey(Type implementedContract)
2110 if (this.reflectedContracts.Contains(implementedContract))
2112 return ReflectedContractCollection.GetConfigKey(reflectedContracts[implementedContract]);
2115 if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract))
2117 return ServiceMetadataBehavior.MexContractName;
2120 Fx.Assert("Calls to GetConfigKey are preceeded by calls to Contains.");
2121 #pragma warning suppress 56506 // implementedContract is never null at this point
2122 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, string.Empty)));