XmlDataSource.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / UI / WebControls / XmlDataSource.cs / 1305376 / XmlDataSource.cs

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

namespace System.Web.UI.WebControls { 
 
    using System;
    using System.Collections; 
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Design; 
    using System.Globalization;
    using System.IO; 
    using System.Text; 
    using System.Web;
    using System.Web.Hosting; 
    using System.Web.Caching;
    using System.Web.UI;
    using System.Xml;
    using System.Xml.Xsl; 
    using System.Web.Util;
 
 

    ///  
    /// Represents an XML file as both an IDataSource and an IHierarchicalDataSource.
    /// The XML data is retrieved either from a file specified by the DataFile property
    /// or by inline XML content in the Data property.
    ///  
    [
    DefaultEvent("Transforming"), 
    DefaultProperty("DataFile"), 
    Designer("System.Web.UI.Design.WebControls.XmlDataSourceDesigner, " + AssemblyRef.SystemDesign),
    ParseChildren(true), 
    PersistChildren(false),
    ToolboxBitmap(typeof(XmlDataSource)),
    WebSysDescription(SR.XmlDataSource_Description),
    WebSysDisplayName(SR.XmlDataSource_DisplayName) 
    ]
    public class XmlDataSource : HierarchicalDataSourceControl, IDataSource, IListSource { 
 
        private static readonly object EventTransforming = new object();
        private const string DefaultViewName = "DefaultView"; 

        private DataSourceCache _cache;
        private bool _cacheLookupDone;
        private bool _disallowChanges; 
        private XsltArgumentList _transformArgumentList;
        private ICollection _viewNames; 
        private XmlDocument _xmlDocument; 
        private string _writeableDataFile;
 
        private string _data;
        private string _dataFile;
        private string _transform;
        private string _transformFile; 
        private string _xPath;
 
 
        /// 
        /// Specifies the cache settings for this data source. 
        /// 
        private DataSourceCache Cache {
            get {
                if (_cache == null) { 
                    _cache = new DataSourceCache();
                    _cache.Enabled = true; 
                } 
                return _cache;
            } 
        }


        ///  
        /// The duration, in seconds, of the expiration. The expiration policy is specified by the CacheExpirationPolicy property.
        ///  
        [ 
        DefaultValue(DataSourceCache.Infinite),
        TypeConverterAttribute(typeof(DataSourceCacheDurationConverter)), 
        WebCategory("Cache"),
        WebSysDescription(SR.DataSourceCache_Duration),
        ]
        public virtual int CacheDuration { 
            get {
                return Cache.Duration; 
            } 
            set {
                Cache.Duration = value; 
            }
        }

        ///  
        /// The expiration policy of the cache. The duration for the expiration is specified by the CacheDuration property.
        ///  
        [ 
        DefaultValue(DataSourceCacheExpiry.Absolute),
        WebCategory("Cache"), 
        WebSysDescription(SR.DataSourceCache_ExpirationPolicy),
        ]
        public virtual DataSourceCacheExpiry CacheExpirationPolicy {
            get { 
                return Cache.ExpirationPolicy;
            } 
            set { 
                Cache.ExpirationPolicy = value;
            } 
        }

        /// 
        /// Indicates an arbitrary cache key to make this cache entry depend on. This allows 
        /// the user to further customize when this cache entry will expire.
        ///  
        [ 
        DefaultValue(""),
        WebCategory("Cache"), 
        WebSysDescription(SR.DataSourceCache_KeyDependency),
        ]
        public virtual string CacheKeyDependency {
            get { 
                return Cache.KeyDependency;
            } 
            set { 
                Cache.KeyDependency = value;
            } 
        }

        [
        DefaultValue(""), 
        WebCategory("Cache"),
        WebSysDescription(SR.XmlDataSource_CacheKeyContext), 
        ] 
        public virtual string CacheKeyContext {
            get { 
                return (string)ViewState["CacheKeyContext "] ?? String.Empty;
            }
            set {
                ViewState["CacheKeyContext "] = value; 
            }
        } 
 
        /// 
        /// Inline XML content. 
        /// 
        [
        DefaultValue(""),
        Editor("System.ComponentModel.Design.MultilineStringEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TypeConverter("System.ComponentModel.MultilineStringConverter," + AssemblyRef.System), 
        WebCategory("Data"), 
        WebSysDescription(SR.XmlDataSource_Data),
        ] 
        public virtual string Data {
            get {
                if (_data == null) {
                    return String.Empty; 
                }
                return _data; 
            } 
            set {
                if (value != null) { 
                    value = value.Trim();
                }
                if (Data != value) {
                    if (_disallowChanges) { 
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "Data", ID));
                    } 
                    _data = value; 
                    _xmlDocument = null;
                    OnDataSourceChanged(EventArgs.Empty); 
                }
            }
        }
 
        /// 
        /// Path to an XML file. 
        ///  
        [
        DefaultValue(""), 
        Editor("System.Web.UI.Design.XmlDataFileEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_DataFile),
        ] 
        public virtual string DataFile {
            get { 
                if (_dataFile == null) { 
                    return String.Empty;
                } 
                return _dataFile;
            }
            set {
                if (DataFile != value) { 
                    if (_disallowChanges) {
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "DataFile", ID)); 
                    } 
                    _dataFile = value;
                    _xmlDocument = null; 
                    _writeableDataFile = null;
                    OnDataSourceChanged(EventArgs.Empty);
                }
            } 
        }
 
        ///  
        /// Whether caching is enabled for this data source.
        ///  
        [
        DefaultValue(true),
        WebCategory("Cache"),
        WebSysDescription(SR.DataSourceCache_Enabled), 
        ]
        public virtual bool EnableCaching { 
            get { 
                return Cache.Enabled;
            } 
            set {
                Cache.Enabled = value;
            }
        } 

        ///  
        /// Indicates whether the XML data can be modified. 
        /// This is also used by XmlDataSourceView to determine whether CanDelete/Insert/Update are true.
        ///  
        internal bool IsModifiable {
            get {
                return (String.IsNullOrEmpty(TransformFile) &&
                        String.IsNullOrEmpty(Transform) && 
                        !String.IsNullOrEmpty(WriteableDataFile));
            } 
        } 

        ///  
        /// Inline XSL transform.
        /// 
        [
        DefaultValue(""), 
        Editor("System.ComponentModel.Design.MultilineStringEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty), 
        TypeConverter("System.ComponentModel.MultilineStringConverter," + AssemblyRef.System), 
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_Transform), 
        ]
        public virtual string Transform {
            get {
                if (_transform == null) { 
                    return String.Empty;
                } 
                return _transform; 
            }
            set { 
                if (value != null) {
                    value = value.Trim();
                }
                if (Transform != value) { 
                    if (_disallowChanges) {
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "Transform", ID)); 
                    } 
                    _transform = value;
                    _xmlDocument = null; 
                    OnDataSourceChanged(EventArgs.Empty);
                }
            }
        } 

        ///  
        /// Arguments for the XSL transform. 
        /// This should be populated in the Transforming event.
        ///  
        [
        Browsable(false),
        ]
        public virtual XsltArgumentList TransformArgumentList { 
            get {
                return _transformArgumentList; 
            } 
            set {
                _transformArgumentList = value; 
            }
        }

        ///  
        /// Path to an XSL transform file.
        ///  
        [ 
        DefaultValue(""),
        Editor("System.Web.UI.Design.XslTransformFileEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_TransformFile),
        ]
        public virtual string TransformFile { 
            get {
                if (_transformFile == null) { 
                    return String.Empty; 
                }
                return _transformFile; 
            }
            set {
                if (TransformFile != value) {
                    if (_disallowChanges) { 
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "TransformFile", ID));
                    } 
                    _transformFile = value; 
                    _xmlDocument = null;
                    OnDataSourceChanged(EventArgs.Empty); 
                }
            }
        }
 
        /// 
        /// Gets a physical path of the data file that can be written to. 
        /// The value is null if the path is not a writable path. 
        /// 
        private string WriteableDataFile { 
            get {
                if (_writeableDataFile == null) {
                    _writeableDataFile = GetWriteableDataFile();
                } 
                return _writeableDataFile;
            } 
        } 

        ///  
        /// Specifies an initial XPath that is applied to the XML data.
        /// 
        [
        DefaultValue(""), 
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_XPath), 
        ] 
        public virtual string XPath {
            get { 
                if (_xPath == null) {
                    return String.Empty;
                }
                return _xPath; 
            }
            set { 
                if (XPath != value) { 
                    if (_disallowChanges) {
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "XPath", ID)); 
                    }
                    _xPath = value;
                    OnDataSourceChanged(EventArgs.Empty);
                } 
            }
        } 
 

        ///  
        /// Raised before the XSL transform is applied.
        /// 
        [
        WebCategory("Data"), 
        WebSysDescription(SR.XmlDataSource_Transforming),
        ] 
        public event EventHandler Transforming { 
            add {
                Events.AddHandler(EventTransforming, value); 
            }
            remove {
                Events.RemoveHandler(EventTransforming, value);
            } 
        }
 
 
        /// 
        /// Creates a unique cache key for this data source's data. 
        /// 
        // Made internal for unit testing
        internal string CreateCacheKey() {
            StringBuilder sb = new StringBuilder(CacheInternal.PrefixDataSourceControl, 1024); 
            sb.Append(GetType().GetHashCode().ToString(CultureInfo.InvariantCulture));
 
            sb.Append(CacheDuration.ToString(CultureInfo.InvariantCulture)); 
            sb.Append(':');
            sb.Append(((int)CacheExpirationPolicy).ToString(CultureInfo.InvariantCulture)); 

            bool includeUniqueID = false;

            if (!String.IsNullOrEmpty(CacheKeyContext)) { 
                sb.Append(':');
                sb.Append(CacheKeyContext); 
            } 

            if (DataFile.Length > 0) { 
                sb.Append(':');
                sb.Append(DataFile);
            }
            else { 
                if (Data.Length > 0) {
                    includeUniqueID = true; 
                } 
            }
 
            if (TransformFile.Length > 0) {
                sb.Append(':');
                sb.Append(TransformFile);
            } 
            else {
                if (Transform.Length > 0) { 
                    includeUniqueID = true; 
                }
            } 

            if (includeUniqueID) {
                // If we don't have any paths, use the Page
                if (Page != null) { 
                    sb.Append(':');
                    sb.Append(Page.GetType().AssemblyQualifiedName); 
                } 
                sb.Append(':');
                string uniqueID = UniqueID; 
                if (String.IsNullOrEmpty(uniqueID)) {
                    throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_NeedUniqueIDForCache));
                }
                sb.Append(uniqueID); 
            }
 
            return sb.ToString(); 
        }
 
        /// 
        /// Returns a HierarchicalDataSourceView based on an XPath specified by viewPath.
        /// 
        protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath) { 
            return new XmlHierarchicalDataSourceView(this, viewPath);
        } 
 
        /// 
        /// Gets an XmlReader representing XML or XSL content, and optionally a cache 
        /// dependency for that content.
        /// Supported paths are: Relative paths, physical paths, UNC paths, and HTTP URLs
        /// If a path is not provided, the content parameter is assumed to contain the
        /// actual content. 
        /// If there is no data, null is returned.
        /// This method is fully compatible with Virtual Path Providers. 
        ///  
        private XmlReader GetReader(string path, string content, out CacheDependency cacheDependency) {
            // If a filename is specified, load from file. Otherwise load from inner content. 
            if (path.Length != 0) {
                // First try to detect if it is an HTTP URL
                Uri uri;
                bool success = Uri.TryCreate(path, UriKind.Absolute, out uri); 
                if (success) {
                    if (uri.Scheme == Uri.UriSchemeHttp) { 
                        // Check for Web permissions for the URL we want 
                        if (!HttpRuntime.HasWebPermission(uri)) {
                            throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_NoWebPermission, uri.PathAndQuery, ID)); 
                        }
                        // Dependencies are not supported with HTTP URLs
                        cacheDependency = null;
                        // If it is an HTTP URL and we have permissions, get a reader 
                        return new XmlTextReader(path);
                    } 
                } 

                // Now see what kind of file-based path it is 
                VirtualPath virtualPath;
                string physicalPath;
                ResolvePhysicalOrVirtualPath(path, out virtualPath, out physicalPath);
 
                if (virtualPath != null && DesignMode) {
                    // This exception should never be thrown - the designer always maps paths 
                    // before using the runtime control. 
                    throw new NotSupportedException(SR.GetString(SR.XmlDataSource_DesignTimeRelativePathsNotSupported, ID));
                } 

                Stream dataStream = OpenFileAndGetDependency(virtualPath, physicalPath, out cacheDependency);
                return new XmlTextReader(dataStream);
            } 
            else {
                // Dependencies are not supported with inline content 
                cacheDependency = null; 
                content = content.Trim();
                if (content.Length == 0) { 
                    return null;
                }
                else {
                    return new XmlTextReader(new StringReader(content)); 
                }
            } 
        } 

        ///  
        /// Gets a path to a writeable file where we can save data to.
        /// The return value is null if a writeable path cannot be found.
        /// 
        private string GetWriteableDataFile() { 
            if (DataFile.Length != 0) {
                // First try to detect if it is an HTTP URL 
                Uri uri; 
                bool success = Uri.TryCreate(DataFile, UriKind.Absolute, out uri);
                if (success) { 
                    if (uri.Scheme == Uri.UriSchemeHttp) {
                        // Cannot write to HTTP URLs
                        return null;
                    } 
                }
 
                if (HostingEnvironment.UsingMapPathBasedVirtualPathProvider) { 
                    // Now see what kind of file-based path it is
                    VirtualPath virtualPath; 
                    string physicalPath;
                    ResolvePhysicalOrVirtualPath(DataFile, out virtualPath, out physicalPath);
                    if (physicalPath == null) {
                        physicalPath = virtualPath.MapPathInternal(this.TemplateControlVirtualDirectory, true /*allowCrossAppMapping*/); 
                    }
                    return physicalPath; 
                } 
                else {
                    // File is coming from a custom virtual path provider, and there is no support for writing 
                    return null;
                }
            }
            else { 
                // Data is specified using Data property, so it is not writeable
                return null; 
            } 
        }
 
        /// 
        /// Returns the XmlDocument representing the XML data.
        /// If necessary, the XML data will be reloaded along with the transform, if available.
        ///  
        public XmlDocument GetXmlDocument() {
 
            string cacheKey = null; 

            if (!_cacheLookupDone && Cache.Enabled) { 
                // If caching is enabled, attempt to load from cache.
                cacheKey = CreateCacheKey();
                _xmlDocument = Cache.LoadDataFromCache(cacheKey) as XmlDocument;
 
                _cacheLookupDone = true;
            } 
 
            if (_xmlDocument == null) {
 
                // Load up the data
                _xmlDocument = new XmlDocument();
                CacheDependency transformCacheDependency;
                CacheDependency dataCacheDependency; 

                PopulateXmlDocument(_xmlDocument, out dataCacheDependency, out transformCacheDependency); 
 
                if (cacheKey != null) {
                    Debug.Assert(Cache.Enabled); 

                    // If caching is enabled, save the XmlDocument to cache.
                    CacheDependency fileDependency;
                    if (dataCacheDependency != null) { 
                        if (transformCacheDependency != null) {
                            // We have both a data file as well as a transform file dependency 
                            AggregateCacheDependency aggregateDependency = new AggregateCacheDependency(); 
                            aggregateDependency.Add(dataCacheDependency, transformCacheDependency);
                            fileDependency = aggregateDependency; 
                        }
                        else {
                            // We only have a data file dependency
                            fileDependency = dataCacheDependency; 
                        }
                    } 
                    else { 
                        // We have at most only a transform file dependency (or no dependency at all)
                        fileDependency = transformCacheDependency; 
                    }

                    Cache.SaveDataToCache(cacheKey, _xmlDocument, fileDependency);
                } 
            }
 
            return _xmlDocument; 
        }
 
        /// 
        /// Populates an XmlDocument with the appropriate XML data, including applying transforms.
        /// 
        private void PopulateXmlDocument(XmlDocument document, out CacheDependency dataCacheDependency, out CacheDependency transformCacheDependency) { 
            XmlReader transformReader = null;
            XmlReader dataReader = null; 
            XmlReader tempDataReader = null; 

            try { 
                // Don't allow changes to the XmlDataSource while we are loading the document
                _disallowChanges = true;

                // Check if transform is specified. 
                // If there is a transform, load the data, then the transform, and get an XmlReader from the transformation.
                transformReader = GetReader(TransformFile, Transform, out transformCacheDependency); 
                if (transformReader != null) { 
                    // Now load the transform and pass it off to the reader
 
#pragma warning disable 0618    // To avoid deprecation warning
                    XslTransform transform = new XslTransform();
#pragma warning restore 0618
 
                    transform.Load(transformReader, null, null);
 
                    OnTransforming(EventArgs.Empty); 

                    XmlDocument tempDocument = new XmlDocument(); 
                    tempDataReader = GetReader(DataFile, Data, out dataCacheDependency);
                    tempDocument.Load(tempDataReader);

                    // The XmlResolver cast on the third parameter is required to eliminate an ambiguity 
                    // from the compiler.
                    dataReader = transform.Transform(tempDocument, _transformArgumentList, (XmlResolver)null); 
                } 
                else {
                    dataReader = GetReader(DataFile, Data, out dataCacheDependency); 
                }

                // Finally, load up the actual data
                document.Load(dataReader); 
            }
            finally { 
                _disallowChanges = false; 

                if (dataReader != null) { 
                    dataReader.Close();
                }
                if (tempDataReader != null) {
                    tempDataReader.Close(); 
                }
                if (transformReader != null) { 
                    transformReader.Close(); 
                }
            } 
        }

        /// 
        /// Called right before the XSLT transform is applied. 
        /// This allows a developer to supply an XsltArgumentList in the TransformArgumentList property.
        ///  
        protected virtual void OnTransforming(EventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventTransforming];
            if (handler != null) { 
                handler(this, e);
            }
        }
 
        /// 
        /// Saves the XML data to disk. 
        ///  
        public void Save() {
            if (!IsModifiable) { 
                throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_SaveNotAllowed, ID));
            }

            string writeableDataFile = WriteableDataFile; 
            Debug.Assert(!String.IsNullOrEmpty(writeableDataFile), "Did not expect WriteableDataFile to be empty in Save()");
 
            // Check for write permissions 
            HttpRuntime.CheckFilePermission(writeableDataFile, true);
 
            // Save the document
            GetXmlDocument().Save(writeableDataFile);
        }
 

        #region Implementation of IDataSource 
        event EventHandler IDataSource.DataSourceChanged { 
            add {
                ((IHierarchicalDataSource)this).DataSourceChanged += value; 
            }
            remove {
                ((IHierarchicalDataSource)this).DataSourceChanged -= value;
            } 
        }
 
 
        /// 
        DataSourceView IDataSource.GetView(string viewName) { 
            if (viewName.Length == 0) {
                viewName = DefaultViewName;
            }
            return new XmlDataSourceView(this, viewName); 
        }
 
 
        /// 
        ICollection IDataSource.GetViewNames() { 
            if (_viewNames == null) {
                _viewNames = new string[1] { DefaultViewName };
            }
            return _viewNames; 
        }
        #endregion 
 
        #region Implementation of IListSource
        ///  
        bool IListSource.ContainsListCollection {
            get {
                if (DesignMode) {
                    return false; 
                }
                return ListSourceHelper.ContainsListCollection(this); 
            } 
        }
 

        /// 
        IList IListSource.GetList() {
            if (DesignMode) { 
                return null;
            } 
            return ListSourceHelper.GetList(this); 
        }
        #endregion 
    }
}


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

namespace System.Web.UI.WebControls { 
 
    using System;
    using System.Collections; 
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Design; 
    using System.Globalization;
    using System.IO; 
    using System.Text; 
    using System.Web;
    using System.Web.Hosting; 
    using System.Web.Caching;
    using System.Web.UI;
    using System.Xml;
    using System.Xml.Xsl; 
    using System.Web.Util;
 
 

    ///  
    /// Represents an XML file as both an IDataSource and an IHierarchicalDataSource.
    /// The XML data is retrieved either from a file specified by the DataFile property
    /// or by inline XML content in the Data property.
    ///  
    [
    DefaultEvent("Transforming"), 
    DefaultProperty("DataFile"), 
    Designer("System.Web.UI.Design.WebControls.XmlDataSourceDesigner, " + AssemblyRef.SystemDesign),
    ParseChildren(true), 
    PersistChildren(false),
    ToolboxBitmap(typeof(XmlDataSource)),
    WebSysDescription(SR.XmlDataSource_Description),
    WebSysDisplayName(SR.XmlDataSource_DisplayName) 
    ]
    public class XmlDataSource : HierarchicalDataSourceControl, IDataSource, IListSource { 
 
        private static readonly object EventTransforming = new object();
        private const string DefaultViewName = "DefaultView"; 

        private DataSourceCache _cache;
        private bool _cacheLookupDone;
        private bool _disallowChanges; 
        private XsltArgumentList _transformArgumentList;
        private ICollection _viewNames; 
        private XmlDocument _xmlDocument; 
        private string _writeableDataFile;
 
        private string _data;
        private string _dataFile;
        private string _transform;
        private string _transformFile; 
        private string _xPath;
 
 
        /// 
        /// Specifies the cache settings for this data source. 
        /// 
        private DataSourceCache Cache {
            get {
                if (_cache == null) { 
                    _cache = new DataSourceCache();
                    _cache.Enabled = true; 
                } 
                return _cache;
            } 
        }


        ///  
        /// The duration, in seconds, of the expiration. The expiration policy is specified by the CacheExpirationPolicy property.
        ///  
        [ 
        DefaultValue(DataSourceCache.Infinite),
        TypeConverterAttribute(typeof(DataSourceCacheDurationConverter)), 
        WebCategory("Cache"),
        WebSysDescription(SR.DataSourceCache_Duration),
        ]
        public virtual int CacheDuration { 
            get {
                return Cache.Duration; 
            } 
            set {
                Cache.Duration = value; 
            }
        }

        ///  
        /// The expiration policy of the cache. The duration for the expiration is specified by the CacheDuration property.
        ///  
        [ 
        DefaultValue(DataSourceCacheExpiry.Absolute),
        WebCategory("Cache"), 
        WebSysDescription(SR.DataSourceCache_ExpirationPolicy),
        ]
        public virtual DataSourceCacheExpiry CacheExpirationPolicy {
            get { 
                return Cache.ExpirationPolicy;
            } 
            set { 
                Cache.ExpirationPolicy = value;
            } 
        }

        /// 
        /// Indicates an arbitrary cache key to make this cache entry depend on. This allows 
        /// the user to further customize when this cache entry will expire.
        ///  
        [ 
        DefaultValue(""),
        WebCategory("Cache"), 
        WebSysDescription(SR.DataSourceCache_KeyDependency),
        ]
        public virtual string CacheKeyDependency {
            get { 
                return Cache.KeyDependency;
            } 
            set { 
                Cache.KeyDependency = value;
            } 
        }

        [
        DefaultValue(""), 
        WebCategory("Cache"),
        WebSysDescription(SR.XmlDataSource_CacheKeyContext), 
        ] 
        public virtual string CacheKeyContext {
            get { 
                return (string)ViewState["CacheKeyContext "] ?? String.Empty;
            }
            set {
                ViewState["CacheKeyContext "] = value; 
            }
        } 
 
        /// 
        /// Inline XML content. 
        /// 
        [
        DefaultValue(""),
        Editor("System.ComponentModel.Design.MultilineStringEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TypeConverter("System.ComponentModel.MultilineStringConverter," + AssemblyRef.System), 
        WebCategory("Data"), 
        WebSysDescription(SR.XmlDataSource_Data),
        ] 
        public virtual string Data {
            get {
                if (_data == null) {
                    return String.Empty; 
                }
                return _data; 
            } 
            set {
                if (value != null) { 
                    value = value.Trim();
                }
                if (Data != value) {
                    if (_disallowChanges) { 
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "Data", ID));
                    } 
                    _data = value; 
                    _xmlDocument = null;
                    OnDataSourceChanged(EventArgs.Empty); 
                }
            }
        }
 
