PackWebRequest.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / IO / Packaging / PackWebRequest.cs / 1 / PackWebRequest.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  WebRequest class to handle pack-specific URI's 
//
// History: 
//  10/09/2003: BruceMac: Created.
//  11/25/2003: BruceMac: Removed IDisposable and create a new WebResponse for
//              each call to GetResponse().
//  01/08/2004: BruceMac: Disable serialization 
//  05/10/2004: BruceMac: Convert to pack scheme
//  04/26/2005: BruceMac: Hold and return whatever credentials are provided by caller in cache case 
//  09/21/2005: BruceMac: Delay inner-webrequest creation until a WebRequest property is set/get so 
//                        that requests that hit a cached package don't require WebPermission.
// 
//-----------------------------------------------------------------------------

#if DEBUG
#define TRACE 
#endif
 
using System; 
using System.IO;
using System.Net; 
using System.Net.Cache;                 // for RequestCachePolicy
using System.Runtime.Serialization;
using System.Diagnostics;               // For Assert
using MS.Utility;                       // for EventTrace 
using MS.Internal.IO.Packaging;         // for PackageCacheEntry
using MS.Internal.PresentationCore;     // for SRID exception strings 
using System.Security;                  // for SecurityCritical 
using MS.Internal;
 
namespace System.IO.Packaging
{
    /// 
    /// pack-specific WebRequest handler 
    /// 
    ///  
    /// This WebRequest overload exists to handle pack-specific URI's based on the "pack" custom schema. 
    /// Note that this schema may or may not be "registered" with the .NET WebRequest factory so callers
    /// should be sure to use the PackUriHelper static class to prepare their Uri's.  PackUriHelper use has the 
    /// side effect of registering the "pack" scheme and associating the PackWebRequest class as its default handler.
    /// 
    public sealed class PackWebRequest : WebRequest
    { 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 
        /// 
        /// Constructor
        /// 
        /// uri to resolve 
        /// uri of the package
        /// uri of the part - may be null 
        /// This should only be called by PackWebRequestFactory  
        /// Will throw an ArgumentException if the given URI is not of the correct scheme
        internal PackWebRequest(Uri uri, Uri packageUri, Uri partUri) 
            : this(uri, packageUri, partUri, null, false, false)
        {
        }
 
        /// 
        /// Cached instance constructor 
        ///  
        /// cache entry to base this response on
        /// uri to resolve 
        /// uri of the package
        /// uri of the part - may be null
        /// should we throw if cache policy conflicts?
        /// is the cacheEntry thread-safe? 
        /// This should only be called by PackWebRequestFactory
        /// Will throw an ArgumentException if the given URI is not of the correct scheme 
        internal PackWebRequest(Uri uri, Uri packageUri, Uri partUri, Package cacheEntry, 
            bool respectCachePolicy, bool cachedPackageIsThreadSafe)
        { 
            Debug.Assert(uri != null, "PackWebRequest uri cannot be null");
            Debug.Assert(packageUri != null, "packageUri cannot be null");

            // keep these 
            _uri = uri;
            _innerUri = packageUri; 
            _partName = partUri; 
            _cacheEntry = cacheEntry;
            _respectCachePolicy = respectCachePolicy; 
            _cachedPackageIsThreadSafe = cachedPackageIsThreadSafe;
            _cachePolicy = _defaultCachePolicy;         // always use default and then let them change it

#if DEBUG 
            if (PackWebRequestFactory._traceSwitch.Enabled && (cacheEntry != null))
                System.Diagnostics.Trace.TraceInformation( 
                        DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " + 
                        System.Threading.Thread.CurrentThread.ManagedThreadId + ": " +
                        "PackWebRequest - working from Package Cache"); 
#endif
        }

        //------------------------------------------------------ 
        //
        //  Public Methods 
        // 
        //-----------------------------------------------------
        #region WebRequest - [....] 
        /// 
        /// GetRequestStream
        /// 
        /// stream 
        /// writing not supported
        public override Stream GetRequestStream() 
        { 
            throw new NotSupportedException();
        } 

        /// 
        /// Returns a WebResponse object
        ///  
        /// PackWebResponse
        /// Caller must eventually call Close() to avoid leaking resources. 
        ///  
        /// Critical
        ///  1) accesses Critical _webRequest 
        ///  2) calling Critical PackWebResponse constructor
        /// Safe
        ///  1) PublicOK
        ///  2) PublicOK 
        /// 
        [SecurityCritical] 
        public override WebResponse GetResponse() 
        {
            bool cachedPackageAvailable = IsCachedPackage; 

            // if there is no cached package or it is from the public PackageStore, we must respect CachePolicy
            if (!cachedPackageAvailable || (cachedPackageAvailable && _respectCachePolicy))
            { 
                // inspect and act on CachePolicy
                RequestCacheLevel policy = _cachePolicy.Level; 
                if (policy == RequestCacheLevel.Default) 
                    policy = _defaultCachePolicy.Level;
 
                switch (policy)
                {
                    case RequestCacheLevel.BypassCache:
                        { 
                            // ignore cache entry
                            cachedPackageAvailable = false; 
                        } break; 

                    case RequestCacheLevel.CacheOnly: 
                        {
                            // only use cached value
                            if (!cachedPackageAvailable)
                                throw new WebException(SR.Get(SRID.ResourceNotFoundUnderCacheOnlyPolicy)); 
                        } break;
 
                    case RequestCacheLevel.CacheIfAvailable: 
                        {
                            // use cached value if possible - we need take no explicit action here 
                        } break;

                    default:
                        { 
                            throw new WebException(SR.Get(SRID.PackWebRequestCachePolicyIllegal));
                        } 
                } 
            }
 
            if (cachedPackageAvailable)
            {
#if DEBUG
                if (PackWebRequestFactory._traceSwitch.Enabled) 
                    System.Diagnostics.Trace.TraceInformation(
                        DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " + 
                        System.Threading.Thread.CurrentThread.ManagedThreadId + ": " + 
                        "PackWebRequest - Getting response from Package Cache");
#endif 
                return new PackWebResponse(_uri, _innerUri, _partName, _cacheEntry, _cachedPackageIsThreadSafe);
            }
            else
            { 
                // only return a real WebRequest instance - throw on a PseudoWebRequest
                WebRequest request = GetRequest(false); 
                if (_webRequest == null || _webRequest is PseudoWebRequest) 
                    throw new InvalidOperationException(SR.Get(SRID.SchemaInvalidForTransport));
 
#if DEBUG
                if (PackWebRequestFactory._traceSwitch.Enabled)
                    System.Diagnostics.Trace.TraceInformation(
                        DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " + 
                        System.Threading.Thread.CurrentThread.ManagedThreadId + ": " +
                        "PackWebRequest - Getting new response"); 
#endif 
                // Create a new response for every call
                return new PackWebResponse(_uri, _innerUri, _partName, request); 
            }
        }
        #endregion
 
        //------------------------------------------------------
        // 
        //  Public Properties 
        //
        //------------------------------------------------------ 
        #region Properties

        /// 
        /// CachePolicy for the PackWebRequest 
        /// 
        /// This value is distinct from the CachePolicy of the InnerRequest. 
        ///  
        public override RequestCachePolicy CachePolicy
        { 
            get
            {
                return _cachePolicy;
            } 
            set
            { 
                if (value == null) 
                    _cachePolicy = _defaultCachePolicy;
                else 
                {
                    switch (value.Level)
                    {
                        case RequestCacheLevel.BypassCache: break; 
                        case RequestCacheLevel.CacheOnly: break;
                        case RequestCacheLevel.CacheIfAvailable: break; 
                        default: 
                            throw new WebException(SR.Get(SRID.PackWebRequestCachePolicyIllegal));
                    } 

                    _cachePolicy = value;
                }
            } 
        }
 
        ///  
        /// ConnectionGroupName
        ///  
        /// This value is shared with the InnerRequest.
        /// name of current connection group
        public override string ConnectionGroupName
        { 
            get
            { 
                return GetRequest().ConnectionGroupName; 
            }
            set 
            {
                GetRequest().ConnectionGroupName = value;
            }
        } 

 
        ///  
        /// ContentLength
        ///  
        /// length of RequestStream
        /// This value is shared with the InnerRequest.
        /// Set is not supported as PackWebRequest is read-only.
        public override long ContentLength 
        {
            get 
            { 
                return GetRequest().ContentLength;
            } 
            set
            {
                // we don't upload so no reason to support this
                throw new NotSupportedException(); 
            }
        } 
 

        ///  
        /// ContentType
        /// 
        /// Content type of the request data being sent or data being requested.  Null is explicitly allowed.
        /// This value is shared with the InnerRequest. 
        public override string ContentType
        { 
            get 
            {
                string contentType = GetRequest().ContentType; 
                if (contentType == null)
                    return contentType;
                else
                    //We call the ContentType constructor to validate the grammar for 
                    //content type string.
                    return new MS.Internal.ContentType(contentType).ToString(); 
            } 
            set
            { 
                // this property can indicate to the server what content type we prefer
                GetRequest().ContentType = value;
            }
        } 

 
        ///  
        /// Credentials
        ///  
        /// Credentials to use when authenticating against the resource
        /// This value is shared with the InnerRequest.
        public override ICredentials Credentials
        { 
            get
            { 
                return GetRequest().Credentials; 
            }
            set 
            {
                GetRequest().Credentials = value;
            }
        } 

 
        ///  
        /// Headers
        ///  
        /// collection of header name/value pairs associated with the request
        /// This value is shared with the InnerRequest.
        public override WebHeaderCollection Headers
        { 
            get
            { 
                return GetRequest().Headers; 
            }
            set 
            {
                GetRequest().Headers = value;
            }
        } 

        ///  
        /// Method 
        /// 
        /// protocol method to use in this request 
        /// This value is shared with the InnerRequest.
        public override string Method
        {
            get 
            {
                return GetRequest().Method; 
            } 
            set
            { 
                GetRequest().Method = value;
            }
        }
 

        ///  
        /// PreAuthenticate 
        /// 
        /// indicates whether to preauthenticate the request 
        /// This value is shared with the InnerRequest.
        public override bool PreAuthenticate
        {
            get 
            {
                return GetRequest().PreAuthenticate; 
            } 
            set
            { 
                GetRequest().PreAuthenticate = value;
            }
        }
 

        ///  
        /// Proxy 
        /// 
        /// network proxy to use to access this Internet resource 
        /// This value is shared with the InnerRequest.
        /// 
        /// Critical
        ///  1) gets/sets Critical member _webRequest.Proxy() 
        /// Safe
        ///  2) PublicOK 
        ///  
        public override IWebProxy Proxy
        { 
            [SecurityCritical]
            get
            {
                return GetRequest().Proxy; 
            }
            [SecurityCritical] 
            set 
            {
                GetRequest().Proxy = value; 
            }
        }

 
        /// 
        /// RequestUri 
        ///  
        /// URI of the Internet resource associated with the request
        public override Uri RequestUri 
        {
            get
            {
                return _uri; 
            }
        } 
 
        /// 
        /// Timeout 
        /// 
        /// length of time before the request times out
        /// This value is shared with the InnerRequest.
        /// Value must be >= -1 
        public override int Timeout
        { 
            get 
            {
                return GetRequest().Timeout; 
            }
            set
            {
                // negative time that is not -1 (infinite) is an error case 
                if (value < 0 && value != System.Threading.Timeout.Infinite)
                    throw new ArgumentOutOfRangeException("value"); 
 
                GetRequest().Timeout = value;
            } 
        }

        /// 
        /// UseDefaultCredentials 
        /// 
        public override bool UseDefaultCredentials 
        { 
            get
            { 
                return GetRequest().UseDefaultCredentials;
            }
            set
            { 
                GetRequest().UseDefaultCredentials = value;
            } 
        } 

        #endregion 

        #region New Properties
        /// 
        /// GetInnerRequest 
        /// 
        /// Inner WebRequest object. 
        /// Inner uri is not resolvable to a valid transport protocol (such as 
        /// ftp or http) and the request cannot be satisfied from the PackageStore.
        /// The inner WebRequest is provided for advanced scenarios only and 
        /// need not be accessed in most cases.
        /// A WebRequest created using the inner-uri or null if the inner uri is not resolvable and we
        /// have a valid PackageStore entry that can be used to provide data.
        public WebRequest GetInnerRequest() 
        {
            WebRequest request = GetRequest(false); 
            if (request == null || request is PseudoWebRequest) 
                return null;
 
            return request;
        }
        #endregion
 
        //-----------------------------------------------------
        // 
        //  Internal Methods 
        //
        //------------------------------------------------------ 
        //-----------------------------------------------------
        //
        //  Internal Properties
        // 
        //-----------------------------------------------------
        //----------------------------------------------------- 
        // 
        //  Private Methods
        // 
        //------------------------------------------------------
        /// 
        /// Returns a WebRequest - should be called from properties
        ///  
        /// Actual WebRequest or PseudoWebRequest
        /// protocol does not have a registered handler 
        private WebRequest GetRequest() 
        {
            return GetRequest(true); 
        }

        /// 
        /// Returns a WebRequest - can be called from properties and from GetInnerRequest() 
        /// 
        /// if this is false, caller will not accept a PseudoWebRequest 
        /// Actual WebRequest or PseudoWebRequest 
        /// protocol does not have a registered handler
        ///  
        /// Critical
        ///  1) accesses Critical _webRequest
        /// Safe
        ///  1) Not modifying Proxy member which is what is really Critical 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private WebRequest GetRequest(bool allowPseudoRequest) 
        {
            if (_webRequest == null) 
            {
                // Don't even attempt to create if we know it will fail.  This does not eliminate all failure cases
                // but most and is very common so let's save an expensive exception.
                // We still create a webRequest if possible even if we have a potential cacheEntry 
                // because the caller may still specify BypassCache policy before calling GetResponse() that will force us to hit the server.
                if (!IsPreloadedPackage) 
                { 
                    // Need inner request so we can get/set properties or create a real WebResponse.
                    // Note: WebRequest.Create throws NotSupportedException for schemes that it does not recognize. 
                    // We need to be open-ended in our support of schemes, so we need to always try to create.
                    // If WebRequest throws NotSupportedException then we catch and ignore if the WebRequest can be
                    // satisfied from the cache.  If the cache entry is missing then we simply re-throw because the request
                    // cannot possibly succeed. 
                    try
                    { 
                        _webRequest = WpfWebRequestHelper.CreateRequest(_innerUri); 

                        // special optimization for ftp - Passive mode won't return lengths on ISA servers 
                        FtpWebRequest ftpWebRequest = _webRequest as FtpWebRequest;
                        if (ftpWebRequest != null)
                        {
                            ftpWebRequest.UsePassive = false;  // default but allow override 
                        }
 
                    } 
                    catch (NotSupportedException)
                    { 
                        // If the inner Uri does not match any cache entry then we throw.
                        if (!IsCachedPackage)
                            throw;
                    } 
                }
 
                // Just return null if caller cannot accept a PseudoWebRequest 
                if (_webRequest == null && allowPseudoRequest)
                { 
                    // We get here if the caller can accept a PseudoWebRequest (based on argument to the function)
                    // and one of these two cases is true:
                    // 1. We have a package from the PreloadedPackages collection
                    // 2. If WebRequest.Create() failed and we have a cached package 
                    // In either case, we create a pseudo request to house property values.
                    // In case 1, we know there will never be a cache bypass (we ignore cache policy for PreloadedPackages) 
                    // In case 2, the caller is using a schema that we cannot use for transport (not on of ftp, http, file, etc) 
                    // and we will silently accept and ignore their property modifications/queries.
                    // Note that if they change the cache policy to BypassCache they will get an exception when they call 
                    // GetResponse().  If they leave cache policy intact, and call GetResponse()
                    // they will get data from the cached package.
                    _webRequest = new PseudoWebRequest(_uri, _innerUri, _partName, _cacheEntry);
                } 
            }
 
            return _webRequest; 
        }
 
        //-----------------------------------------------------
        //
        //  Private Properties
        // 
        //------------------------------------------------------
        ///  
        /// True if we have a package from either that PreloadedPackages or PackageStore 
        /// 
        private bool IsCachedPackage 
        {
            get
            {
                return (_cacheEntry != null); 
            }
        } 
 
