ScriptReference.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Extensions / UI / ScriptReference.cs / 1305376 / ScriptReference.cs

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

namespace System.Web.UI { 
    using System; 
    using System.Collections;
    using System.ComponentModel; 
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Reflection;
    using System.Web; 
    using System.Web.Handlers;
    using System.Web.Resources; 
    using System.Web.Util; 
    using Debug = System.Diagnostics.Debug;
    using Tuple = System.Web.Util.Tuple; 

    [
    DefaultProperty("Path"),
    ] 
    public class ScriptReference : ScriptReferenceBase {
        // Maps Pair(resource name, assembly) to string (partial script path) 
        private static readonly Hashtable _scriptPathCache = Hashtable.Synchronized(new Hashtable()); 

        private string _assembly; 
        private bool _ignoreScriptPath;
        private string _name;
        private ScriptEffectiveInfo _scriptInfo;
 
        public ScriptReference() : base() {}
 
        public ScriptReference(string name, string assembly) : this() { 
            Name = name;
            Assembly = assembly; 
        }

        public ScriptReference(string path) : this() {
            Path = path; 
        }
 
        internal ScriptReference(string name, IClientUrlResolver clientUrlResolver, Control containingControl) : this() { 
            Debug.Assert(!String.IsNullOrEmpty(name), "The script's name must be specified.");
            Debug.Assert(clientUrlResolver != null && clientUrlResolver is ScriptManager, "The clientUrlResolver must be the ScriptManager."); 
            Name = name;
            ClientUrlResolver = clientUrlResolver;
            IsStaticReference = true;
            ContainingControl = containingControl; 
        }
 
        internal bool IsDirectRegistration { 
            // set to true internally to disable checking for adding .debug
            // used when registering a script directly through SM.RegisterClientScriptResource 
            get;
            set;
        }
 
        [
        Category("Behavior"), 
        DefaultValue(""), 
        ResourceDescription("ScriptReference_Assembly")
        ] 
        public string Assembly {
            get {
                return (_assembly == null) ? String.Empty : _assembly;
            } 
            set {
                _assembly = value; 
                _scriptInfo = null; 
            }
        } 

        internal Assembly EffectiveAssembly {
            get {
                return ScriptInfo.Assembly; 
            }
        } 
 
        internal string EffectivePath {
            get { 
                return String.IsNullOrEmpty(Path) ? ScriptInfo.Path : Path;
            }
        }
 
        internal string EffectiveResourceName {
            get { 
                return ScriptInfo.ResourceName; 
            }
        } 

        internal ScriptMode EffectiveScriptMode {
            get {
                if (ScriptMode == ScriptMode.Auto) { 
                    // - When a mapping.DebugPath exists, ScriptMode.Auto is equivilent to ScriptMode.Inherit,
                    //   since a debug path exists, even though it may not be an assembly based script. 
                    // - An explicitly set Path on the ScriptReference effectively ignores a DebugPath. 
                    // - When only Path is specified, ScriptMode.Auto is equivalent to ScriptMode.Release.
                    // - When only Name is specified, ScriptMode.Auto is equivalent to ScriptMode.Inherit. 
                    // - When Name and Path are both specified, the Path is used instead of the Name, but
                    //   ScriptMode.Auto is still equivalent to ScriptMode.Inherit, since the assumption
                    //   is that if the Assembly contains both release and debug scripts, the Path should
                    //   contain both as well. 
                    return ((String.IsNullOrEmpty(EffectiveResourceName) &&
                        (!String.IsNullOrEmpty(Path) || String.IsNullOrEmpty(ScriptInfo.DebugPath))) ? 
                        ScriptMode.Release : ScriptMode.Inherit); 
                }
                else { 
                    return ScriptMode;
                }
            }
        } 

        [ 
        Category("Behavior"), 
        DefaultValue(false),
        ResourceDescription("ScriptReference_IgnoreScriptPath"), 
        Obsolete("This property is obsolete. Instead of using ScriptManager.ScriptPath, set the Path property on each individual ScriptReference.")
        ]
        public bool IgnoreScriptPath {
            get { 
                return _ignoreScriptPath;
            } 
            set { 
                _ignoreScriptPath = value;
            } 
        }

        [
        Category("Behavior"), 
        DefaultValue(""),
        ResourceDescription("ScriptReference_Name") 
        ] 
        public string Name {
            get { 
                return (_name == null) ? String.Empty : _name;
            }
            set {
                _name = value; 
                _scriptInfo = null;
            } 
        } 

        internal ScriptEffectiveInfo ScriptInfo { 
            get {
                if (_scriptInfo == null) {
                    _scriptInfo = new ScriptEffectiveInfo(this);
                } 
                return _scriptInfo;
            } 
        } 

        private string AddCultureName(ScriptManager scriptManager, string resourceName) { 
            Debug.Assert(!String.IsNullOrEmpty(resourceName));
            CultureInfo culture = (scriptManager.EnableScriptLocalization ?
                DetermineCulture(scriptManager) : CultureInfo.InvariantCulture);
            if (!culture.Equals(CultureInfo.InvariantCulture)) { 
                return AddCultureName(culture, resourceName);
            } 
            else { 
                return resourceName;
            } 
        }

        private static string AddCultureName(CultureInfo culture, string resourceName) {
            if (resourceName.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) { 
                resourceName = resourceName.Substring(0, resourceName.Length - 2) +
                    culture.Name + ".js"; 
            } 
            return resourceName;
        } 

        internal bool DetermineResourceNameAndAssembly(ScriptManager scriptManager, bool isDebuggingEnabled, ref string resourceName, ref Assembly assembly) {
            // If the assembly is the AjaxFrameworkAssembly, the resource may come from that assembly
            // or from the fallback assembly (SWE). 
            if (assembly == scriptManager.AjaxFrameworkAssembly) {
                assembly = ApplyFallbackResource(assembly, resourceName); 
            } 
            // ShouldUseDebugScript throws exception if the resource name does not exist in the assembly
            bool isDebug = ShouldUseDebugScript(resourceName, assembly, 
                isDebuggingEnabled, scriptManager.AjaxFrameworkAssembly);
            if (isDebug) {
                resourceName = GetDebugName(resourceName);
            } 
            // returning true means the debug version is selected
            return isDebug; 
        } 

        internal CultureInfo DetermineCulture(ScriptManager scriptManager) { 
            if ((ResourceUICultures == null) || (ResourceUICultures.Length == 0)) {
                // In this case we want to determine available cultures from assembly info if available
                if (!String.IsNullOrEmpty(EffectiveResourceName)) {
                    return ScriptResourceHandler 
                        .DetermineNearestAvailableCulture(GetAssembly(scriptManager), EffectiveResourceName, CultureInfo.CurrentUICulture);
                } 
                return CultureInfo.InvariantCulture; 
            }
            CultureInfo currentCulture = CultureInfo.CurrentUICulture; 
            while (!currentCulture.Equals(CultureInfo.InvariantCulture)) {
                string cultureName = currentCulture.ToString();
                foreach (string uiCulture in ResourceUICultures) {
                    if (String.Equals(cultureName, uiCulture.Trim(), StringComparison.OrdinalIgnoreCase)) { 
                        return currentCulture;
                    } 
                } 
                currentCulture = currentCulture.Parent;
            } 
            return currentCulture;
        }

        internal Assembly GetAssembly() { 
            return String.IsNullOrEmpty(Assembly) ? null : AssemblyCache.Load(Assembly);
        } 
 
        internal Assembly GetAssembly(ScriptManager scriptManager) {
            // normalizes the effective assembly by redirecting it to the given scriptmanager's 
            // ajax framework assembly when it is set to SWE.
            // EffectiveAssembly can't do this since ScriptReference does not have access by itself
            // to the script manager.
            Debug.Assert(scriptManager != null); 
            Assembly assembly = EffectiveAssembly;
            if (assembly == null) { 
                return scriptManager.AjaxFrameworkAssembly; 
            }
            else { 
                return ((assembly == AssemblyCache.SystemWebExtensions) ?
                    scriptManager.AjaxFrameworkAssembly :
                    assembly);
            } 
        }
 
        // Release: foo.js 
        // Debug:   foo.debug.js
        private static string GetDebugName(string releaseName) { 
            // Since System.Web.Handlers.AssemblyResourceLoader treats the resource name as case-sensitive,
            // we must do the same when verifying the extension.
            // Ignore trailing whitespace. For example, "MicrosoftAjax.js " is valid (at least from
            // a debug/release naming perspective). 
            if (!releaseName.EndsWith(".js", StringComparison.Ordinal)) {
                throw new InvalidOperationException( 
                    String.Format(CultureInfo.CurrentUICulture, AtlasWeb.ScriptReference_InvalidReleaseScriptName, releaseName)); 
            }
 
            return ReplaceExtension(releaseName);
        }

        internal string GetPath(ScriptManager scriptManager, string releasePath, string predeterminedDebugPath, bool isDebuggingEnabled) { 
            // convert the release path to a debug path if:
            // isDebuggingEnabled && not resource based 
            // isDebuggingEnabled && resource based && debug resource exists 
            // ShouldUseDebugScript is called even when isDebuggingEnabled=false as it verfies
            // the existence of the resource. 
            // applies the culture name to the path if appropriate
            string path;
            if (!String.IsNullOrEmpty(EffectiveResourceName)) {
                Assembly assembly = GetAssembly(scriptManager); 
                string resourceName = EffectiveResourceName;
                isDebuggingEnabled = DetermineResourceNameAndAssembly(scriptManager, isDebuggingEnabled, ref resourceName, ref assembly); 
            } 

            if (isDebuggingEnabled) { 
                // Just use predeterminedDebugPath if it is provided. This may be because
                // a script mapping has DebugPath set. If it is empty or null, then '.debug' is added
                // to the .js extension of the release path.
                path = String.IsNullOrEmpty(predeterminedDebugPath) ? GetDebugPath(releasePath) : predeterminedDebugPath; 
            }
            else { 
                path = releasePath; 
            }
            return AddCultureName(scriptManager, path); 
        }

        internal Assembly ApplyFallbackResource(Assembly assembly, string releaseName) {
            // fall back to SWE if the assembly does not contain the requested resource 
            if ((assembly != AssemblyCache.SystemWebExtensions) &&
                !WebResourceUtil.AssemblyContainsWebResource(assembly, releaseName)) { 
                assembly = AssemblyCache.SystemWebExtensions; 
            }
            return assembly; 
        }

        // Format: ///
        // This function does not canonicalize the path in any way (i.e. remove duplicate slashes). 
        // You must call ResolveClientUrl() on this path before rendering to the page.
        internal static string GetScriptPath( 
            string resourceName, 
            Assembly assembly,
            CultureInfo culture, 
            string scriptPath) {

            return scriptPath + "/" + GetScriptPathCached(resourceName, assembly, culture);
        } 

        // Cache partial script path, since Version.ToString() and HttpUtility.UrlEncode() are expensive. 
        // Increases requests/second by 50% in ScriptManagerScriptPath.aspx test. 
        private static string GetScriptPathCached(string resourceName, Assembly assembly, CultureInfo culture) {
            Tuple key = new Tuple(resourceName, assembly, culture); 
            string scriptPath = (string)_scriptPathCache[key];

            if (scriptPath == null) {
                // Need to use "new AssemblyName(assembly.FullName)" instead of "assembly.GetName()", 
                // since Assembly.GetName() requires FileIOPermission to the path of the assembly.
                // In partial trust, we may not have this permission. 
                AssemblyName assemblyName = new AssemblyName(assembly.FullName); 

                string name = assemblyName.Name; 
                string version = assemblyName.Version.ToString();
                string fileVersion = AssemblyUtil.GetAssemblyFileVersion(assembly);

                if (!culture.Equals(CultureInfo.InvariantCulture)) { 
                    resourceName = AddCultureName(culture, resourceName);
                } 
 
                // Assembly name, fileVersion, and resource name may contain invalid URL characters (like '#' or '/'),
                // so they must be url-encoded. 
                scriptPath = String.Join("/", new string[] {
                    HttpUtility.UrlEncode(name), version, HttpUtility.UrlEncode(fileVersion), HttpUtility.UrlEncode(resourceName)
                });
 
                _scriptPathCache[key] = scriptPath;
            } 
 
            return scriptPath;
        } 

