HostedAspNetEnvironment.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / System.ServiceModel.Activation / System / ServiceModel / Activation / HostedAspNetEnvironment.cs / 1407647 / HostedAspNetEnvironment.cs

                            //---------------------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------------------

namespace System.ServiceModel.Activation 
{
    using System.Collections.Generic; 
    using System.Configuration; 
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization; 
    using System.Net;
    using System.Runtime;
    using System.Runtime.CompilerServices;
    using System.Security; 
    using System.Security.Authentication.ExtendedProtection;
    using System.Security.Permissions; 
    using System.ServiceModel; 
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description; 
    using System.Threading;
    using System.Transactions;
    using System.Web;
    using System.Web.Compilation; 
    using System.Web.Configuration;
 
    class HostedAspNetEnvironment : AspNetEnvironment 
    {
        // used to cache SiteName|ApplicationVirtualPath 
        static string cachedServiceReference;

        // used to cache if windows auth is being used
        Nullable isWindowsAuthentication; 

        HostedAspNetEnvironment() 
            : base() 
        {
        } 

        public override bool AspNetCompatibilityEnabled
        {
            get 
            {
                return ServiceHostingEnvironment.AspNetCompatibilityEnabled; 
            } 
        }
 
        public override string ConfigurationPath
        {
            get
            { 
                if (ServiceHostingEnvironment.CurrentVirtualPath != null)
                { 
                    return ServiceHostingEnvironment.CurrentVirtualPath + "web.config"; 
                }
                else 
                {
                    return base.ConfigurationPath;
                }
            } 
        }
 
        public override bool IsConfigurationBased 
        {
            get 
            {
                return ServiceHostingEnvironment.IsConfigurationBased;
            }
        } 

        public override string CurrentVirtualPath 
        { 
            get
            { 
                return ServiceHostingEnvironment.CurrentVirtualPath;
            }
        }
 
        public override string XamlFileBaseLocation
        { 
            get 
            {
                return ServiceHostingEnvironment.XamlFileBaseLocation; 
            }
        }

        public static void Enable() 
        {
            AspNetEnvironment hostedEnvironment = new HostedAspNetEnvironment(); 
            AspNetEnvironment.Current = hostedEnvironment; 
        }
 
        public override void AddHostingBehavior(ServiceHostBase serviceHost, ServiceDescription description)
        {
            VirtualPathExtension virtualPathExtension = serviceHost.Extensions.Find();
            if (virtualPathExtension != null) 
            {
                description.Behaviors.Add(new HostedBindingBehavior(virtualPathExtension)); 
            } 
        }
 
        public override bool IsWebConfigAboveApplication(object configHostingContext)
        {
            WebContext context = configHostingContext as WebContext;
            if (context != null) 
            {
                return context.ApplicationLevel == WebApplicationLevel.AboveApplication; 
            } 

            return false; // if we don't recognize the context we can't enforce the special web.config logic 
        }

        public override void EnsureCompatibilityRequirements(ServiceDescription description)
        { 
            AspNetCompatibilityRequirementsAttribute aspNetCompatibilityRequirements = description.Behaviors.Find();
            if (aspNetCompatibilityRequirements == null) 
            { 
                aspNetCompatibilityRequirements = new AspNetCompatibilityRequirementsAttribute();
                description.Behaviors.Add(aspNetCompatibilityRequirements); 
            }
        }

        public override bool TryGetFullVirtualPath(out string virtualPath) 
        {
            // subclass will use the virtual path from the compiled string 
            virtualPath = ServiceHostingEnvironment.FullVirtualPath; 
            return true;
        } 

