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);
1082 if (TD.ServiceHostOpenStopIsEnabled())
1084 TD.ServiceHostOpenStop(this.EventTraceActivity);
1088 internal void OnRemoveChannelDispatcher(ChannelDispatcherBase channelDispatcher)
1090 lock (this.ThisLock)
1092 this.ThrowIfClosedOrOpened();
1093 channelDispatcher.DetachInternal(this);
1097 void OnChannelDispatcherFaulted(object sender, EventArgs e)
1102 void OnServiceHostFaulted(object sender, EventArgs args)
1104 if (TD.ServiceHostFaultedIsEnabled())
1106 TD.ServiceHostFaulted(this.EventTraceActivity, this);
1109 if (DiagnosticUtility.ShouldTraceWarning)
1111 TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostFaulted,
1112 SR.GetString(SR.TraceCodeServiceHostFaulted), this);
1115 foreach (ICommunicationObject channelDispatcher in this.SnapshotChannelDispatchers())
1117 if (channelDispatcher.State == CommunicationState.Opened)
1119 channelDispatcher.Abort();
1124 internal void RaiseUnknownMessageReceived(Message message)
1128 EventHandler<UnknownMessageReceivedEventArgs> handler = UnknownMessageReceived;
1129 if (handler != null)
1131 handler(this, new UnknownMessageReceivedEventArgs(message));
1139 throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
1143 protected void ReleasePerformanceCounters()
1145 if (this.servicePerformanceCounters != null)
1147 lock (this.ThisLock)
1149 if (this.servicePerformanceCounters != null)
1151 this.servicePerformanceCounters.Dispose();
1152 this.servicePerformanceCounters = null;
1156 if (this.defaultPerformanceCounters != null)
1158 lock (this.ThisLock)
1160 if (this.defaultPerformanceCounters != null)
1162 this.defaultPerformanceCounters.Dispose();
1163 this.defaultPerformanceCounters = null;
1169 ICommunicationObject[] SnapshotChannelDispatchers()
1171 lock (this.ThisLock)
1173 ICommunicationObject[] array = new ICommunicationObject[this.ChannelDispatchers.Count];
1174 for (int i = 0; i < array.Length; i++)
1176 array[i] = this.ChannelDispatchers[i];
1182 internal virtual void UnbindInstance(InstanceContext instance)
1184 this.instances.Remove(instance);
1185 if (null != this.servicePerformanceCounters)
1187 lock (this.ThisLock)
1189 if (null != this.servicePerformanceCounters)
1191 this.servicePerformanceCounters.ServiceInstanceRemoved();
1197 internal void IncrementBusyCount()
1199 if (AspNetEnvironment.Enabled)
1201 AspNetEnvironment.Current.IncrementBusyCount();
1202 Interlocked.Increment(ref this.busyCount);
1205 EventHandler handler = this.BusyCountIncremented;
1206 if (handler != null)
1210 handler(this, EventArgs.Empty);
1212 catch (Exception exception)
1214 if (Fx.IsFatal(exception))
1217 throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(exception);
1222 internal void DecrementBusyCount()
1224 if (AspNetEnvironment.Enabled)
1226 Interlocked.Decrement(ref this.busyCount);
1227 AspNetEnvironment.Current.DecrementBusyCount();
1231 internal int BusyCount
1235 return this.busyCount;
1239 class OpenAsyncResult : AsyncResult
1241 static AsyncCompletion handleEndAfterInitializeRuntime = new AsyncCompletion(HandleEndAfterInitializeRuntime);
1242 static AsyncCompletion handleEndOpenChannelDispatchers = new AsyncCompletion(HandleEndOpenChannelDispatchers);
1244 TimeoutHelper timeoutHelper;
1245 ServiceHostBase host;
1247 public OpenAsyncResult(ServiceHostBase host, TimeSpan timeout, AsyncCallback callback, object state)
1248 : base(callback, state)
1250 this.timeoutHelper = new TimeoutHelper(timeout);
1253 if (ProcessAfterInitializeRuntime())
1259 bool ProcessAfterInitializeRuntime()
1261 IAsyncResult result = this.host.BeginAfterInitializeRuntime(
1262 this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(handleEndAfterInitializeRuntime), this);
1264 return SyncContinue(result);
1267 static bool HandleEndAfterInitializeRuntime(IAsyncResult result)
1269 OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState;
1270 thisPtr.host.EndAfterInitializeRuntime(result);
1272 return thisPtr.ProcessOpenChannelDispatchers();
1275 bool ProcessOpenChannelDispatchers()
1277 IAsyncResult result = this.host.BeginOpenChannelDispatchers(
1278 this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(handleEndOpenChannelDispatchers), this);
1280 return SyncContinue(result);
1283 static bool HandleEndOpenChannelDispatchers(IAsyncResult result)
1285 OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState;
1286 thisPtr.host.EndOpenChannelDispatchers(result);
1291 public static void End(IAsyncResult result)
1293 AsyncResult.End<OpenAsyncResult>(result);
1297 class CloseAsyncResult : AsyncResult
1299 ServiceHostBase serviceHost;
1300 TimeoutHelper timeoutHelper;
1302 public CloseAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ServiceHostBase serviceHost)
1303 : base(callback, state)
1305 this.timeoutHelper = new TimeoutHelper(timeout);
1306 this.serviceHost = serviceHost;
1308 if (ManagementExtension.IsEnabled && null != serviceHost.Description)
1310 ManagementExtension.OnServiceClosing(serviceHost);
1313 this.CloseListeners(true);
1316 void CloseListeners(bool completedSynchronously)
1318 List<ICommunicationObject> listeners = new List<ICommunicationObject>();
1319 for (int i = 0; i < this.serviceHost.ChannelDispatchers.Count; i++)
1321 if (this.serviceHost.ChannelDispatchers[i].Listener != null)
1323 listeners.Add(this.serviceHost.ChannelDispatchers[i].Listener);
1327 AsyncCallback callback = Fx.ThunkCallback(this.CloseListenersCallback);
1328 TimeSpan timeout = this.timeoutHelper.RemainingTime();
1329 Exception exception = null;
1330 IAsyncResult result = null;
1333 result = new CloseCollectionAsyncResult(timeout, callback, this, listeners);
1337 if (Fx.IsFatal(e) || completedSynchronously)
1344 if (exception != null)
1346 this.CallComplete(completedSynchronously, exception);
1348 else if (result.CompletedSynchronously)
1350 this.FinishCloseListeners(result, completedSynchronously);
1354 void CloseListenersCallback(IAsyncResult result)
1356 if (!result.CompletedSynchronously)
1358 ((CloseAsyncResult)result.AsyncState).FinishCloseListeners(result, false);
1362 void FinishCloseListeners(IAsyncResult result, bool completedSynchronously)
1364 Exception exception = null;
1367 CloseCollectionAsyncResult.End(result);
1371 if (Fx.IsFatal(e) || completedSynchronously)
1378 if (exception != null)
1380 this.CallComplete(completedSynchronously, exception);
1384 this.CloseInput(completedSynchronously);
1388 // Wait for existing work to complete
1389 void CloseInput(bool completedSynchronously)
1391 AsyncCallback callback = Fx.ThunkCallback(this.CloseInputCallback);
1392 Exception exception = null;
1393 IAsyncResult result = null;
1397 for (int i = 0; i < this.serviceHost.ChannelDispatchers.Count; i++)
1399 ChannelDispatcherBase dispatcher = this.serviceHost.ChannelDispatchers[i];
1400 dispatcher.CloseInput(this.timeoutHelper.RemainingTime());
1403 result = this.serviceHost.instances.BeginCloseInput(this.timeoutHelper.RemainingTime(), callback, this);
1407 if (Fx.IsFatal(e) || completedSynchronously)
1415 if (exception != null)
1417 // Any exception during async processing causes this
1418 // async callback to report the error and then relies on
1419 // Abort to cleanup any unclosed channels or instance contexts.
1420 FxTrace.Exception.AsWarning(exception);
1421 this.CallComplete(completedSynchronously, exception);
1423 else if (result.CompletedSynchronously)
1425 this.FinishCloseInput(result, completedSynchronously);
1429 void CloseInputCallback(IAsyncResult result)
1431 if (!result.CompletedSynchronously)
1433 ((CloseAsyncResult)result.AsyncState).FinishCloseInput(result, false);
1437 void FinishCloseInput(IAsyncResult result, bool completedSynchronously)
1439 Exception exception = null;
1442 serviceHost.instances.EndCloseInput(result);
1446 if (Fx.IsFatal(e) || completedSynchronously)
1453 if (exception != null)
1455 this.CallComplete(completedSynchronously, exception);
1459 this.CloseInstances(completedSynchronously);
1463 // Close instances (closes contexts/channels)
1464 void CloseInstances(bool completedSynchronously)
1466 AsyncCallback callback = Fx.ThunkCallback(this.CloseInstancesCallback);
1467 TimeSpan timeout = this.timeoutHelper.RemainingTime();
1468 Exception exception = null;
1469 IAsyncResult result = null;
1473 result = this.serviceHost.instances.BeginClose(timeout, callback, this);
1477 if (Fx.IsFatal(e) || completedSynchronously)
1484 if (exception != null)
1486 this.CallComplete(completedSynchronously, exception);
1488 else if (result.CompletedSynchronously)
1490 this.FinishCloseInstances(result, completedSynchronously);
1494 void CloseInstancesCallback(IAsyncResult result)
1496 if (!result.CompletedSynchronously)
1498 ((CloseAsyncResult)result.AsyncState).FinishCloseInstances(result, false);
1502 void FinishCloseInstances(IAsyncResult result, bool completedSynchronously)
1504 Exception exception = null;
1507 this.serviceHost.instances.EndClose(result);
1511 if (Fx.IsFatal(e) || completedSynchronously)
1518 if (exception != null)
1520 this.CallComplete(completedSynchronously, exception);
1524 this.CloseChannelDispatchers(completedSynchronously);
1528 void CloseChannelDispatchers(bool completedSynchronously)
1530 IList<ICommunicationObject> channelDispatchers = this.serviceHost.SnapshotChannelDispatchers();
1531 AsyncCallback callback = Fx.ThunkCallback(this.CloseChannelDispatchersCallback);
1532 TimeSpan timeout = this.timeoutHelper.RemainingTime();
1533 Exception exception = null;
1534 IAsyncResult result = null;
1537 result = new CloseCollectionAsyncResult(timeout, callback, this, channelDispatchers);
1541 if (Fx.IsFatal(e) || completedSynchronously)
1548 if (exception != null)
1550 this.CallComplete(completedSynchronously, exception);
1552 else if (result.CompletedSynchronously)
1554 this.FinishCloseChannelDispatchers(result, completedSynchronously);
1558 void CloseChannelDispatchersCallback(IAsyncResult result)
1560 if (!result.CompletedSynchronously)
1562 ((CloseAsyncResult)result.AsyncState).FinishCloseChannelDispatchers(result, false);
1566 void FinishCloseChannelDispatchers(IAsyncResult result, bool completedSynchronously)
1568 Exception exception = null;
1571 CloseCollectionAsyncResult.End(result);
1575 if (Fx.IsFatal(e) || completedSynchronously)
1582 this.CallComplete(completedSynchronously, exception);
1585 void CallComplete(bool completedSynchronously, Exception exception)
1587 this.Complete(completedSynchronously, exception);
1590 public static void End(IAsyncResult result)
1592 AsyncResult.End<CloseAsyncResult>(result);
1596 class ImplementedContractsContractResolver : IContractResolver
1598 IDictionary<string, ContractDescription> implementedContracts;
1600 public ImplementedContractsContractResolver(IDictionary<string, ContractDescription> implementedContracts)
1602 this.implementedContracts = implementedContracts;
1605 public ContractDescription ResolveContract(string contractName)
1607 return this.implementedContracts != null && this.implementedContracts.ContainsKey(contractName) ? this.implementedContracts[contractName] : null;
1611 internal class ServiceAndBehaviorsContractResolver : IContractResolver
1613 IContractResolver serviceResolver;
1614 Dictionary<string, ContractDescription> behaviorContracts;
1616 public Dictionary<string, ContractDescription> BehaviorContracts
1618 get { return behaviorContracts; }
1621 public ServiceAndBehaviorsContractResolver(IContractResolver serviceResolver)
1623 this.serviceResolver = serviceResolver;
1624 behaviorContracts = new Dictionary<string, ContractDescription>();
1627 public ContractDescription ResolveContract(string contractName)
1629 ContractDescription contract = serviceResolver.ResolveContract(contractName);
1631 if (contract == null)
1633 contract = this.behaviorContracts.ContainsKey(contractName) ? this.behaviorContracts[contractName] : null;
1639 public void AddBehaviorContractsToResolver(KeyedByTypeCollection<IServiceBehavior> behaviors)
1641 // It would be nice to make this loop over all Behaviors... someday.
1642 if (behaviors != null && behaviors.Contains(typeof(ServiceMetadataBehavior)))
1644 behaviors.Find<ServiceMetadataBehavior>().AddImplementedContracts(this);
1650 public class ServiceHost : ServiceHostBase
1652 object singletonInstance;
1654 ReflectedContractCollection reflectedContracts;
1655 IDisposable disposableInstance;
1657 protected ServiceHost()
1661 public ServiceHost(Type serviceType, params Uri[] baseAddresses)
1663 if (serviceType == null)
1665 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType"));
1668 this.serviceType = serviceType;
1669 using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
1671 if (DiagnosticUtility.ShouldUseActivity)
1673 ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct);
1676 InitializeDescription(serviceType, new UriSchemeKeyedCollection(baseAddresses));
1680 public ServiceHost(object singletonInstance, params Uri[] baseAddresses)
1682 if (singletonInstance == null)
1684 throw new ArgumentNullException("singletonInstance");
1687 this.singletonInstance = singletonInstance;
1688 this.serviceType = singletonInstance.GetType();
1689 using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
1691 if (DiagnosticUtility.ShouldUseActivity)
1693 ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct);
1696 InitializeDescription(singletonInstance, new UriSchemeKeyedCollection(baseAddresses));
1700 public object SingletonInstance
1704 return this.singletonInstance;
1708 internal override object DisposableInstance
1712 return this.disposableInstance;
1716 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address)
1718 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null);
1721 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri)
1723 if (address == null)
1725 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address"));
1728 ServiceEndpoint endpoint = this.AddServiceEndpoint(implementedContract, binding, new Uri(address, UriKind.RelativeOrAbsolute));
1729 if (listenUri != null)
1731 listenUri = MakeAbsoluteUri(listenUri, binding);
1732 endpoint.ListenUri = listenUri;
1737 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address)
1739 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null);
1742 void ValidateContractType(Type implementedContract, ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts)
1744 if (!implementedContract.IsDefined(typeof(ServiceContractAttribute), false))
1746 #pragma warning suppress 56506 // implementedContract is never null at this point
1747 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxServiceContractAttributeNotFound, implementedContract.FullName)));
1749 if (!reflectedAndBehaviorContracts.Contains(implementedContract))
1751 if (implementedContract == typeof(IMetadataExchange))
1752 #pragma warning suppress 56506 // ServiceType is never null at this point
1753 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFoundIMetadataExchange, this.serviceType.FullName)));
1755 #pragma warning suppress 56506 // implementedContract and ServiceType are never null at this point
1756 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, this.serviceType.FullName)));
1760 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri)
1762 if (implementedContract == null)
1764 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("implementedContract"));
1766 if (this.reflectedContracts == null)
1768 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractsNotInitialized1, implementedContract.FullName)));
1770 ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts = new ReflectedAndBehaviorContractCollection(this.reflectedContracts, this.Description.Behaviors);
1771 ValidateContractType(implementedContract, reflectedAndBehaviorContracts);
1772 ServiceEndpoint endpoint = AddServiceEndpoint(reflectedAndBehaviorContracts.GetConfigKey(implementedContract), binding, address);
1773 if (listenUri != null)
1775 listenUri = MakeAbsoluteUri(listenUri, binding);
1776 endpoint.ListenUri = listenUri;
1781 internal override void AddDefaultEndpoints(Binding defaultBinding, List<ServiceEndpoint> defaultEndpoints)
1783 // don't generate endpoints for contracts that serve as the base type for other reflected contracts
1784 List<ContractDescription> mostSpecificContracts = new List<ContractDescription>();
1785 for (int i = 0; i < this.reflectedContracts.Count; i++)
1787 bool addContractEndpoint = true;
1788 ContractDescription contract = this.reflectedContracts[i];
1789 Type contractType = contract.ContractType;
1790 if (contractType != null)
1792 for (int j = 0; j < this.reflectedContracts.Count; j++)
1794 ContractDescription otherContract = this.reflectedContracts[j];
1795 Type otherContractType = otherContract.ContractType;
1796 if (i == j || otherContractType == null)
1800 if (contractType.IsAssignableFrom(otherContractType))
1802 addContractEndpoint = false;
1807 if (addContractEndpoint)
1809 mostSpecificContracts.Add(contract);
1813 foreach (ContractDescription contract in mostSpecificContracts)
1815 ServiceEndpoint endpoint = AddServiceEndpoint(contract.ConfigurationName, defaultBinding, string.Empty);
1816 ConfigLoader.LoadDefaultEndpointBehaviors(endpoint);
1817 defaultEndpoints.Add(endpoint);
1821 // Run static Configure method on service type if it exists, else load configuration from Web.config/App.config
1822 protected override void ApplyConfiguration()
1824 // Load from static Configure method if it exists with the right signature
1825 Type serviceType = this.Description.ServiceType;
1826 if (serviceType != null)
1828 MethodInfo configure = GetConfigureMethod(serviceType);
1829 if (configure != null)
1831 // load <host> config
1832 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts));
1833 LoadHostConfigurationInternal(configLoader, this.Description, this.Description.ConfigurationName);
1835 // Invoke configure method for service
1836 ServiceConfiguration configuration = new ServiceConfiguration(this);
1837 InvokeConfigure(configure, configuration);
1843 // else just load from Web.config/App.config
1844 base.ApplyConfiguration();
1847 // Find the Configure method with the required signature, closest to serviceType in the type hierarchy
1848 static MethodInfo GetConfigureMethod(Type serviceType)
1850 // Use recursion instead of BindingFlags.FlattenHierarchy because we require return type to be void
1852 // base case: all Types are rooted in object eventually
1853 if (serviceType == typeof(object))
1858 // signature: "public static void Configure(ServiceConfiguration)"
1859 MethodInfo configure = serviceType.GetMethod("Configure", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(ServiceConfiguration) }, null);
1861 if (configure != null && configure.ReturnType == typeof(void))
1867 return GetConfigureMethod(serviceType.BaseType);
1871 static void InvokeConfigure(MethodInfo configureMethod, ServiceConfiguration configuration)
1873 Action<ServiceConfiguration> call = Delegate.CreateDelegate(typeof(Action<ServiceConfiguration>), configureMethod) as Action<ServiceConfiguration>;
1874 call(configuration);
1877 // called from ServiceConfiguration.LoadFromConfiguration()
1878 internal void LoadFromConfiguration()
1880 if (this.Description == null)
1882 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription)));
1885 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts));
1887 // Call the overload of LoadConfigurationSectionInternal which looks up the serviceElement from ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
1888 LoadConfigurationSectionExceptHostInternal(configLoader, this.Description, this.Description.ConfigurationName);
1889 EnsureAuthenticationAuthorizationDebug(this.Description);
1892 // called from ServiceConfiguration.LoadFromConfiguration(configuration)
1893 internal void LoadFromConfiguration(System.Configuration.Configuration configuration)
1895 if (this.Description == null)
1897 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription)));
1900 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts));
1902 // 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
1903 ServicesSection servicesSection = (ServicesSection)configuration.GetSection(ConfigurationStrings.ServicesSectionPath);
1904 ServiceElement serviceElement = configLoader.LookupService(this.Description.ConfigurationName, servicesSection);
1905 configLoader.LoadServiceDescription(this, this.Description, serviceElement, this.LoadConfigurationSectionHelper, skipHost: true);
1907 EnsureAuthenticationAuthorizationDebug(this.Description);
1910 // Load only "host" section within "service" tag
1911 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.",
1912 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")]
1913 [SecuritySafeCritical]
1914 void LoadHostConfigurationInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)
1916 ServiceElement serviceSection = configLoader.LookupService(configurationName);
1917 if (serviceSection != null)
1919 configLoader.LoadHostConfig(serviceSection, this, (addr => this.InternalBaseAddresses.Add(addr)));
1923 // Load service description for service from config, but skip "host" section within "service" tag
1924 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.",
1925 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")]
1926 [SecuritySafeCritical]
1927 void LoadConfigurationSectionExceptHostInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)
1929 ServiceElement serviceSection = configLoader.LookupService(configurationName);
1930 configLoader.LoadServiceDescription(this, description, serviceSection, this.LoadConfigurationSectionHelper, skipHost: true);
1933 internal override string CloseActivityName
1935 get { return SR.GetString(SR.ActivityCloseServiceHost, this.serviceType.FullName); }
1938 internal override string OpenActivityName
1940 get { return SR.GetString(SR.ActivityOpenServiceHost, this.serviceType.FullName); }
1943 protected override ServiceDescription CreateDescription(out IDictionary<string, ContractDescription> implementedContracts)
1945 if (this.serviceType == null)
1947 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostCannotCreateDescriptionWithoutServiceType)));
1950 ServiceDescription description;
1951 if (this.SingletonInstance != null)
1953 description = ServiceDescription.GetService(this.SingletonInstance);
1957 description = ServiceDescription.GetService(this.serviceType);
1959 ServiceBehaviorAttribute serviceBehavior = description.Behaviors.Find<ServiceBehaviorAttribute>();
1960 object serviceInstanceUsedAsABehavior = serviceBehavior.GetWellKnownSingleton();
1961 if (serviceInstanceUsedAsABehavior == null)
1963 serviceInstanceUsedAsABehavior = serviceBehavior.GetHiddenSingleton();
1964 this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable;
1967 if ((typeof(IServiceBehavior).IsAssignableFrom(this.serviceType) || typeof(IContractBehavior).IsAssignableFrom(this.serviceType))
1968 && serviceInstanceUsedAsABehavior == null)
1970 serviceInstanceUsedAsABehavior = ServiceDescription.CreateImplementation(this.serviceType);
1971 this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable;
1974 if (this.SingletonInstance == null)
1976 if (serviceInstanceUsedAsABehavior is IServiceBehavior)
1978 description.Behaviors.Add((IServiceBehavior)serviceInstanceUsedAsABehavior);
1982 ReflectedContractCollection reflectedContracts = new ReflectedContractCollection();
1983 List<Type> interfaces = ServiceReflector.GetInterfaces(this.serviceType);
1984 for (int i = 0; i < interfaces.Count; i++)
1986 Type contractType = interfaces[i];
1987 if (!reflectedContracts.Contains(contractType))
1989 ContractDescription contract = null;
1990 if (serviceInstanceUsedAsABehavior != null)
1992 contract = ContractDescription.GetContract(contractType, serviceInstanceUsedAsABehavior);
1996 contract = ContractDescription.GetContract(contractType, this.serviceType);
1999 reflectedContracts.Add(contract);
2000 Collection<ContractDescription> inheritedContracts = contract.GetInheritedContracts();
2001 for (int j = 0; j < inheritedContracts.Count; j++)
2003 ContractDescription inheritedContract = inheritedContracts[j];
2004 if (!reflectedContracts.Contains(inheritedContract.ContractType))
2006 reflectedContracts.Add(inheritedContract);
2011 this.reflectedContracts = reflectedContracts;
2013 implementedContracts = reflectedContracts.ToImplementedContracts();
2017 protected void InitializeDescription(object singletonInstance, UriSchemeKeyedCollection baseAddresses)
2019 if (singletonInstance == null)
2021 throw new ArgumentNullException("singletonInstance");
2024 this.singletonInstance = singletonInstance;
2025 InitializeDescription(singletonInstance.GetType(), baseAddresses);
2028 protected void InitializeDescription(Type serviceType, UriSchemeKeyedCollection baseAddresses)
2030 if (serviceType == null)
2032 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType"));
2035 this.serviceType = serviceType;
2037 base.InitializeDescription(baseAddresses);
2040 protected override void OnClosed()
2043 if (this.disposableInstance != null)
2045 this.disposableInstance.Dispose();
2049 class ReflectedContractCollection : KeyedCollection<Type, ContractDescription>
2051 public ReflectedContractCollection()
2056 protected override Type GetKeyForItem(ContractDescription item)
2059 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("item");
2061 return item.ContractType;
2064 public IDictionary<string, ContractDescription> ToImplementedContracts()
2066 Dictionary<string, ContractDescription> implementedContracts = new Dictionary<string, ContractDescription>();
2067 foreach (ContractDescription contract in this.Items)
2069 implementedContracts.Add(GetConfigKey(contract), contract);
2071 return implementedContracts;
2074 internal static string GetConfigKey(ContractDescription contract)
2076 return contract.ConfigurationName;
2080 class ReflectedAndBehaviorContractCollection
2082 ReflectedContractCollection reflectedContracts;
2083 KeyedByTypeCollection<IServiceBehavior> behaviors;
2084 public ReflectedAndBehaviorContractCollection(ReflectedContractCollection reflectedContracts, KeyedByTypeCollection<IServiceBehavior> behaviors)
2086 this.reflectedContracts = reflectedContracts;
2087 this.behaviors = behaviors;
2090 internal bool Contains(Type implementedContract)
2092 if (this.reflectedContracts.Contains(implementedContract))
2097 if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract))
2105 internal string GetConfigKey(Type implementedContract)
2107 if (this.reflectedContracts.Contains(implementedContract))
2109 return ReflectedContractCollection.GetConfigKey(reflectedContracts[implementedContract]);
2112 if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract))
2114 return ServiceMetadataBehavior.MexContractName;
2117 Fx.Assert("Calls to GetConfigKey are preceeded by calls to Contains.");
2118 #pragma warning suppress 56506 // implementedContract is never null at this point
2119 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, string.Empty)));