PartialCachingControl.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / xsp / System / Web / UI / PartialCachingControl.cs / 1 / PartialCachingControl.cs

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

namespace System.Web.UI { 
 
using System;
using System.IO; 
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel; 
using System.ComponentModel.Design;
using System.Globalization; 
using System.Web; 
using System.Web.Util;
using System.Web.UI.HtmlControls; 
using System.Web.UI.WebControls;
using System.Web.Caching;
using System.Web.Compilation;
using System.Web.Configuration; 
using System.Security.Permissions;
 
 
/// 
///    [To be supplied.] 
/// 
[
ToolboxItem(false)
] 
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
public abstract class BasePartialCachingControl : Control { 

    internal Control _cachedCtrl; 
    private long _nonVaryHashCode;
    internal string _ctrlID;
    internal string _guid;
    internal DateTime _utcExpirationTime; 
    internal bool _useSlidingExpiration;
    internal HttpCacheVaryByParams _varyByParamsCollection; 
    internal string[] _varyByControlsCollection; 
    internal string _varyByCustom;
    internal string _sqlDependency; 
    internal bool _cachingDisabled;
    private string _outputString;
    private string _cssStyleString;
    private string _cacheKey; 
    private CacheDependency _cacheDependency;
    private PartialCachingCacheEntry _cacheEntry; 
    private ControlCachePolicy _cachePolicy; 
    private ArrayList _registeredCallDataForEventValidation;
    private ArrayList _registeredStyleInfo = null; 

    internal const char varySeparator = ';';
    internal const string varySeparatorString = ";";
 
    // Keeps track of one call to Page Register* API
    // The semantics of the fields depends to the call type 
    class RegisterCallData { 
        internal ClientAPIRegisterType Type;
        internal ScriptKey Key; 
        internal string StringParam1;
        internal string StringParam2;
        internal string StringParam3;
    } 

    // Data that we need to cache 
    class PartialCachingCacheEntry { 
        internal string OutputString;
        internal string CssStyleString; 
        internal ArrayList RegisteredClientCalls;
    }

    internal override void InitRecursive(Control namingContainer) { 

        HashCodeCombiner combinedHashCode = new HashCodeCombiner(); 
 
        _cacheKey = ComputeNonVaryCacheKey(combinedHashCode);
 
        // Save the non-varying hash, so we don't need to recalculate it later
        _nonVaryHashCode = combinedHashCode.CombinedHash;

        PartialCachingCacheEntry cacheEntry = null; 

        // Check if there is a cache entry for the non-varying key 
        object tmpCacheEntry = HttpRuntime.CacheInternal.Get(_cacheKey); 

        if (tmpCacheEntry != null) { 
            ControlCachedVary cachedVary = tmpCacheEntry as ControlCachedVary;
            if (cachedVary != null) {
                string varyCachedKey = ComputeVaryCacheKey(combinedHashCode, cachedVary);
 
                // Check if there is a cache entry for the varying key
                cacheEntry = (PartialCachingCacheEntry) HttpRuntime.CacheInternal.Get(varyCachedKey); 
            } 
            else {
                // If it wasn't a ControlCachedVary, it must be a PartialCachingCacheEntry 
                cacheEntry = (PartialCachingCacheEntry) tmpCacheEntry;
            }
        }
 
        // If it's a cache miss, create the control and make it our child
        if (cacheEntry == null) { 
 
            // Cache miss
 
            _cacheEntry = new PartialCachingCacheEntry();

            _cachedCtrl = CreateCachedControl();
            Controls.Add(_cachedCtrl); 

            // Make sure the Page knows about us while the control's OnInit is called 
            Page.PushCachingControl(this); 
            base.InitRecursive(namingContainer);
            Page.PopCachingControl(); 
        }
        else {

            // Cache hit 

            _outputString = cacheEntry.OutputString; 
            _cssStyleString = cacheEntry.CssStyleString; 

            // If any calls to Register* API's were made when the control was run, 
            // make them now to restore correct behavior (VSWhidbey 80907)
            if (cacheEntry.RegisteredClientCalls != null) {
                foreach (RegisterCallData registerCallData in cacheEntry.RegisteredClientCalls) {
                    switch (registerCallData.Type) { 

                        case ClientAPIRegisterType.WebFormsScript: 
                            Page.RegisterWebFormsScript(); 
                            break;
 
                        case ClientAPIRegisterType.PostBackScript:
                            Page.RegisterPostBackScript();
                            break;
 
                        case ClientAPIRegisterType.FocusScript:
                            Page.RegisterFocusScript(); 
                            break; 

                        case ClientAPIRegisterType.ClientScriptBlocks: 
                        case ClientAPIRegisterType.ClientScriptBlocksWithoutTags:
                        case ClientAPIRegisterType.ClientStartupScripts:
                        case ClientAPIRegisterType.ClientStartupScriptsWithoutTags:
                            Page.ClientScript.RegisterScriptBlock(registerCallData.Key, 
                                registerCallData.StringParam2, registerCallData.Type);
                            break; 
 
                        case ClientAPIRegisterType.OnSubmitStatement:
                            Page.ClientScript.RegisterOnSubmitStatementInternal(registerCallData.Key, 
                                registerCallData.StringParam2);
                            break;

                        case ClientAPIRegisterType.ArrayDeclaration: 
                            Page.ClientScript.RegisterArrayDeclaration(registerCallData.StringParam1,
                                registerCallData.StringParam2); 
                            break; 

                        case ClientAPIRegisterType.HiddenField: 
                            Page.ClientScript.RegisterHiddenField(registerCallData.StringParam1,
                                registerCallData.StringParam2);
                            break;
 
                        case ClientAPIRegisterType.ExpandoAttribute:
                            Page.ClientScript.RegisterExpandoAttribute(registerCallData.StringParam1, 
                                registerCallData.StringParam2, registerCallData.StringParam3, false); 
                            break;
 
                        case ClientAPIRegisterType.EventValidation:
                            if (_registeredCallDataForEventValidation == null) {
                                _registeredCallDataForEventValidation = new ArrayList();
                            } 

                            _registeredCallDataForEventValidation.Add(registerCallData); 
                            break; 
                        default:
                            Debug.Assert(false); 
                            break;
                    }
                }
            } 

            base.InitRecursive(namingContainer); 
        } 
    }
 
    internal override void LoadRecursive() {

        // If we're in a cache hit, don't do anything special
        if (_outputString != null) { 
            base.LoadRecursive();
            return; 
        } 

        // Make sure the Page knows about us while the control's OnLoad is called 
        Page.PushCachingControl(this);
        base.LoadRecursive();
        Page.PopCachingControl();
    } 

    internal override void PreRenderRecursiveInternal() { 
 
        // If we're in a cache hit, don't do anything special
        if (_outputString != null) { 
            base.PreRenderRecursiveInternal();

            // register the cached styles on the Header control.
            if (_cssStyleString != null && Page.Header != null) { 
                Page.Header.RegisterCssStyleString(_cssStyleString);
            } 
 
            return;
        } 

        // Make sure the Page knows about us while the control's OnPreRender is called
        Page.PushCachingControl(this);
        base.PreRenderRecursiveInternal(); 
        Page.PopCachingControl();
    } 
 

    ///  
    public override void Dispose() {
        if (_cacheDependency != null) {
            _cacheDependency.Dispose();
            _cacheDependency = null; 
        }
 
        base.Dispose(); 
    }
 
    internal abstract Control CreateCachedControl();


    ///  
    ///     Gets or sets the CacheDependency used to cache the control output.
    ///  
    public CacheDependency Dependency { 
        get { return _cacheDependency; }
        set { _cacheDependency = value; } 
    }


    public ControlCachePolicy CachePolicy { 
        get {
            // Create the ControlCachePolicy object on demand 
            if (_cachePolicy == null) 
                _cachePolicy = new ControlCachePolicy(this);
 
            return _cachePolicy;
        }
    }
 
    internal HttpCacheVaryByParams VaryByParams {
        get { 
            if (_varyByParamsCollection == null) { 
                _varyByParamsCollection = new HttpCacheVaryByParams();
                _varyByParamsCollection.IgnoreParams = true; 
            }

            return _varyByParamsCollection;
        } 
    }
 
    internal string VaryByControl { 
        get {
            if (_varyByControlsCollection == null) 
                return String.Empty;

            return String.Join(varySeparatorString, _varyByControlsCollection);
        } 

        set { 
            if (String.IsNullOrEmpty(value)) { 
                _varyByControlsCollection = null;
            } 
            else {
                _varyByControlsCollection = value.Split(varySeparator);
            }
        } 
    }
 
    internal TimeSpan Duration { 
        get {
            // Special case MaxValue 
            if (_utcExpirationTime == DateTime.MaxValue)
                return TimeSpan.MaxValue;

            return _utcExpirationTime - DateTime.UtcNow; 
        }
 
        set { 
            if (value == TimeSpan.MaxValue) {
                // If it's the max timespan, just make it DateTime.MaxValue to avoid 
                // an overflow when adding (VSWhidbey 273271)
                _utcExpirationTime = DateTime.MaxValue;
            }
            else { 
                // Compute the expiration time
                _utcExpirationTime = DateTime.UtcNow.Add(value); 
            } 
        }
    } 

    private void RegisterValidationEvents() {
        if (_registeredCallDataForEventValidation != null) {
            foreach (RegisterCallData registerCallData in _registeredCallDataForEventValidation) { 
                Page.ClientScript.RegisterForEventValidation(registerCallData.StringParam1,
                    registerCallData.StringParam2); 
            } 
        }
    } 

    internal void RegisterStyleInfo(SelectorStyleInfo selectorInfo) {
        if (_registeredStyleInfo == null) {
            _registeredStyleInfo = new ArrayList(); 
        }
 
        _registeredStyleInfo.Add(selectorInfo); 
    }
 
    /// 
    /// 
    ///    [To be supplied.]
    ///  
    protected internal override void Render(HtmlTextWriter output) {
        CacheDependency sqlCacheDep = null; 
 
        // If the output is cached, use it and do nothing else
        if (_outputString != null) { 
            output.Write(_outputString);
            RegisterValidationEvents();
            return;
        } 

        // If caching was turned off, just render the control 
        if (_cachingDisabled || !RuntimeConfig.GetAppConfig().OutputCache.EnableFragmentCache) { 
            _cachedCtrl.RenderControl(output);
            return; 
        }

        // Create SQL cache dependency before we render the page
        if (_sqlDependency != null) { 
            sqlCacheDep = SqlCacheDependency.CreateOutputCacheDependency(_sqlDependency);
        } 
 
        _cacheEntry.CssStyleString = GetCssStyleRenderString(output.GetType());
 
        // Create a new HtmlTextWriter, with the same type as the current one (see ASURT 118922)
        StringWriter tmpWriter = new StringWriter();
        HtmlTextWriter tmpHtmlWriter = Page.CreateHtmlTextWriterFromType(tmpWriter, output.GetType());
        CacheDependency cacheDep; 
        TextWriter savedWriter = Context.Response.SwitchWriter(tmpWriter);
 
        try { 
            // Make sure the Page knows about us while the control's OnPreRender is called
            Page.PushCachingControl(this); 
            _cachedCtrl.RenderControl(tmpHtmlWriter);
            Page.PopCachingControl();
        }
        finally { 
            Context.Response.SwitchWriter(savedWriter);
        } 
 
        _cacheEntry.OutputString = tmpWriter.ToString();
 
        // Send the output to the response
        output.Write(_cacheEntry.OutputString);

        // Cache the output 

        cacheDep = _cacheDependency; 
 
        if (sqlCacheDep != null) {
            if (cacheDep == null) { 
                cacheDep = sqlCacheDep;
            }
            else {
                AggregateCacheDependency aggr = new AggregateCacheDependency(); 

                aggr.Add(cacheDep); 
                aggr.Add(sqlCacheDep); 
                cacheDep = aggr;
            } 
        }

        string realItemCacheKey;
 
        CacheInternal cacheInternal = HttpRuntime.CacheInternal;
 
        // If there are no varies, use the non-varying key 
        if (_varyByParamsCollection == null && _varyByControlsCollection == null && _varyByCustom == null) {
            realItemCacheKey = _cacheKey; 
        }
        else {
            string[] varyByParams = null;
            if (_varyByParamsCollection != null) 
                varyByParams = _varyByParamsCollection.GetParams();
 
            ControlCachedVary cachedVary = new ControlCachedVary(varyByParams, 
                _varyByControlsCollection, _varyByCustom);
 
            HashCodeCombiner combinedHashCode = new HashCodeCombiner(_nonVaryHashCode);
            realItemCacheKey = ComputeVaryCacheKey(combinedHashCode, cachedVary);

            /* 
             * Add the ControlCachedVary item so that a request will know
             * which varies are needed to issue another request. 
             * 
             * Use the Add method so that we guarantee we only use
             * a single ControlCachedVary and don't overwrite existing ones. 
             */
            ControlCachedVary cachedVaryInCache = (ControlCachedVary) cacheInternal.UtcAdd(
                    _cacheKey, cachedVary, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
                    CacheItemPriority.Default, null); 

            if (cachedVaryInCache != null) { 
                if (!cachedVary.Equals(cachedVaryInCache)) { 
                    // If it was already in the cache but is different, replace it
                    cacheInternal.UtcInsert(_cacheKey, cachedVary); 
                }
            }

            // Add the non-varying cache entry to the dependencies of the cached one. 

            CacheDependency cacheDepNonVary = new CacheDependency(0, null, new string[1] {_cacheKey}); 
 
            if (cacheDep == null) {
                cacheDep = cacheDepNonVary; 
            }
            else {
                AggregateCacheDependency aggr = new AggregateCacheDependency();
                aggr.Add(cacheDep, cacheDepNonVary); 
                cacheDep = aggr;
            } 
        } 

        // Compute the correct expiration, sliding or absolute 
        DateTime utcExpirationTime;
        TimeSpan slidingExpiration;
        if (_useSlidingExpiration) {
            utcExpirationTime = Cache.NoAbsoluteExpiration; 
            slidingExpiration = _utcExpirationTime - DateTime.UtcNow;
        } 
        else { 
            utcExpirationTime = _utcExpirationTime;
            slidingExpiration = Cache.NoSlidingExpiration; 
        }

        cacheInternal.UtcInsert(realItemCacheKey, _cacheEntry, cacheDep /*dependencies*/,
            utcExpirationTime, slidingExpiration); 
    }
 
    // Return the key used to cache the output 
    private string ComputeNonVaryCacheKey(HashCodeCombiner combinedHashCode) {
 
        // Create a cache key by combining various elements

        // Start with the guid
        combinedHashCode.AddObject(_guid); 

        // Make the key vary based on the type of the writer (ASURT 118922) 
        HttpBrowserCapabilities browserCap = Context.Request.Browser; 
        if (browserCap != null)
            combinedHashCode.AddObject(browserCap.TagWriter); 

        return CacheInternal.PrefixPartialCachingControl + combinedHashCode.CombinedHashString;
    }
 
    private string ComputeVaryCacheKey(HashCodeCombiner combinedHashCode,
        ControlCachedVary cachedVary) { 
 
        // Add something to the has to differentiate it from the non-vary hash.
        // This is needed in case this method doesn't add anything else to the hash (VSWhidbey 194199) 
        combinedHashCode.AddInt(1);

        // Get the request value collection
        NameValueCollection reqValCollection = Page.RequestValueCollection; 

        // If it's not set, get it based on the method 
        if (reqValCollection == null) 
            reqValCollection = Page.GetCollectionBasedOnMethod(true /*dontReturnNull*/);
 
        if (cachedVary._varyByParams != null) {

            ICollection itemsToUseForHashCode;
 
            // If '*' was specified, use all the items in the request collection.
            // Otherwise, use only those specified. 
            if (cachedVary._varyByParams.Length == 1 && cachedVary._varyByParams[0] == "*") 
                itemsToUseForHashCode = reqValCollection;
            else 
                itemsToUseForHashCode = cachedVary._varyByParams;

            // Add the items and their values to compute the hash code
            foreach (string varyByParam in itemsToUseForHashCode) { 

                // Note: we use to ignore certain system fields here (like VIEWSTATE), but decided 
                // not to for consistency with pahe output caching (VSWhidbey 196267, 479252) 

                combinedHashCode.AddCaseInsensitiveString(varyByParam); 
                string val = reqValCollection[varyByParam];
                if (val != null)
                    combinedHashCode.AddObject(val);
            } 
        }
 
        if (cachedVary._varyByControls != null) { 

            // Prepend them with a prefix to make them fully qualified 
            string prefix;
            if (NamingContainer == Page) {
                // No prefix if it's the page
                prefix = String.Empty; 
            }
            else { 
                prefix = NamingContainer.UniqueID; 
                Debug.Assert(!String.IsNullOrEmpty(prefix));
                prefix += IdSeparator; 
            }

            prefix += _ctrlID + IdSeparator;
 
            // Add all the relative vary params and their values to the hash code
            foreach (string varyByParam in cachedVary._varyByControls) { 
 
                string temp = prefix + varyByParam.Trim();
                combinedHashCode.AddCaseInsensitiveString(temp); 
                string val = reqValCollection[temp];
                if (val != null)
                    combinedHashCode.AddObject(reqValCollection[temp]);
            } 
        }
 
        if (cachedVary._varyByCustom != null) { 
            string customString = Context.ApplicationInstance.GetVaryByCustomString(
                Context, cachedVary._varyByCustom); 
            if (customString != null)
                combinedHashCode.AddObject(customString);
        }
 
        return CacheInternal.PrefixPartialCachingControl + combinedHashCode.CombinedHashString;
    } 
 
    private string GetCssStyleRenderString(Type htmlTextWriterType) {
        // Nothing to do if no styles are registered. 
        if (_registeredStyleInfo == null) {
            return null;
        }
 
        // Create an empty cssStringWriter
        StringWriter cssStringWriter = new StringWriter(CultureInfo.CurrentCulture); 
 
        // Create a new HtmlTextWriter, with the same type as the current one
        HtmlTextWriter cssHtmlTextWriter = 
            Page.CreateHtmlTextWriterFromType(cssStringWriter, htmlTextWriterType);

        CssTextWriter cssWriter = new CssTextWriter(cssHtmlTextWriter);
 
        foreach (SelectorStyleInfo si in _registeredStyleInfo) {
            HtmlHead.RenderCssRule(cssWriter, si.selector, si.style, si.urlResolver); 
        } 

        // Return the css style rendered string 
        return cssStringWriter.ToString();
    }

    internal void SetVaryByParamsCollectionFromString(string varyByParams) { 

        Debug.Assert(_varyByParamsCollection == null); 
 
        if (varyByParams == null)
            return; 

        string[] varyByParamsStrings = varyByParams.Split(varySeparator);
        _varyByParamsCollection = new HttpCacheVaryByParams();
        _varyByParamsCollection.ResetFromParams(varyByParamsStrings); 
    }
 
    internal void RegisterPostBackScript() { 
        RegisterClientCall(ClientAPIRegisterType.PostBackScript, String.Empty, null);
    } 

    internal void RegisterFocusScript() {
        RegisterClientCall(ClientAPIRegisterType.FocusScript, String.Empty, null);
    } 

    internal void RegisterWebFormsScript() { 
        RegisterClientCall(ClientAPIRegisterType.WebFormsScript, String.Empty, null); 
    }
 
    private void RegisterClientCall(ClientAPIRegisterType type,
        ScriptKey scriptKey, string stringParam2) {

        // Keep track of the call, in order to be able to call it again when there is a cache hit. 

        RegisterCallData registerCallData = new RegisterCallData(); 
        registerCallData.Type = type; 
        registerCallData.Key = scriptKey;
        registerCallData.StringParam2 = stringParam2; 

        if (_cacheEntry.RegisteredClientCalls == null)
            _cacheEntry.RegisteredClientCalls = new ArrayList();
 
        _cacheEntry.RegisteredClientCalls.Add(registerCallData);
    } 
 
    private void RegisterClientCall(ClientAPIRegisterType type,
        string stringParam1, string stringParam2) { 
        RegisterClientCall(type, stringParam1, stringParam2, null);
    }

    private void RegisterClientCall(ClientAPIRegisterType type, 
        string stringParam1, string stringParam2, string stringParam3) {
 
        // Keep track of the call, in order to be able to call it again when there is a cache hit. 

        RegisterCallData registerCallData = new RegisterCallData(); 
        registerCallData.Type = type;
        registerCallData.StringParam1 = stringParam1;
        registerCallData.StringParam2 = stringParam2;
        registerCallData.StringParam3 = stringParam3; 

        if (_cacheEntry.RegisteredClientCalls == null) 
            _cacheEntry.RegisteredClientCalls = new ArrayList(); 

        _cacheEntry.RegisteredClientCalls.Add(registerCallData); 
    }

    internal void RegisterScriptBlock(ClientAPIRegisterType type, ScriptKey key, string script) {
        RegisterClientCall(type, key, script); 
    }
 
    internal void RegisterOnSubmitStatement(ScriptKey key, string script) { 
        RegisterClientCall(ClientAPIRegisterType.OnSubmitStatement, key, script);
    } 

    internal void RegisterArrayDeclaration(string arrayName, string arrayValue) {
        RegisterClientCall(ClientAPIRegisterType.ArrayDeclaration,
            arrayName, arrayValue); 
    }
 
    internal void RegisterHiddenField(string hiddenFieldName, string hiddenFieldInitialValue) { 
        RegisterClientCall(ClientAPIRegisterType.HiddenField,
            hiddenFieldName, hiddenFieldInitialValue); 
    }

    internal void RegisterExpandoAttribute(string controlID, string attributeName, string attributeValue) {
        RegisterClientCall(ClientAPIRegisterType.ExpandoAttribute, controlID, attributeName, attributeValue); 
    }
 
    internal void RegisterForEventValidation(string uniqueID, string argument) { 
        RegisterClientCall(ClientAPIRegisterType.EventValidation, uniqueID, argument);
    } 
}


///  
///    [To be supplied.]
///  
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public class StaticPartialCachingControl : BasePartialCachingControl { 

    private BuildMethod _buildMethod;

 
    /// 
    ///  
    ///    [To be supplied.] 
    /// 
    public StaticPartialCachingControl(string ctrlID, string guid, int duration, 
        string varyByParams, string varyByControls, string varyByCustom,
        BuildMethod buildMethod)
        :this(ctrlID, guid, duration, varyByParams, varyByControls,
            varyByCustom, null, buildMethod) 
    {
    } 
 

    ///  
    /// 
    ///    [To be supplied.]
    /// 
    public StaticPartialCachingControl(string ctrlID, string guid, int duration, 
        string varyByParams, string varyByControls, string varyByCustom, string sqlDependency,
        BuildMethod buildMethod) { 
        _ctrlID = ctrlID; 
        Duration = new TimeSpan(0 /*hours*/, 0 /*mins*/, duration /*seconds*/);
 
        SetVaryByParamsCollectionFromString(varyByParams);

        if (varyByControls != null)
            _varyByControlsCollection = varyByControls.Split(varySeparator); 
        _varyByCustom = varyByCustom;
        _guid = guid; 
        _buildMethod = buildMethod; 
        _sqlDependency = sqlDependency;
    } 

    internal override Control CreateCachedControl() {
        return _buildMethod();
    } 

    /* 
     * Called by generated code (hence must be public). 
     * Create a StaticPartialCachingControl and add it as a child
     */ 

    /// 
    /// 
    ///    [To be supplied.] 
    /// 
    static public void BuildCachedControl(Control parent, string ctrlID, string guid, 
        int duration, string varyByParams, string varyByControls, string varyByCustom, 
        BuildMethod buildMethod) {
        BuildCachedControl(parent, ctrlID, guid, duration, varyByParams, 
            varyByControls, varyByCustom, null, buildMethod);
    }

 
    /// 
    ///  
    ///    [To be supplied.] 
    /// 
    static public void BuildCachedControl(Control parent, string ctrlID, string guid, 
        int duration, string varyByParams, string varyByControls, string varyByCustom, string sqlDependency,
        BuildMethod buildMethod) {

        StaticPartialCachingControl pcc = new StaticPartialCachingControl( 
            ctrlID, guid, duration, varyByParams, varyByControls, varyByCustom, sqlDependency,
            buildMethod); 
 
        ((IParserAccessor)parent).AddParsedSubObject(pcc);
    } 
}


///  
///    [To be supplied.]
///  
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public class PartialCachingControl : BasePartialCachingControl { 

    private IWebObjectFactory _objectFactory;
    private Type _createCachedControlType;
    private object[] _args; 

 
    public Control CachedControl { get { return _cachedCtrl; } } 

    internal PartialCachingControl(IWebObjectFactory objectFactory, Type createCachedControlType, 
        PartialCachingAttribute cacheAttrib, string cacheKey, object[] args) {

        _ctrlID = cacheKey;
        Duration = new TimeSpan(0 /*hours*/, 0 /*mins*/, cacheAttrib.Duration /*seconds*/); 

        SetVaryByParamsCollectionFromString(cacheAttrib.VaryByParams); 
 
        if (cacheAttrib.VaryByControls != null)
            _varyByControlsCollection = cacheAttrib.VaryByControls.Split(varySeparator); 
        _varyByCustom = cacheAttrib.VaryByCustom;
        _sqlDependency = cacheAttrib.SqlDependency;
        _guid = cacheKey;
        _objectFactory = objectFactory; 
        _createCachedControlType = createCachedControlType;
        _args = args; 
    } 

    internal override Control CreateCachedControl() { 

        Control cachedControl;

        if (_objectFactory != null) { 
            cachedControl = (Control) _objectFactory.CreateInstance();
        } 
        else { 
            // Instantiate the control
            cachedControl = (Control) HttpRuntime.CreatePublicInstance(_createCachedControlType, _args); 
        }

        // If it's a user control, do some extra initialization
        UserControl uc = cachedControl as UserControl; 
        if (uc != null)
            uc.InitializeAsUserControl(Page); 
 
        cachedControl.ID = _ctrlID;
 
        return cachedControl;
    }
}
 
/*
 * Holds param names that this cached item varies by. 
 */ 
internal class ControlCachedVary {
    internal readonly string[]  _varyByParams; 
    internal readonly string    _varyByCustom;
    internal readonly string[]  _varyByControls;

    internal ControlCachedVary(string[] varyByParams, 
        string[] varyByControls, string varyByCustom) {
        _varyByParams = varyByParams; 
        _varyByControls = varyByControls; 
        _varyByCustom = varyByCustom;
    } 

    public override bool Equals (Object obj) {

        if (!(obj is ControlCachedVary)) 
            return false;
 
        ControlCachedVary cv = (ControlCachedVary) obj; 

        return  _varyByCustom == cv._varyByCustom               && 
                StringUtil.StringArrayEquals(_varyByParams, cv._varyByParams) &&
                StringUtil.StringArrayEquals(_varyByControls, cv._varyByControls);
    }
 
    public override int GetHashCode () {
        HashCodeCombiner hashCodeCombiner = new HashCodeCombiner(); 
 
        // Cast _varyByCustom to an object, since the HashCodeCombiner.AddObject(string)
        // overload uses StringUtil.GetStringHashCode().  We want to use String.GetHashCode() 
        // in this method, since we do not require a stable hash code across architectures.
        hashCodeCombiner.AddObject((object)_varyByCustom);

        hashCodeCombiner.AddArray(_varyByParams); 
        hashCodeCombiner.AddArray(_varyByControls);
        return hashCodeCombiner.CombinedHash32; 
    } 
}
 
}


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

namespace System.Web.UI { 
 
using System;
using System.IO; 
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel; 
using System.ComponentModel.Design;
using System.Globalization; 
using System.Web; 
using System.Web.Util;
using System.Web.UI.HtmlControls; 
using System.Web.UI.WebControls;
using System.Web.Caching;
using System.Web.Compilation;
using System.Web.Configuration; 
using System.Security.Permissions;
 
 
/// 
///    [To be supplied.] 
/// 
[
ToolboxItem(false)
] 
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
public abstract class BasePartialCachingControl : Control { 

    internal Control _cachedCtrl; 
    private long _nonVaryHashCode;
    internal string _ctrlID;
    internal string _guid;
    internal DateTime _utcExpirationTime; 
    internal bool _useSlidingExpiration;
    internal HttpCacheVaryByParams _varyByParamsCollection; 
    internal string[] _varyByControlsCollection; 
    internal string _varyByCustom;
    internal string _sqlDependency; 
    internal bool _cachingDisabled;
    private string _outputString;
    private string _cssStyleString;
    private string _cacheKey; 
    private CacheDependency _cacheDependency;
    private PartialCachingCacheEntry _cacheEntry; 
    private ControlCachePolicy _cachePolicy; 
    private ArrayList _registeredCallDataForEventValidation;
    private ArrayList _registeredStyleInfo = null; 

    internal const char varySeparator = ';';
    internal const string varySeparatorString = ";";
 
    // Keeps track of one call to Page Register* API
    // The semantics of the fields depends to the call type 
    class RegisterCallData { 
        internal ClientAPIRegisterType Type;
        internal ScriptKey Key; 
        internal string StringParam1;
        internal string StringParam2;
        internal string StringParam3;
    } 

    // Data that we need to cache 
    class PartialCachingCacheEntry { 
        internal string OutputString;
        internal string CssStyleString; 
        internal ArrayList RegisteredClientCalls;
    }

    internal override void InitRecursive(Control namingContainer) { 

        HashCodeCombiner combinedHashCode = new HashCodeCombiner(); 
 
        _cacheKey = ComputeNonVaryCacheKey(combinedHashCode);
 
        // Save the non-varying hash, so we don't need to recalculate it later
        _nonVaryHashCode = combinedHashCode.CombinedHash;

        PartialCachingCacheEntry cacheEntry = null; 

        // Check if there is a cache entry for the non-varying key 
        object tmpCacheEntry = HttpRuntime.CacheInternal.Get(_cacheKey); 

        if (tmpCacheEntry != null) { 
            ControlCachedVary cachedVary = tmpCacheEntry as ControlCachedVary;
            if (cachedVary != null) {
                string varyCachedKey = ComputeVaryCacheKey(combinedHashCode, cachedVary);
 
                // Check if there is a cache entry for the varying key
                cacheEntry = (PartialCachingCacheEntry) HttpRuntime.CacheInternal.Get(varyCachedKey); 
            } 
            else {
                // If it wasn't a ControlCachedVary, it must be a PartialCachingCacheEntry 
                cacheEntry = (PartialCachingCacheEntry) tmpCacheEntry;
            }
        }
 
        // If it's a cache miss, create the control and make it our child
        if (cacheEntry == null) { 
 
            // Cache miss
 
            _cacheEntry = new PartialCachingCacheEntry();

            _cachedCtrl = CreateCachedControl();
            Controls.Add(_cachedCtrl); 

            // Make sure the Page knows about us while the control's OnInit is called 
            Page.PushCachingControl(this); 
            base.InitRecursive(namingContainer);
            Page.PopCachingControl(); 
        }
        else {

            // Cache hit 

            _outputString = cacheEntry.OutputString; 
            _cssStyleString = cacheEntry.CssStyleString; 

            // If any calls to Register* API's were made when the control was run, 
            // make them now to restore correct behavior (VSWhidbey 80907)
            if (cacheEntry.RegisteredClientCalls != null) {
                foreach (RegisterCallData registerCallData in cacheEntry.RegisteredClientCalls) {
                    switch (registerCallData.Type) { 

                        case ClientAPIRegisterType.WebFormsScript: 
                            Page.RegisterWebFormsScript(); 
                            break;
 
                        case ClientAPIRegisterType.PostBackScript:
                            Page.RegisterPostBackScript();
                            break;
 
                        case ClientAPIRegisterType.FocusScript:
                            Page.RegisterFocusScript(); 
                            break; 

                        case ClientAPIRegisterType.ClientScriptBlocks: 
                        case ClientAPIRegisterType.ClientScriptBlocksWithoutTags:
                        case ClientAPIRegisterType.ClientStartupScripts:
                        case ClientAPIRegisterType.ClientStartupScriptsWithoutTags:
                            Page.ClientScript.RegisterScriptBlock(registerCallData.Key, 
                                registerCallData.StringParam2, registerCallData.Type);
                            break; 
 
                        case ClientAPIRegisterType.OnSubmitStatement:
                            Page.ClientScript.RegisterOnSubmitStatementInternal(registerCallData.Key, 
                                registerCallData.StringParam2);
                            break;

                        case ClientAPIRegisterType.ArrayDeclaration: 
                            Page.ClientScript.RegisterArrayDeclaration(registerCallData.StringParam1,
                                registerCallData.StringParam2); 
                            break; 

                        case ClientAPIRegisterType.HiddenField: 
                            Page.ClientScript.RegisterHiddenField(registerCallData.StringParam1,
                                registerCallData.StringParam2);
                            break;
 
                        case ClientAPIRegisterType.ExpandoAttribute:
                            Page.ClientScript.RegisterExpandoAttribute(registerCallData.StringParam1, 
                                registerCallData.StringParam2, registerCallData.StringParam3, false); 
                            break;
 
                        case ClientAPIRegisterType.EventValidation:
                            if (_registeredCallDataForEventValidation == null) {
                                _registeredCallDataForEventValidation = new ArrayList();
                            } 

                            _registeredCallDataForEventValidation.Add(registerCallData); 
                            break; 
                        default:
                            Debug.Assert(false); 
                            break;
                    }
                }
            } 

            base.InitRecursive(namingContainer); 
        } 
    }
 
    internal override void LoadRecursive() {

        // If we're in a cache hit, don't do anything special
        if (_outputString != null) { 
            base.LoadRecursive();
            return; 
        } 

        // Make sure the Page knows about us while the control's OnLoad is called 
        Page.PushCachingControl(this);
        base.LoadRecursive();
        Page.PopCachingControl();
    } 

    internal override void PreRenderRecursiveInternal() { 
 
        // If we're in a cache hit, don't do anything special
        if (_outputString != null) { 
            base.PreRenderRecursiveInternal();

            // register the cached styles on the Header control.
            if (_cssStyleString != null && Page.Header != null) { 
                Page.Header.RegisterCssStyleString(_cssStyleString);
            } 
 
            return;
        } 

        // Make sure the Page knows about us while the control's OnPreRender is called
        Page.PushCachingControl(this);
        base.PreRenderRecursiveInternal(); 
        Page.PopCachingControl();
    } 
 

    ///  
    public override void Dispose() {
        if (_cacheDependency != null) {
            _cacheDependency.Dispose();
            _cacheDependency = null; 
        }
 
        base.Dispose(); 
    }
 
    internal abstract Control CreateCachedControl();


    ///  
    ///     Gets or sets the CacheDependency used to cache the control output.
    ///  
    public CacheDependency Dependency { 
        get { return _cacheDependency; }
        set { _cacheDependency = value; } 
    }


    public ControlCachePolicy CachePolicy { 
        get {
            // Create the ControlCachePolicy object on demand 
            if (_cachePolicy == null) 
                _cachePolicy = new ControlCachePolicy(this);
 
            return _cachePolicy;
        }
    }
 
    internal HttpCacheVaryByParams VaryByParams {
        get { 
            if (_varyByParamsCollection == null) { 
                _varyByParamsCollection = new HttpCacheVaryByParams();
                _varyByParamsCollection.IgnoreParams = true; 
            }

            return _varyByParamsCollection;
        } 
    }
 
    internal string VaryByControl { 
        get {
            if (_varyByControlsCollection == null) 
                return String.Empty;

            return String.Join(varySeparatorString, _varyByControlsCollection);
        } 

        set { 
            if (String.IsNullOrEmpty(value)) { 
                _varyByControlsCollection = null;
            } 
            else {
                _varyByControlsCollection = value.Split(varySeparator);
            }
        } 
    }
 
    internal TimeSpan Duration { 
        get {
            // Special case MaxValue 
            if (_utcExpirationTime == DateTime.MaxValue)
                return TimeSpan.MaxValue;

            return _utcExpirationTime - DateTime.UtcNow; 
        }
 
        set { 
            if (value == TimeSpan.MaxValue) {
                // If it's the max timespan, just make it DateTime.MaxValue to avoid 
                // an overflow when adding (VSWhidbey 273271)
                _utcExpirationTime = DateTime.MaxValue;
            }
            else { 
                // Compute the expiration time
                _utcExpirationTime = DateTime.UtcNow.Add(value); 
            } 
        }
    } 

    private void RegisterValidationEvents() {
        if (_registeredCallDataForEventValidation != null) {
            foreach (RegisterCallData registerCallData in _registeredCallDataForEventValidation) { 
                Page.ClientScript.RegisterForEventValidation(registerCallData.StringParam1,
                    registerCallData.StringParam2); 
            } 
        }
    } 

    internal void RegisterStyleInfo(SelectorStyleInfo selectorInfo) {
        if (_registeredStyleInfo == null) {
            _registeredStyleInfo = new ArrayList(); 
        }
 
        _registeredStyleInfo.Add(selectorInfo); 
    }
 
    /// 
    /// 
    ///    [To be supplied.]
    ///  
    protected internal override void Render(HtmlTextWriter output) {
        CacheDependency sqlCacheDep = null; 
 
        // If the output is cached, use it and do nothing else
        if (_outputString != null) { 
            output.Write(_outputString);
            RegisterValidationEvents();
            return;
        } 

        // If caching was turned off, just render the control 
        if (_cachingDisabled || !RuntimeConfig.GetAppConfig().OutputCache.EnableFragmentCache) { 
            _cachedCtrl.RenderControl(output);
            return; 
        }

        // Create SQL cache dependency before we render the page
        if (_sqlDependency != null) { 
            sqlCacheDep = SqlCacheDependency.CreateOutputCacheDependency(_sqlDependency);
        } 
 
        _cacheEntry.CssStyleString = GetCssStyleRenderString(output.GetType());
 
        // Create a new HtmlTextWriter, with the same type as the current one (see ASURT 118922)
        StringWriter tmpWriter = new StringWriter();
        HtmlTextWriter tmpHtmlWriter = Page.CreateHtmlTextWriterFromType(tmpWriter, output.GetType());
        CacheDependency cacheDep; 
        TextWriter savedWriter = Context.Response.SwitchWriter(tmpWriter);
 
        try { 
            // Make sure the Page knows about us while the control's OnPreRender is called
            Page.PushCachingControl(this); 
            _cachedCtrl.RenderControl(tmpHtmlWriter);
            Page.PopCachingControl();
        }
        finally { 
            Context.Response.SwitchWriter(savedWriter);
        } 
 
        _cacheEntry.OutputString = tmpWriter.ToString();
 
        // Send the output to the response
        output.Write(_cacheEntry.OutputString);

        // Cache the output 

        cacheDep = _cacheDependency; 
 
        if (sqlCacheDep != null) {
            if (cacheDep == null) { 
                cacheDep = sqlCacheDep;
            }
            else {
                AggregateCacheDependency aggr = new AggregateCacheDependency(); 

                aggr.Add(cacheDep); 
                aggr.Add(sqlCacheDep); 
                cacheDep = aggr;
            } 
        }

        string realItemCacheKey;
 
        CacheInternal cacheInternal = HttpRuntime.CacheInternal;
 
        // If there are no varies, use the non-varying key 
        if (_varyByParamsCollection == null && _varyByControlsCollection == null && _varyByCustom == null) {
            realItemCacheKey = _cacheKey; 
        }
        else {
            string[] varyByParams = null;
            if (_varyByParamsCollection != null) 
                varyByParams = _varyByParamsCollection.GetParams();
 
            ControlCachedVary cachedVary = new ControlCachedVary(varyByParams, 
                _varyByControlsCollection, _varyByCustom);
 
            HashCodeCombiner combinedHashCode = new HashCodeCombiner(_nonVaryHashCode);
            realItemCacheKey = ComputeVaryCacheKey(combinedHashCode, cachedVary);

            /* 
             * Add the ControlCachedVary item so that a request will know
             * which varies are needed to issue another request. 
             * 
             * Use the Add method so that we guarantee we only use
             * a single ControlCachedVary and don't overwrite existing ones. 
             */
            ControlCachedVary cachedVaryInCache = (ControlCachedVary) cacheInternal.UtcAdd(
                    _cacheKey, cachedVary, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
                    CacheItemPriority.Default, null); 

            if (cachedVaryInCache != null) { 
                if (!cachedVary.Equals(cachedVaryInCache)) { 
                    // If it was already in the cache but is different, replace it
                    cacheInternal.UtcInsert(_cacheKey, cachedVary); 
                }
            }

            // Add the non-varying cache entry to the dependencies of the cached one. 

            CacheDependency cacheDepNonVary = new CacheDependency(0, null, new string[1] {_cacheKey}); 
 
            if (cacheDep == null) {
                cacheDep = cacheDepNonVary; 
            }
            else {
                AggregateCacheDependency aggr = new AggregateCacheDependency();
                aggr.Add(cacheDep, cacheDepNonVary); 
                cacheDep = aggr;
            } 
        } 

        // Compute the correct expiration, sliding or absolute 
        DateTime utcExpirationTime;
        TimeSpan slidingExpiration;
        if (_useSlidingExpiration) {
            utcExpirationTime = Cache.NoAbsoluteExpiration; 
            slidingExpiration = _utcExpirationTime - DateTime.UtcNow;
        } 
        else { 
            utcExpirationTime = _utcExpirationTime;
            slidingExpiration = Cache.NoSlidingExpiration; 
        }

        cacheInternal.UtcInsert(realItemCacheKey, _cacheEntry, cacheDep /*dependencies*/,
            utcExpirationTime, slidingExpiration); 
    }
 
    // Return the key used to cache the output 
    private string ComputeNonVaryCacheKey(HashCodeCombiner combinedHashCode) {
 
        // Create a cache key by combining various elements

        // Start with the guid
        combinedHashCode.AddObject(_guid); 

        // Make the key vary based on the type of the writer (ASURT 118922) 
        HttpBrowserCapabilities browserCap = Context.Request.Browser; 
        if (browserCap != null)
            combinedHashCode.AddObject(browserCap.TagWriter); 

        return CacheInternal.PrefixPartialCachingControl + combinedHashCode.CombinedHashString;
    }
 
    private string ComputeVaryCacheKey(HashCodeCombiner combinedHashCode,
        ControlCachedVary cachedVary) { 
 
        // Add something to the has to differentiate it from the non-vary hash.
        // This is needed in case this method doesn't add anything else to the hash (VSWhidbey 194199) 
        combinedHashCode.AddInt(1);

        // Get the request value collection
        NameValueCollection reqValCollection = Page.RequestValueCollection; 

        // If it's not set, get it based on the method 
        if (reqValCollection == null) 
            reqValCollection = Page.GetCollectionBasedOnMethod(true /*dontReturnNull*/);
 
        if (cachedVary._varyByParams != null) {

            ICollection itemsToUseForHashCode;
 
            // If '*' was specified, use all the items in the request collection.
            // Otherwise, use only those specified. 
            if (cachedVary._varyByParams.Length == 1 && cachedVary._varyByParams[0] == "*") 
                itemsToUseForHashCode = reqValCollection;
            else 
                itemsToUseForHashCode = cachedVary._varyByParams;

            // Add the items and their values to compute the hash code
            foreach (string varyByParam in itemsToUseForHashCode) { 

                // Note: we use to ignore certain system fields here (like VIEWSTATE), but decided 
                // not to for consistency with pahe output caching (VSWhidbey 196267, 479252) 

                combinedHashCode.AddCaseInsensitiveString(varyByParam); 
                string val = reqValCollection[varyByParam];
                if (val != null)
                    combinedHashCode.AddObject(val);
            } 
        }
 
        if (cachedVary._varyByControls != null) { 

            // Prepend them with a prefix to make them fully qualified 
            string prefix;
            if (NamingContainer == Page) {
                // No prefix if it's the page
                prefix = String.Empty; 
            }
            else { 
                prefix = NamingContainer.UniqueID; 
                Debug.Assert(!String.IsNullOrEmpty(prefix));
                prefix += IdSeparator; 
            }

            prefix += _ctrlID + IdSeparator;
 
            // Add all the relative vary params and their values to the hash code
            foreach (string varyByParam in cachedVary._varyByControls) { 
 
                string temp = prefix + varyByParam.Trim();
                combinedHashCode.AddCaseInsensitiveString(temp); 
                string val = reqValCollection[temp];
                if (val != null)
                    combinedHashCode.AddObject(reqValCollection[temp]);
            } 
        }
 
        if (cachedVary._varyByCustom != null) { 
            string customString = Context.ApplicationInstance.GetVaryByCustomString(
                Context, cachedVary._varyByCustom); 
            if (customString != null)
                combinedHashCode.AddObject(customString);
        }
 
        return CacheInternal.PrefixPartialCachingControl + combinedHashCode.CombinedHashString;
    } 
 
    private string GetCssStyleRenderString(Type htmlTextWriterType) {
        // Nothing to do if no styles are registered. 
        if (_registeredStyleInfo == null) {
            return null;
        }
 
        // Create an empty cssStringWriter
        StringWriter cssStringWriter = new StringWriter(CultureInfo.CurrentCulture); 
 
        // Create a new HtmlTextWriter, with the same type as the current one
        HtmlTextWriter cssHtmlTextWriter = 
            Page.CreateHtmlTextWriterFromType(cssStringWriter, htmlTextWriterType);

        CssTextWriter cssWriter = new CssTextWriter(cssHtmlTextWriter);
 
        foreach (SelectorStyleInfo si in _registeredStyleInfo) {
            HtmlHead.RenderCssRule(cssWriter, si.selector, si.style, si.urlResolver); 
        } 

        // Return the css style rendered string 
        return cssStringWriter.ToString();
    }

    internal void SetVaryByParamsCollectionFromString(string varyByParams) { 

        Debug.Assert(_varyByParamsCollection == null); 
 
        if (varyByParams == null)
            return; 

        string[] varyByParamsStrings = varyByParams.Split(varySeparator);
        _varyByParamsCollection = new HttpCacheVaryByParams();
        _varyByParamsCollection.ResetFromParams(varyByParamsStrings); 
    }
 
    internal void RegisterPostBackScript() { 
        RegisterClientCall(ClientAPIRegisterType.PostBackScript, String.Empty, null);
    } 

    internal void RegisterFocusScript() {
        RegisterClientCall(ClientAPIRegisterType.FocusScript, String.Empty, null);
    } 

    internal void RegisterWebFormsScript() { 
        RegisterClientCall(ClientAPIRegisterType.WebFormsScript, String.Empty, null); 
    }
 
    private void RegisterClientCall(ClientAPIRegisterType type,
        ScriptKey scriptKey, string stringParam2) {

        // Keep track of the call, in order to be able to call it again when there is a cache hit. 

        RegisterCallData registerCallData = new RegisterCallData(); 
        registerCallData.Type = type; 
        registerCallData.Key = scriptKey;
        registerCallData.StringParam2 = stringParam2; 

        if (_cacheEntry.RegisteredClientCalls == null)
            _cacheEntry.RegisteredClientCalls = new ArrayList();
 
        _cacheEntry.RegisteredClientCalls.Add(registerCallData);
    } 
 
    private void RegisterClientCall(ClientAPIRegisterType type,
        string stringParam1, string stringParam2) { 
        RegisterClientCall(type, stringParam1, stringParam2, null);
    }

    private void RegisterClientCall(ClientAPIRegisterType type, 
        string stringParam1, string stringParam2, string stringParam3) {
 
        // Keep track of the call, in order to be able to call it again when there is a cache hit. 

        RegisterCallData registerCallData = new RegisterCallData(); 
        registerCallData.Type = type;
        registerCallData.StringParam1 = stringParam1;
        registerCallData.StringParam2 = stringParam2;
        registerCallData.StringParam3 = stringParam3; 

        if (_cacheEntry.RegisteredClientCalls == null) 
            _cacheEntry.RegisteredClientCalls = new ArrayList(); 

        _cacheEntry.RegisteredClientCalls.Add(registerCallData); 
    }

    internal void RegisterScriptBlock(ClientAPIRegisterType type, ScriptKey key, string script) {
        RegisterClientCall(type, key, script); 
    }
 
    internal void RegisterOnSubmitStatement(ScriptKey key, string script) { 
        RegisterClientCall(ClientAPIRegisterType.OnSubmitStatement, key, script);
    } 

    internal void RegisterArrayDeclaration(string arrayName, string arrayValue) {
        RegisterClientCall(ClientAPIRegisterType.ArrayDeclaration,
            arrayName, arrayValue); 
    }
 
    internal void RegisterHiddenField(string hiddenFieldName, string hiddenFieldInitialValue) { 
        RegisterClientCall(ClientAPIRegisterType.HiddenField,
            hiddenFieldName, hiddenFieldInitialValue); 
    }

    internal void RegisterExpandoAttribute(string controlID, string attributeName, string attributeValue) {
        RegisterClientCall(ClientAPIRegisterType.ExpandoAttribute, controlID, attributeName, attributeValue); 
    }
 
    internal void RegisterForEventValidation(string uniqueID, string argument) { 
        RegisterClientCall(ClientAPIRegisterType.EventValidation, uniqueID, argument);
    } 
}


///  
///    [To be supplied.]
///  
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public class StaticPartialCachingControl : BasePartialCachingControl { 

    private BuildMethod _buildMethod;

 
    /// 
    ///  
    ///    [To be supplied.] 
    /// 
    public StaticPartialCachingControl(string ctrlID, string guid, int duration, 
        string varyByParams, string varyByControls, string varyByCustom,
        BuildMethod buildMethod)
        :this(ctrlID, guid, duration, varyByParams, varyByControls,
            varyByCustom, null, buildMethod) 
    {
    } 
 

    ///  
    /// 
    ///    [To be supplied.]
    /// 
    public StaticPartialCachingControl(string ctrlID, string guid, int duration, 
        string varyByParams, string varyByControls, string varyByCustom, string sqlDependency,
        BuildMethod buildMethod) { 
        _ctrlID = ctrlID; 
        Duration = new TimeSpan(0 /*hours*/, 0 /*mins*/, duration /*seconds*/);
 
        SetVaryByParamsCollectionFromString(varyByParams);

        if (varyByControls != null)
            _varyByControlsCollection = varyByControls.Split(varySeparator); 
        _varyByCustom = varyByCustom;
        _guid = guid; 
        _buildMethod = buildMethod; 
        _sqlDependency = sqlDependency;
    } 

    internal override Control CreateCachedControl() {
        return _buildMethod();
    } 

    /* 
     * Called by generated code (hence must be public). 
     * Create a StaticPartialCachingControl and add it as a child
     */ 

    /// 
    /// 
    ///    [To be supplied.] 
    /// 
    static public void BuildCachedControl(Control parent, string ctrlID, string guid, 
        int duration, string varyByParams, string varyByControls, string varyByCustom, 
        BuildMethod buildMethod) {
        BuildCachedControl(parent, ctrlID, guid, duration, varyByParams, 
            varyByControls, varyByCustom, null, buildMethod);
    }

 
    /// 
    ///  
    ///    [To be supplied.] 
    /// 
    static public void BuildCachedControl(Control parent, string ctrlID, string guid, 
        int duration, string varyByParams, string varyByControls, string varyByCustom, string sqlDependency,
        BuildMethod buildMethod) {

        StaticPartialCachingControl pcc = new StaticPartialCachingControl( 
            ctrlID, guid, duration, varyByParams, varyByControls, varyByCustom, sqlDependency,
            buildMethod); 
 
        ((IParserAccessor)parent).AddParsedSubObject(pcc);
    } 
}


///  
///    [To be supplied.]
///  
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public class PartialCachingControl : BasePartialCachingControl { 

    private IWebObjectFactory _objectFactory;
    private Type _createCachedControlType;
    private object[] _args; 

 
    public Control CachedControl { get { return _cachedCtrl; } } 

    internal PartialCachingControl(IWebObjectFactory objectFactory, Type createCachedControlType, 
        PartialCachingAttribute cacheAttrib, string cacheKey, object[] args) {

        _ctrlID = cacheKey;
        Duration = new TimeSpan(0 /*hours*/, 0 /*mins*/, cacheAttrib.Duration /*seconds*/); 

        SetVaryByParamsCollectionFromString(cacheAttrib.VaryByParams); 
 
        if (cacheAttrib.VaryByControls != null)
            _varyByControlsCollection = cacheAttrib.VaryByControls.Split(varySeparator); 
        _varyByCustom = cacheAttrib.VaryByCustom;
        _sqlDependency = cacheAttrib.SqlDependency;
        _guid = cacheKey;
        _objectFactory = objectFactory; 
        _createCachedControlType = createCachedControlType;
        _args = args; 
    } 

    internal override Control CreateCachedControl() { 

        Control cachedControl;

        if (_objectFactory != null) { 
            cachedControl = (Control) _objectFactory.CreateInstance();
        } 
        else { 
            // Instantiate the control
            cachedControl = (Control) HttpRuntime.CreatePublicInstance(_createCachedControlType, _args); 
        }

        // If it's a user control, do some extra initialization
        UserControl uc = cachedControl as UserControl; 
        if (uc != null)
            uc.InitializeAsUserControl(Page); 
 
        cachedControl.ID = _ctrlID;
 
        return cachedControl;
    }
}
 
/*
 * Holds param names that this cached item varies by. 
 */ 
internal class ControlCachedVary {
    internal readonly string[]  _varyByParams; 
    internal readonly string    _varyByCustom;
    internal readonly string[]  _varyByControls;

    internal ControlCachedVary(string[] varyByParams, 
        string[] varyByControls, string varyByCustom) {
        _varyByParams = varyByParams; 
        _varyByControls = varyByControls; 
        _varyByCustom = varyByCustom;
    } 

    public override bool Equals (Object obj) {

        if (!(obj is ControlCachedVary)) 
            return false;
 
        ControlCachedVary cv = (ControlCachedVary) obj; 

        return  _varyByCustom == cv._varyByCustom               && 
                StringUtil.StringArrayEquals(_varyByParams, cv._varyByParams) &&
                StringUtil.StringArrayEquals(_varyByControls, cv._varyByControls);
    }
 
    public override int GetHashCode () {
        HashCodeCombiner hashCodeCombiner = new HashCodeCombiner(); 
 
        // Cast _varyByCustom to an object, since the HashCodeCombiner.AddObject(string)
        // overload uses StringUtil.GetStringHashCode().  We want to use String.GetHashCode() 
        // in this method, since we do not require a stable hash code across architectures.
        hashCodeCombiner.AddObject((object)_varyByCustom);

        hashCodeCombiner.AddArray(_varyByParams); 
        hashCodeCombiner.AddArray(_varyByControls);
        return hashCodeCombiner.CombinedHash32; 
    } 
}
 
}


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