        public override string GetAnnotationFromHost(ServiceHostBase host)
        {
            //Format Website name\Application Virtual Path|\relative service virtual path|serviceName 
            if (host != null && host.Extensions != null)
            { 
                string serviceName = (host.Description != null) ? host.Description.Name : string.Empty; 
                string application = ServiceHostingEnvironment.ApplicationVirtualPath;
                string servicePath = string.Empty; 
                VirtualPathExtension extension = host.Extensions.Find();
                if (extension != null && extension.VirtualPath != null)
                {
                    servicePath = extension.VirtualPath.Replace("~", application + "|"); 
                    return string.Format(CultureInfo.InvariantCulture, "{0}{1}|{2}", ServiceHostingEnvironment.SiteName, servicePath, serviceName);
                } 
            } 
            if (string.IsNullOrEmpty(HostedAspNetEnvironment.cachedServiceReference))
            { 
                HostedAspNetEnvironment.cachedServiceReference = string.Format(CultureInfo.InvariantCulture, "{0}{1}", ServiceHostingEnvironment.SiteName, ServiceHostingEnvironment.ApplicationVirtualPath);
            }
            return HostedAspNetEnvironment.cachedServiceReference;
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - can be called outside of user context.")] 
        public override void EnsureAllReferencedAssemblyLoaded() 
        {
            BuildManager.GetReferencedAssemblies(); 
        }

        public override BaseUriWithWildcard GetBaseUri(string transportScheme, Uri listenUri)
        { 
            BaseUriWithWildcard baseAddress = null;
            HostedTransportConfigurationBase hostedConfiguration = 
                HostedTransportConfigurationManager.GetConfiguration(transportScheme) as HostedTransportConfigurationBase; 
            if (hostedConfiguration != null)
            { 
                baseAddress = hostedConfiguration.FindBaseAddress(listenUri);
                if (baseAddress == null)
                {
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_TransportBindingNotFound(listenUri.ToString()))); 
                }
            } 
            return baseAddress; 
        }
 
