AdRotator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

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

namespace System.Web.UI.WebControls { 
    using System.IO; 
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls; 
    using System.Web.UI;
    using System.Web.Caching;
    using System.Web;
    using System; 
    using System.Collections;
    using System.Collections.Specialized; 
    using System.ComponentModel; 
    using System.ComponentModel.Design;
    using System.Drawing.Design; 
    using System.Xml;
    using System.Globalization;
    using System.Web.Util;
    using System.Security.Permissions; 
    using System.Reflection;
    using System.Text; 
 

    ///  
    ///    Displays a randomly selected ad banner on a page.
    /// 
    [
    DefaultEvent("AdCreated"), 
    DefaultProperty("AdvertisementFile"),
    Designer("System.Web.UI.Design.WebControls.AdRotatorDesigner, " + AssemblyRef.SystemDesign), 
    ToolboxData("<{0}:AdRotator runat=\"server\">") 
    ]
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    public class AdRotator : DataBoundControl {

        private static readonly object EventAdCreated = new object(); 

        private const string XmlDocumentTag = "Advertisements"; 
        private const string XmlDocumentRootXPath = "/" + XmlDocumentTag; 
        private const string XmlAdTag = "Ad";
 
        private const string KeywordProperty = "Keyword";
        private const string ImpressionsProperty = "Impressions";

        // static copy of the Random object. This is a pretty hefty object to 
        // initialize, so you don't want to create one each time.
        private static Random _random; 
 
        private String _baseUrl;
        private string _advertisementFile; 
        private AdCreatedEventArgs _adCreatedEventArgs;

        private AdRec [] _adRecs;
        private bool _isPostCacheAdHelper; 
        private string _uniqueID;
 
        private static readonly Type _adrotatorType = typeof(AdRotator); 
        private static readonly Type[] _AdCreatedParameterTypes = {typeof(AdCreatedEventArgs)};
 

        /// 
        /// Initializes a new instance of the  class.
        ///  
        public AdRotator() {
        } 
 

        ///  
        ///    Gets or sets the path to the XML file that contains advertisement data.
        /// 
        [
        Bindable(true), 
        WebCategory("Behavior"),
        DefaultValue(""), 
        Editor("System.Web.UI.Design.XmlUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        UrlProperty(),
        WebSysDescription(SR.AdRotator_AdvertisementFile) 
        ]
        public string AdvertisementFile {
            get {
                return((_advertisementFile == null) ? String.Empty : _advertisementFile); 
            }
            set { 
                _advertisementFile = value; 
            }
        } 


        [
#if ORCAS 
        Verification("WCAG", "1.1", VerificationReportLevel.Error, 1, SR.Accessibility_ImageAlternateTextFieldMissing),
        Verification("ADA", "1194.22(a)", VerificationReportLevel.Error, 1, SR.Accessibility_ImageAlternateTextFieldMissing), 
#endif 
        WebCategory("Behavior"),
        DefaultValue(AdCreatedEventArgs.AlternateTextElement), 
        WebSysDescription(SR.AdRotator_AlternateTextField)

        ]
        public String AlternateTextField { 
            get {
                String s = (String) ViewState["AlternateTextField"]; 
                return((s != null) ? s : AdCreatedEventArgs.AlternateTextElement); 
            }
            set { 
                ViewState["AlternateTextField"] = value;
            }
        }
 
        /// 
        ///   The base url corresponds for mapping of other url elements such as 
        ///   imageUrl and navigateUrl. 
        /// 
        internal String BaseUrl { 
            get {
                if (_baseUrl == null) {
                    // Deal with app relative syntax (e.g. ~/foo)
                    string tplSourceDir = TemplateControlVirtualDirectory.VirtualPathString; 

                    // For the AdRotator, use the AdvertisementFile directory as the base, and fall back to the 
                    // page/user control location as the base. 
                    String absoluteFile = null;
                    String fileDirectory = null; 
                    if (!String.IsNullOrEmpty(AdvertisementFile)) {
                        absoluteFile = UrlPath.Combine(tplSourceDir, AdvertisementFile);
                        fileDirectory = UrlPath.GetDirectory(absoluteFile);
                    } 

                    _baseUrl = string.Empty; 
                    if (fileDirectory != null) { 
                        _baseUrl = fileDirectory;
                    } 
                    if (_baseUrl.Length == 0) {
                        _baseUrl = tplSourceDir;
                    }
                } 
                return _baseUrl;
            } 
        } 

#if SITECOUNTERS 

        [
        WebCategory("SiteCounters"),
        DefaultValue("AdRotator"), 
        Themeable(false),
        WebSysDescription(SR.AdRotator_CounterGroup), 
        ] 
        public String CounterGroup {
            get { 
                String s = (String)ViewState["CounterGroup"];
                return((s == null) ? "AdRotator" : s);
            }
            set { 
                ViewState["CounterGroup"] = value;
            } 
        } 

 
        [
        WebCategory("SiteCounters"),
        DefaultValue(""),
        Themeable(false), 
        WebSysDescription(SR.AdRotator_CounterName),
        ] 
        public String CounterName { 
            get {
                String s = (String)ViewState["CounterName"]; 
                return((s == null) ? String.Empty : s);
            }
            set {
                ViewState["CounterName"] = value; 
            }
        } 
 

        [ 
        WebCategory("SiteCounters"),
        DefaultValue(false),
        Themeable(false),
        WebSysDescription(SR.AdRotator_CountClicks), 
        ]
        public bool CountClicks { 
            get { 
                object b = ViewState["CountClicks"];
                return((b == null) ? false : (bool)b); 
            }
            set {
                ViewState["CountClicks"] = value;
            } 
        }
 
 
        [
        WebCategory("SiteCounters"), 
        DefaultValue(false),
        Themeable(false),
        WebSysDescription(SR.AdRotator_CountViews),
        ] 
        public bool CountViews {
            get { 
                object b = ViewState["CountViews"]; 
                return((b == null) ? false : (bool)b);
            } 
            set {
                ViewState["CountViews"] = value;
            }
        } 
#endif
 
 
        /// 
        ///  
        ///    Font property. Has no effect on this control, so hide it.
        /// 
        [
        Browsable(false), 
        EditorBrowsableAttribute(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        ] 
        public override FontInfo Font {
            get { 
                return base.Font;
            }
        }
 

        [ 
        WebCategory("Behavior"), 
        DefaultValue(AdCreatedEventArgs.ImageUrlElement),
        WebSysDescription(SR.AdRotator_ImageUrlField) 
        ]
        public String ImageUrlField {
            get {
                String s = (String) ViewState["ImageUrlField"]; 
                return((s != null) ? s : AdCreatedEventArgs.ImageUrlElement);
            } 
            set { 
                ViewState["ImageUrlField"] = value;
            } 
        }

        private bool IsTargetSet {
            get { 
                return (ViewState["Target"] != null);
            } 
        } 

        internal bool IsPostCacheAdHelper { 
            get {
                return _isPostCacheAdHelper;
            }
            set { 
                _isPostCacheAdHelper = value;
            } 
        } 

 
        /// 
        ///    Gets or sets a category keyword used for matching related advertisements in the advertisement file.
        /// 
        [ 
        Bindable(true),
        WebCategory("Behavior"), 
        DefaultValue(""), 
        WebSysDescription(SR.AdRotator_KeywordFilter)
        ] 
        public string KeywordFilter {
            get {
                string s = (string)ViewState["KeywordFilter"];
                return((s == null) ? String.Empty : s); 
            }
            set { 
                // trim the filter value 
                if (String.IsNullOrEmpty(value)) {
                    ViewState.Remove("KeywordFilter"); 
                }
                else {
                    ViewState["KeywordFilter"] = value.Trim();
                } 
            }
        } 
 

        [ 
        WebCategory("Behavior"),
        DefaultValue(AdCreatedEventArgs.NavigateUrlElement),
        WebSysDescription(SR.AdRotator_NavigateUrlField)
        ] 
        public String NavigateUrlField {
            get { 
                String s = (String) ViewState["NavigateUrlField"]; 
                return((s != null) ? s : AdCreatedEventArgs.NavigateUrlElement);
            } 
            set {
                ViewState["NavigateUrlField"] = value;
            }
        } 

#if SITECOUNTERS 
 
        [
        WebCategory("SiteCounters"), 
        DefaultValue(-1),
        Themeable(false),
        WebSysDescription(SR.Control_For_SiteCounters_RowsPerDay),
        ] 
        public int RowsPerDay {
            get { 
                Object o = ViewState["RowsPerDay"]; 
                return((o == null) ? -1 : (int) o);
            } 
            set {
                if (value == 0) {
                    throw new ArgumentOutOfRangeException("RowsPerDay");
                } 
                ViewState["RowsPerDay"] = value;
            } 
        } 
#endif
 
        private AdCreatedEventArgs SelectedAdArgs {
            get {
                return _adCreatedEventArgs;
            } 
            set {
                _adCreatedEventArgs = value; 
            } 
        }
 
#if SITECOUNTERS

        [
        WebCategory("SiteCounters"), 
        DefaultValue(""),
        Themeable(false), 
        WebSysDescription(SR.Control_For_SiteCounters_SiteCountersProvider) 
        ]
        public String SiteCountersProvider { 
            get {
                String s = (String) ViewState["SiteCountersProvider"];
                return((s != null) ? s : String.Empty);
            } 
            set {
                ViewState["SiteCountersProvider"] = value; 
            } 
        }
#endif 


        /// 
        ///    Gets 
        ///       or sets the name of the browser window or frame to display the advertisement.
        ///  
        [ 
        Bindable(true),
        WebCategory("Behavior"), 
        DefaultValue("_top"),
        WebSysDescription(SR.AdRotator_Target),
        TypeConverter(typeof(TargetConverter))
        ] 
        public string Target {
            get { 
                string s = (string)ViewState["Target"]; 
                return((s == null) ? "_top" : s);
            } 
            set {
                ViewState["Target"] = value;
            }
        } 

#if SITECOUNTERS 
 
        [
        WebCategory("SiteCounters"), 
        DefaultValue(true),
        Themeable(false),
        WebSysDescription(SR.Control_For_SiteCounters_TrackApplicationName),
        ] 
        public bool TrackApplicationName {
            get { 
                object b = ViewState["TrackApplicationName"]; 
                return((b == null) ? true : (bool)b);
            } 
            set {
                ViewState["TrackApplicationName"] = value;
            }
        } 

 
        [ 
        WebCategory("SiteCounters"),
        DefaultValue(true), 
        Themeable(false),
        WebSysDescription(SR.Control_For_SiteCounters_TrackNavigateUrl),
        ]
        public bool TrackNavigateUrl { 
            get {
                object b = ViewState["TrackNavigateUrl"]; 
                return((b == null) ? true : (bool)b); 
            }
            set { 
                ViewState["TrackNavigateUrl"] = value;
            }
        }
 

        [ 
        WebCategory("SiteCounters"), 
        DefaultValue(true),
        Themeable(false), 
        WebSysDescription(SR.Control_For_SiteCounters_TrackPageUrl),
        ]
        public bool TrackPageUrl {
            get { 
                object b = ViewState["TrackPageUrl"];
                return((b == null) ? true : (bool)b); 
            } 
            set {
                ViewState["TrackPageUrl"] = value; 
            }
        }
#endif
 
        protected override HtmlTextWriterTag TagKey {
            get { 
                return HtmlTextWriterTag.A; 
            }
        } 

        public override string UniqueID {
            get {
                if (_uniqueID == null) { 
                    _uniqueID = base.UniqueID;
                } 
                return _uniqueID; 
            }
        } 


        /// 
        ///    Occurs once per round trip after the creation of the 
        ///       control before the page is rendered. 
        ///  
        [ 
        WebCategory("Action"),
        WebSysDescription(SR.AdRotator_OnAdCreated) 
        ]
        public event AdCreatedEventHandler AdCreated {
            add {
                Events.AddHandler(EventAdCreated, value); 
            }
            remove { 
                Events.RemoveHandler(EventAdCreated, value); 
            }
        } 

        private void CheckOnlyOneDataSource() {
            int numOfDataSources = ((AdvertisementFile.Length > 0) ? 1 : 0);
            numOfDataSources += ((DataSourceID.Length > 0) ? 1 : 0); 
            numOfDataSources += ((DataSource != null) ? 1 : 0);
 
            if (numOfDataSources > 1) { 
                throw new HttpException(SR.GetString(SR.AdRotator_only_one_datasource, ID));
            } 
        }

        // Currently this is designed to be called when PostCache Substitution is being initialized
        internal void CopyFrom(AdRotator adRotator) { 
            _adRecs = adRotator._adRecs;
 
            AccessKey = adRotator.AccessKey; 
            AlternateTextField = adRotator.AlternateTextField;
            Enabled = adRotator.Enabled; 
            ImageUrlField = adRotator.ImageUrlField;
            NavigateUrlField = adRotator.NavigateUrlField;
            TabIndex = adRotator.TabIndex;
            Target = adRotator.Target; 
            ToolTip = adRotator.ToolTip;
 
#if SITECOUNTERS 
            CounterGroup = adRotator.CounterGroup;
            CounterName = adRotator.CounterName; 
            CountClicks = adRotator.CountClicks;
            CountViews = adRotator.CountViews;
            RowsPerDay = adRotator.RowsPerDay;
            SiteCountersProvider = adRotator.SiteCountersProvider; 
            TrackApplicationName = adRotator.TrackApplicationName;
            TrackNavigateUrl = adRotator.TrackNavigateUrl; 
            TrackPageUrl = adRotator.TrackPageUrl; 
#endif
 
            string id = adRotator.ID;
            if (!String.IsNullOrEmpty(id)) {
                ID = adRotator.ClientID;
            } 

            // Below are properties that need to be handled specially and saved 
            // to private variables. 
            _uniqueID = adRotator.UniqueID;
            _baseUrl = adRotator.BaseUrl; 

            // Special copy to properties that cannot be assigned directly
            if (adRotator.HasAttributes) {
                foreach(string key in adRotator.Attributes.Keys) { 
                    Attributes[key] = adRotator.Attributes[key];
                } 
            } 

            if (adRotator.ControlStyleCreated) { 
                ControlStyle.CopyFrom(adRotator.ControlStyle);
            }
        }
 
#if SITECOUNTERS
        // Consider: Expose for adapter extensibility 
        internal void CountViewEvent(AdCreatedEventArgs adArgs) { 
            if (CountViews) {
                SiteCounters siteCounters = Context.SiteCounters; 
                string navigateUrl = adArgs.NavigateUrl;
                string defaultCounterName = (!String.IsNullOrEmpty(navigateUrl)) ? navigateUrl : ID;
                string counterName = GetCounterName(adArgs, defaultCounterName);
                string counterGroup = GetCounterGroup(adArgs); 
                int rowsPerDay = RowsPerDay;
                string providerName = SiteCountersProvider; 
                bool trackAppName = TrackApplicationName; 
                bool trackNavUrl = TrackNavigateUrl;
                bool trackPageUrl = TrackPageUrl; 

                siteCounters.Write(counterGroup, counterName, SiteCounters.ViewEventText,
                                   ((trackNavUrl) ? navigateUrl : null),
                                   trackAppName, trackPageUrl, 
                                   providerName, rowsPerDay);
            } 
        } 
#endif
 
        private ArrayList CreateAutoGeneratedFields(IEnumerable dataSource) {
            if (dataSource == null) {
                return null;
            } 

            ArrayList generatedFields = new ArrayList(); 
            PropertyDescriptorCollection propertyDescriptors = null; 

            if (dataSource is ITypedList) { 
                propertyDescriptors =
                    ((ITypedList)dataSource).GetItemProperties(new PropertyDescriptor[0]);
            }
 
            if (propertyDescriptors == null) {
 
                IEnumerator enumerator = dataSource.GetEnumerator(); 
                if (enumerator.MoveNext()) {
 
                    Object sampleItem = enumerator.Current;
                    if (IsBindableType(sampleItem.GetType())) {
                        // Raise error since we are expecting some record
                        // containing multiple data values. 
                        throw new HttpException(SR.GetString(
                                SR.AdRotator_expect_records_with_advertisement_properties, 
                                ID, sampleItem.GetType())); 
                    }
                    else { 
                        propertyDescriptors = TypeDescriptor.GetProperties(sampleItem);
                    }
                }
            } 
            if (propertyDescriptors != null && propertyDescriptors.Count > 0) {
 
                foreach (PropertyDescriptor pd in propertyDescriptors) { 
                    if (IsBindableType(pd.PropertyType)) {
                        generatedFields.Add(pd.Name); 
                    }
                }
            }
 
            return generatedFields;
        } 
 

        // 



 

 
 

        internal bool DoPostCacheSubstitutionAsNeeded(HtmlTextWriter writer) { 
            if (!IsPostCacheAdHelper && SelectedAdArgs == null &&
                Page.Response.HasCachePolicy &&
                (int)Page.Response.Cache.GetCacheability() != (int)HttpCacheabilityLimits.None) {
 
                // The checking of the cacheability is to see if the page is output cached
                AdPostCacheSubstitution adPostCacheSubstitution = new AdPostCacheSubstitution(this); 
                adPostCacheSubstitution.RegisterPostCacheCallBack(Context, Page, writer); 
                return true;
            } 
            return false;
        }

        ///  
        ///     Select an ad from ad records and create the event
        ///     argument object. 
        ///  
        private AdCreatedEventArgs GetAdCreatedEventArgs() {
            IDictionary adInfo = SelectAdFromRecords(); 
            AdCreatedEventArgs adArgs =
                new AdCreatedEventArgs(adInfo,
                                       ImageUrlField,
                                       NavigateUrlField, 
                                       AlternateTextField);
           return adArgs; 
        } 

#if SITECOUNTERS 
        // Consider: Expose for adapter extensibility
        internal string GetCountClicksUrl(AdCreatedEventArgs adArgs) {
            string countClicksUrl = adArgs.NavigateUrl;
 
            if (CountClicks && !String.IsNullOrEmpty(countClicksUrl)) {
                SiteCounters siteCounters = Context.SiteCounters; 
                string counterName = GetCounterName(adArgs, countClicksUrl); 
                string counterGroup = GetCounterGroup(adArgs);
                int rowsPerDay = RowsPerDay; 
                string providerName = SiteCountersProvider;
                bool trackAppName = TrackApplicationName;
                bool trackNavUrl = TrackNavigateUrl;
                bool trackPageUrl = TrackPageUrl; 

                countClicksUrl = siteCounters.GetRedirectUrl( 
                                    counterGroup, counterName, SiteCounters.ClickEventText, 
                                    countClicksUrl, trackAppName,
                                    trackPageUrl, trackNavUrl, 
                                    providerName, rowsPerDay);
            }

            return countClicksUrl; 
        }
 
        private string GetCounterGroup(AdCreatedEventArgs adCreatedEvent) { 
            string counterGroup;
 
            // The precedence of the group field in site counter data is
            // 1. CounterGroup specified within the ad record, if provided
            // 2. CounterGroup, if provided
            IDictionary adProps = adCreatedEvent.AdProperties; 
            string adGroup = (adProps == null) ? null : (string) adProps["CounterGroup"];
            if (adGroup != null) { 
                counterGroup = adGroup; 
            }
            else { 
                counterGroup = CounterGroup;
            }

            return counterGroup; 
        }
 
        private string GetCounterName(AdCreatedEventArgs adCreatedEvent, string defaultName) { 
            string counterName;
 
            // The precedence of the target field in site counter data is
            // 1. CounterName specified within the ad record, if provided
            // 2. CounterName on the AdRotator control, if provided
            // 3. ID of the AdRotator, if provided 
            IDictionary adProps = adCreatedEvent.AdProperties;
            string adName = (adProps == null) ? null : (string) adProps["CounterName"]; 
            if (adName != null) { 
                counterName = adName;
            } 
            else if (CounterName.Length > 0) {
                counterName = CounterName;
            }
            else { 
                counterName = defaultName;
            } 
 
            return counterName;
        } 
#endif

        private AdRec [] GetDataSourceData(IEnumerable dataSource) {
 
            ArrayList fields = CreateAutoGeneratedFields(dataSource);
 
            ArrayList adDicts = new ArrayList(); 
            IEnumerator enumerator = dataSource.GetEnumerator();
            while(enumerator.MoveNext()) { 
                IDictionary dict = null;
                foreach (String field in fields){
                    if (dict == null) {
                        dict = new HybridDictionary(); 
                    }
                    dict.Add(field, DataBinder.GetPropertyValue(enumerator.Current, field)); 
                } 

                if (dict != null) { 
                    adDicts.Add(dict);
                }
            }
 
            return SetAdRecs(adDicts);
        } 
 

        ///  
        ///   Gets the ad data for the given file by loading the file, or reading from the
        ///   application-level cache.
        /// 
        private AdRec [] GetFileData(string fileName) { 

            // VSWhidbey 208626: Adopting similar code from xml.cs to support virtual path provider 
 
            // First, figure out if it's a physical or virtual path
            VirtualPath virtualPath; 
            string physicalPath;
            ResolvePhysicalOrVirtualPath(fileName, out virtualPath, out physicalPath);

            // try to get it from the ASP.NET cache 
            string fileKey = CacheInternal.PrefixAdRotator + ((!String.IsNullOrEmpty(physicalPath)) ?
                physicalPath : virtualPath.VirtualPathString); 
            CacheInternal cacheInternal = System.Web.HttpRuntime.CacheInternal; 
            AdRec [] adRecs = cacheInternal[fileKey] as AdRec[];
 
            if (adRecs == null) {
                // Otherwise load it
                CacheDependency dependency;
                try { 
                    using (Stream stream = OpenFileAndGetDependency(virtualPath, physicalPath, out dependency)) {
                        adRecs = LoadStream(stream); 
                        Debug.Assert(adRecs != null); 
                    }
                } 
                catch (Exception e) {
                    if (!String.IsNullOrEmpty(physicalPath) && HttpRuntime.HasPathDiscoveryPermission(physicalPath)) {
                        // We want to catch the error message, but not propage the inner exception. Otherwise we can throw up
                        // logon prompts through IE; 
                        throw new HttpException(SR.GetString(SR.AdRotator_cant_open_file, ID, e.Message));
                    } 
                    else { 
                        throw new HttpException(SR.GetString(SR.AdRotator_cant_open_file_no_permission, ID));
                    } 
                }

                // Cache it, but only if we got a dependency
                if (dependency != null) { 
                    using (dependency) {
                        // and store it in the cache, dependent on the file name 
                        cacheInternal.UtcInsert(fileKey, adRecs, dependency); 
                    }
                } 
            }
            return adRecs;
        }
 
        private static int GetRandomNumber(int maxValue) {
            if (_random == null) { 
                _random = new Random(); 
            }
            return _random.Next(maxValue) + 1; 
        }

        private AdRec [] GetXmlDataSourceData(XmlDataSource xmlDataSource) {
            Debug.Assert(xmlDataSource != null); 

            XmlDocument doc = xmlDataSource.GetXmlDocument(); 
            if (doc == null) { 
                return null;
            } 
            return LoadXmlDocument(doc);
        }

        private bool IsBindableType(Type type) { 
            return(type.IsPrimitive ||
                   (type == typeof(String)) || 
                   (type == typeof(DateTime)) || 
                   (type == typeof(Decimal)));
        } 

        private bool IsOnAdCreatedOverridden() {
            bool result = false;
            Type type = this.GetType(); 
            if (type != _adrotatorType) {
                MethodInfo methodInfo = type.GetMethod("OnAdCreated", 
                                                       BindingFlags.NonPublic | BindingFlags.Instance, 
                                                       null,
                                                       _AdCreatedParameterTypes, 
                                                       null);
                if (methodInfo.DeclaringType != _adrotatorType) {
                    result = true;
                } 
            }
            return result; 
        } 

        private AdRec [] LoadFromXmlReader(XmlReader reader) { 
            ArrayList adDicts = new ArrayList();

            while (reader.Read()) {
                if (reader.Name == "Advertisements") { 
                    if (reader.Depth != 0) {
                        return null; 
                    } 
                    break;
                } 
            }

            while (reader.Read()) {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "Ad" && reader.Depth == 1) { 

                    IDictionary dict = null; 
                    reader.Read(); 
                    while (!(reader.NodeType == XmlNodeType.EndElement)) {
                        if (reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement) { 
                            if (dict == null) {
                                dict = new HybridDictionary();
                            }
                            dict.Add(reader.LocalName, reader.ReadString()); 
                        }
                        reader.Skip(); 
                    } 

                    if (dict != null) { 
                        adDicts.Add(dict);
                    }
                }
            } 

            AdRec [] adRecs = SetAdRecs(adDicts); 
            return adRecs; 
        }
 
        /// 
        ///   Loads the given XML stream into an array of AdRec structures
        /// 
        private AdRec [] LoadStream(Stream stream) { 

            AdRec [] adRecs = null; 
            try { 
                // Read the XML stream into an array of dictionaries
                XmlReader reader = new XmlTextReader(stream); 

                // Perf: We use LoadFromXmlReader instead of LoadXmlDocument to
                // do the text parsing only once
                adRecs = LoadFromXmlReader(reader); 
            }
            catch (Exception e) { 
                throw new HttpException( 
                    SR.GetString(SR.AdRotator_parse_error, ID, e.Message), e);
            } 

            if (adRecs == null) {
                throw new HttpException(
                    SR.GetString(SR.AdRotator_no_advertisements, ID, AdvertisementFile)); 
            }
 
            return adRecs; 
        }
 
        private AdRec [] LoadXmlDocument(XmlDocument doc) {
            // Read the XML data into an array of dictionaries
            ArrayList adDicts = new ArrayList();
 
            if (doc.DocumentElement != null &&
                doc.DocumentElement.LocalName == XmlDocumentTag) { 
 
                XmlNode elem = doc.DocumentElement.FirstChild;
 
                while (elem != null) {
                    IDictionary dict = null;
                    if (elem.LocalName.Equals(XmlAdTag)) {
                        XmlNode prop = elem.FirstChild; 
                        while (prop != null) {
                            if (prop.NodeType == XmlNodeType.Element) { 
                                if (dict == null) { 
                                    dict = new HybridDictionary();
                                } 
                                dict.Add(prop.LocalName, prop.InnerText);
                            }
                            prop = prop.NextSibling;
                        } 
                    }
                    if (dict != null) { 
                        adDicts.Add(dict); 
                    }
                    elem = elem.NextSibling; 
                }
            }

            AdRec [] adRecs = SetAdRecs(adDicts); 
            return adRecs;
        } 
 
        /// 
        ///   Used to determine if the advertisement meets current criteria. Does a comparison with 
        ///   KeywordFilter if it is set.
        /// 
        private bool MatchingAd(AdRec adRec, string keywordFilter) {
            Debug.Assert(keywordFilter != null && keywordFilter.Length > 0); 
            return(String.Equals(keywordFilter, adRec.keyword, StringComparison.OrdinalIgnoreCase));
        } 
 

        ///  
        /// Raises the  event for an .
        /// 
        protected virtual void OnAdCreated(AdCreatedEventArgs e) {
            AdCreatedEventHandler handler = (AdCreatedEventHandler)Events[EventAdCreated]; 
            if (handler != null) handler(this, e);
        } 
 

        protected internal override void OnInit(EventArgs e) { 
            base.OnInit(e);

            // VSWhidbey 419600: We just always need binding data every time since
            // AdRotator doesn't store the entire Ad data in ViewState for selecting 
            // Ad during postbacks.  It's too big for storing in ViewState.
            RequiresDataBinding = true; 
        } 

        ///  
        /// 
        ///    Gets the advertisement information for rendering in its parameter, then calls
        ///     the OnAdCreated event to render the ads.
        ///  
        protected internal override void OnPreRender(EventArgs e) {
            base.OnPreRender(e); 
 
            // If after PreRender (which would call DataBind if DataSource or DataSourceID available)
            // and no _adRecs created, it must be the normal v1 behavior which uses ad file. 
            if (_adRecs == null && AdvertisementFile.Length > 0) {
                PerformAdFileBinding();
            }
 
            // If handler is specified, we don't do any post-cache
            // substitution because the handler code would not be executed. 
            // 
            // VSWhidbey 213759: We also don't want any post-cache substitution
            // if OnAdCreated has been overridden 
            if (Events[EventAdCreated] != null || IsOnAdCreatedOverridden()) {
                // Fire the user event for further customization
                SelectedAdArgs = GetAdCreatedEventArgs();
                OnAdCreated(SelectedAdArgs); 
            }
        } 
 
        private void PerformAdFileBinding() {
            // Getting ad data from physical file is V1 way which is not supported 
            // by the base class DataBoundControl so we had above code to handle
            // this case.  However, we need to support DataBound control events
            // in Whidbey and since above code doesn't go through the event
            // raising in the base class DataBoundControl, here we mimic them. 
            OnDataBinding(EventArgs.Empty);
 
            // get the ads from the file or app cache 
            _adRecs = GetFileData(AdvertisementFile);
 
            OnDataBound(EventArgs.Empty);
        }

        protected internal override void PerformDataBinding(IEnumerable data) { 
            if (data != null) {
                // We retrieve ad data from xml format in a specific way. 
                XmlDataSource xmlDataSource = null; 
                object dataSource = DataSource;
                if (dataSource != null) { 
                    xmlDataSource = dataSource as XmlDataSource;
                }
                else { // DataSourceID case, we know that only one source is available
                    xmlDataSource = GetDataSource() as XmlDataSource; 
                }
 
                if (xmlDataSource != null) { 
                    _adRecs = GetXmlDataSourceData(xmlDataSource);
                } 
                else {
                    _adRecs = GetDataSourceData(data);
                }
            } 
        }
 
        protected override void PerformSelect() { 
            // VSWhidbey 141362
            CheckOnlyOneDataSource(); 

            if (AdvertisementFile.Length > 0) {
                PerformAdFileBinding();
            } 
            else {
                base.PerformSelect(); 
            } 
        }
 
        //
        internal AdCreatedEventArgs PickAd() {
            AdCreatedEventArgs adArgs = SelectedAdArgs;
            if (adArgs == null) { 
                adArgs = GetAdCreatedEventArgs();
            } 
            adArgs.ImageUrl = ResolveAdRotatorUrl(BaseUrl, adArgs.ImageUrl); 
            adArgs.NavigateUrl = ResolveAdRotatorUrl(BaseUrl, adArgs.NavigateUrl);
            return adArgs; 
        }


        ///  
        /// 
        /// Displays the  on the client. 
        ///  
        protected internal override void Render(HtmlTextWriter writer) {
            if (!DesignMode && !IsPostCacheAdHelper && 
                DoPostCacheSubstitutionAsNeeded(writer)) {
                return;
            }
 
            AdCreatedEventArgs adArgs = PickAd();
            RenderLink(writer, adArgs); 
#if SITECOUNTERS 
            CountViewEvent(adArgs);
#endif 
        }

        private void RenderLink(HtmlTextWriter writer, AdCreatedEventArgs adArgs) {
            Debug.Assert(writer != null); 
            Debug.Assert(adArgs != null);
 
            HyperLink bannerLink = new HyperLink(); 

#if SITECOUNTERS 
            bannerLink.NavigateUrl = GetCountClicksUrl(adArgs);
#else
            bannerLink.NavigateUrl = adArgs.NavigateUrl;
#endif 
            bannerLink.Target = Target;
 
            if (HasAttributes) { 
                foreach(string key in Attributes.Keys) {
                    bannerLink.Attributes[key] = Attributes[key]; 
                }
            }

            string id = ID; 
            if (!String.IsNullOrEmpty(id)) {
                bannerLink.ID = ClientID; 
            } 

            if (!Enabled) { 
                bannerLink.Enabled = false;
            }

            // WebControl's properties use a private flag to determine if a 
            // property is set and does not return the value unless the flag is
            // marked.  So here we access those properites (inherited from WebControl) 
            // directly from the ViewState bag because if ViewState bag reference 
            // was copied to the helper class in the optimized case during the
            // Initialize() method, the flags of the properties wouldn't be set 
            // in the helper class.
            string accessKey = (string) ViewState["AccessKey"];
            if (!String.IsNullOrEmpty(accessKey)) {
                bannerLink.AccessKey = accessKey; 
            }
 
            object o = ViewState["TabIndex"]; 
            if (o != null) {
                short tabIndex = (short) o; 
                if (tabIndex != (short) 0) {
                    bannerLink.TabIndex = tabIndex;
                }
            } 

            bannerLink.RenderBeginTag(writer); 
 
            // create inner Image
            Image bannerImage = new Image(); 
            // apply styles to image
            if (ControlStyleCreated) {
                bannerImage.ApplyStyle(ControlStyle);
            } 

            string alternateText = adArgs.AlternateText; 
            if (!String.IsNullOrEmpty(alternateText)) { 
                bannerImage.AlternateText = alternateText;
            } 
            else {
                // 25914 Do not render empty 'alt' attribute if  tag is never specified
                IDictionary adProps = adArgs.AdProperties;
                string altTextKey = (AlternateTextField.Length != 0) 
                                        ? AlternateTextField : AdCreatedEventArgs.AlternateTextElement;
                string altText = (adProps == null) ? null : (string) adProps[altTextKey]; 
                if (altText != null && altText.Length == 0) { 
                    bannerImage.GenerateEmptyAlternateText = true;
                } 
            }

            // Perf work: AdRotator should have resolved the NavigateUrl and
            // ImageUrl when assigning them and have UrlResolved set properly. 
            bannerImage.UrlResolved = true;
            string imageUrl = adArgs.ImageUrl; 
            if (!String.IsNullOrEmpty(imageUrl)) { 
                bannerImage.ImageUrl = imageUrl;
            } 

            if (adArgs.HasWidth) {
                bannerImage.ControlStyle.Width = adArgs.Width;
            } 

            if (adArgs.HasHeight) { 
                bannerImage.ControlStyle.Height = adArgs.Height; 
            }
 
            string toolTip = (string) ViewState["ToolTip"];
            if (!String.IsNullOrEmpty(toolTip)) {
                bannerImage.ToolTip = toolTip;
            } 

            bannerImage.RenderControl(writer); 
            bannerLink.RenderEndTag(writer); 
        }
 
        private string ResolveAdRotatorUrl(string baseUrl, string relativeUrl) {

            if ((relativeUrl == null) ||
                (relativeUrl.Length == 0) || 
                (UrlPath.IsRelativeUrl(relativeUrl) == false) ||
                (baseUrl == null) || 
                (baseUrl.Length == 0)) { 
                return relativeUrl;
            } 

            // make it absolute
            return UrlPath.Combine(baseUrl, relativeUrl);
        } 

        ///  
        ///     Selects an advertisement from the a list of records based 
        ///     on different factors.
        ///  
        private IDictionary SelectAdFromRecords() {
            if (_adRecs == null || _adRecs.Length == 0) {
                return null;
            } 

            string keywordFilter = KeywordFilter; 
            bool noKeywordFilter = String.IsNullOrEmpty(keywordFilter); 
            if (!noKeywordFilter) {
                // do a lower case comparison 
                keywordFilter = keywordFilter.ToLower(CultureInfo.InvariantCulture);
            }

            // sum the matching impressions 
            int totalImpressions = 0;
            for (int i = 0; i < _adRecs.Length; i++) { 
                if (noKeywordFilter || MatchingAd(_adRecs[i], keywordFilter)) { 
                    totalImpressions += _adRecs[i].impressions;
                } 
            }

            if (totalImpressions == 0) {
                return null; 
            }
 
            // select one using a random number between 1 and totalImpressions 
            int selectedImpression = GetRandomNumber(totalImpressions);
            int impressionCounter = 0; 
            int selectedIndex = -1;
            for (int i = 0; i < _adRecs.Length; i++) {
                // Is this the ad?
                if (noKeywordFilter || MatchingAd(_adRecs[i], keywordFilter)) { 
                    impressionCounter += _adRecs[i].impressions;
                    if (selectedImpression <= impressionCounter) { 
                        selectedIndex = i; 
                        break;
                    } 
                }
            }
            Debug.Assert(selectedIndex >= 0 && selectedIndex < _adRecs.Length, "Index not found");
 
            return _adRecs[selectedIndex].adProperties;
        } 
 
        private AdRec [] SetAdRecs(ArrayList adDicts) {
            if (adDicts == null || adDicts.Count == 0) { 
                return null;
            }

            // Create an array of AdRec structures from the dictionaries, removing blanks 
            AdRec [] adRecs = new AdRec[adDicts.Count];
            int iRec = 0; 
            for (int i = 0; i < adDicts.Count; i++) { 
                if (adDicts[i] != null) {
                    adRecs[iRec].Initialize((IDictionary) adDicts[i]); 
                    iRec++;
                }
            }
            Debug.Assert(iRec == adDicts.Count, "Record count did not match non-null entries"); 

            return adRecs; 
        } 

 

        /// 
        ///   Structure to store ads in memory for fast selection by multiple instances of adrotator
        ///   Stores the dictionary and caches some values for easier selection. 
        /// 
        private struct AdRec { 
            public string keyword; 
            public int impressions;
            public IDictionary adProperties; 


            /// 
            ///   Initialize the stuct based on a dictionary containing the advertisement properties 
            /// 
            public void Initialize(IDictionary adProperties) { 
 
                // Initialize the values we need to keep for ad selection
                Debug.Assert(adProperties != null, "Required here"); 
                this.adProperties = adProperties;

                // remove null and trim keyword for easier comparisons.
                // VSWhidbey 114634: Be defensive and only retrieve the keyword 
                // value if it is in string type
                object keywordValue = adProperties[KeywordProperty]; 
                if (keywordValue != null && keywordValue is string) { 
                    keyword = ((string) keywordValue).Trim();
                } 
                else {
                    keyword = string.Empty;
                }
 
                // get the impressions, but be defensive: let the schema enforce the rules. Default to 1.
                string impressionsString = adProperties[ImpressionsProperty] as string; 
                if (String.IsNullOrEmpty(impressionsString) || 
                    !int.TryParse(impressionsString, NumberStyles.Integer,
                                   CultureInfo.InvariantCulture, out impressions)) { 
                    impressions = 1;
                }
                if (impressions < 0) {
                    impressions = 1; 
                }
            } 
        } 
    }
} 

// 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.IO; 
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls; 
    using System.Web.UI;
    using System.Web.Caching;
    using System.Web;
    using System; 
    using System.Collections;
    using System.Collections.Specialized; 
    using System.ComponentModel; 
    using System.ComponentModel.Design;
    using System.Drawing.Design; 
    using System.Xml;
    using System.Globalization;
    using System.Web.Util;
    using System.Security.Permissions; 
    using System.Reflection;
    using System.Text; 
 

    ///  
    ///    Displays a randomly selected ad banner on a page.
    /// 
    [
    DefaultEvent("AdCreated"), 
    DefaultProperty("AdvertisementFile"),
    Designer("System.Web.UI.Design.WebControls.AdRotatorDesigner, " + AssemblyRef.SystemDesign), 
    ToolboxData("<{0}:AdRotator runat=\"server\">") 
    ]
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    public class AdRotator : DataBoundControl {

        private static readonly object EventAdCreated = new object(); 

        private const string XmlDocumentTag = "Advertisements"; 
        private const string XmlDocumentRootXPath = "/" + XmlDocumentTag; 
        private const string XmlAdTag = "Ad";
 
        private const string KeywordProperty = "Keyword";
        private const string ImpressionsProperty = "Impressions";

        // static copy of the Random object. This is a pretty hefty object to 
        // initialize, so you don't want to create one each time.
        private static Random _random; 
 
        private String _baseUrl;
        private string _advertisementFile; 
        private AdCreatedEventArgs _adCreatedEventArgs;

        private AdRec [] _adRecs;
        private bool _isPostCacheAdHelper; 
        private string _uniqueID;
 
        private static readonly Type _adrotatorType = typeof(AdRotator); 
        private static readonly Type[] _AdCreatedParameterTypes = {typeof(AdCreatedEventArgs)};
 

        /// 
        /// Initializes a new instance of the  class.
        ///  
        public AdRotator() {
        } 
 

        ///  
        ///    Gets or sets the path to the XML file that contains advertisement data.
        /// 
        [
        Bindable(true), 
        WebCategory("Behavior"),
        DefaultValue(""), 
        Editor("System.Web.UI.Design.XmlUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        UrlProperty(),
        WebSysDescription(SR.AdRotator_AdvertisementFile) 
        ]
        public string AdvertisementFile {
            get {
                return((_advertisementFile == null) ? String.Empty : _advertisementFile); 
            }
            set { 
                _advertisementFile = value; 
            }
        } 


        [
#if ORCAS 
        Verification("WCAG", "1.1", VerificationReportLevel.Error, 1, SR.Accessibility_ImageAlternateTextFieldMissing),
        Verification("ADA", "1194.22(a)", VerificationReportLevel.Error, 1, SR.Accessibility_ImageAlternateTextFieldMissing), 
#endif 
        WebCategory("Behavior"),
        DefaultValue(AdCreatedEventArgs.AlternateTextElement), 
        WebSysDescription(SR.AdRotator_AlternateTextField)

        ]
        public String AlternateTextField { 
            get {
                String s = (String) ViewState["AlternateTextField"]; 
                return((s != null) ? s : AdCreatedEventArgs.AlternateTextElement); 
            }
            set { 
                ViewState["AlternateTextField"] = value;
            }
        }
 
        /// 
        ///   The base url corresponds for mapping of other url elements such as 
        ///   imageUrl and navigateUrl. 
        /// 
        internal String BaseUrl { 
            get {
                if (_baseUrl == null) {
                    // Deal with app relative syntax (e.g. ~/foo)
                    string tplSourceDir = TemplateControlVirtualDirectory.VirtualPathString; 

                    // For the AdRotator, use the AdvertisementFile directory as the base, and fall back to the 
                    // page/user control location as the base. 
                    String absoluteFile = null;
                    String fileDirectory = null; 
                    if (!String.IsNullOrEmpty(AdvertisementFile)) {
                        absoluteFile = UrlPath.Combine(tplSourceDir, AdvertisementFile);
                        fileDirectory = UrlPath.GetDirectory(absoluteFile);
                    } 

                    _baseUrl = string.Empty; 
                    if (fileDirectory != null) { 
                        _baseUrl = fileDirectory;
                    } 
                    if (_baseUrl.Length == 0) {
                        _baseUrl = tplSourceDir;
                    }
                } 
                return _baseUrl;
            } 
        } 

#if SITECOUNTERS 

        [
        WebCategory("SiteCounters"),
        DefaultValue("AdRotator"), 
        Themeable(false),
        WebSysDescription(SR.AdRotator_CounterGroup), 
        ] 
        public String CounterGroup {
            get { 
                String s = (String)ViewState["CounterGroup"];
                return((s == null) ? "AdRotator" : s);
            }
            set { 
                ViewState["CounterGroup"] = value;
            } 
        } 

 
        [
        WebCategory("SiteCounters"),
        DefaultValue(""),
        Themeable(false), 
        WebSysDescription(SR.AdRotator_CounterName),
        ] 
        public String CounterName { 
            get {
                String s = (String)ViewState["CounterName"]; 
                return((s == null) ? String.Empty : s);
            }
            set {
                ViewState["CounterName"] = value; 
            }
        } 
 

        [ 
        WebCategory("SiteCounters"),
        DefaultValue(false),
        Themeable(false),
        WebSysDescription(SR.AdRotator_CountClicks), 
        ]
        public bool CountClicks { 
            get { 
                object b = ViewState["CountClicks"];
                return((b == null) ? false : (bool)b); 
            }
            set {
                ViewState["CountClicks"] = value;
            } 
        }
 
 
        [
        WebCategory("SiteCounters"), 
        DefaultValue(false),
        Themeable(false),
        WebSysDescription(SR.AdRotator_CountViews),
        ] 
        public bool CountViews {
            get { 
                object b = ViewState["CountViews"]; 
                return((b == null) ? false : (bool)b);
            } 
            set {
                ViewState["CountViews"] = value;
            }
        } 
#endif
 
 
        /// 
        ///  
        ///    Font property. Has no effect on this control, so hide it.
        /// 
        [
        Browsable(false), 
        EditorBrowsableAttribute(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        ] 
        public override FontInfo Font {
            get { 
                return base.Font;
            }
        }
 

        [ 
        WebCategory("Behavior"), 
        DefaultValue(AdCreatedEventArgs.ImageUrlElement),
        WebSysDescription(SR.AdRotator_ImageUrlField) 
        ]
        public String ImageUrlField {
            get {
                String s = (String) ViewState["ImageUrlField"]; 
                return((s != null) ? s : AdCreatedEventArgs.ImageUrlElement);
            } 
            set { 
                ViewState["ImageUrlField"] = value;
            } 
        }

        private bool IsTargetSet {
            get { 
                return (ViewState["Target"] != null);
            } 
        } 

        internal bool IsPostCacheAdHelper { 
            get {
                return _isPostCacheAdHelper;
            }
            set { 
                _isPostCacheAdHelper = value;
            } 
        } 

 
        /// 
        ///    Gets or sets a category keyword used for matching related advertisements in the advertisement file.
        /// 
        [ 
        Bindable(true),
        WebCategory("Behavior"), 
        DefaultValue(""), 
        WebSysDescription(SR.AdRotator_KeywordFilter)
        ] 
        public string KeywordFilter {
            get {
                string s = (string)ViewState["KeywordFilter"];
                return((s == null) ? String.Empty : s); 
            }
            set { 
                // trim the filter value 
                if (String.IsNullOrEmpty(value)) {
                    ViewState.Remove("KeywordFilter"); 
                }
                else {
                    ViewState["KeywordFilter"] = value.Trim();
                } 
            }
        } 
 

        [ 
        WebCategory("Behavior"),
        DefaultValue(AdCreatedEventArgs.NavigateUrlElement),
        WebSysDescription(SR.AdRotator_NavigateUrlField)
        ] 
        public String NavigateUrlField {
            get { 
                String s = (String) ViewState["NavigateUrlField"]; 
                return((s != null) ? s : AdCreatedEventArgs.NavigateUrlElement);
            } 
            set {
                ViewState["NavigateUrlField"] = value;
            }
        } 

#if SITECOUNTERS 
 
        [
        WebCategory("SiteCounters"), 
        DefaultValue(-1),
        Themeable(false),
        WebSysDescription(SR.Control_For_SiteCounters_RowsPerDay),
        ] 
        public int RowsPerDay {
            get { 
                Object o = ViewState["RowsPerDay"]; 
                return((o == null) ? -1 : (int) o);
            } 
            set {
                if (value == 0) {
                    throw new ArgumentOutOfRangeException("RowsPerDay");
                } 
                ViewState["RowsPerDay"] = value;
            } 
        } 
#endif
 
        private AdCreatedEventArgs SelectedAdArgs {
            get {
                return _adCreatedEventArgs;
            } 
            set {
                _adCreatedEventArgs = value; 
            } 
        }
 
#if SITECOUNTERS

        [
        WebCategory("SiteCounters"), 
        DefaultValue(""),
        Themeable(false), 
        WebSysDescription(SR.Control_For_SiteCounters_SiteCountersProvider) 
        ]
        public String SiteCountersProvider { 
            get {
                String s = (String) ViewState["SiteCountersProvider"];
                return((s != null) ? s : String.Empty);
            } 
            set {
                ViewState["SiteCountersProvider"] = value; 
            } 
        }
#endif 


        /// 
        ///    Gets 
        ///       or sets the name of the browser window or frame to display the advertisement.
        ///  
        [ 
        Bindable(true),
        WebCategory("Behavior"), 
        DefaultValue("_top"),
        WebSysDescription(SR.AdRotator_Target),
        TypeConverter(typeof(TargetConverter))
        ] 
        public string Target {
            get { 
                string s = (string)ViewState["Target"]; 
                return((s == null) ? "_top" : s);
            } 
            set {
                ViewState["Target"] = value;
            }
        } 

#if SITECOUNTERS 
 
        [
        WebCategory("SiteCounters"), 
        DefaultValue(true),
        Themeable(false),
        WebSysDescription(SR.Control_For_SiteCounters_TrackApplicationName),
        ] 
        public bool TrackApplicationName {
            get { 
                object b = ViewState["TrackApplicationName"]; 
                return((b == null) ? true : (bool)b);
            } 
            set {
                ViewState["TrackApplicationName"] = value;
            }
        } 

 
        [ 
        WebCategory("SiteCounters"),
        DefaultValue(true), 
        Themeable(false),
        WebSysDescription(SR.Control_For_SiteCounters_TrackNavigateUrl),
        ]
        public bool TrackNavigateUrl { 
            get {
                object b = ViewState["TrackNavigateUrl"]; 
                return((b == null) ? true : (bool)b); 
            }
            set { 
                ViewState["TrackNavigateUrl"] = value;
            }
        }
 

        [ 
        WebCategory("SiteCounters"), 
        DefaultValue(true),
        Themeable(false), 
        WebSysDescription(SR.Control_For_SiteCounters_TrackPageUrl),
        ]
        public bool TrackPageUrl {
            get { 
                object b = ViewState["TrackPageUrl"];
                return((b == null) ? true : (bool)b); 
            } 
            set {
                ViewState["TrackPageUrl"] = value; 
            }
        }
#endif
 
        protected override HtmlTextWriterTag TagKey {
            get { 
                return HtmlTextWriterTag.A; 
            }
        } 

        public override string UniqueID {
            get {
                if (_uniqueID == null) { 
                    _uniqueID = base.UniqueID;
                } 
                return _uniqueID; 
            }
        } 


        /// 
        ///    Occurs once per round trip after the creation of the 
        ///       control before the page is rendered. 
        ///  
        [ 
        WebCategory("Action"),
        WebSysDescription(SR.AdRotator_OnAdCreated) 
        ]
        public event AdCreatedEventHandler AdCreated {
            add {
                Events.AddHandler(EventAdCreated, value); 
            }
            remove { 
                Events.RemoveHandler(EventAdCreated, value); 
            }
        } 

        private void CheckOnlyOneDataSource() {
            int numOfDataSources = ((AdvertisementFile.Length > 0) ? 1 : 0);
            numOfDataSources += ((DataSourceID.Length > 0) ? 1 : 0); 
            numOfDataSources += ((DataSource != null) ? 1 : 0);
 
            if (numOfDataSources > 1) { 
                throw new HttpException(SR.GetString(SR.AdRotator_only_one_datasource, ID));
            } 
        }

        // Currently this is designed to be called when PostCache Substitution is being initialized
        internal void CopyFrom(AdRotator adRotator) { 
            _adRecs = adRotator._adRecs;
 
            AccessKey = adRotator.AccessKey; 
            AlternateTextField = adRotator.AlternateTextField;
            Enabled = adRotator.Enabled; 
            ImageUrlField = adRotator.ImageUrlField;
            NavigateUrlField = adRotator.NavigateUrlField;
            TabIndex = adRotator.TabIndex;
            Target = adRotator.Target; 
            ToolTip = adRotator.ToolTip;
 
#if SITECOUNTERS 
            CounterGroup = adRotator.CounterGroup;
            CounterName = adRotator.CounterName; 
            CountClicks = adRotator.CountClicks;
            CountViews = adRotator.CountViews;
            RowsPerDay = adRotator.RowsPerDay;
            SiteCountersProvider = adRotator.SiteCountersProvider; 
            TrackApplicationName = adRotator.TrackApplicationName;
            TrackNavigateUrl = adRotator.TrackNavigateUrl; 
            TrackPageUrl = adRotator.TrackPageUrl; 
#endif
 
            string id = adRotator.ID;
            if (!String.IsNullOrEmpty(id)) {
                ID = adRotator.ClientID;
            } 

            // Below are properties that need to be handled specially and saved 
            // to private variables. 
            _uniqueID = adRotator.UniqueID;
            _baseUrl = adRotator.BaseUrl; 

            // Special copy to properties that cannot be assigned directly
            if (adRotator.HasAttributes) {
                foreach(string key in adRotator.Attributes.Keys) { 
                    Attributes[key] = adRotator.Attributes[key];
                } 
            } 

            if (adRotator.ControlStyleCreated) { 
                ControlStyle.CopyFrom(adRotator.ControlStyle);
            }
        }
 
#if SITECOUNTERS
        // Consider: Expose for adapter extensibility 
        internal void CountViewEvent(AdCreatedEventArgs adArgs) { 
            if (CountViews) {
                SiteCounters siteCounters = Context.SiteCounters; 
                string navigateUrl = adArgs.NavigateUrl;
                string defaultCounterName = (!String.IsNullOrEmpty(navigateUrl)) ? navigateUrl : ID;
                string counterName = GetCounterName(adArgs, defaultCounterName);
                string counterGroup = GetCounterGroup(adArgs); 
                int rowsPerDay = RowsPerDay;
                string providerName = SiteCountersProvider; 
                bool trackAppName = TrackApplicationName; 
                bool trackNavUrl = TrackNavigateUrl;
                bool trackPageUrl = TrackPageUrl; 

                siteCounters.Write(counterGroup, counterName, SiteCounters.ViewEventText,
                                   ((trackNavUrl) ? navigateUrl : null),
                                   trackAppName, trackPageUrl, 
                                   providerName, rowsPerDay);
            } 
        } 
#endif
 
        private ArrayList CreateAutoGeneratedFields(IEnumerable dataSource) {
            if (dataSource == null) {
                return null;
            } 

            ArrayList generatedFields = new ArrayList(); 
            PropertyDescriptorCollection propertyDescriptors = null; 

            if (dataSource is ITypedList) { 
                propertyDescriptors =
                    ((ITypedList)dataSource).GetItemProperties(new PropertyDescriptor[0]);
            }
 
            if (propertyDescriptors == null) {
 
                IEnumerator enumerator = dataSource.GetEnumerator(); 
                if (enumerator.MoveNext()) {
 
                    Object sampleItem = enumerator.Current;
                    if (IsBindableType(sampleItem.GetType())) {
                        // Raise error since we are expecting some record
                        // containing multiple data values. 
                        throw new HttpException(SR.GetString(
                                SR.AdRotator_expect_records_with_advertisement_properties, 
                                ID, sampleItem.GetType())); 
                    }
                    else { 
                        propertyDescriptors = TypeDescriptor.GetProperties(sampleItem);
                    }
                }
            } 
            if (propertyDescriptors != null && propertyDescriptors.Count > 0) {
 
                foreach (PropertyDescriptor pd in propertyDescriptors) { 
                    if (IsBindableType(pd.PropertyType)) {
                        generatedFields.Add(pd.Name); 
                    }
                }
            }
 
            return generatedFields;
        } 
 

        // 



 

 
 

        internal bool DoPostCacheSubstitutionAsNeeded(HtmlTextWriter writer) { 
            if (!IsPostCacheAdHelper && SelectedAdArgs == null &&
                Page.Response.HasCachePolicy &&
                (int)Page.Response.Cache.GetCacheability() != (int)HttpCacheabilityLimits.None) {
 
                // The checking of the cacheability is to see if the page is output cached
                AdPostCacheSubstitution adPostCacheSubstitution = new AdPostCacheSubstitution(this); 
                adPostCacheSubstitution.RegisterPostCacheCallBack(Context, Page, writer); 
                return true;
            } 
            return false;
        }

        ///  
        ///     Select an ad from ad records and create the event
        ///     argument object. 
        ///  
        private AdCreatedEventArgs GetAdCreatedEventArgs() {
            IDictionary adInfo = SelectAdFromRecords(); 
            AdCreatedEventArgs adArgs =
                new AdCreatedEventArgs(adInfo,
                                       ImageUrlField,
                                       NavigateUrlField, 
                                       AlternateTextField);
           return adArgs; 
        } 

#if SITECOUNTERS 
        // Consider: Expose for adapter extensibility
        internal string GetCountClicksUrl(AdCreatedEventArgs adArgs) {
            string countClicksUrl = adArgs.NavigateUrl;
 
            if (CountClicks && !String.IsNullOrEmpty(countClicksUrl)) {
                SiteCounters siteCounters = Context.SiteCounters; 
                string counterName = GetCounterName(adArgs, countClicksUrl); 
                string counterGroup = GetCounterGroup(adArgs);
                int rowsPerDay = RowsPerDay; 
                string providerName = SiteCountersProvider;
                bool trackAppName = TrackApplicationName;
                bool trackNavUrl = TrackNavigateUrl;
                bool trackPageUrl = TrackPageUrl; 

                countClicksUrl = siteCounters.GetRedirectUrl( 
                                    counterGroup, counterName, SiteCounters.ClickEventText, 
                                    countClicksUrl, trackAppName,
                                    trackPageUrl, trackNavUrl, 
                                    providerName, rowsPerDay);
            }

            return countClicksUrl; 
        }
 
        private string GetCounterGroup(AdCreatedEventArgs adCreatedEvent) { 
            string counterGroup;
 
            // The precedence of the group field in site counter data is
            // 1. CounterGroup specified within the ad record, if provided
            // 2. CounterGroup, if provided
            IDictionary adProps = adCreatedEvent.AdProperties; 
            string adGroup = (adProps == null) ? null : (string) adProps["CounterGroup"];
            if (adGroup != null) { 
                counterGroup = adGroup; 
            }
            else { 
                counterGroup = CounterGroup;
            }

            return counterGroup; 
        }
 
        private string GetCounterName(AdCreatedEventArgs adCreatedEvent, string defaultName) { 
            string counterName;
 
            // The precedence of the target field in site counter data is
            // 1. CounterName specified within the ad record, if provided
            // 2. CounterName on the AdRotator control, if provided
            // 3. ID of the AdRotator, if provided 
            IDictionary adProps = adCreatedEvent.AdProperties;
            string adName = (adProps == null) ? null : (string) adProps["CounterName"]; 
            if (adName != null) { 
                counterName = adName;
            } 
            else if (CounterName.Length > 0) {
                counterName = CounterName;
            }
            else { 
                counterName = defaultName;
            } 
 
            return counterName;
        } 
#endif

        private AdRec [] GetDataSourceData(IEnumerable dataSource) {
 
            ArrayList fields = CreateAutoGeneratedFields(dataSource);
 
            ArrayList adDicts = new ArrayList(); 
            IEnumerator enumerator = dataSource.GetEnumerator();
            while(enumerator.MoveNext()) { 
                IDictionary dict = null;
                foreach (String field in fields){
                    if (dict == null) {
                        dict = new HybridDictionary(); 
                    }
                    dict.Add(field, DataBinder.GetPropertyValue(enumerator.Current, field)); 
                } 

                if (dict != null) { 
                    adDicts.Add(dict);
                }
            }
 
            return SetAdRecs(adDicts);
        } 
 

        ///  
        ///   Gets the ad data for the given file by loading the file, or reading from the
        ///   application-level cache.
        /// 
        private AdRec [] GetFileData(string fileName) { 

            // VSWhidbey 208626: Adopting similar code from xml.cs to support virtual path provider 
 
            // First, figure out if it's a physical or virtual path
            VirtualPath virtualPath; 
            string physicalPath;
            ResolvePhysicalOrVirtualPath(fileName, out virtualPath, out physicalPath);

            // try to get it from the ASP.NET cache 
            string fileKey = CacheInternal.PrefixAdRotator + ((!String.IsNullOrEmpty(physicalPath)) ?
                physicalPath : virtualPath.VirtualPathString); 
            CacheInternal cacheInternal = System.Web.HttpRuntime.CacheInternal; 
            AdRec [] adRecs = cacheInternal[fileKey] as AdRec[];
 
            if (adRecs == null) {
                // Otherwise load it
                CacheDependency dependency;
                try { 
                    using (Stream stream = OpenFileAndGetDependency(virtualPath, physicalPath, out dependency)) {
                        adRecs = LoadStream(stream); 
                        Debug.Assert(adRecs != null); 
                    }
                } 
                catch (Exception e) {
                    if (!String.IsNullOrEmpty(physicalPath) && HttpRuntime.HasPathDiscoveryPermission(physicalPath)) {
                        // We want to catch the error message, but not propage the inner exception. Otherwise we can throw up
                        // logon prompts through IE; 
                        throw new HttpException(SR.GetString(SR.AdRotator_cant_open_file, ID, e.Message));
                    } 
                    else { 
                        throw new HttpException(SR.GetString(SR.AdRotator_cant_open_file_no_permission, ID));
                    } 
                }

                // Cache it, but only if we got a dependency
                if (dependency != null) { 
                    using (dependency) {
                        // and store it in the cache, dependent on the file name 
                        cacheInternal.UtcInsert(fileKey, adRecs, dependency); 
                    }
                } 
            }
            return adRecs;
        }
 
        private static int GetRandomNumber(int maxValue) {
            if (_random == null) { 
                _random = new Random(); 
            }
            return _random.Next(maxValue) + 1; 
        }

        private AdRec [] GetXmlDataSourceData(XmlDataSource xmlDataSource) {
            Debug.Assert(xmlDataSource != null); 

            XmlDocument doc = xmlDataSource.GetXmlDocument(); 
            if (doc == null) { 
                return null;
            } 
            return LoadXmlDocument(doc);
        }

        private bool IsBindableType(Type type) { 
            return(type.IsPrimitive ||
                   (type == typeof(String)) || 
                   (type == typeof(DateTime)) || 
                   (type == typeof(Decimal)));
        } 

        private bool IsOnAdCreatedOverridden() {
            bool result = false;
            Type type = this.GetType(); 
            if (type != _adrotatorType) {
                MethodInfo methodInfo = type.GetMethod("OnAdCreated", 
                                                       BindingFlags.NonPublic | BindingFlags.Instance, 
                                                       null,
                                                       _AdCreatedParameterTypes, 
                                                       null);
                if (methodInfo.DeclaringType != _adrotatorType) {
                    result = true;
                } 
            }
            return result; 
        } 

        private AdRec [] LoadFromXmlReader(XmlReader reader) { 
            ArrayList adDicts = new ArrayList();

            while (reader.Read()) {
                if (reader.Name == "Advertisements") { 
                    if (reader.Depth != 0) {
                        return null; 
                    } 
                    break;
                } 
            }

            while (reader.Read()) {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "Ad" && reader.Depth == 1) { 

                    IDictionary dict = null; 
                    reader.Read(); 
                    while (!(reader.NodeType == XmlNodeType.EndElement)) {
                        if (reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement) { 
                            if (dict == null) {
                                dict = new HybridDictionary();
                            }
                            dict.Add(reader.LocalName, reader.ReadString()); 
                        }
                        reader.Skip(); 
                    } 

                    if (dict != null) { 
                        adDicts.Add(dict);
                    }
                }
            } 

            AdRec [] adRecs = SetAdRecs(adDicts); 
            return adRecs; 
        }
 
        /// 
        ///   Loads the given XML stream into an array of AdRec structures
        /// 
        private AdRec [] LoadStream(Stream stream) { 

            AdRec [] adRecs = null; 
            try { 
                // Read the XML stream into an array of dictionaries
                XmlReader reader = new XmlTextReader(stream); 

                // Perf: We use LoadFromXmlReader instead of LoadXmlDocument to
                // do the text parsing only once
                adRecs = LoadFromXmlReader(reader); 
            }
            catch (Exception e) { 
                throw new HttpException( 
                    SR.GetString(SR.AdRotator_parse_error, ID, e.Message), e);
            } 

            if (adRecs == null) {
                throw new HttpException(
                    SR.GetString(SR.AdRotator_no_advertisements, ID, AdvertisementFile)); 
            }
 
            return adRecs; 
        }
 
        private AdRec [] LoadXmlDocument(XmlDocument doc) {
            // Read the XML data into an array of dictionaries
            ArrayList adDicts = new ArrayList();
 
            if (doc.DocumentElement != null &&
                doc.DocumentElement.LocalName == XmlDocumentTag) { 
 
                XmlNode elem = doc.DocumentElement.FirstChild;
 
                while (elem != null) {
                    IDictionary dict = null;
                    if (elem.LocalName.Equals(XmlAdTag)) {
                        XmlNode prop = elem.FirstChild; 
                        while (prop != null) {
                            if (prop.NodeType == XmlNodeType.Element) { 
                                if (dict == null) { 
                                    dict = new HybridDictionary();
                                } 
                                dict.Add(prop.LocalName, prop.InnerText);
                            }
                            prop = prop.NextSibling;
                        } 
                    }
                    if (dict != null) { 
                        adDicts.Add(dict); 
                    }
                    elem = elem.NextSibling; 
                }
            }

            AdRec [] adRecs = SetAdRecs(adDicts); 
            return adRecs;
        } 
 
        /// 
        ///   Used to determine if the advertisement meets current criteria. Does a comparison with 
        ///   KeywordFilter if it is set.
        /// 
        private bool MatchingAd(AdRec adRec, string keywordFilter) {
            Debug.Assert(keywordFilter != null && keywordFilter.Length > 0); 
            return(String.Equals(keywordFilter, adRec.keyword, StringComparison.OrdinalIgnoreCase));
        } 
 

        ///  
        /// Raises the  event for an .
        /// 
        protected virtual void OnAdCreated(AdCreatedEventArgs e) {
            AdCreatedEventHandler handler = (AdCreatedEventHandler)Events[EventAdCreated]; 
            if (handler != null) handler(this, e);
        } 
 

        protected internal override void OnInit(EventArgs e) { 
            base.OnInit(e);

            // VSWhidbey 419600: We just always need binding data every time since
            // AdRotator doesn't store the entire Ad data in ViewState for selecting 
            // Ad during postbacks.  It's too big for storing in ViewState.
            RequiresDataBinding = true; 
        } 

        ///  
        /// 
        ///    Gets the advertisement information for rendering in its parameter, then calls
        ///     the OnAdCreated event to render the ads.
        ///  
        protected internal override void OnPreRender(EventArgs e) {
            base.OnPreRender(e); 
 
            // If after PreRender (which would call DataBind if DataSource or DataSourceID available)
            // and no _adRecs created, it must be the normal v1 behavior which uses ad file. 
            if (_adRecs == null && AdvertisementFile.Length > 0) {
                PerformAdFileBinding();
            }
 
            // If handler is specified, we don't do any post-cache
            // substitution because the handler code would not be executed. 
            // 
            // VSWhidbey 213759: We also don't want any post-cache substitution
            // if OnAdCreated has been overridden 
            if (Events[EventAdCreated] != null || IsOnAdCreatedOverridden()) {
                // Fire the user event for further customization
                SelectedAdArgs = GetAdCreatedEventArgs();
                OnAdCreated(SelectedAdArgs); 
            }
        } 
 
        private void PerformAdFileBinding() {
            // Getting ad data from physical file is V1 way which is not supported 
            // by the base class DataBoundControl so we had above code to handle
            // this case.  However, we need to support DataBound control events
            // in Whidbey and since above code doesn't go through the event
            // raising in the base class DataBoundControl, here we mimic them. 
            OnDataBinding(EventArgs.Empty);
 
            // get the ads from the file or app cache 
            _adRecs = GetFileData(AdvertisementFile);
 
            OnDataBound(EventArgs.Empty);
        }

        protected internal override void PerformDataBinding(IEnumerable data) { 
            if (data != null) {
                // We retrieve ad data from xml format in a specific way. 
                XmlDataSource xmlDataSource = null; 
                object dataSource = DataSource;
                if (dataSource != null) { 
                    xmlDataSource = dataSource as XmlDataSource;
                }
                else { // DataSourceID case, we know that only one source is available
                    xmlDataSource = GetDataSource() as XmlDataSource; 
                }
 
                if (xmlDataSource != null) { 
                    _adRecs = GetXmlDataSourceData(xmlDataSource);
                } 
                else {
                    _adRecs = GetDataSourceData(data);
                }
            } 
        }
 
        protected override void PerformSelect() { 
            // VSWhidbey 141362
            CheckOnlyOneDataSource(); 

            if (AdvertisementFile.Length > 0) {
                PerformAdFileBinding();
            } 
            else {
                base.PerformSelect(); 
            } 
        }
 
        //
        internal AdCreatedEventArgs PickAd() {
            AdCreatedEventArgs adArgs = SelectedAdArgs;
            if (adArgs == null) { 
                adArgs = GetAdCreatedEventArgs();
            } 
            adArgs.ImageUrl = ResolveAdRotatorUrl(BaseUrl, adArgs.ImageUrl); 
            adArgs.NavigateUrl = ResolveAdRotatorUrl(BaseUrl, adArgs.NavigateUrl);
            return adArgs; 
        }


        ///  
        /// 
        /// Displays the  on the client. 
        ///  
        protected internal override void Render(HtmlTextWriter writer) {
            if (!DesignMode && !IsPostCacheAdHelper && 
                DoPostCacheSubstitutionAsNeeded(writer)) {
                return;
            }
 
            AdCreatedEventArgs adArgs = PickAd();
            RenderLink(writer, adArgs); 
#if SITECOUNTERS 
            CountViewEvent(adArgs);
#endif 
        }

        private void RenderLink(HtmlTextWriter writer, AdCreatedEventArgs adArgs) {
            Debug.Assert(writer != null); 
            Debug.Assert(adArgs != null);
 
            HyperLink bannerLink = new HyperLink(); 

#if SITECOUNTERS 
            bannerLink.NavigateUrl = GetCountClicksUrl(adArgs);
#else
            bannerLink.NavigateUrl = adArgs.NavigateUrl;
#endif 
            bannerLink.Target = Target;
 
            if (HasAttributes) { 
                foreach(string key in Attributes.Keys) {
                    bannerLink.Attributes[key] = Attributes[key]; 
                }
            }

            string id = ID; 
            if (!String.IsNullOrEmpty(id)) {
                bannerLink.ID = ClientID; 
            } 

            if (!Enabled) { 
                bannerLink.Enabled = false;
            }

            // WebControl's properties use a private flag to determine if a 
            // property is set and does not return the value unless the flag is
            // marked.  So here we access those properites (inherited from WebControl) 
            // directly from the ViewState bag because if ViewState bag reference 
            // was copied to the helper class in the optimized case during the
            // Initialize() method, the flags of the properties wouldn't be set 
            // in the helper class.
            string accessKey = (string) ViewState["AccessKey"];
            if (!String.IsNullOrEmpty(accessKey)) {
                bannerLink.AccessKey = accessKey; 
            }
 
            object o = ViewState["TabIndex"]; 
            if (o != null) {
                short tabIndex = (short) o; 
                if (tabIndex != (short) 0) {
                    bannerLink.TabIndex = tabIndex;
                }
            } 

            bannerLink.RenderBeginTag(writer); 
 
            // create inner Image
            Image bannerImage = new Image(); 
            // apply styles to image
            if (ControlStyleCreated) {
                bannerImage.ApplyStyle(ControlStyle);
            } 

            string alternateText = adArgs.AlternateText; 
            if (!String.IsNullOrEmpty(alternateText)) { 
                bannerImage.AlternateText = alternateText;
            } 
            else {
                // 25914 Do not render empty 'alt' attribute if  tag is never specified
                IDictionary adProps = adArgs.AdProperties;
                string altTextKey = (AlternateTextField.Length != 0) 
                                        ? AlternateTextField : AdCreatedEventArgs.AlternateTextElement;
                string altText = (adProps == null) ? null : (string) adProps[altTextKey]; 
                if (altText != null && altText.Length == 0) { 
                    bannerImage.GenerateEmptyAlternateText = true;
                } 
            }

            // Perf work: AdRotator should have resolved the NavigateUrl and
            // ImageUrl when assigning them and have UrlResolved set properly. 
            bannerImage.UrlResolved = true;
            string imageUrl = adArgs.ImageUrl; 
            if (!String.IsNullOrEmpty(imageUrl)) { 
                bannerImage.ImageUrl = imageUrl;
            } 

            if (adArgs.HasWidth) {
                bannerImage.ControlStyle.Width = adArgs.Width;
            } 

            if (adArgs.HasHeight) { 
                bannerImage.ControlStyle.Height = adArgs.Height; 
            }
 
            string toolTip = (string) ViewState["ToolTip"];
            if (!String.IsNullOrEmpty(toolTip)) {
                bannerImage.ToolTip = toolTip;
            } 

            bannerImage.RenderControl(writer); 
            bannerLink.RenderEndTag(writer); 
        }
 
        private string ResolveAdRotatorUrl(string baseUrl, string relativeUrl) {

            if ((relativeUrl == null) ||
                (relativeUrl.Length == 0) || 
                (UrlPath.IsRelativeUrl(relativeUrl) == false) ||
                (baseUrl == null) || 
                (baseUrl.Length == 0)) { 
                return relativeUrl;
            } 

            // make it absolute
            return UrlPath.Combine(baseUrl, relativeUrl);
        } 

        ///  
        ///     Selects an advertisement from the a list of records based 
        ///     on different factors.
        ///  
        private IDictionary SelectAdFromRecords() {
            if (_adRecs == null || _adRecs.Length == 0) {
                return null;
            } 

            string keywordFilter = KeywordFilter; 
            bool noKeywordFilter = String.IsNullOrEmpty(keywordFilter); 
            if (!noKeywordFilter) {
                // do a lower case comparison 
                keywordFilter = keywordFilter.ToLower(CultureInfo.InvariantCulture);
            }

            // sum the matching impressions 
            int totalImpressions = 0;
            for (int i = 0; i < _adRecs.Length; i++) { 
                if (noKeywordFilter || MatchingAd(_adRecs[i], keywordFilter)) { 
                    totalImpressions += _adRecs[i].impressions;
                } 
            }

            if (totalImpressions == 0) {
                return null; 
            }
 
            // select one using a random number between 1 and totalImpressions 
            int selectedImpression = GetRandomNumber(totalImpressions);
            int impressionCounter = 0; 
            int selectedIndex = -1;
            for (int i = 0; i < _adRecs.Length; i++) {
                // Is this the ad?
                if (noKeywordFilter || MatchingAd(_adRecs[i], keywordFilter)) { 
                    impressionCounter += _adRecs[i].impressions;
                    if (selectedImpression <= impressionCounter) { 
                        selectedIndex = i; 
                        break;
                    } 
                }
            }
            Debug.Assert(selectedIndex >= 0 && selectedIndex < _adRecs.Length, "Index not found");
 
            return _adRecs[selectedIndex].adProperties;
        } 
 
        private AdRec [] SetAdRecs(ArrayList adDicts) {
            if (adDicts == null || adDicts.Count == 0) { 
                return null;
            }

            // Create an array of AdRec structures from the dictionaries, removing blanks 
            AdRec [] adRecs = new AdRec[adDicts.Count];
            int iRec = 0; 
            for (int i = 0; i < adDicts.Count; i++) { 
                if (adDicts[i] != null) {
                    adRecs[iRec].Initialize((IDictionary) adDicts[i]); 
                    iRec++;
                }
            }
            Debug.Assert(iRec == adDicts.Count, "Record count did not match non-null entries"); 

            return adRecs; 
        } 

 

        /// 
        ///   Structure to store ads in memory for fast selection by multiple instances of adrotator
        ///   Stores the dictionary and caches some values for easier selection. 
        /// 
        private struct AdRec { 
            public string keyword; 
            public int impressions;
            public IDictionary adProperties; 


            /// 
            ///   Initialize the stuct based on a dictionary containing the advertisement properties 
            /// 
            public void Initialize(IDictionary adProperties) { 
 
                // Initialize the values we need to keep for ad selection
                Debug.Assert(adProperties != null, "Required here"); 
                this.adProperties = adProperties;

                // remove null and trim keyword for easier comparisons.
                // VSWhidbey 114634: Be defensive and only retrieve the keyword 
                // value if it is in string type
                object keywordValue = adProperties[KeywordProperty]; 
                if (keywordValue != null && keywordValue is string) { 
                    keyword = ((string) keywordValue).Trim();
                } 
                else {
                    keyword = string.Empty;
                }
 
                // get the impressions, but be defensive: let the schema enforce the rules. Default to 1.
                string impressionsString = adProperties[ImpressionsProperty] as string; 
                if (String.IsNullOrEmpty(impressionsString) || 
                    !int.TryParse(impressionsString, NumberStyles.Integer,
                                   CultureInfo.InvariantCulture, out impressions)) { 
                    impressions = 1;
                }
                if (impressions < 0) {
                    impressions = 1; 
                }
            } 
        } 
    }
} 

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