        [SuppressMessage("Microsoft.Design", "CA1055", Justification = "Consistent with other URL properties in ASP.NET.")]
        protected internal override string GetUrl(ScriptManager scriptManager, bool zip) {
            bool hasName = !String.IsNullOrEmpty(Name); 
            bool hasAssembly = !String.IsNullOrEmpty(Assembly);
 
            if (!hasName && String.IsNullOrEmpty(Path)) { 
                throw new InvalidOperationException(AtlasWeb.ScriptReference_NameAndPathCannotBeEmpty);
            } 

            if (hasAssembly && !hasName) {
                throw new InvalidOperationException(AtlasWeb.ScriptReference_AssemblyRequiresName);
            } 

            return GetUrlInternal(scriptManager, zip); 
        } 

        internal string GetUrlInternal(ScriptManager scriptManager, bool zip) { 
            if (!String.IsNullOrEmpty(EffectiveResourceName) && !IsAjaxFrameworkScript(scriptManager) &&
                AssemblyCache.IsAjaxFrameworkAssembly(GetAssembly(scriptManager))) {
                // it isnt an AjaxFrameworkScript but it might be from an assembly that is meant to
                // be an ajax script assembly, in which case we should throw an error. 
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
                    AtlasWeb.ScriptReference_ResourceRequiresAjaxAssembly, EffectiveResourceName, GetAssembly(scriptManager))); 
            } 

            if (!String.IsNullOrEmpty(Path)) { 
                // if an explicit path is set on the SR (not on a mapping) it always
                // takes precedence, even when EnableCdn=true.
                // Also, even if a script mapping has a DebugPath, the explicitly set path
                // overrides all -- so path.debug.js is used instead of the mapping's DebugPath, 
                // hence the null 3rd parameter.
                return GetUrlFromPath(scriptManager, Path, null); 
            } 
            else if (!String.IsNullOrEmpty(ScriptInfo.Path)) {
                // when only the mapping has a path, CDN takes first priority 
                if (scriptManager.EnableCdn) {
                    // first determine the actual resource name and assembly to be used
                    // This is so we can (1) apply fallback logic, where ajax fx scripts can come from the
                    // current ajax assembly or from SWE, whichever is first, and (2) the .debug resource 
                    // name is applied if appropriate.
                    string resourceName = EffectiveResourceName; 
                    Assembly assembly = null; 
                    bool hasDebugResource = false;
                    if (!String.IsNullOrEmpty(resourceName)) { 
                        assembly = GetAssembly(scriptManager);
                        hasDebugResource = DetermineResourceNameAndAssembly(scriptManager,
                            IsDebuggingEnabled(scriptManager), ref resourceName, ref assembly);
                    } 
                    string cdnPath = GetUrlForCdn(scriptManager, resourceName, assembly, hasDebugResource);
                    if (!String.IsNullOrEmpty(cdnPath)) { 
                        return cdnPath; 
                    }
                } 
                // the mapping's DebugPath applies if it exists
                return GetUrlFromPath(scriptManager, ScriptInfo.Path, ScriptInfo.DebugPath);
            }
 
            Debug.Assert(!String.IsNullOrEmpty(EffectiveResourceName));
            return GetUrlFromName(scriptManager, scriptManager.Control, zip); 
        } 

        private string GetUrlForCdn(ScriptManager scriptManager, string resourceName, Assembly assembly, bool hasDebugResource) { 
            // if EnableCdn, then url always comes from mapping.Cdn[Debug]Path or WRA.CdnPath, if available.
            // first see if the script description mapping has a cdn path defined
            bool isDebuggingEnabled = IsDebuggingEnabled(scriptManager);
            bool isAssemblyResource = !String.IsNullOrEmpty(resourceName); 
            bool secureConnection = scriptManager.IsSecureConnection;
            isDebuggingEnabled = isDebuggingEnabled && (hasDebugResource || !isAssemblyResource); 
            string cdnPath = isDebuggingEnabled ? 
                (secureConnection ? ScriptInfo.CdnDebugPathSecureConnection : ScriptInfo.CdnDebugPath) :
                (secureConnection ? ScriptInfo.CdnPathSecureConnection : ScriptInfo.CdnPath); 

            // then see if the WebResourceAttribute for the resource has one
            // EXCEPT when the ScriptInfo has a cdnpath but it wasn't selected due to this being a secure connection
            // and it does not support secure connections. Avoid having the HTTP cdn path come from the mapping and the 
            // HTTPS path come from the WRA.
            if (isAssemblyResource && String.IsNullOrEmpty(cdnPath) && String.IsNullOrEmpty(isDebuggingEnabled ? ScriptInfo.CdnDebugPath : ScriptInfo.CdnPath)) { 
                ScriptResourceInfo scriptResourceInfo = ScriptResourceInfo.GetInstance(assembly, resourceName); 
                if (scriptResourceInfo != null) {
                    cdnPath = secureConnection ? scriptResourceInfo.CdnPathSecureConnection : scriptResourceInfo.CdnPath; 
                }
            }
            return String.IsNullOrEmpty(cdnPath) ? null : ClientUrlResolver.ResolveClientUrl(AddCultureName(scriptManager, cdnPath));
        } 

        private string GetUrlFromName(ScriptManager scriptManager, IControl scriptManagerControl, bool zip) { 
            string resourceName = EffectiveResourceName; 
            Assembly assembly = GetAssembly(scriptManager);
            bool hasDebugResource = DetermineResourceNameAndAssembly(scriptManager, IsDebuggingEnabled(scriptManager), 
                ref resourceName, ref assembly);

            if (scriptManager.EnableCdn) {
                string cdnPath = GetUrlForCdn(scriptManager, resourceName, assembly, hasDebugResource); 
                if (!String.IsNullOrEmpty(cdnPath)) {
                    return cdnPath; 
                } 
            }
 
            CultureInfo culture = (scriptManager.EnableScriptLocalization ?
                DetermineCulture(scriptManager) : CultureInfo.InvariantCulture);
#pragma warning disable 618
// ScriptPath is obsolete but still functional 
            if (IgnoreScriptPath || String.IsNullOrEmpty(scriptManager.ScriptPath)) {
                return ScriptResourceHandler.GetScriptResourceUrl(assembly, resourceName, culture, zip); 
            } 
            else {
                string path = GetScriptPath(resourceName, assembly, culture, scriptManager.ScriptPath); 
                // Always want to resolve ScriptPath urls against the ScriptManager itself,
                // regardless of whether the ScriptReference was declared on the ScriptManager
                // or a ScriptManagerProxy.
                return scriptManagerControl.ResolveClientUrl(path); 
            }
#pragma warning restore 618 
        } 

        private string GetUrlFromPath(ScriptManager scriptManager, string releasePath, string predeterminedDebugPath) { 
            string path = GetPath(scriptManager, releasePath, predeterminedDebugPath, IsDebuggingEnabled(scriptManager));
            return ClientUrlResolver.ResolveClientUrl(path);
        }
 
        private bool IsDebuggingEnabled(ScriptManager scriptManager) {
            // Deployment mode retail overrides all values of ScriptReference.ScriptMode. 
            if (IsDirectRegistration || scriptManager.DeploymentSectionRetail) { 
                return false;
            } 

            switch (EffectiveScriptMode) {
                case ScriptMode.Inherit:
                    return scriptManager.IsDebuggingEnabled; 
                case ScriptMode.Debug:
                    return true; 
                case ScriptMode.Release: 
                    return false;
                default: 
                    Debug.Fail("Invalid value for ScriptReference.EffectiveScriptMode");
                    return false;
            }
        } 

        protected internal override bool IsAjaxFrameworkScript(ScriptManager scriptManager) { 
            return (GetAssembly(scriptManager) == scriptManager.AjaxFrameworkAssembly); 
        }
 
        [Obsolete("This method is obsolete. Use IsAjaxFrameworkScript(ScriptManager) instead.")]
        protected internal override bool IsFromSystemWebExtensions() {
            return (EffectiveAssembly == AssemblyCache.SystemWebExtensions);
        } 

        internal bool IsFromSystemWeb() { 
            return (EffectiveAssembly == AssemblyCache.SystemWeb); 
        }
 
        internal bool ShouldUseDebugScript(string releaseName, Assembly assembly,
            bool isDebuggingEnabled, Assembly currentAjaxAssembly) {
            bool useDebugScript;
            string debugName = null; 

            if (isDebuggingEnabled) { 
                debugName = GetDebugName(releaseName); 

                // If an assembly contains a release script but not a corresponding debug script, and we 
                // need to register the debug script, we normally throw an exception.  However, we automatically
                // use the release script if ScriptReference.ScriptMode is Auto.  This improves the developer
                // experience when ScriptMode is Auto, yet still gives the developer full control with the
                // other ScriptModes. 
                if (ScriptMode == ScriptMode.Auto && !WebResourceUtil.AssemblyContainsWebResource(assembly, debugName)) {
                    useDebugScript = false; 
                } 
                else {
                    useDebugScript = true; 
                }
            }
            else {
                useDebugScript = false; 
            }
 
            // Verify that assembly contains required web resources.  Always check for release 
            // script before debug script.
            if (!IsDirectRegistration) { 
                // Don't check if direct registration, because calls to ScriptManager.RegisterClientScriptResource
                // with resources that do not exist does not throw an exception until the resource is served.
                // This was the existing behavior and matches the behavior with ClientScriptManager.GetWebResourceUrl.
                WebResourceUtil.VerifyAssemblyContainsReleaseWebResource(assembly, releaseName, currentAjaxAssembly); 
                if (useDebugScript) {
                    Debug.Assert(debugName != null); 
                    WebResourceUtil.VerifyAssemblyContainsDebugWebResource(assembly, debugName); 
                }
            } 

            return useDebugScript;
        }
 
        // Improves the UI in the VS collection editor, by displaying the Name or Path (if available), or
        // the short type name. 
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] 
        public override string ToString() {
            if (!String.IsNullOrEmpty(Name)) { 
                return Name;
            }
            else if (!String.IsNullOrEmpty(Path)) {
                return Path; 
            }
            else { 
                return GetType().Name; 
            }
        } 

        internal class ScriptEffectiveInfo {
            private string _resourceName;
            private Assembly _assembly; 
            private string _path;
            private string _debugPath; 
            private string _cdnPath; 
            private string _cdnDebugPath;
            private string _cdnPathSecureConnection; 
            private string _cdnDebugPathSecureConnection;

            public ScriptEffectiveInfo(ScriptReference scriptReference) {
                ScriptResourceDefinition definition = 
                    ScriptManager.ScriptResourceMapping.GetDefinition(scriptReference);
                string name = scriptReference.Name; 
                string path = scriptReference.Path; 
                Assembly assembly = scriptReference.GetAssembly();
                if (definition != null) { 
                    if (String.IsNullOrEmpty(path)) {
                        // only when the SR has no path, the mapping's path and debug path, if any, apply
                        path = definition.Path;
                        _debugPath = definition.DebugPath; 
                    }
                    name = definition.ResourceName; 
                    assembly = definition.ResourceAssembly; 
                    _cdnPath = definition.CdnPath;
                    _cdnDebugPath = definition.CdnDebugPath; 
                    _cdnPathSecureConnection = definition.CdnPathSecureConnection;
                    _cdnDebugPathSecureConnection = definition.CdnDebugPathSecureConnection;
                }
                else if ((assembly == null) && !String.IsNullOrEmpty(name)) { 
                    // name is set and there is no mapping, default to SWE for assembly
                    assembly = AssemblyCache.SystemWebExtensions; 
                } 
                _resourceName = name;
                _assembly = assembly; 
                _path = path;
            }

            public Assembly Assembly { 
                get {
                    return _assembly; 
                } 
            }
 
            public string CdnDebugPath {
                get {
                    return _cdnDebugPath;
                } 
            }
 
            public string CdnPath { 
                get {
                    return _cdnPath; 
                }
            }

            public string CdnDebugPathSecureConnection { 
                get {
                    return _cdnDebugPathSecureConnection; 
                } 
            }
 
            public string CdnPathSecureConnection {
                get {
                    return _cdnPathSecureConnection;
                } 
            }
 
            public string DebugPath { 
                get {
                    return _debugPath; 
                }
            }

            public string Path { 
                get {
                    return _path; 
                } 
            }
 
            public string ResourceName {
                get {
                    return _resourceName;
                } 
            }
        } 
    } 
}

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

namespace System.Web.UI { 
    using System; 
    using System.Collections;
    using System.ComponentModel; 
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Reflection;
    using System.Web; 
    using System.Web.Handlers;
    using System.Web.Resources; 
    using System.Web.Util; 
    using Debug = System.Diagnostics.Debug;
    using Tuple = System.Web.Util.Tuple; 

    [
    DefaultProperty("Path"),
    ] 
    public class ScriptReference : ScriptReferenceBase {
        // Maps Pair(resource name, assembly) to string (partial script path) 
        private static readonly Hashtable _scriptPathCache = Hashtable.Synchronized(new Hashtable()); 

        private string _assembly; 
        private bool _ignoreScriptPath;
        private string _name;
        private ScriptEffectiveInfo _scriptInfo;
 
        public ScriptReference() : base() {}
 
        public ScriptReference(string name, string assembly) : this() { 
            Name = name;
            Assembly = assembly; 
        }

        public ScriptReference(string path) : this() {
            Path = path; 
        }
 
        internal ScriptReference(string name, IClientUrlResolver clientUrlResolver, Control containingControl) : this() { 
            Debug.Assert(!String.IsNullOrEmpty(name), "The script's name must be specified.");
            Debug.Assert(clientUrlResolver != null && clientUrlResolver is ScriptManager, "The clientUrlResolver must be the ScriptManager."); 
            Name = name;
            ClientUrlResolver = clientUrlResolver;
            IsStaticReference = true;
            ContainingControl = containingControl; 
        }
 
        internal bool IsDirectRegistration { 
            // set to true internally to disable checking for adding .debug
            // used when registering a script directly through SM.RegisterClientScriptResource 
            get;
            set;
        }
 
        [
        Category("Behavior"), 
        DefaultValue(""), 
        ResourceDescription("ScriptReference_Assembly")
        ] 
        public string Assembly {
            get {
                return (_assembly == null) ? String.Empty : _assembly;
            } 
            set {
                _assembly = value; 
                _scriptInfo = null; 
            }
        } 

        internal Assembly EffectiveAssembly {
            get {
                return ScriptInfo.Assembly; 
            }
        } 
 
        internal string EffectivePath {
            get { 
                return String.IsNullOrEmpty(Path) ? ScriptInfo.Path : Path;
            }
        }
 
        internal string EffectiveResourceName {
            get { 
                return ScriptInfo.ResourceName; 
            }
        } 

        internal ScriptMode EffectiveScriptMode {
            get {
                if (ScriptMode == ScriptMode.Auto) { 
                    // - When a mapping.DebugPath exists, ScriptMode.Auto is equivilent to ScriptMode.Inherit,
                    //   since a debug path exists, even though it may not be an assembly based script. 
                    // - An explicitly set Path on the ScriptReference effectively ignores a DebugPath. 
                    // - When only Path is specified, ScriptMode.Auto is equivalent to ScriptMode.Release.
                    // - When only Name is specified, ScriptMode.Auto is equivalent to ScriptMode.Inherit. 
                    // - When Name and Path are both specified, the Path is used instead of the Name, but
                    //   ScriptMode.Auto is still equivalent to ScriptMode.Inherit, since the assumption
                    //   is that if the Assembly contains both release and debug scripts, the Path should
                    //   contain both as well. 
                    return ((String.IsNullOrEmpty(EffectiveResourceName) &&
                        (!String.IsNullOrEmpty(Path) || String.IsNullOrEmpty(ScriptInfo.DebugPath))) ? 
                        ScriptMode.Release : ScriptMode.Inherit); 
                }
                else { 
                    return ScriptMode;
                }
            }
        } 

        [ 
        Category("Behavior"), 
        DefaultValue(false),
        ResourceDescription("ScriptReference_IgnoreScriptPath"), 
        Obsolete("This property is obsolete. Instead of using ScriptManager.ScriptPath, set the Path property on each individual ScriptReference.")
        ]
        public bool IgnoreScriptPath {
            get { 
                return _ignoreScriptPath;
            } 
            set { 
                _ignoreScriptPath = value;
            } 
        }

        [
        Category("Behavior"), 
        DefaultValue(""),
        ResourceDescription("ScriptReference_Name") 
        ] 
        public string Name {
            get { 
                return (_name == null) ? String.Empty : _name;
            }
            set {
                _name = value; 
                _scriptInfo = null;
            } 
        } 

        internal ScriptEffectiveInfo ScriptInfo { 
            get {
                if (_scriptInfo == null) {
                    _scriptInfo = new ScriptEffectiveInfo(this);
                } 
                return _scriptInfo;
            } 
        } 

        private string AddCultureName(ScriptManager scriptManager, string resourceName) { 
            Debug.Assert(!String.IsNullOrEmpty(resourceName));
            CultureInfo culture = (scriptManager.EnableScriptLocalization ?
                DetermineCulture(scriptManager) : CultureInfo.InvariantCulture);
            if (!culture.Equals(CultureInfo.InvariantCulture)) { 
                return AddCultureName(culture, resourceName);
            } 
            else { 
                return resourceName;
            } 
        }

        private static string AddCultureName(CultureInfo culture, string resourceName) {
            if (resourceName.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) { 
                resourceName = resourceName.Substring(0, resourceName.Length - 2) +
                    culture.Name + ".js"; 
            } 
            return resourceName;
        } 

        internal bool DetermineResourceNameAndAssembly(ScriptManager scriptManager, bool isDebuggingEnabled, ref string resourceName, ref Assembly assembly) {
            // If the assembly is the AjaxFrameworkAssembly, the resource may come from that assembly
            // or from the fallback assembly (SWE). 
            if (assembly == scriptManager.AjaxFrameworkAssembly) {
                assembly = ApplyFallbackResource(assembly, resourceName); 
            } 
            // ShouldUseDebugScript throws exception if the resource name does not exist in the assembly
            bool isDebug = ShouldUseDebugScript(resourceName, assembly, 
                isDebuggingEnabled, scriptManager.AjaxFrameworkAssembly);
            if (isDebug) {
                resourceName = GetDebugName(resourceName);
            } 
            // returning true means the debug version is selected
            return isDebug; 
        } 