        /// 
        /// Path to an XML file. 
        ///  
        [
        DefaultValue(""), 
        Editor("System.Web.UI.Design.XmlDataFileEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_DataFile),
        ] 
        public virtual string DataFile {
            get { 
                if (_dataFile == null) { 
                    return String.Empty;
                } 
                return _dataFile;
            }
            set {
                if (DataFile != value) { 
                    if (_disallowChanges) {
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "DataFile", ID)); 
                    } 
                    _dataFile = value;
                    _xmlDocument = null; 
                    _writeableDataFile = null;
                    OnDataSourceChanged(EventArgs.Empty);
                }
            } 
        }
 
        ///  
        /// Whether caching is enabled for this data source.
        ///  
        [
        DefaultValue(true),
        WebCategory("Cache"),
        WebSysDescription(SR.DataSourceCache_Enabled), 
        ]
        public virtual bool EnableCaching { 
            get { 
                return Cache.Enabled;
            } 
            set {
                Cache.Enabled = value;
            }
        } 

        ///  
        /// Indicates whether the XML data can be modified. 
        /// This is also used by XmlDataSourceView to determine whether CanDelete/Insert/Update are true.
        ///  
        internal bool IsModifiable {
            get {
                return (String.IsNullOrEmpty(TransformFile) &&
                        String.IsNullOrEmpty(Transform) && 
                        !String.IsNullOrEmpty(WriteableDataFile));
            } 
        } 

        ///  
        /// Inline XSL transform.
        /// 
        [
        DefaultValue(""), 
        Editor("System.ComponentModel.Design.MultilineStringEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty), 
        TypeConverter("System.ComponentModel.MultilineStringConverter," + AssemblyRef.System), 
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_Transform), 
        ]
        public virtual string Transform {
            get {
                if (_transform == null) { 
                    return String.Empty;
                } 
                return _transform; 
            }
            set { 
                if (value != null) {
                    value = value.Trim();
                }
                if (Transform != value) { 
                    if (_disallowChanges) {
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "Transform", ID)); 
                    } 
                    _transform = value;
                    _xmlDocument = null; 
                    OnDataSourceChanged(EventArgs.Empty);
                }
            }
        } 

        ///  
        /// Arguments for the XSL transform. 
        /// This should be populated in the Transforming event.
        ///  
        [
        Browsable(false),
        ]
        public virtual XsltArgumentList TransformArgumentList { 
            get {
                return _transformArgumentList; 
            } 
            set {
                _transformArgumentList = value; 
            }
        }

        ///  
        /// Path to an XSL transform file.
        ///  
        [ 
        DefaultValue(""),
        Editor("System.Web.UI.Design.XslTransformFileEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_TransformFile),
        ]
        public virtual string TransformFile { 
            get {
                if (_transformFile == null) { 
                    return String.Empty; 
                }
                return _transformFile; 
            }
            set {
                if (TransformFile != value) {
                    if (_disallowChanges) { 
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "TransformFile", ID));
                    } 
                    _transformFile = value; 
                    _xmlDocument = null;
                    OnDataSourceChanged(EventArgs.Empty); 
                }
            }
        }
 
        /// 
        /// Gets a physical path of the data file that can be written to. 
        /// The value is null if the path is not a writable path. 
        /// 
        private string WriteableDataFile { 
            get {
                if (_writeableDataFile == null) {
                    _writeableDataFile = GetWriteableDataFile();
                } 
                return _writeableDataFile;
            } 
        } 

        ///  
        /// Specifies an initial XPath that is applied to the XML data.
        /// 
        [
        DefaultValue(""), 
        WebCategory("Data"),
        WebSysDescription(SR.XmlDataSource_XPath), 
        ] 
        public virtual string XPath {
            get { 
                if (_xPath == null) {
                    return String.Empty;
                }
                return _xPath; 
            }
            set { 
                if (XPath != value) { 
                    if (_disallowChanges) {
                        throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_CannotChangeWhileLoading, "XPath", ID)); 
                    }
                    _xPath = value;
                    OnDataSourceChanged(EventArgs.Empty);
                } 
            }
        } 
 

        ///  
        /// Raised before the XSL transform is applied.
        /// 
        [
        WebCategory("Data"), 
        WebSysDescription(SR.XmlDataSource_Transforming),
        ] 
        public event EventHandler Transforming { 
            add {
                Events.AddHandler(EventTransforming, value); 
            }
            remove {
                Events.RemoveHandler(EventTransforming, value);
            } 
        }
 
 
        /// 
        /// Creates a unique cache key for this data source's data. 
        /// 
        // Made internal for unit testing
        internal string CreateCacheKey() {
            StringBuilder sb = new StringBuilder(CacheInternal.PrefixDataSourceControl, 1024); 
            sb.Append(GetType().GetHashCode().ToString(CultureInfo.InvariantCulture));
 
            sb.Append(CacheDuration.ToString(CultureInfo.InvariantCulture)); 
            sb.Append(':');
            sb.Append(((int)CacheExpirationPolicy).ToString(CultureInfo.InvariantCulture)); 

            bool includeUniqueID = false;

            if (!String.IsNullOrEmpty(CacheKeyContext)) { 
                sb.Append(':');
                sb.Append(CacheKeyContext); 
            } 

            if (DataFile.Length > 0) { 
                sb.Append(':');
                sb.Append(DataFile);
            }
            else { 
                if (Data.Length > 0) {
                    includeUniqueID = true; 
                } 
            }
 
            if (TransformFile.Length > 0) {
                sb.Append(':');
                sb.Append(TransformFile);
            } 
            else {
                if (Transform.Length > 0) { 
                    includeUniqueID = true; 
                }
            } 

            if (includeUniqueID) {
                // If we don't have any paths, use the Page
                if (Page != null) { 
                    sb.Append(':');
                    sb.Append(Page.GetType().AssemblyQualifiedName); 
                } 
                sb.Append(':');
                string uniqueID = UniqueID; 
                if (String.IsNullOrEmpty(uniqueID)) {
                    throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_NeedUniqueIDForCache));
                }
                sb.Append(uniqueID); 
            }
 
            return sb.ToString(); 
        }
 
        /// 
        /// Returns a HierarchicalDataSourceView based on an XPath specified by viewPath.
        /// 
        protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath) { 
            return new XmlHierarchicalDataSourceView(this, viewPath);
        } 
 
        /// 
        /// Gets an XmlReader representing XML or XSL content, and optionally a cache 
        /// dependency for that content.
        /// Supported paths are: Relative paths, physical paths, UNC paths, and HTTP URLs
        /// If a path is not provided, the content parameter is assumed to contain the
        /// actual content. 
        /// If there is no data, null is returned.
        /// This method is fully compatible with Virtual Path Providers. 
        ///  
        private XmlReader GetReader(string path, string content, out CacheDependency cacheDependency) {
            // If a filename is specified, load from file. Otherwise load from inner content. 
            if (path.Length != 0) {
                // First try to detect if it is an HTTP URL
                Uri uri;
                bool success = Uri.TryCreate(path, UriKind.Absolute, out uri); 
                if (success) {
                    if (uri.Scheme == Uri.UriSchemeHttp) { 
                        // Check for Web permissions for the URL we want 
                        if (!HttpRuntime.HasWebPermission(uri)) {
                            throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_NoWebPermission, uri.PathAndQuery, ID)); 
                        }
                        // Dependencies are not supported with HTTP URLs
                        cacheDependency = null;
                        // If it is an HTTP URL and we have permissions, get a reader 
                        return new XmlTextReader(path);
                    } 
                } 

                // Now see what kind of file-based path it is 
                VirtualPath virtualPath;
                string physicalPath;
                ResolvePhysicalOrVirtualPath(path, out virtualPath, out physicalPath);
 
                if (virtualPath != null && DesignMode) {
                    // This exception should never be thrown - the designer always maps paths 
                    // before using the runtime control. 
                    throw new NotSupportedException(SR.GetString(SR.XmlDataSource_DesignTimeRelativePathsNotSupported, ID));
                } 

                Stream dataStream = OpenFileAndGetDependency(virtualPath, physicalPath, out cacheDependency);
                return new XmlTextReader(dataStream);
            } 
            else {
                // Dependencies are not supported with inline content 
                cacheDependency = null; 
                content = content.Trim();
                if (content.Length == 0) { 
                    return null;
                }
                else {
                    return new XmlTextReader(new StringReader(content)); 
                }
            } 
        } 

        ///  
        /// Gets a path to a writeable file where we can save data to.
        /// The return value is null if a writeable path cannot be found.
        /// 
        private string GetWriteableDataFile() { 
            if (DataFile.Length != 0) {
                // First try to detect if it is an HTTP URL 
                Uri uri; 
                bool success = Uri.TryCreate(DataFile, UriKind.Absolute, out uri);
                if (success) { 
                    if (uri.Scheme == Uri.UriSchemeHttp) {
                        // Cannot write to HTTP URLs
                        return null;
                    } 
                }
 
                if (HostingEnvironment.UsingMapPathBasedVirtualPathProvider) { 
                    // Now see what kind of file-based path it is
                    VirtualPath virtualPath; 
                    string physicalPath;
                    ResolvePhysicalOrVirtualPath(DataFile, out virtualPath, out physicalPath);
                    if (physicalPath == null) {
                        physicalPath = virtualPath.MapPathInternal(this.TemplateControlVirtualDirectory, true /*allowCrossAppMapping*/); 
                    }
                    return physicalPath; 
                } 
                else {
                    // File is coming from a custom virtual path provider, and there is no support for writing 
                    return null;
                }
            }
            else { 
                // Data is specified using Data property, so it is not writeable
                return null; 
            } 
        }
 
        /// 
        /// Returns the XmlDocument representing the XML data.
        /// If necessary, the XML data will be reloaded along with the transform, if available.
        ///  
        public XmlDocument GetXmlDocument() {
 
            string cacheKey = null; 

            if (!_cacheLookupDone && Cache.Enabled) { 
                // If caching is enabled, attempt to load from cache.
                cacheKey = CreateCacheKey();
                _xmlDocument = Cache.LoadDataFromCache(cacheKey) as XmlDocument;
 
                _cacheLookupDone = true;
            } 
 
            if (_xmlDocument == null) {
 
                // Load up the data
                _xmlDocument = new XmlDocument();
                CacheDependency transformCacheDependency;
                CacheDependency dataCacheDependency; 

                PopulateXmlDocument(_xmlDocument, out dataCacheDependency, out transformCacheDependency); 
 
                if (cacheKey != null) {
                    Debug.Assert(Cache.Enabled); 

                    // If caching is enabled, save the XmlDocument to cache.
                    CacheDependency fileDependency;
                    if (dataCacheDependency != null) { 
                        if (transformCacheDependency != null) {
                            // We have both a data file as well as a transform file dependency 
                            AggregateCacheDependency aggregateDependency = new AggregateCacheDependency(); 
                            aggregateDependency.Add(dataCacheDependency, transformCacheDependency);
                            fileDependency = aggregateDependency; 
                        }
                        else {
                            // We only have a data file dependency
                            fileDependency = dataCacheDependency; 
                        }
                    } 
                    else { 
                        // We have at most only a transform file dependency (or no dependency at all)
                        fileDependency = transformCacheDependency; 
                    }

                    Cache.SaveDataToCache(cacheKey, _xmlDocument, fileDependency);
                } 
            }
 
            return _xmlDocument; 
        }
 
        /// 
        /// Populates an XmlDocument with the appropriate XML data, including applying transforms.
        /// 
        private void PopulateXmlDocument(XmlDocument document, out CacheDependency dataCacheDependency, out CacheDependency transformCacheDependency) { 
            XmlReader transformReader = null;
            XmlReader dataReader = null; 
            XmlReader tempDataReader = null; 

            try { 
                // Don't allow changes to the XmlDataSource while we are loading the document
                _disallowChanges = true;

                // Check if transform is specified. 
                // If there is a transform, load the data, then the transform, and get an XmlReader from the transformation.
                transformReader = GetReader(TransformFile, Transform, out transformCacheDependency); 
                if (transformReader != null) { 
                    // Now load the transform and pass it off to the reader
 
#pragma warning disable 0618    // To avoid deprecation warning
                    XslTransform transform = new XslTransform();
#pragma warning restore 0618
 
                    transform.Load(transformReader, null, null);
 
                    OnTransforming(EventArgs.Empty); 

                    XmlDocument tempDocument = new XmlDocument(); 
                    tempDataReader = GetReader(DataFile, Data, out dataCacheDependency);
                    tempDocument.Load(tempDataReader);

                    // The XmlResolver cast on the third parameter is required to eliminate an ambiguity 
                    // from the compiler.
                    dataReader = transform.Transform(tempDocument, _transformArgumentList, (XmlResolver)null); 
                } 
                else {
                    dataReader = GetReader(DataFile, Data, out dataCacheDependency); 
                }

                // Finally, load up the actual data
                document.Load(dataReader); 
            }
            finally { 
                _disallowChanges = false; 

                if (dataReader != null) { 
                    dataReader.Close();
                }
                if (tempDataReader != null) {
                    tempDataReader.Close(); 
                }
                if (transformReader != null) { 
                    transformReader.Close(); 
                }
            } 
        }

        /// 
        /// Called right before the XSLT transform is applied. 
        /// This allows a developer to supply an XsltArgumentList in the TransformArgumentList property.
        ///  
        protected virtual void OnTransforming(EventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventTransforming];
            if (handler != null) { 
                handler(this, e);
            }
        }
 
        /// 
        /// Saves the XML data to disk. 
        ///  
        public void Save() {
            if (!IsModifiable) { 
                throw new InvalidOperationException(SR.GetString(SR.XmlDataSource_SaveNotAllowed, ID));
            }

            string writeableDataFile = WriteableDataFile; 
            Debug.Assert(!String.IsNullOrEmpty(writeableDataFile), "Did not expect WriteableDataFile to be empty in Save()");
 
            // Check for write permissions 
            HttpRuntime.CheckFilePermission(writeableDataFile, true);
 
            // Save the document
            GetXmlDocument().Save(writeableDataFile);
        }
 

        #region Implementation of IDataSource 
        event EventHandler IDataSource.DataSourceChanged { 
            add {
                ((IHierarchicalDataSource)this).DataSourceChanged += value; 
            }
            remove {
                ((IHierarchicalDataSource)this).DataSourceChanged -= value;
            } 
        }
 
 
        /// 
        DataSourceView IDataSource.GetView(string viewName) { 
            if (viewName.Length == 0) {
                viewName = DefaultViewName;
            }
            return new XmlDataSourceView(this, viewName); 
        }
 
 
        /// 
        ICollection IDataSource.GetViewNames() { 
            if (_viewNames == null) {
                _viewNames = new string[1] { DefaultViewName };
            }
            return _viewNames; 
        }
        #endregion 
 
        #region Implementation of IListSource
        ///  
        bool IListSource.ContainsListCollection {
            get {
                if (DesignMode) {
                    return false; 
                }
                return ListSourceHelper.ContainsListCollection(this); 
            } 
        }
 

        /// 
        IList IListSource.GetList() {
            if (DesignMode) { 
                return null;
            } 
            return ListSourceHelper.GetList(this); 
        }
        #endregion 
    }
}


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