XmlDataSource.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FXUpdate3074 / FXUpdate3074 / 1.1 / DEVDIV / depot / DevDiv / releases / whidbey / QFE / ndp / fx / src / xsp / System / Web / UI / WebControls / XmlDataSource.cs / 2 / 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.Security.Permissions; 
    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)
    ] 
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    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;
            }
        } 

        ///  
        /// 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. 
        /// 
        private 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 (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.
//------------------------------------------------------------------------------ 
// 
//     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.Security.Permissions; 
    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)
    ] 
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    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;
            }
        } 

        ///  
        /// 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. 
        /// 
        private 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 (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.

                        

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