CachingParameterInspector.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 / NetFx35 / System.ServiceModel.Web / System / ServiceModel / Web / CachingParameterInspector.cs / 1305376 / CachingParameterInspector.cs

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

using System.Collections.Generic; 
using System.Diagnostics;
using System.Runtime; 
using System.Runtime.Serialization; 
using System.Security;
using System.ServiceModel; 
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Dispatcher;
using System.Web; 
using System.Web.Caching;
using System.Web.Configuration; 
using System.Web.UI; 
using System.ServiceModel.Activation;
 
namespace System.ServiceModel.Web
{
    class CachingParameterInspector : IParameterInspector
    { 
        const char seperatorChar = ';';
        const char escapeChar = '\\'; 
        const char tableDbSeperatorChar = ':'; 
        const string invalidSqlDependencyString = "Invalid Sql dependency string.";
 
        [Fx.Tag.SecurityNote(Critical = "A config object, which should not be leaked.")]
        [SecurityCritical]
        OutputCacheProfile cacheProfile;
 
        SqlDependencyInfo[] cacheDependencyInfoArray;
 
        [Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.", 
            Safe="The config object never leaves the CachingParameterInspector.")]
        [SecuritySafeCritical] 
        public CachingParameterInspector(string cacheProfileName)
        {
            if (string.IsNullOrEmpty(cacheProfileName))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.CacheProfileNameNullOrEmpty));
            } 
 
            OutputCacheSettingsSection cacheSettings = AspNetEnvironment.Current.UnsafeGetConfigurationSection("system.web/caching/outputCacheSettings") as OutputCacheSettingsSection;
            if (cacheSettings == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileNotConfigured, cacheProfileName)));
            }
 
            this.cacheProfile = cacheSettings.OutputCacheProfiles[cacheProfileName];
            if (this.cacheProfile == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileNotConfigured, cacheProfileName)));
            } 

            // Validate the cacheProfile
            if (this.cacheProfile.Location != OutputCacheLocation.None)
            { 
                // Duration must be set; Duration default value is -1
                if (this.cacheProfile.Duration == -1) 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileValueMissing, this.cacheProfile.Name, "Duration")));
                } 
                if (this.cacheProfile.VaryByParam == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileValueMissing, this.cacheProfile.Name, "VaryByParam")));
                } 
            }
 
            if (string.Equals(this.cacheProfile.SqlDependency, "CommandNotification", StringComparison.OrdinalIgnoreCase)) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.CommandNotificationSqlDependencyNotSupported)); 
            }

            if (!string.IsNullOrEmpty(this.cacheProfile.SqlDependency))
            { 
                ParseSqlDependencyString(cacheProfile.SqlDependency);
            } 
        } 

        [Fx.Tag.SecurityNote(Critical = "Handles config objects, which should not be leaked.", 
            Safe = "The config object never leaves the CachingParameterInspector.")]
        [SecuritySafeCritical]
        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        { 
            if (this.cacheProfile != null &&
                this.cacheProfile.Enabled && 
                OperationContext.Current.IncomingMessage.Version == MessageVersion.None) 
            {
                if (DiagnosticUtility.ShouldTraceWarning && !IsAnonymous()) 
                {
                    TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AddingAuthenticatedResponseToOutputCache, SR2.GetString(SR2.TraceCodeAddingAuthenticatedResponseToOutputCache, operationName));
                }
                else if (DiagnosticUtility.ShouldTraceInformation) 
                {
                    TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AddingResponseToOutputCache, SR2.GetString(SR2.TraceCodeAddingResponseToOutputCache, operationName)); 
                } 

                SetCacheFromCacheProfile(); 
            }
        }

        public object BeforeCall(string operationName, object[] inputs) 
        {
            return null; 
        } 

        bool IsAnonymous() 
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                return false; 
            }
            else 
            { 
                if (OperationContext.Current.ServiceSecurityContext == null)
                { 
                    return true;
                }
                else
                { 
                    return OperationContext.Current.ServiceSecurityContext.IsAnonymous;
                } 
            } 
        }
 
        static SqlDependencyInfo[] ParseSqlDependencyString(string sqlDependencyString)
        {
            // The code for this method was taken from private code in
            // System.Web.SqlCacheDependency.ParseSql7OutputCacheDependency. 
            // Alter if only absolutely necessary since we want to reproduce the same ASP.NET caching behavior.
 
            List dependencyList = new List(); 
            bool escapeSequenceFlag = false;
            int startIndexForDatabaseName = 0; 
            int startIndexForTableName = -1;
            string databaseName = null;

            try 
            {
                for (int currentIndex = 0; currentIndex < (sqlDependencyString.Length + 1); currentIndex++) 
                { 
                    if (escapeSequenceFlag)
                    { 
                        escapeSequenceFlag = false;
                    }
                    else if ((currentIndex != sqlDependencyString.Length) &&
                             (sqlDependencyString[currentIndex] == escapeChar)) 
                    {
                        escapeSequenceFlag = true; 
                    } 
                    else
                    { 
                        int subStringLength;
                        if ((currentIndex == sqlDependencyString.Length) ||
                            (sqlDependencyString[currentIndex] == seperatorChar))
                        { 
                            if (databaseName == null)
                            { 
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString); 
                            }
                            subStringLength = currentIndex - startIndexForTableName; 
                            if (subStringLength == 0)
                            {
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString);
                            } 
                            string tableName = sqlDependencyString.Substring(startIndexForTableName, subStringLength);
                            SqlDependencyInfo info = new SqlDependencyInfo(); 
                            info.Database = VerifyAndRemoveEscapeCharacters(databaseName); 
                            info.Table = VerifyAndRemoveEscapeCharacters(tableName);
                            dependencyList.Add(info); 
                            startIndexForDatabaseName = currentIndex + 1;
                            databaseName = null;
                        }
                        if (currentIndex == sqlDependencyString.Length) 
                        {
                            break; 
                        } 
                        if (sqlDependencyString[currentIndex] == tableDbSeperatorChar)
                        { 
                            if (databaseName != null)
                            {
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString);
                            } 
                            subStringLength = currentIndex - startIndexForDatabaseName;
                            if (subStringLength == 0) 
                            { 
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(invalidSqlDependencyString);
                            } 
                            databaseName = sqlDependencyString.Substring(startIndexForDatabaseName, subStringLength);
                            startIndexForTableName = currentIndex + 1;
                        }
                    } 
                }
            } 
            catch (ArgumentException) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileSqlDependencyIsInvalid, sqlDependencyString))); 
            }
            if (dependencyList.Count == 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.CacheProfileSqlDependencyIsInvalid, sqlDependencyString))); 
            }
            return dependencyList.ToArray(); 
        } 

        static string VerifyAndRemoveEscapeCharacters(string str) 
        {
            // The code for this method was taken from private code in
            // System.Web.SqlCacheDependency.VerifyAndRemoveEscapeCharacters.
            // Alter if only absolutely necessary since we want to reproduce the same ASP.NET caching behavior. 

            bool escapeSequenceFlag = false; 
            for (int currentIndex = 0; currentIndex < str.Length; currentIndex++) 
            {
                if (escapeSequenceFlag) 
                {
                    if (((str[currentIndex] != escapeChar) &&
                         (str[currentIndex] != tableDbSeperatorChar)) &&
                         (str[currentIndex] != seperatorChar)) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(str); 
                    } 
                    escapeSequenceFlag = false;
                } 
                else if (str[currentIndex] == escapeChar)
                {
                    if ((currentIndex + 1) == str.Length)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(str);
                    } 
                    escapeSequenceFlag = true; 
                    str = str.Remove(currentIndex, 1);
                    currentIndex--; 
                }
            }
            return str;
        } 

        CacheDependency CreateSingleCacheDependency(string sqlDependency) 
        { 
            if (this.cacheDependencyInfoArray == null)
            { 
                this.cacheDependencyInfoArray = CachingParameterInspector.ParseSqlDependencyString(sqlDependency);
            }

            // cacheDependencyInfoArray will never have length = 0 

            if (this.cacheDependencyInfoArray.Length == 1) 
            { 
                return new SqlCacheDependency(this.cacheDependencyInfoArray[0].Database, this.cacheDependencyInfoArray[0].Table);
            } 

            AggregateCacheDependency cacheDependency = new AggregateCacheDependency();
            foreach (SqlDependencyInfo dependencyInfo in this.cacheDependencyInfoArray)
            { 
                cacheDependency.Add(new CacheDependency[] { new SqlCacheDependency(dependencyInfo.Database, dependencyInfo.Table) });
            } 
            return cacheDependency; 
        }
 
        [Fx.Tag.SecurityNote(Critical = "Uses config object to set properties of the HttpCachePolicy.",
            Safe = "The config object itself doesn't leak.")]
        [SecuritySafeCritical]
        void SetCacheFromCacheProfile() 
        {
            HttpCachePolicy cache = HttpContext.Current.Response.Cache; 
 
            if (this.cacheProfile.NoStore)
            { 
                cache.SetNoStore();
            }

            // Location is not required to be set in the config.  The default is Any, 
            // but if it is not set in the config the value will be -1.  So must correct for this.
            if ((int)(this.cacheProfile.Location) == -1) 
            { 
                cache.SetCacheability(HttpCacheability.Public);
            } 
            else
            {
                switch (this.cacheProfile.Location)
                { 
                    case OutputCacheLocation.Any:
                        cache.SetCacheability(HttpCacheability.Public); 
                        break; 
                    case OutputCacheLocation.Client:
                        cache.SetCacheability(HttpCacheability.Private); 
                        break;
                    case OutputCacheLocation.Downstream:
                        cache.SetCacheability(HttpCacheability.Public);
                        cache.SetNoServerCaching(); 
                        break;
                    case OutputCacheLocation.None: 
                        cache.SetCacheability(HttpCacheability.NoCache); 
                        break;
                    case OutputCacheLocation.Server: 
                        cache.SetCacheability(HttpCacheability.ServerAndNoCache);
                        break;
                    case OutputCacheLocation.ServerAndClient:
                        cache.SetCacheability(HttpCacheability.ServerAndPrivate); 
                        break;
                    default: 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.CacheProfileLocationNotSupported, this.cacheProfile.Location))); 
                }
            } 

            if (this.cacheProfile.Location != OutputCacheLocation.None)
            {
                cache.SetExpires(HttpContext.Current.Timestamp.AddSeconds((double)this.cacheProfile.Duration)); 
                cache.SetMaxAge(new TimeSpan(0, 0, this.cacheProfile.Duration));
                cache.SetValidUntilExpires(true); 
                cache.SetLastModified(HttpContext.Current.Timestamp); 

                if (this.cacheProfile.Location != OutputCacheLocation.Client) 
                {
                    if (!string.IsNullOrEmpty(this.cacheProfile.VaryByContentEncoding))
                    {
                        foreach (string contentEncoding in this.cacheProfile.VaryByContentEncoding.Split(seperatorChar)) 
                        {
                            cache.VaryByContentEncodings[contentEncoding.Trim()] = true; 
                        } 
                    }
 
                    if (!string.IsNullOrEmpty(this.cacheProfile.VaryByHeader))
                    {
                        foreach (string header in this.cacheProfile.VaryByHeader.Split(seperatorChar))
                        { 
                            cache.VaryByHeaders[header.Trim()] = true;
                        } 
                    } 

                    if (this.cacheProfile.Location != OutputCacheLocation.Downstream) 
                    {
                        if (!string.IsNullOrEmpty(this.cacheProfile.VaryByCustom))
                        {
                            cache.SetVaryByCustom(this.cacheProfile.VaryByCustom); 
                        }
 
                        if (!string.IsNullOrEmpty(this.cacheProfile.VaryByParam)) 
                        {
                            foreach (string parameter in cacheProfile.VaryByParam.Split(seperatorChar)) 
                            {
                                cache.VaryByParams[parameter.Trim()] = true;
                            }
                        } 

                        if (!string.IsNullOrEmpty(this.cacheProfile.SqlDependency)) 
                        { 
                           CacheDependency cacheDependency = this.CreateSingleCacheDependency(cacheProfile.SqlDependency);
                           HttpContext.Current.Response.AddCacheDependency(new CacheDependency[] { cacheDependency }); 
                        }
                    }
                }
            } 
        }
 
        private struct SqlDependencyInfo 
        {
            public string Database; 
            public string Table;
        }

    } 
}

// 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