        public override void ValidateHttpSettings(string virtualPath, bool isMetadataListener, bool usingDefaultSpnList, ref AuthenticationSchemes supportedSchemes, ref ExtendedProtectionPolicy extendedProtectionPolicy, ref string realm)
        {
            // Verify the authentication settings
            AuthenticationSchemes hostedSupportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(virtualPath); 

            if (supportedSchemes == AuthenticationSchemes.Anonymous) 
            { 
                if ((hostedSupportedSchemes & AuthenticationSchemes.Anonymous) == 0)
                { 
                    if (isMetadataListener)
                    {
                        // We apply IIS settings to the ChannelListener to fix mex endpoints.
                        if ((hostedSupportedSchemes & AuthenticationSchemes.Negotiate) != AuthenticationSchemes.None) 
                        {
                            supportedSchemes = AuthenticationSchemes.Negotiate; 
                        } 
                        else
                        { 
                            supportedSchemes = hostedSupportedSchemes;
                        }
                    }
                } 
            }
 
            if ((supportedSchemes & hostedSupportedSchemes) == 0) 
            {
                if (AuthenticationSchemesHelper.IsWindowsAuth(supportedSchemes)) 
                {
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireWindowsAuth));
                }
                else 
                {
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_AuthSchemesRequireOtherAuth(supportedSchemes.ToString()))); 
                } 
            }
 
            if (supportedSchemes != AuthenticationSchemes.Anonymous)
            {
                //Compare the ExtendedProtectionPolicy setttings to IIS
                ExtendedProtectionPolicy iisPolicy = HostedTransportConfigurationManager.MetabaseSettings.GetExtendedProtectionPolicy(virtualPath); 

                if (iisPolicy == null) //OS doesn't support CBT 
                { 
                    if (extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.Always)
                    { 
                        throw FxTrace.Exception.AsError(new NotSupportedException(SR.ExtendedProtectionNotSupported));
                    }
                }
                else 
                {
                    if (isMetadataListener && ChannelBindingUtility.IsDefaultPolicy(extendedProtectionPolicy)) 
                    { 
                        //push the IIS policy onto the metadataListener if and only if the default policy is
                        //in force. policy for non metadata listeners will still have to match IIS policy. 
                        extendedProtectionPolicy = iisPolicy;
                    }
                    else
                    { 
                        if (!ChannelBindingUtility.AreEqual(iisPolicy, extendedProtectionPolicy))
                        { 
                            string mismatchErrorMessage; 
                            if (iisPolicy.PolicyEnforcement != extendedProtectionPolicy.PolicyEnforcement)
                            { 
                                mismatchErrorMessage = SR.ExtendedProtectionPolicyEnforcementMismatch(iisPolicy.PolicyEnforcement, extendedProtectionPolicy.PolicyEnforcement);
                            }
                            else if (iisPolicy.ProtectionScenario != extendedProtectionPolicy.ProtectionScenario)
                            { 
                                mismatchErrorMessage = SR.ExtendedProtectionPolicyScenarioMismatch(iisPolicy.ProtectionScenario, extendedProtectionPolicy.ProtectionScenario);
                            } 
                            else 
                            {
                                Fx.Assert(iisPolicy.CustomChannelBinding != extendedProtectionPolicy.CustomChannelBinding, "new case in ChannelBindingUtility.AreEqual to account for"); 
                                mismatchErrorMessage = SR.ExtendedProtectionPolicyCustomChannelBindingMismatch;
                            }

                            if (mismatchErrorMessage != null) 
                            {
                                throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(mismatchErrorMessage))); 
                            } 
                        }
 
                        //when using the default SPN list we auto generate, we should make sure that the IIS policy is also the default...
                        ServiceNameCollection listenerSpnList = usingDefaultSpnList ? null : extendedProtectionPolicy.CustomServiceNames;
                        if (!ChannelBindingUtility.IsSubset(iisPolicy.CustomServiceNames, listenerSpnList))
                        { 
                            throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_ExtendedProtectionPoliciesMustMatch(SR.Hosting_ExtendedProtectionSPNListNotSubset)));
                        } 
                    } 
                }
            } 



            // Do not set realm for Cassini. 
            if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
            { 
                // Set the realm 
                realm = HostedTransportConfigurationManager.MetabaseSettings.GetRealm(virtualPath);
            } 
        }

        public override bool ValidateHttpsSettings(string virtualPath, ref Nullable requireClientCertificate)
        { 
            bool useHostedClientCertificateMapping = false;
 
            // Do not validate settings for Cassini. Actually current implementation of Cassini does not support HTTPS. 
            if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
            { 
                // Validate Ssl Settings
                HttpAccessSslFlags sslFlags = HostedTransportConfigurationManager.MetabaseSettings.GetAccessSslFlags(virtualPath);
                HttpAccessSslFlags channelListenerSslFlags = HttpAccessSslFlags.None;
 
                // Validating SSL flags. SslRequireCert means "require client certificate" in IIS terminology.
                bool mismatched = false; 
                if ((sslFlags & HttpAccessSslFlags.SslRequireCert) != 0) 
                {
                    // Require SSL. 
                    if (requireClientCertificate.HasValue)
                    {
                        if (!requireClientCertificate.Value)
                        { 
                            // IIS requires client cert but the binding does not.
                            mismatched = true; 
                        } 
                    }
                    else 
                    {
                        // We apply IIS settings to the ChannelListener to fix mex endpoints.
                        requireClientCertificate = true;
                    } 
                }
                else if (requireClientCertificate.GetValueOrDefault()) 
                { 
                    // IIS does not require client cert but the binding does.
                    channelListenerSslFlags |= HttpAccessSslFlags.SslRequireCert; 
                    mismatched = true;
                }

                if (!mismatched) 
                {
                    if ((sslFlags & HttpAccessSslFlags.SslMapCert) != 0) 
                    { 
                        useHostedClientCertificateMapping = true;
                    } 
                }

                if (mismatched)
                { 
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.Hosting_SslSettingsMisconfigured(
                        channelListenerSslFlags.ToString(), sslFlags.ToString()))); 
                } 
            }
            return useHostedClientCertificateMapping; 
        }

        public override void ProcessNotMatchedEndpointAddress(Uri uri, string endpointName)
        { 
            if (!object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttp) &&
                !object.ReferenceEquals(uri.Scheme, Uri.UriSchemeHttps)) 
            { 
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_NonHTTPInCompatibilityMode(endpointName)));
            } 
        }

        public override void ValidateCompatibilityRequirements(AspNetCompatibilityRequirementsMode compatibilityMode)
        { 
            if (compatibilityMode == AspNetCompatibilityRequirementsMode.Allowed)
            { 
                return; 
            }
            else if (ServiceHostingEnvironment.AspNetCompatibilityEnabled && 
                compatibilityMode == AspNetCompatibilityRequirementsMode.NotAllowed)
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityNotAllowed));
            } 
            else if (!ServiceHostingEnvironment.AspNetCompatibilityEnabled &&
                compatibilityMode == AspNetCompatibilityRequirementsMode.Required) 
            { 
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ServiceCompatibilityRequire));
            } 
        }

        public override IAspNetMessageProperty GetHostingProperty(Message message)
        { 
            return GetHostingProperty(message, false);
        } 
 
        IAspNetMessageProperty GetHostingProperty(Message message, bool removeFromMessage)
        { 
            IAspNetMessageProperty result = null;
            object property;

            if (message.Properties.TryGetValue(HostingMessageProperty.Name, out property)) 
            {
                result = (HostingMessageProperty)property; 
                if (removeFromMessage) 
                {
                    message.Properties.Remove(HostingMessageProperty.Name); 
                }
            }

            return result; 
        }
 
        public override IAspNetMessageProperty PrepareMessageForDispatch(Message message) 
        {
            ReceiveContext context = null; 
            if (ReceiveContext.TryGet(message, out context) && !(context is ReceiveContextBusyCountWrapper))
            {
                ReceiveContextBusyCountWrapper wrapper = new ReceiveContextBusyCountWrapper(context);
                message.Properties.Remove(ReceiveContext.Name); 
                message.Properties.Add(ReceiveContext.Name, wrapper);
            } 
            return GetHostingProperty(message, true); 
        }
 
        public override void ApplyHostedContext(TransportChannelListener listener, BindingContext context)
        {
            VirtualPathExtension virtualPathExtension = context.BindingParameters.Find();
 
            if (virtualPathExtension != null)
            { 
                HostedMetadataBindingParameter metadataBindingParameter = context.BindingParameters.Find(); 
                listener.ApplyHostedContext(virtualPathExtension.VirtualPath, metadataBindingParameter != null);
            } 
        }

        public override void ProcessBehaviorForMetadataExtension(IServiceBehavior serviceBehavior, BindingParameterCollection bindingParameters)
        { 
            if (serviceBehavior is HostedBindingBehavior)
            { 
                bindingParameters.Add(((HostedBindingBehavior)serviceBehavior).VirtualPathExtension); 
                bindingParameters.Add(new HostedMetadataBindingParameter());
            } 
        }

        public override void IncrementBusyCount()
        { 
            HostingEnvironmentWrapper.IncrementBusyCount();
        } 
 
        public override void DecrementBusyCount()
        { 
            HostingEnvironmentWrapper.DecrementBusyCount();
        }

        public override bool TraceIncrementBusyCountIsEnabled() 
        {
            return TD.IncrementBusyCountIsEnabled(); 
        } 

        public override bool TraceDecrementBusyCountIsEnabled() 
        {
            return TD.DecrementBusyCountIsEnabled();
        }
        public override void TraceIncrementBusyCount(string data) 
        {
            if (data == null) 
            { 
                data = SR.DefaultBusyCountSource;
            } 
            TD.IncrementBusyCount(data);
        }

        public override void TraceDecrementBusyCount(string data) 
        {
            if (data == null) 
            { 
                data = SR.DefaultBusyCountSource;
            } 
            TD.DecrementBusyCount(data);
        }

        public override object GetConfigurationSection(string sectionPath) 
        {
            return GetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath); 
        } 

        [Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeGetSectionFromWebConfigurationManager which elevates.")] 
        [SecurityCritical]
        public override object UnsafeGetConfigurationSection(string sectionPath)
        {
            return UnsafeGetSectionFromWebConfigurationManager(sectionPath, ServiceHostingEnvironment.FullVirtualPath); 
        }
 
        public override AuthenticationSchemes GetAuthenticationSchemes(Uri baseAddress) 
        {
            string fileName = VirtualPathUtility.GetFileName(baseAddress.AbsolutePath); 
            string virtualPath = ServiceHostingEnvironment.CurrentVirtualPath;
            string completePath;
            if (virtualPath != null && virtualPath.EndsWith("/", StringComparison.Ordinal))
            { 
                completePath = virtualPath + fileName;
            } 
            else 
            {
                completePath = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", virtualPath, fileName); 
            }
            AuthenticationSchemes supportedSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(completePath);

            if (ServiceHostingEnvironment.IsSimpleApplicationHost) 
            {
                // Cassini always reports the auth scheme as anonymous or Ntlm. Map this to Ntlm, except when forms auth 
                // is requested 
                if (supportedSchemes == (AuthenticationSchemes.Anonymous | AuthenticationSchemes.Ntlm))
                { 
                    if (IsWindowsAuthenticationConfigured())
                    {
                        supportedSchemes = AuthenticationSchemes.Ntlm;
                    } 
                    else
                    { 
                        supportedSchemes = AuthenticationSchemes.Anonymous; 
                    }
                } 
            }

            return supportedSchemes;
        } 

        [Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.", 
             Safe = "Doesn't leak config objects out of SecurityCritical code.")] 
        [SecuritySafeCritical]
        [MethodImpl(MethodImplOptions.NoInlining)] 
        bool IsWindowsAuthenticationConfigured()
        {
            if (!this.isWindowsAuthentication.HasValue)
            { 
                AuthenticationSection authSection = (AuthenticationSection)UnsafeGetConfigurationSection("system.web/authentication");
                if (authSection != null) 
                { 
                    this.isWindowsAuthentication = (authSection.Mode == AuthenticationMode.Windows);
                } 
                else
                {
                    this.isWindowsAuthentication = false;
                } 
            }
 
            return this.isWindowsAuthentication.Value; 
        }
 
        /// Be sure to update UnsafeGetSectionFromWebConfigurationManager if you modify this method
        [MethodImpl(MethodImplOptions.NoInlining)]
        static object GetSectionFromWebConfigurationManager(string sectionPath, string virtualPath)
        { 
            if (virtualPath != null)
            { 
                return WebConfigurationManager.GetSection(sectionPath, virtualPath); 
            }
            else 
            {
                return WebConfigurationManager.GetSection(sectionPath);
            }
        } 

        // Be sure to update GetSectionFromWebConfigurationManager if you modify this method 
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "This is from an internal helper class and users have no way to pass arbitrary information to this code.")] 
        [Fx.Tag.SecurityNote(Critical = "Asserts ConfigurationPermission in order to fetch config from WebConfigurationManager,"
            + "caller must guard return value.")] 
        [SecurityCritical]
        [ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
        [MethodImpl(MethodImplOptions.NoInlining)]
        internal static object UnsafeGetSectionFromWebConfigurationManager(string sectionPath, string virtualPath) 
        {
            if (virtualPath != null) 
            { 
                return WebConfigurationManager.GetSection(sectionPath, virtualPath);
            } 
            else
            {
                return WebConfigurationManager.GetSection(sectionPath);
            } 
        }
 
 
        // This class is intended to be empty.
        class HostedMetadataBindingParameter 
        {
        }

        class ReceiveContextBusyCountWrapper : ReceiveContext 
        {
            ReceiveContext wrappedContext; 
            //possible values are 0 and 1. 
            //using an integer to allow usage with Interlocked methods
            //synchronized access needed as there could be ---- between calls 
            //to EndComplete and Tx notification.
            int busyCount;
            //possible values are 0 and 1
            //using an integer to allow usage with Interlocked methods 
            //synchronized access needed as there could be ---- between calls
            //to EndComplete and Tx Status notification. 
            int ambientTransactionCount; 

            internal ReceiveContextBusyCountWrapper(ReceiveContext context) 
            {
                this.wrappedContext = context;
                this.wrappedContext.Faulted += new EventHandler(OnWrappedContextFaulted);
                AspNetEnvironment.Current.IncrementBusyCount(); 
                if (AspNetEnvironment.Current.TraceIncrementBusyCountIsEnabled())
                { 
                    AspNetEnvironment.Current.TraceIncrementBusyCount(this.GetType().FullName); 
                }
                Interlocked.Increment(ref busyCount); 
            }

            protected override void OnAbandon(TimeSpan timeout)
            { 
                this.wrappedContext.Abandon(timeout);
                DecrementBusyCount(); 
            } 

            protected override IAsyncResult OnBeginAbandon(TimeSpan timeout, AsyncCallback callback, object state) 
            {
                return this.wrappedContext.BeginAbandon(timeout, callback, state);
            }
 
            protected override IAsyncResult OnBeginComplete(TimeSpan timeout, AsyncCallback callback, object state)
            { 
                RegisterForTransactionNotification(Transaction.Current); 
                return this.wrappedContext.BeginComplete(timeout, callback, state);
            } 

            protected override void OnComplete(TimeSpan timeout)
            {
                RegisterForTransactionNotification(Transaction.Current); 
                this.wrappedContext.Complete(timeout);
                DecrementOnNoAmbientTransaction(); 
 
            }
 
            protected override void OnEndAbandon(IAsyncResult result)
            {
                this.wrappedContext.EndAbandon(result);
                DecrementBusyCount(); 
            }
 
            protected override void OnEndComplete(IAsyncResult result) 
            {
                this.wrappedContext.EndComplete(result); 
                DecrementOnNoAmbientTransaction();
            }

            protected override void OnFaulted() 
            {
                try 
                { 
                    this.wrappedContext.Fault();
                } 
                finally
                {
                    base.OnFaulted();
                } 
            }
 
            void OnWrappedContextFaulted(object sender, EventArgs e) 
            {
                try 
                {
                    Fault();
                }
                finally 
                {
                    DecrementBusyCount(); 
                } 
            }
 
            void RegisterForTransactionNotification(Transaction transaction)
            {
                if (Transaction.Current != null)
                { 
                    ReceiveContextEnlistmentNotification notification = new ReceiveContextEnlistmentNotification(this);
                    transaction.EnlistVolatile(notification, EnlistmentOptions.None); 
                    Interlocked.Increment(ref this.ambientTransactionCount); 
                }
            } 

            void DecrementOnNoAmbientTransaction()
            {
                if (Interlocked.Exchange(ref this.ambientTransactionCount, 0) != 1) 
                {
                    DecrementBusyCount(); 
                } 

            } 

            void DecrementBusyCount()
            {
                if (Interlocked.Exchange(ref this.busyCount, 0) == 1) 
                {
                    AspNetEnvironment.Current.DecrementBusyCount(); 
                    if (AspNetEnvironment.Current.TraceDecrementBusyCountIsEnabled()) 
                    {
                        AspNetEnvironment.Current.TraceDecrementBusyCount(this.GetType().FullName); 
                    }
                }
            }
 
            class ReceiveContextEnlistmentNotification : IEnlistmentNotification
            { 
                ReceiveContextBusyCountWrapper context; 

                internal ReceiveContextEnlistmentNotification(ReceiveContextBusyCountWrapper context) 
                {
                    this.context = context;
                }
 
                public void Commit(Enlistment enlistment)
                { 
                    this.context.DecrementBusyCount(); 
                    enlistment.Done();
                } 

                public void InDoubt(Enlistment enlistment)
                {
                    this.context.DecrementBusyCount(); 
                    enlistment.Done();
                } 
 
                public void Prepare(PreparingEnlistment preparingEnlistment)
                { 
                    preparingEnlistment.Prepared();
                }

                public void Rollback(Enlistment enlistment) 
                {
                    enlistment.Done(); 
                } 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK