TransactionValidationBehavior.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Dispatcher / TransactionValidationBehavior.cs / 1 / TransactionValidationBehavior.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{ 
    using System.Collections.ObjectModel;
    using System.ServiceModel.Channels; 
    using System.ServiceModel; 
    using System.ServiceModel.Description;
    using System.Collections.Generic; 
    using System.Runtime.CompilerServices;
    using System.ServiceModel.Transactions;

    class TransactionValidationBehavior : IEndpointBehavior, IServiceBehavior 
    {
        static TransactionValidationBehavior instance; 
 
        internal static TransactionValidationBehavior Instance
        { 
            get
            {
                if (instance == null)
                    instance = new TransactionValidationBehavior(); 
                return instance;
            } 
        } 

        TransactionValidationBehavior() {} 

        void ValidateTransactionFlowRequired(string resource, string name, ServiceEndpoint endpoint)
        {
            bool anOperationRequiresTxFlow = false; 
            for (int i = 0; i < endpoint.Contract.Operations.Count; i++)
            { 
                OperationDescription operationDescription = endpoint.Contract.Operations[i]; 
                TransactionFlowAttribute transactionFlow = operationDescription.Behaviors.Find();
                if (transactionFlow != null && transactionFlow.Transactions == TransactionFlowOption.Mandatory) 
                {
                    anOperationRequiresTxFlow = true;
                    break;
                } 
            }
 
            if (anOperationRequiresTxFlow) 
            {
                CustomBinding binding = new CustomBinding(endpoint.Binding); 
                TransactionFlowBindingElement transactionFlowBindingElement =
                                              binding.Elements.Find();

                if (transactionFlowBindingElement == null || !transactionFlowBindingElement.Transactions) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        String.Format(Globalization.CultureInfo.CurrentCulture, SR.GetString(resource), name, binding.Name))); 
                }
            } 
        }

        void IEndpointBehavior.Validate(ServiceEndpoint serviceEndpoint)
        { 
            if (serviceEndpoint == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceEndpoint"); 
            ValidateTransactionFlowRequired(SR.ChannelHasAtLeastOneOperationWithTransactionFlowEnabled, 
                           serviceEndpoint.Contract.Name,
                           serviceEndpoint); 
            EnsureNoOneWayTransactions(serviceEndpoint);
            ValidateNoMSMQandTransactionFlow(serviceEndpoint);
            ValidateCallbackBehaviorAttributeWithNoScopeRequired(serviceEndpoint);
            OperationDescription autoCompleteFalseOperation = GetAutoCompleteFalseOperation(serviceEndpoint); 
            if(autoCompleteFalseOperation != null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                    SR.GetString(SR.SFxTransactionAutoCompleteFalseOnCallbackContract, autoCompleteFalseOperation.Name, serviceEndpoint.Contract.Name)));
            } 

        }

        void ValidateCallbackBehaviorAttributeWithNoScopeRequired(ServiceEndpoint endpoint) 
        {
            // If the endpoint has no operations with TransactionScopeRequired=true, disallow any 
            // transaction-related properties on the CallbackBehaviorAttribute 
            if (!HasTransactedOperations(endpoint))
            { 
                CallbackBehaviorAttribute attribute = endpoint.Behaviors.Find();
                if (attribute != null)
                {
                    if (attribute.TransactionTimeoutSet) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                            SR.GetString(SR.SFxTransactionTransactionTimeoutNeedsScope, endpoint.Contract.Name))); 
                    }
 
                    if (attribute.IsolationLevelSet)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                            SR.GetString(SR.SFxTransactionIsolationLevelNeedsScope, endpoint.Contract.Name))); 
                    }
                } 
            } 
        }
 
        void IEndpointBehavior.AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters)
        {
        }
 
        void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
        { 
        } 

        void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior) 
        {
        }

        void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection parameters) 
        {
        } 
 
        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription service, ServiceHostBase serviceHostBase)
        { 
        }

        void IServiceBehavior.Validate(ServiceDescription service, ServiceHostBase serviceHostBase)
        { 
            if (service == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("service"); 
 
            ValidateNotConcurrentWhenReleaseServiceInstanceOnTxComplete(service);
            bool singleThreaded = IsSingleThreaded(service); 

            for (int i = 0; i < service.Endpoints.Count; i++)
            {
                ServiceEndpoint endpoint = service.Endpoints[i]; 

                ValidateTransactionFlowRequired(SR.ServiceHasAtLeastOneOperationWithTransactionFlowEnabled, 
                               service.Name, 
                               endpoint);
                EnsureNoOneWayTransactions(endpoint); 
                ValidateNoMSMQandTransactionFlow(endpoint);

                ContractDescription contract = endpoint.Contract;
                for (int j = 0; j < contract.Operations.Count; j++) 
                {
                    OperationDescription operation = contract.Operations[j]; 
                    ValidateScopeRequiredAndAutoComplete(operation, singleThreaded, contract.Name); 
                }
 
                ValidateAutoCompleteFalseRequirements(service, endpoint);
            }

            ValidateServiceBehaviorAttributeWithNoScopeRequired(service); 
            ValidateTransactionAutoCompleteOnSessionCloseHasSession(service);
        } 
 

        void ValidateAutoCompleteFalseRequirements(ServiceDescription service, ServiceEndpoint endpoint) 
        {
            OperationDescription autoCompleteFalseOperation = GetAutoCompleteFalseOperation(endpoint);

            if (autoCompleteFalseOperation != null) 
            {
                // Does the service have InstanceContextMode.PerSession or Shareable? 
                ServiceBehaviorAttribute serviceBehavior = service.Behaviors.Find(); 
                if (serviceBehavior != null)
                { 
                    InstanceContextMode instanceMode = serviceBehavior.InstanceContextMode;
                    if (instanceMode != InstanceContextMode.PerSession)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                            SR.GetString(SR.SFxTransactionAutoCompleteFalseAndInstanceContextMode,
                            endpoint.Contract.Name, autoCompleteFalseOperation.Name))); 
                    } 
                }
 
                // Does the binding support sessions?
                if (!RequiresSessions(endpoint))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(SR.SFxTransactionAutoCompleteFalseAndSupportsSession,
                        endpoint.Contract.Name, autoCompleteFalseOperation.Name))); 
                } 
            }
        } 

        OperationDescription GetAutoCompleteFalseOperation(ServiceEndpoint endpoint)
        {
            foreach (OperationDescription operation in endpoint.Contract.Operations) 
            {
                if (!IsAutoComplete(operation)) 
                { 
                    return operation;
                } 
            }
            return null;
        }
 
        void ValidateTransactionAutoCompleteOnSessionCloseHasSession(ServiceDescription service)
        { 
            ServiceBehaviorAttribute serviceBehavior = service.Behaviors.Find(); 

            if (serviceBehavior != null) 
            {
                InstanceContextMode instanceMode = serviceBehavior.InstanceContextMode;
                if (serviceBehavior.TransactionAutoCompleteOnSessionClose&&
                    instanceMode != InstanceContextMode.PerSession) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(SR.SFxTransactionAutoCompleteOnSessionCloseNoSession, service.Name))); 
                }
            } 

        }

 
        void ValidateServiceBehaviorAttributeWithNoScopeRequired(ServiceDescription service)
        { 
            // If the service has no operations with TransactionScopeRequired=true, disallow any 
            // transaction-related properties on the ServiceBehaviorAttribute
            if (!HasTransactedOperations(service)) 
            {
                ServiceBehaviorAttribute attribute = service.Behaviors.Find();
                if (attribute != null)
                { 
                    if (attribute.TransactionTimeoutSet)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                            SR.GetString(SR.SFxTransactionTransactionTimeoutNeedsScope, service.Name)));
                    } 

                    if (attribute.IsolationLevelSet)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                            SR.GetString(SR.SFxTransactionIsolationLevelNeedsScope, service.Name)));
                    } 
 
                    if (attribute.ReleaseServiceInstanceOnTransactionCompleteSet)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                            SR.GetString(SR.SFxTransactionReleaseServiceInstanceOnTransactionCompleteNeedsScope, service.Name)));
                    }
 
                    if (attribute.TransactionAutoCompleteOnSessionCloseSet)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                            SR.GetString(SR.SFxTransactionTransactionAutoCompleteOnSessionCloseNeedsScope, service.Name)));
                    } 
                }
            }
        }
 
        void EnsureNoOneWayTransactions(ServiceEndpoint endpoint)
        { 
            CustomBinding binding = new CustomBinding(endpoint.Binding); 
            TransactionFlowBindingElement txFlowBindingElement = binding.Elements.Find();
            if (txFlowBindingElement != null) 
            {
                for (int i = 0; i < endpoint.Contract.Operations.Count; i++)
                {
                    OperationDescription operation = endpoint.Contract.Operations[i]; 
                    if (operation.IsOneWay)
                    { 
                        TransactionFlowAttribute tfbp = operation.Behaviors.Find(); 
                        TransactionFlowOption transactions;
                        if (tfbp != null) 
                        {
                            transactions = tfbp.Transactions;
                        }
                        else 
                        {
                            transactions = TransactionFlowOption.NotAllowed; 
                        } 
                        if (TransactionFlowOptionHelper.AllowedOrRequired(transactions))
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                                SR.GetString(SR.SFxOneWayAndTransactionsIncompatible, endpoint.Contract.Name, operation.Name)));
                        }
                    } 
                }
            } 
        } 

        bool HasTransactedOperations(ServiceDescription service) 
        {
            for (int i = 0; i < service.Endpoints.Count; i++)
            {
                if(HasTransactedOperations(service.Endpoints[i])) 
                {
                    return true; 
                } 
            }
            return false; 
        }

        bool HasTransactedOperations(ServiceEndpoint endpoint)
        { 
            for (int j = 0; j < endpoint.Contract.Operations.Count; j++)
            { 
                OperationDescription operation = endpoint.Contract.Operations[j]; 
                OperationBehaviorAttribute attribute = operation.Behaviors.Find();
 
                if (attribute != null && attribute.TransactionScopeRequired)
                {
                    return true;
                } 
            }
            return false; 
        } 

        bool IsSingleThreaded(ServiceDescription service) 
        {
            ServiceBehaviorAttribute attribute = service.Behaviors.Find();

            if (attribute != null) 
            {
                return (attribute.ConcurrencyMode == ConcurrencyMode.Single); 
            } 

            // The default is ConcurrencyMode.Single 
            return true;
        }

        bool IsAutoComplete(OperationDescription operation) 
        {
            OperationBehaviorAttribute attribute = operation.Behaviors.Find(); 
 
            if (attribute != null)
            { 
                return attribute.TransactionAutoComplete;
            }

            // The default is TransactionAutoComplete=true 
            return true;
        } 
 
        bool RequiresSessions(ServiceEndpoint endpoint)
        { 
            return endpoint.Contract.SessionMode == SessionMode.Required;
        }

        void ValidateScopeRequiredAndAutoComplete(OperationDescription operation, 
                                                  bool singleThreaded,
                                                  string contractName) 
        { 
            OperationBehaviorAttribute attribute = operation.Behaviors.Find();
 
            if (attribute != null)
            {
                if (!attribute.TransactionScopeRequired && !attribute.TransactionAutoComplete)
                { 
                    string id = SR.SFxTransactionAutoEnlistOrAutoComplete2;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(id, contractName, operation.Name))); 
                }
 
                if (!singleThreaded && !attribute.TransactionAutoComplete)
                {
                    string id = SR.SFxTransactionNonConcurrentOrAutoComplete2;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(id, contractName, operation.Name)));
                } 
            } 
        }
 
        void ValidateNoMSMQandTransactionFlow(ServiceEndpoint endpoint)
        {
            BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements();
 
            if(bindingElements.Find() != null &&
                bindingElements.Find() != null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                        SR.GetString(SR.SFxTransactionFlowAndMSMQ, endpoint.Address.Uri.AbsoluteUri))); 
            }
        }

        void ValidateNotConcurrentWhenReleaseServiceInstanceOnTxComplete(ServiceDescription service) 
        {
            ServiceBehaviorAttribute attribute = service.Behaviors.Find(); 
 
            if (attribute != null && HasTransactedOperations(service))
            { 
                if (attribute.ReleaseServiceInstanceOnTransactionComplete && !IsSingleThreaded(service))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR.GetString( 
                            SR.SFxTransactionNonConcurrentOrReleaseServiceInstanceOnTxComplete, service.Name)));
                } 
 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

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