        internal CultureInfo DetermineCulture(ScriptManager scriptManager) { 
            if ((ResourceUICultures == null) || (ResourceUICultures.Length == 0)) {
                // In this case we want to determine available cultures from assembly info if available
                if (!String.IsNullOrEmpty(EffectiveResourceName)) {
                    return ScriptResourceHandler 
                        .DetermineNearestAvailableCulture(GetAssembly(scriptManager), EffectiveResourceName, CultureInfo.CurrentUICulture);
                } 
                return CultureInfo.InvariantCulture; 
            }
            CultureInfo currentCulture = CultureInfo.CurrentUICulture; 
            while (!currentCulture.Equals(CultureInfo.InvariantCulture)) {
                string cultureName = currentCulture.ToString();
                foreach (string uiCulture in ResourceUICultures) {
                    if (String.Equals(cultureName, uiCulture.Trim(), StringComparison.OrdinalIgnoreCase)) { 
                        return currentCulture;
                    } 
                } 
                currentCulture = currentCulture.Parent;
            } 
            return currentCulture;
        }

        internal Assembly GetAssembly() { 
            return String.IsNullOrEmpty(Assembly) ? null : AssemblyCache.Load(Assembly);
        } 
 
        internal Assembly GetAssembly(ScriptManager scriptManager) {
            // normalizes the effective assembly by redirecting it to the given scriptmanager's 
            // ajax framework assembly when it is set to SWE.
            // EffectiveAssembly can't do this since ScriptReference does not have access by itself
            // to the script manager.
            Debug.Assert(scriptManager != null); 
            Assembly assembly = EffectiveAssembly;
            if (assembly == null) { 
                return scriptManager.AjaxFrameworkAssembly; 
            }
            else { 
                return ((assembly == AssemblyCache.SystemWebExtensions) ?
                    scriptManager.AjaxFrameworkAssembly :
                    assembly);
            } 
        }
 
        // Release: foo.js 
        // Debug:   foo.debug.js
        private static string GetDebugName(string releaseName) { 
            // Since System.Web.Handlers.AssemblyResourceLoader treats the resource name as case-sensitive,
            // we must do the same when verifying the extension.
            // Ignore trailing whitespace. For example, "MicrosoftAjax.js " is valid (at least from
            // a debug/release naming perspective). 
            if (!releaseName.EndsWith(".js", StringComparison.Ordinal)) {
                throw new InvalidOperationException( 
                    String.Format(CultureInfo.CurrentUICulture, AtlasWeb.ScriptReference_InvalidReleaseScriptName, releaseName)); 
            }
 
            return ReplaceExtension(releaseName);
        }

        internal string GetPath(ScriptManager scriptManager, string releasePath, string predeterminedDebugPath, bool isDebuggingEnabled) { 
            // convert the release path to a debug path if:
            // isDebuggingEnabled && not resource based 
            // isDebuggingEnabled && resource based && debug resource exists 
            // ShouldUseDebugScript is called even when isDebuggingEnabled=false as it verfies
            // the existence of the resource. 
            // applies the culture name to the path if appropriate
            string path;
            if (!String.IsNullOrEmpty(EffectiveResourceName)) {
                Assembly assembly = GetAssembly(scriptManager); 
                string resourceName = EffectiveResourceName;
                isDebuggingEnabled = DetermineResourceNameAndAssembly(scriptManager, isDebuggingEnabled, ref resourceName, ref assembly); 
            } 

            if (isDebuggingEnabled) { 
                // Just use predeterminedDebugPath if it is provided. This may be because
                // a script mapping has DebugPath set. If it is empty or null, then '.debug' is added
                // to the .js extension of the release path.
                path = String.IsNullOrEmpty(predeterminedDebugPath) ? GetDebugPath(releasePath) : predeterminedDebugPath; 
            }
            else { 
                path = releasePath; 
            }
            return AddCultureName(scriptManager, path); 
        }

        internal Assembly ApplyFallbackResource(Assembly assembly, string releaseName) {
            // fall back to SWE if the assembly does not contain the requested resource 
            if ((assembly != AssemblyCache.SystemWebExtensions) &&
                !WebResourceUtil.AssemblyContainsWebResource(assembly, releaseName)) { 
                assembly = AssemblyCache.SystemWebExtensions; 
            }
            return assembly; 
        }

        // Format: ///
        // This function does not canonicalize the path in any way (i.e. remove duplicate slashes). 
        // You must call ResolveClientUrl() on this path before rendering to the page.
        internal static string GetScriptPath( 
            string resourceName, 
            Assembly assembly,
            CultureInfo culture, 
            string scriptPath) {

            return scriptPath + "/" + GetScriptPathCached(resourceName, assembly, culture);
        } 

        // Cache partial script path, since Version.ToString() and HttpUtility.UrlEncode() are expensive. 
        // Increases requests/second by 50% in ScriptManagerScriptPath.aspx test. 
        private static string GetScriptPathCached(string resourceName, Assembly assembly, CultureInfo culture) {
            Tuple key = new Tuple(resourceName, assembly, culture); 
            string scriptPath = (string)_scriptPathCache[key];

            if (scriptPath == null) {
                // Need to use "new AssemblyName(assembly.FullName)" instead of "assembly.GetName()", 
                // since Assembly.GetName() requires FileIOPermission to the path of the assembly.
                // In partial trust, we may not have this permission. 
                AssemblyName assemblyName = new AssemblyName(assembly.FullName); 

                string name = assemblyName.Name; 
                string version = assemblyName.Version.ToString();
                string fileVersion = AssemblyUtil.GetAssemblyFileVersion(assembly);

                if (!culture.Equals(CultureInfo.InvariantCulture)) { 
                    resourceName = AddCultureName(culture, resourceName);
                } 
 
                // Assembly name, fileVersion, and resource name may contain invalid URL characters (like '#' or '/'),
                // so they must be url-encoded. 
                scriptPath = String.Join("/", new string[] {
                    HttpUtility.UrlEncode(name), version, HttpUtility.UrlEncode(fileVersion), HttpUtility.UrlEncode(resourceName)
                });
 
                _scriptPathCache[key] = scriptPath;
            } 
 
            return scriptPath;
        } 

        [SuppressMessage("Microsoft.Design", "CA1055", Justification = "Consistent with other URL properties in ASP.NET.")]
        protected internal override string GetUrl(ScriptManager scriptManager, bool zip) {
            bool hasName = !String.IsNullOrEmpty(Name); 
            bool hasAssembly = !String.IsNullOrEmpty(Assembly);
 
            if (!hasName && String.IsNullOrEmpty(Path)) { 
                throw new InvalidOperationException(AtlasWeb.ScriptReference_NameAndPathCannotBeEmpty);
            } 

            if (hasAssembly && !hasName) {
                throw new InvalidOperationException(AtlasWeb.ScriptReference_AssemblyRequiresName);
            } 

            return GetUrlInternal(scriptManager, zip); 
        } 

        internal string GetUrlInternal(ScriptManager scriptManager, bool zip) { 
            if (!String.IsNullOrEmpty(EffectiveResourceName) && !IsAjaxFrameworkScript(scriptManager) &&
                AssemblyCache.IsAjaxFrameworkAssembly(GetAssembly(scriptManager))) {
                // it isnt an AjaxFrameworkScript but it might be from an assembly that is meant to
                // be an ajax script assembly, in which case we should throw an error. 
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
                    AtlasWeb.ScriptReference_ResourceRequiresAjaxAssembly, EffectiveResourceName, GetAssembly(scriptManager))); 
            } 

            if (!String.IsNullOrEmpty(Path)) { 
                // if an explicit path is set on the SR (not on a mapping) it always
                // takes precedence, even when EnableCdn=true.
                // Also, even if a script mapping has a DebugPath, the explicitly set path
                // overrides all -- so path.debug.js is used instead of the mapping's DebugPath, 
                // hence the null 3rd parameter.
                return GetUrlFromPath(scriptManager, Path, null); 
            } 
            else if (!String.IsNullOrEmpty(ScriptInfo.Path)) {
                // when only the mapping has a path, CDN takes first priority 
                if (scriptManager.EnableCdn) {
                    // first determine the actual resource name and assembly to be used
                    // This is so we can (1) apply fallback logic, where ajax fx scripts can come from the
                    // current ajax assembly or from SWE, whichever is first, and (2) the .debug resource 
                    // name is applied if appropriate.
                    string resourceName = EffectiveResourceName; 
                    Assembly assembly = null; 
                    bool hasDebugResource = false;
                    if (!String.IsNullOrEmpty(resourceName)) { 
                        assembly = GetAssembly(scriptManager);
                        hasDebugResource = DetermineResourceNameAndAssembly(scriptManager,
                            IsDebuggingEnabled(scriptManager), ref resourceName, ref assembly);
                    } 
                    string cdnPath = GetUrlForCdn(scriptManager, resourceName, assembly, hasDebugResource);
                    if (!String.IsNullOrEmpty(cdnPath)) { 
                        return cdnPath; 
                    }
                } 
                // the mapping's DebugPath applies if it exists
                return GetUrlFromPath(scriptManager, ScriptInfo.Path, ScriptInfo.DebugPath);
            }
 
            Debug.Assert(!String.IsNullOrEmpty(EffectiveResourceName));
            return GetUrlFromName(scriptManager, scriptManager.Control, zip); 
        } 

        private string GetUrlForCdn(ScriptManager scriptManager, string resourceName, Assembly assembly, bool hasDebugResource) { 
            // if EnableCdn, then url always comes from mapping.Cdn[Debug]Path or WRA.CdnPath, if available.
            // first see if the script description mapping has a cdn path defined
            bool isDebuggingEnabled = IsDebuggingEnabled(scriptManager);
            bool isAssemblyResource = !String.IsNullOrEmpty(resourceName); 
            bool secureConnection = scriptManager.IsSecureConnection;
            isDebuggingEnabled = isDebuggingEnabled && (hasDebugResource || !isAssemblyResource); 
            string cdnPath = isDebuggingEnabled ? 
                (secureConnection ? ScriptInfo.CdnDebugPathSecureConnection : ScriptInfo.CdnDebugPath) :
                (secureConnection ? ScriptInfo.CdnPathSecureConnection : ScriptInfo.CdnPath); 

            // then see if the WebResourceAttribute for the resource has one
            // EXCEPT when the ScriptInfo has a cdnpath but it wasn't selected due to this being a secure connection
            // and it does not support secure connections. Avoid having the HTTP cdn path come from the mapping and the 
            // HTTPS path come from the WRA.
            if (isAssemblyResource && String.IsNullOrEmpty(cdnPath) && String.IsNullOrEmpty(isDebuggingEnabled ? ScriptInfo.CdnDebugPath : ScriptInfo.CdnPath)) { 
                ScriptResourceInfo scriptResourceInfo = ScriptResourceInfo.GetInstance(assembly, resourceName); 
                if (scriptResourceInfo != null) {
                    cdnPath = secureConnection ? scriptResourceInfo.CdnPathSecureConnection : scriptResourceInfo.CdnPath; 
                }
            }
            return String.IsNullOrEmpty(cdnPath) ? null : ClientUrlResolver.ResolveClientUrl(AddCultureName(scriptManager, cdnPath));
        } 

        private string GetUrlFromName(ScriptManager scriptManager, IControl scriptManagerControl, bool zip) { 
            string resourceName = EffectiveResourceName; 
            Assembly assembly = GetAssembly(scriptManager);
            bool hasDebugResource = DetermineResourceNameAndAssembly(scriptManager, IsDebuggingEnabled(scriptManager), 
                ref resourceName, ref assembly);

            if (scriptManager.EnableCdn) {
                string cdnPath = GetUrlForCdn(scriptManager, resourceName, assembly, hasDebugResource); 
                if (!String.IsNullOrEmpty(cdnPath)) {
                    return cdnPath; 
                } 
            }
 
            CultureInfo culture = (scriptManager.EnableScriptLocalization ?
                DetermineCulture(scriptManager) : CultureInfo.InvariantCulture);
#pragma warning disable 618
// ScriptPath is obsolete but still functional 
            if (IgnoreScriptPath || String.IsNullOrEmpty(scriptManager.ScriptPath)) {
                return ScriptResourceHandler.GetScriptResourceUrl(assembly, resourceName, culture, zip); 
            } 
            else {
                string path = GetScriptPath(resourceName, assembly, culture, scriptManager.ScriptPath); 
                // Always want to resolve ScriptPath urls against the ScriptManager itself,
                // regardless of whether the ScriptReference was declared on the ScriptManager
                // or a ScriptManagerProxy.
                return scriptManagerControl.ResolveClientUrl(path); 
            }
#pragma warning restore 618 
        } 

        private string GetUrlFromPath(ScriptManager scriptManager, string releasePath, string predeterminedDebugPath) { 
            string path = GetPath(scriptManager, releasePath, predeterminedDebugPath, IsDebuggingEnabled(scriptManager));
            return ClientUrlResolver.ResolveClientUrl(path);
        }
 
        private bool IsDebuggingEnabled(ScriptManager scriptManager) {
            // Deployment mode retail overrides all values of ScriptReference.ScriptMode. 
            if (IsDirectRegistration || scriptManager.DeploymentSectionRetail) { 
                return false;
            } 

            switch (EffectiveScriptMode) {
                case ScriptMode.Inherit:
                    return scriptManager.IsDebuggingEnabled; 
                case ScriptMode.Debug:
                    return true; 
                case ScriptMode.Release: 
                    return false;
                default: 
                    Debug.Fail("Invalid value for ScriptReference.EffectiveScriptMode");
                    return false;
            }
        } 

        protected internal override bool IsAjaxFrameworkScript(ScriptManager scriptManager) { 
            return (GetAssembly(scriptManager) == scriptManager.AjaxFrameworkAssembly); 
        }
 
        [Obsolete("This method is obsolete. Use IsAjaxFrameworkScript(ScriptManager) instead.")]
        protected internal override bool IsFromSystemWebExtensions() {
            return (EffectiveAssembly == AssemblyCache.SystemWebExtensions);
        } 

        internal bool IsFromSystemWeb() { 
            return (EffectiveAssembly == AssemblyCache.SystemWeb); 
        }
 
        internal bool ShouldUseDebugScript(string releaseName, Assembly assembly,
            bool isDebuggingEnabled, Assembly currentAjaxAssembly) {
            bool useDebugScript;
            string debugName = null; 

            if (isDebuggingEnabled) { 
                debugName = GetDebugName(releaseName); 

                // If an assembly contains a release script but not a corresponding debug script, and we 
                // need to register the debug script, we normally throw an exception.  However, we automatically
                // use the release script if ScriptReference.ScriptMode is Auto.  This improves the developer
                // experience when ScriptMode is Auto, yet still gives the developer full control with the
                // other ScriptModes. 
                if (ScriptMode == ScriptMode.Auto && !WebResourceUtil.AssemblyContainsWebResource(assembly, debugName)) {
                    useDebugScript = false; 
                } 
                else {
                    useDebugScript = true; 
                }
            }
            else {
                useDebugScript = false; 
            }
 
            // Verify that assembly contains required web resources.  Always check for release 
            // script before debug script.
            if (!IsDirectRegistration) { 
                // Don't check if direct registration, because calls to ScriptManager.RegisterClientScriptResource
                // with resources that do not exist does not throw an exception until the resource is served.
                // This was the existing behavior and matches the behavior with ClientScriptManager.GetWebResourceUrl.
                WebResourceUtil.VerifyAssemblyContainsReleaseWebResource(assembly, releaseName, currentAjaxAssembly); 
                if (useDebugScript) {
                    Debug.Assert(debugName != null); 
                    WebResourceUtil.VerifyAssemblyContainsDebugWebResource(assembly, debugName); 
                }
            } 

            return useDebugScript;
        }
 
        // Improves the UI in the VS collection editor, by displaying the Name or Path (if available), or
        // the short type name. 
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] 
        public override string ToString() {
            if (!String.IsNullOrEmpty(Name)) { 
                return Name;
            }
            else if (!String.IsNullOrEmpty(Path)) {
                return Path; 
            }
            else { 
                return GetType().Name; 
            }
        } 

        internal class ScriptEffectiveInfo {
            private string _resourceName;
            private Assembly _assembly; 
            private string _path;
            private string _debugPath; 
            private string _cdnPath; 
            private string _cdnDebugPath;
            private string _cdnPathSecureConnection; 
            private string _cdnDebugPathSecureConnection;

            public ScriptEffectiveInfo(ScriptReference scriptReference) {
                ScriptResourceDefinition definition = 
                    ScriptManager.ScriptResourceMapping.GetDefinition(scriptReference);
                string name = scriptReference.Name; 
                string path = scriptReference.Path; 
                Assembly assembly = scriptReference.GetAssembly();
                if (definition != null) { 
                    if (String.IsNullOrEmpty(path)) {
                        // only when the SR has no path, the mapping's path and debug path, if any, apply
                        path = definition.Path;
                        _debugPath = definition.DebugPath; 
                    }
                    name = definition.ResourceName; 
                    assembly = definition.ResourceAssembly; 
                    _cdnPath = definition.CdnPath;
                    _cdnDebugPath = definition.CdnDebugPath; 
                    _cdnPathSecureConnection = definition.CdnPathSecureConnection;
                    _cdnDebugPathSecureConnection = definition.CdnDebugPathSecureConnection;
                }
                else if ((assembly == null) && !String.IsNullOrEmpty(name)) { 
                    // name is set and there is no mapping, default to SWE for assembly
                    assembly = AssemblyCache.SystemWebExtensions; 
                } 
                _resourceName = name;
                _assembly = assembly; 
                _path = path;
            }

            public Assembly Assembly { 
                get {
                    return _assembly; 
                } 
            }
 
            public string CdnDebugPath {
                get {
                    return _cdnDebugPath;
                } 
            }
 
            public string CdnPath { 
                get {
                    return _cdnPath; 
                }
            }

            public string CdnDebugPathSecureConnection { 
                get {
                    return _cdnDebugPathSecureConnection; 
                } 
            }
 
            public string CdnPathSecureConnection {
                get {
                    return _cdnPathSecureConnection;
                } 
            }
 
            public string DebugPath { 
                get {
                    return _debugPath; 
                }
            }

            public string Path { 
                get {
                    return _path; 
                } 
            }
 
            public string ResourceName {
                get {
                    return _resourceName;
                } 
            }
        } 
    } 
}

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