        /// 
        /// True only if we have a package from PreloadedPackages 
        /// 
        private bool IsPreloadedPackage
        {
            get 
            {
                // _respectCachePolicy is only false for packages retrieved from PreloadedPackages 
                return ((_cacheEntry != null) && (!_respectCachePolicy)); 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Fields 
        //
        //----------------------------------------------------- 
        private Uri                 _uri;                   // pack uri 
        private Uri                 _innerUri;              // inner uri extracted from the pack uri
        private Uri                 _partName;              // name of PackagePart (if any) - null for full-container references 
        [SecurityCritical]                                  // only WebRequest.Proxy member is Critical
        private WebRequest          _webRequest;            // our "real" webrequest counterpart - may be a PseudoWebRequest
        private Package             _cacheEntry;            // non-null if we found this in a cache
        private bool                _respectCachePolicy;    // do we throw if cache policy conflicts? 
        private bool                _cachedPackageIsThreadSafe; // pass to WebResponse so it can safely return streams
        private RequestCachePolicy  _cachePolicy;           // outer cache-policy 
 
        // statics
        static private RequestCachePolicy _defaultCachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable); 

        // These are "cached" inner Uri's taken from the available application: and SiteOfOrigin: Uri's.
        // They are kept in statics to eliminate overhead of reparsing them on every request.
        // We are essentially extracting the "application://" out of "pack://application:,," 
        static private Uri _siteOfOriginUri = PackUriHelper.GetPackageUri(System.Windows.Navigation.BaseUriHelper.SiteOfOriginBaseUri);
        static private Uri _appBaseUri = PackUriHelper.GetPackageUri(System.Windows.Navigation.BaseUriHelper.PackAppBaseUri); 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  WebRequest class to handle pack-specific URI's 
//
// History: 
//  10/09/2003: BruceMac: Created.
//  11/25/2003: BruceMac: Removed IDisposable and create a new WebResponse for
//              each call to GetResponse().
//  01/08/2004: BruceMac: Disable serialization 
//  05/10/2004: BruceMac: Convert to pack scheme
//  04/26/2005: BruceMac: Hold and return whatever credentials are provided by caller in cache case 
//  09/21/2005: BruceMac: Delay inner-webrequest creation until a WebRequest property is set/get so 
//                        that requests that hit a cached package don't require WebPermission.
// 
//-----------------------------------------------------------------------------

#if DEBUG
#define TRACE 
#endif
 
using System; 
using System.IO;
using System.Net; 
using System.Net.Cache;                 // for RequestCachePolicy
using System.Runtime.Serialization;
using System.Diagnostics;               // For Assert
using MS.Utility;                       // for EventTrace 
using MS.Internal.IO.Packaging;         // for PackageCacheEntry
using MS.Internal.PresentationCore;     // for SRID exception strings 
using System.Security;                  // for SecurityCritical 
using MS.Internal;
 
namespace System.IO.Packaging
{
    /// 
    /// pack-specific WebRequest handler 
    /// 
    ///  
    /// This WebRequest overload exists to handle pack-specific URI's based on the "pack" custom schema. 
    /// Note that this schema may or may not be "registered" with the .NET WebRequest factory so callers
    /// should be sure to use the PackUriHelper static class to prepare their Uri's.  PackUriHelper use has the 
    /// side effect of registering the "pack" scheme and associating the PackWebRequest class as its default handler.
    /// 
    public sealed class PackWebRequest : WebRequest
    { 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 
        /// 
        /// Constructor
        /// 
        /// uri to resolve 
        /// uri of the package
        /// uri of the part - may be null 
        /// This should only be called by PackWebRequestFactory  
        /// Will throw an ArgumentException if the given URI is not of the correct scheme
        internal PackWebRequest(Uri uri, Uri packageUri, Uri partUri) 
            : this(uri, packageUri, partUri, null, false, false)
        {
        }
 
        /// 
        /// Cached instance constructor 
        ///  
        /// cache entry to base this response on
        /// uri to resolve 
        /// uri of the package
        /// uri of the part - may be null
        /// should we throw if cache policy conflicts?
        /// is the cacheEntry thread-safe? 
        /// This should only be called by PackWebRequestFactory
        /// Will throw an ArgumentException if the given URI is not of the correct scheme 
        internal PackWebRequest(Uri uri, Uri packageUri, Uri partUri, Package cacheEntry, 
            bool respectCachePolicy, bool cachedPackageIsThreadSafe)
        { 
            Debug.Assert(uri != null, "PackWebRequest uri cannot be null");
            Debug.Assert(packageUri != null, "packageUri cannot be null");

            // keep these 
            _uri = uri;
            _innerUri = packageUri; 
            _partName = partUri; 
            _cacheEntry = cacheEntry;
            _respectCachePolicy = respectCachePolicy; 
            _cachedPackageIsThreadSafe = cachedPackageIsThreadSafe;
            _cachePolicy = _defaultCachePolicy;         // always use default and then let them change it

#if DEBUG 
            if (PackWebRequestFactory._traceSwitch.Enabled && (cacheEntry != null))
                System.Diagnostics.Trace.TraceInformation( 
                        DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " + 
                        System.Threading.Thread.CurrentThread.ManagedThreadId + ": " +
                        "PackWebRequest - working from Package Cache"); 
#endif
        }

        //------------------------------------------------------ 
        //
        //  Public Methods 
        // 
        //-----------------------------------------------------
        #region WebRequest - [....] 
        /// 
        /// GetRequestStream
        /// 
        /// stream 
        /// writing not supported
        public override Stream GetRequestStream() 
        { 
            throw new NotSupportedException();
        } 

        /// 
        /// Returns a WebResponse object
        ///  
        /// PackWebResponse
        /// Caller must eventually call Close() to avoid leaking resources. 
        ///  
        /// Critical
        ///  1) accesses Critical _webRequest 
        ///  2) calling Critical PackWebResponse constructor
        /// Safe
        ///  1) PublicOK
        ///  2) PublicOK 
        /// 
        [SecurityCritical] 
        public override WebResponse GetResponse() 
        {
            bool cachedPackageAvailable = IsCachedPackage; 

            // if there is no cached package or it is from the public PackageStore, we must respect CachePolicy
            if (!cachedPackageAvailable || (cachedPackageAvailable && _respectCachePolicy))
            { 
                // inspect and act on CachePolicy
                RequestCacheLevel policy = _cachePolicy.Level; 
                if (policy == RequestCacheLevel.Default) 
                    policy = _defaultCachePolicy.Level;
 
                switch (policy)
                {
                    case RequestCacheLevel.BypassCache:
                        { 
                            // ignore cache entry
                            cachedPackageAvailable = false; 
                        } break; 

                    case RequestCacheLevel.CacheOnly: 
                        {
                            // only use cached value
                            if (!cachedPackageAvailable)
                                throw new WebException(SR.Get(SRID.ResourceNotFoundUnderCacheOnlyPolicy)); 
                        } break;
 
                    case RequestCacheLevel.CacheIfAvailable: 
                        {
                            // use cached value if possible - we need take no explicit action here 
                        } break;

                    default:
                        { 
                            throw new WebException(SR.Get(SRID.PackWebRequestCachePolicyIllegal));
                        } 
                } 
            }
 
            if (cachedPackageAvailable)
            {
#if DEBUG
                if (PackWebRequestFactory._traceSwitch.Enabled) 
                    System.Diagnostics.Trace.TraceInformation(
                        DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " + 
                        System.Threading.Thread.CurrentThread.ManagedThreadId + ": " + 
                        "PackWebRequest - Getting response from Package Cache");
#endif 
                return new PackWebResponse(_uri, _innerUri, _partName, _cacheEntry, _cachedPackageIsThreadSafe);
            }
            else
            { 
                // only return a real WebRequest instance - throw on a PseudoWebRequest
                WebRequest request = GetRequest(false); 
                if (_webRequest == null || _webRequest is PseudoWebRequest) 
                    throw new InvalidOperationException(SR.Get(SRID.SchemaInvalidForTransport));
 
#if DEBUG
                if (PackWebRequestFactory._traceSwitch.Enabled)
                    System.Diagnostics.Trace.TraceInformation(
                        DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " + 
                        System.Threading.Thread.CurrentThread.ManagedThreadId + ": " +
                        "PackWebRequest - Getting new response"); 
#endif 
                // Create a new response for every call
                return new PackWebResponse(_uri, _innerUri, _partName, request); 
            }
        }
        #endregion
 
        //------------------------------------------------------
        // 
        //  Public Properties 
        //
        //------------------------------------------------------ 
        #region Properties

        /// 
        /// CachePolicy for the PackWebRequest 
        /// 
        /// This value is distinct from the CachePolicy of the InnerRequest. 
        ///  
        public override RequestCachePolicy CachePolicy
        { 
            get
            {
                return _cachePolicy;
            } 
            set
            { 
                if (value == null) 
                    _cachePolicy = _defaultCachePolicy;
                else 
                {
                    switch (value.Level)
                    {
                        case RequestCacheLevel.BypassCache: break; 
                        case RequestCacheLevel.CacheOnly: break;
                        case RequestCacheLevel.CacheIfAvailable: break; 
                        default: 
                            throw new WebException(SR.Get(SRID.PackWebRequestCachePolicyIllegal));
                    } 

                    _cachePolicy = value;
                }
            } 
        }
 
        ///  
        /// ConnectionGroupName
        ///  
        /// This value is shared with the InnerRequest.
        /// name of current connection group
        public override string ConnectionGroupName
        { 
            get
            { 
                return GetRequest().ConnectionGroupName; 
            }
            set 
            {
                GetRequest().ConnectionGroupName = value;
            }
        } 

 
        ///  
        /// ContentLength
        ///  
        /// length of RequestStream
        /// This value is shared with the InnerRequest.
        /// Set is not supported as PackWebRequest is read-only.
        public override long ContentLength 
        {
            get 
            { 
                return GetRequest().ContentLength;
            } 
            set
            {
                // we don't upload so no reason to support this
                throw new NotSupportedException(); 
            }
        } 
 

        ///  
        /// ContentType
        /// 
        /// Content type of the request data being sent or data being requested.  Null is explicitly allowed.
        /// This value is shared with the InnerRequest. 
        public override string ContentType
        { 
            get 
            {
                string contentType = GetRequest().ContentType; 
                if (contentType == null)
                    return contentType;
                else
                    //We call the ContentType constructor to validate the grammar for 
                    //content type string.
                    return new MS.Internal.ContentType(contentType).ToString(); 
            } 
            set
            { 
                // this property can indicate to the server what content type we prefer
                GetRequest().ContentType = value;
            }
        } 

 
        ///  
        /// Credentials
        ///  
        /// Credentials to use when authenticating against the resource
        /// This value is shared with the InnerRequest.
        public override ICredentials Credentials
        { 
            get
            { 
                return GetRequest().Credentials; 
            }
            set 
            {
                GetRequest().Credentials = value;
            }
        } 

 
        ///  
        /// Headers
        ///  
        /// collection of header name/value pairs associated with the request
        /// This value is shared with the InnerRequest.
        public override WebHeaderCollection Headers
        { 
            get
            { 
                return GetRequest().Headers; 
            }
            set 
            {
                GetRequest().Headers = value;
            }
        } 

        ///  
        /// Method 
        /// 
        /// protocol method to use in this request 
        /// This value is shared with the InnerRequest.
        public override string Method
        {
            get 
            {
                return GetRequest().Method; 
            } 
            set
            { 
                GetRequest().Method = value;
            }
        }
 

        ///  
        /// PreAuthenticate 
        /// 
        /// indicates whether to preauthenticate the request 
        /// This value is shared with the InnerRequest.
        public override bool PreAuthenticate
        {
            get 
            {
                return GetRequest().PreAuthenticate; 
            } 
            set
            { 
                GetRequest().PreAuthenticate = value;
            }
        }
 

        ///  
        /// Proxy 
        /// 
        /// network proxy to use to access this Internet resource 
        /// This value is shared with the InnerRequest.
        /// 
        /// Critical
        ///  1) gets/sets Critical member _webRequest.Proxy() 
        /// Safe
        ///  2) PublicOK 
        ///  
        public override IWebProxy Proxy
        { 
            [SecurityCritical]
            get
            {
                return GetRequest().Proxy; 
            }
            [SecurityCritical] 
            set 
            {
                GetRequest().Proxy = value; 
            }
        }

 
        /// 
        /// RequestUri 
        ///  
        /// URI of the Internet resource associated with the request
        public override Uri RequestUri 
        {
            get
            {
                return _uri; 
            }
        } 
 
        /// 
        /// Timeout 
        /// 
        /// length of time before the request times out
        /// This value is shared with the InnerRequest.
        /// Value must be >= -1 
        public override int Timeout
        { 
            get 
            {
                return GetRequest().Timeout; 
            }
            set
            {
                // negative time that is not -1 (infinite) is an error case 
                if (value < 0 && value != System.Threading.Timeout.Infinite)
                    throw new ArgumentOutOfRangeException("value"); 
 
                GetRequest().Timeout = value;
            } 
        }

        /// 
        /// UseDefaultCredentials 
        /// 
        public override bool UseDefaultCredentials 
        { 
            get
            { 
                return GetRequest().UseDefaultCredentials;
            }
            set
            { 
                GetRequest().UseDefaultCredentials = value;
            } 
        } 

        #endregion 

        #region New Properties
        /// 
        /// GetInnerRequest 
        /// 
        /// Inner WebRequest object. 
        /// Inner uri is not resolvable to a valid transport protocol (such as 
        /// ftp or http) and the request cannot be satisfied from the PackageStore.
        /// The inner WebRequest is provided for advanced scenarios only and 
        /// need not be accessed in most cases.
        /// A WebRequest created using the inner-uri or null if the inner uri is not resolvable and we
        /// have a valid PackageStore entry that can be used to provide data.
        public WebRequest GetInnerRequest() 
        {
            WebRequest request = GetRequest(false); 
            if (request == null || request is PseudoWebRequest) 
                return null;
 
            return request;
        }
        #endregion
 
        //-----------------------------------------------------
        // 
        //  Internal Methods 
        //
        //------------------------------------------------------ 
        //-----------------------------------------------------
        //
        //  Internal Properties
        // 
        //-----------------------------------------------------
        //----------------------------------------------------- 
        // 
        //  Private Methods
        // 
        //------------------------------------------------------
        /// 
        /// Returns a WebRequest - should be called from properties
        ///  
        /// Actual WebRequest or PseudoWebRequest
        /// protocol does not have a registered handler 
        private WebRequest GetRequest() 
        {
            return GetRequest(true); 
        }

        /// 
        /// Returns a WebRequest - can be called from properties and from GetInnerRequest() 
        /// 
        /// if this is false, caller will not accept a PseudoWebRequest 
        /// Actual WebRequest or PseudoWebRequest 
        /// protocol does not have a registered handler
        ///  
        /// Critical
        ///  1) accesses Critical _webRequest
        /// Safe
        ///  1) Not modifying Proxy member which is what is really Critical 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private WebRequest GetRequest(bool allowPseudoRequest) 
        {
            if (_webRequest == null) 
            {
                // Don't even attempt to create if we know it will fail.  This does not eliminate all failure cases
                // but most and is very common so let's save an expensive exception.
                // We still create a webRequest if possible even if we have a potential cacheEntry 
                // because the caller may still specify BypassCache policy before calling GetResponse() that will force us to hit the server.
                if (!IsPreloadedPackage) 
                { 
                    // Need inner request so we can get/set properties or create a real WebResponse.
                    // Note: WebRequest.Create throws NotSupportedException for schemes that it does not recognize. 
                    // We need to be open-ended in our support of schemes, so we need to always try to create.
                    // If WebRequest throws NotSupportedException then we catch and ignore if the WebRequest can be
                    // satisfied from the cache.  If the cache entry is missing then we simply re-throw because the request
                    // cannot possibly succeed. 
                    try
                    { 
                        _webRequest = WpfWebRequestHelper.CreateRequest(_innerUri); 

                        // special optimization for ftp - Passive mode won't return lengths on ISA servers 
                        FtpWebRequest ftpWebRequest = _webRequest as FtpWebRequest;
                        if (ftpWebRequest != null)
                        {
                            ftpWebRequest.UsePassive = false;  // default but allow override 
                        }
 
                    } 
                    catch (NotSupportedException)
                    { 
                        // If the inner Uri does not match any cache entry then we throw.
                        if (!IsCachedPackage)
                            throw;
                    } 
                }
 
                // Just return null if caller cannot accept a PseudoWebRequest 
                if (_webRequest == null && allowPseudoRequest)
                { 
                    // We get here if the caller can accept a PseudoWebRequest (based on argument to the function)
                    // and one of these two cases is true:
                    // 1. We have a package from the PreloadedPackages collection
                    // 2. If WebRequest.Create() failed and we have a cached package 
                    // In either case, we create a pseudo request to house property values.
                    // In case 1, we know there will never be a cache bypass (we ignore cache policy for PreloadedPackages) 
                    // In case 2, the caller is using a schema that we cannot use for transport (not on of ftp, http, file, etc) 
                    // and we will silently accept and ignore their property modifications/queries.
                    // Note that if they change the cache policy to BypassCache they will get an exception when they call 
                    // GetResponse().  If they leave cache policy intact, and call GetResponse()
                    // they will get data from the cached package.
                    _webRequest = new PseudoWebRequest(_uri, _innerUri, _partName, _cacheEntry);
                } 
            }
 
            return _webRequest; 
        }
 
        //-----------------------------------------------------
        //
        //  Private Properties
        // 
        //------------------------------------------------------
        ///  
        /// True if we have a package from either that PreloadedPackages or PackageStore 
        /// 
        private bool IsCachedPackage 
        {
            get
            {
                return (_cacheEntry != null); 
            }
        } 
 
        /// 
        /// True only if we have a package from PreloadedPackages 
        /// 
        private bool IsPreloadedPackage
        {
            get 
            {
                // _respectCachePolicy is only false for packages retrieved from PreloadedPackages 
                return ((_cacheEntry != null) && (!_respectCachePolicy)); 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Fields 
        //
        //----------------------------------------------------- 
        private Uri                 _uri;                   // pack uri 
        private Uri                 _innerUri;              // inner uri extracted from the pack uri
        private Uri                 _partName;              // name of PackagePart (if any) - null for full-container references 
        [SecurityCritical]                                  // only WebRequest.Proxy member is Critical
        private WebRequest          _webRequest;            // our "real" webrequest counterpart - may be a PseudoWebRequest
        private Package             _cacheEntry;            // non-null if we found this in a cache
        private bool                _respectCachePolicy;    // do we throw if cache policy conflicts? 
        private bool                _cachedPackageIsThreadSafe; // pass to WebResponse so it can safely return streams
        private RequestCachePolicy  _cachePolicy;           // outer cache-policy 
 
        // statics
        static private RequestCachePolicy _defaultCachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable); 

        // These are "cached" inner Uri's taken from the available application: and SiteOfOrigin: Uri's.
        // They are kept in statics to eliminate overhead of reparsing them on every request.
        // We are essentially extracting the "application://" out of "pack://application:,," 
        static private Uri _siteOfOriginUri = PackUriHelper.GetPackageUri(System.Windows.Navigation.BaseUriHelper.SiteOfOriginBaseUri);
        static private Uri _appBaseUri = PackUriHelper.GetPackageUri(System.Windows.Navigation.BaseUriHelper.PackAppBaseUri); 
    } 
}

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

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK