WebUtil.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 / ndp / fx / src / DataWeb / Server / System / Data / Services / WebUtil.cs / 2 / WebUtil.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides some utility functions for this project
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services
{
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Data.Linq; 
    using System.Data.Services.Providers;
    using System.Diagnostics; 
    using System.Globalization;
    using System.Reflection;
    using System.Text;
    using System.Xml; 
    using System.Xml.Linq;
 
    /// Utility methods for this project. 
    internal static class WebUtil
    { 
        /// Bindings Flags for public instance members.
        internal const BindingFlags PublicInstanceBindingFlags = BindingFlags.Public | BindingFlags.Instance;

        /// A zero-length object array. 
        internal static readonly object[] EmptyObjectArray = new object[0];
 
        /// A zero-length string array. 
        internal static readonly string[] EmptyStringArray = new string[0];
 
        // Only StackOverflowException & ThreadAbortException are sealed classes.

        /// Type of OutOfMemoryException.
        private static readonly Type OutOfMemoryType = typeof(System.OutOfMemoryException); 

        /// Type of StackOverflowException. 
        private static readonly Type StackOverflowType = typeof(System.StackOverflowException); 

        /// Type of ThreadAbortException. 
        private static readonly Type ThreadAbortType = typeof(System.Threading.ThreadAbortException);

        /// List of primitive types supported by Astoria and their corresponding edm names.
        private static readonly KeyValuePair[] PrimitiveTypesEdmNameMapping = 
            new KeyValuePair[]
            { 
                new KeyValuePair(typeof(string), XmlConstants.EdmStringTypeName), 
                new KeyValuePair(typeof(Boolean), XmlConstants.EdmBooleanTypeName),
                new KeyValuePair(typeof(Binary), XmlConstants.EdmBinaryTypeName), 
                new KeyValuePair(typeof(Byte), XmlConstants.EdmByteTypeName),
                new KeyValuePair(typeof(DateTime), XmlConstants.EdmDateTimeTypeName),
                new KeyValuePair(typeof(Decimal), XmlConstants.EdmDecimalTypeName),
                new KeyValuePair(typeof(Double), XmlConstants.EdmDoubleTypeName), 
                new KeyValuePair(typeof(Guid), XmlConstants.EdmGuidTypeName),
                new KeyValuePair(typeof(Int16), XmlConstants.EdmInt16TypeName), 
                new KeyValuePair(typeof(Int32), XmlConstants.EdmInt32TypeName), 
                new KeyValuePair(typeof(Int64), XmlConstants.EdmInt64TypeName),
                new KeyValuePair(typeof(SByte), XmlConstants.EdmSByteTypeName), 
                new KeyValuePair(typeof(Single), XmlConstants.EdmSingleTypeName),
                new KeyValuePair(typeof(byte[]), XmlConstants.EdmBinaryTypeName),
                new KeyValuePair(typeof(XElement), XmlConstants.EdmStringTypeName),
            }; 

        /// List of primitive types supported by Astoria and their corresponding default MIME types. 
        private static readonly KeyValuePair[] PrimitiveTypesMimeTypeMapping = 
            new KeyValuePair[]
            { 
                new KeyValuePair(typeof(byte[]), XmlConstants.MimeApplicationOctetStream),
                new KeyValuePair(typeof(Binary), XmlConstants.MimeApplicationOctetStream),
            };
 
        /// List of primitive types supported by Astoria and their corresponding default content format.
        private static readonly KeyValuePair[] PrimitiveTypesContentFormatMapping = 
            new KeyValuePair[] 
            {
                new KeyValuePair(typeof(byte[]), ContentFormat.Binary), 
                new KeyValuePair(typeof(Binary), ContentFormat.Binary),
            };

        /// List of primitive resource types. We don't want to create them again and again, so creating them once and caching them 
        private static ResourceType[] primitiveResourceTypes;
 
        ///  
        /// Applies the host specified in a request if available to the given .
        ///  
        /// URI to update with host (and port) information.
        /// Host header (possibly null or empty)
        /// The updated URI.
        internal static Uri ApplyHostHeader(Uri baseUri, string requestHost) 
        {
            Debug.Assert(baseUri != null, "baseUri"); 
            if (!String.IsNullOrEmpty(requestHost)) 
            {
                UriBuilder builder = new UriBuilder(baseUri); 
                string host;
                int port;
                if (GetHostAndPort(requestHost, baseUri.Scheme, out host, out port))
                { 
                    builder.Host = host;
                    builder.Port = port; 
                } 
                else
                { 
                    builder.Host = requestHost;
                }

                baseUri = builder.Uri; 
            }
 
            return baseUri; 
        }
 
        /// 
        /// Checks the argument value for null and throw ArgumentNullException if it is null
        /// 
        /// type of the argument 
        /// argument whose value needs to be checked
        /// name of the argument 
        /// returns the argument back 
        internal static T CheckArgumentNull(T value, string parameterName) where T : class
        { 
            if (null == value)
            {
                throw Error.ArgumentNull(parameterName);
            } 

            return value; 
        } 

        /// Checks that the  are valid and throws an exception otherwise. 
        /// Value to check.
        /// Name of parameter for the exception message.
        internal static void CheckResourceContainerRights(EntitySetRights rights, string parameterName)
        { 
            if (rights < 0 || rights > EntitySetRights.All)
            { 
                throw Error.ArgumentOutOfRange(parameterName); 
            }
        } 

        /// Checks that the  are valid and throws an exception otherwise.
        /// Value to check.
        /// Name of parameter for the exception message. 
        internal static void CheckServiceOperationRights(ServiceOperationRights rights, string parameterName)
        { 
            if (rights < 0 || rights > ServiceOperationRights.All) 
            {
                throw Error.ArgumentOutOfRange(parameterName); 
            }
        }

        /// Checks the specifid value for syntax validity. 
        /// Whether syntax is valid.
        /// segment indentifier for which the resource was null. 
        /// This helper method is used to keep syntax check code more terse. 
        internal static void CheckResourceExists(bool resourceExists, string identifier)
        { 
            if (!resourceExists)
            {
                throw DataServiceException.CreateResourceNotFound(identifier);
            } 
        }
 
        /// Checks the specifid value for syntax validity. 
        /// Whether syntax is valid.
        /// This helper method is used to keep syntax check code more terse. 
        internal static void CheckSyntaxValid(bool valid)
        {
            if (!valid)
            { 
                throw DataServiceException.CreateSyntaxError();
            } 
        } 

        /// Creates a new instance if the specified value is null. 
        /// Type of variable.
        /// Current value.
        internal static void CreateIfNull(ref T value) where T : new()
        { 
            if (value == null)
            { 
                value = new T(); 
            }
        } 

        /// 
        /// Debug.Assert(Enum.IsDefined(typeof(T), value))
        ///  
        /// type of enum
        /// enum value 
        [Conditional("DEBUG")] 
        internal static void DebugEnumIsDefined(T value)
        { 
            Debug.Assert(Enum.IsDefined(typeof(T), value), "enum value is not valid");
        }

        /// Disposes of  if it implements . 
        /// Object to dispose, possibly null.
        internal static void Dispose(object o) 
        { 
            IDisposable disposable = o as IDisposable;
            if (disposable != null) 
            {
                disposable.Dispose();
            }
        } 

        /// Adds an empty last segment as necessary to the specified . 
        /// An absolute URI. 
        ///  with an empty last segment (ie, "ending with '/'").
        internal static Uri EnsureLastSegmentEmpty(Uri absoluteUri) 
        {
            Debug.Assert(absoluteUri != null, "absoluteUri != null");
            Debug.Assert(absoluteUri.IsAbsoluteUri, "absoluteUri.IsAbsoluteUri");
            string[] segments = absoluteUri.Segments; 
            if (segments.Length > 0)
            { 
                string lastBaseSegment = segments[segments.Length - 1]; 
                if (lastBaseSegment.Length > 0 && lastBaseSegment[lastBaseSegment.Length - 1] != '/')
                { 
                    absoluteUri = new Uri(absoluteUri, lastBaseSegment + "/");
                }
            }
 
            return absoluteUri;
        } 
 
        /// 
        /// Get the expected responseFormat and the content type for the given primitive type 
        /// 
        /// type of the primitive
        /// expected content type for the given primitive type
        /// the expected response format for the given primitive type  
        internal static ContentFormat GetResponseFormatForPrimitiveValue(Type valueType, out string contentType)
        { 
            ContentFormat result = ContentFormat.Text; 
            contentType = XmlConstants.MimeTextPlain;
 
            foreach (KeyValuePair mapping in PrimitiveTypesMimeTypeMapping)
            {
                if (valueType == mapping.Key)
                { 
                    contentType = mapping.Value;
                    break; 
                } 
            }
 
            foreach (KeyValuePair mapping in PrimitiveTypesContentFormatMapping)
            {
                if (valueType == mapping.Key)
                { 
                    result = mapping.Value;
                    break; 
                } 
            }
 
            return result;
        }

        /// Gets the public name for the specified . 
        /// Metadata provider.
        /// Type to get name for. 
        /// A public name for the specified , empty if it cannot be found. 
        internal static string GetTypeName(IDataServiceProvider provider, Type type)
        { 
            Debug.Assert(provider != null, "provider != null");
            Debug.Assert(type != null, "type != null");

            // For open properties, we might not know the type - use a blank string instead. 
            ResourceType resourceType = provider.GetResourceType(type);
            type = Nullable.GetUnderlyingType(type) ?? type; 
            string resourceTypeName = (resourceType == null) ? String.Empty : resourceType.FullName; 
            return resourceTypeName;
        } 

        /// 
        /// Determines whether the specified exception can be caught and
        /// handled, or whether it should be allowed to continue unwinding. 
        /// 
        ///  to test. 
        ///  
        /// true if the specified exception can be caught and handled;
        /// false otherwise. 
        /// 
        internal static bool IsCatchableExceptionType(Exception e)
        {
            // a 'catchable' exception is defined by what it is not. 
            Debug.Assert(e != null, "Unexpected null exception!");
            Type type = e.GetType(); 
 
            return ((type != StackOverflowType) &&
                     (type != OutOfMemoryType) && 
                     (type != ThreadAbortType));
        }

#if ASTORIA_OPEN_OBJECT 

        ///  
        /// Checks whether the specified string is a valid C# identifier. 
        /// 
        /// Non-null value to check. 
        /// 
        /// true if  is a valid C# identifier;
        /// false otherwise.
        ///  
        /// 
        /// See section '2.4.2 Identifiers' of the C# specification at 
        /// http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/csharp%20language%20specification.doc. 
        /// These differences are by design, however:
        /// - An initial '@' character is disallowed rather than used for keywords. 
        /// - Unicode escape sequences are disallowed rather than processed for comparison.
        /// - Formatting characters are disallowed, rather than removed for comparison.
        /// 
        internal static bool IsIdentifier(string identifier) 
        {
            Debug.Assert(identifier != null, "identifier != null"); 
            if (identifier.Length == 0) 
            {
                return false; 
            }

            char startChar = identifier[0];
            if (startChar != '_' && !Char.IsLetter(startChar)) 
            {
                return false; 
            } 

            for (int i = 1; i < identifier.Length; i++) 
            {
                char c = identifier[i];
                System.Globalization.UnicodeCategory category = Char.GetUnicodeCategory(c);
 
                // identifier-part-character:
                // letter-character: A Unicode character of classes Lu, Ll, Lt, Lm, Lo, or Nl 
                // combining-character: A Unicode character of classes Mn or Mc 
                // decimal-digit-character: A Unicode character of the class Nd
                // connecting-character: A Unicode character of the class Pc 
                if (category != System.Globalization.UnicodeCategory.UppercaseLetter &&
                    category != System.Globalization.UnicodeCategory.LowercaseLetter &&
                    category != System.Globalization.UnicodeCategory.TitlecaseLetter &&
                    category != System.Globalization.UnicodeCategory.ModifierLetter && 
                    category != System.Globalization.UnicodeCategory.OtherLetter &&
                    category != System.Globalization.UnicodeCategory.LetterNumber && 
                    category != System.Globalization.UnicodeCategory.NonSpacingMark && 
                    category != System.Globalization.UnicodeCategory.SpacingCombiningMark &&
                    category != System.Globalization.UnicodeCategory.DecimalDigitNumber && 
                    category != System.Globalization.UnicodeCategory.ConnectorPunctuation)
                {
                    return false;
                } 
            }
 
            return true; 
        }
 
#endif

        /// Selects the request format type from the content type.
        /// content type as specified in the request header 
        /// request description for which the content type was specified.
        /// enum representing the response format for the given content type 
        internal static ContentFormat SelectRequestFormat(string contentType, RequestDescription description) 
        {
            ContentFormat contentFormat; 
            switch (contentType)
            {
                case XmlConstants.MimeApplicationJson:
                    contentFormat = ContentFormat.Json; 
                    break;
                case XmlConstants.MimeTextXml: 
                case XmlConstants.MimeApplicationXml: 
                    contentFormat = ContentFormat.PlainXml;
                    break; 
                case XmlConstants.MimeApplicationAtom:
                case XmlConstants.MimeAny:
                    contentFormat = ContentFormat.Atom;
                    break; 
                default:
                    return ContentFormat.Unsupported; 
            } 

            if (description.LinkUri) 
            {
                if (contentFormat == ContentFormat.Atom)
                {
                    throw new DataServiceException( 
                        415,
                        Strings.BadRequest_InvalidContentTypeForRequestUri(contentType, String.Format(CultureInfo.InvariantCulture, "'{0}', '{1}', '{2}'", XmlConstants.MimeApplicationJson, XmlConstants.MimeApplicationXml, XmlConstants.MimeTextXml))); 
                } 
            }
            else if (description.TargetKind == RequestTargetKind.Resource || 
                     description.LastSegmentInfo.HasKeyValues)
            {
                // If the target is a resource (for open properties, it must have key values or its a collection - nav properties)
                // For reference open properties, this check needs to be done in each deserializer 
                if (contentFormat == ContentFormat.PlainXml)
                { 
                    throw new DataServiceException( 
                        415,
                        Strings.BadRequest_InvalidContentTypeForRequestUri(contentType, String.Format(CultureInfo.InvariantCulture, "'{0}', '{1}', '{2}'", XmlConstants.MimeApplicationJson, XmlConstants.MimeApplicationAtom, XmlConstants.MimeAny))); 
                }
            }
            else if (
#if ASTORIA_OPEN_OBJECT 
                description.TargetKind != RequestTargetKind.OpenProperty &&
#endif 
                     contentFormat == ContentFormat.Atom) 
            {
                throw new DataServiceException( 
                    415,
                    Strings.BadRequest_InvalidContentTypeForRequestUri(contentType, String.Format(CultureInfo.InvariantCulture, "'{0}', '{1}', '{2}'", XmlConstants.MimeApplicationJson, XmlConstants.MimeApplicationXml, XmlConstants.MimeTextXml)));
            }
 
            return contentFormat;
        } 
 
#if ASTORIA_CONTAINMENT
 
        /// Converts a text array into comma-separated entries with no quotes.
        /// Strings to convert.
        /// A user-friendly string that represents the text array.
        /// This method can be used to provide a simpler API facade instead of identifier arrays. 
        internal static string SimpleArrayToString(string[] text)
        { 
            if (text == null || text.Length == 0) 
            {
                return String.Empty; 
            }
            else
            {
                return String.Join(",", text); 
            }
        } 
 
#endif
 
        /// Converts comma-separated entries with no quotes into a text array.
        /// Text to convert.
        /// A string array that represents the comma-separated values in the text.
        /// This method can be used to provide a simpler API facade instead of identifier arrays. 
        internal static string[] StringToSimpleArray(string text)
        { 
            if (String.IsNullOrEmpty(text)) 
            {
                return EmptyStringArray; 
            }
            else
            {
                return text.Split(new char[] { ',' }, StringSplitOptions.None); 
            }
        } 
 
        /// 
        /// Creates a delegate that when called creates a new instance of the specified . 
        /// 
        /// Type of the instance.
        /// full name of the given clr type.
        /// If the type name is not specified, it takes the full name from the clr type. 
        /// Type to return from the delegate.
        /// A delegate that when called creates a new instance of the specified . 
        internal static Delegate CreateNewInstanceConstructor(Type type, string fullName, Type targetType) 
        {
            Debug.Assert(type != null, "type != null"); 
            Debug.Assert(targetType != null, "targetType != null");

            // Create the new instance of the type
            ConstructorInfo emptyConstructor = type.GetConstructor(Type.EmptyTypes); 
            if (emptyConstructor == null)
            { 
                fullName = fullName ?? type.FullName; 
                throw new InvalidOperationException(Strings.NoEmptyConstructorFoundForType(fullName));
            } 

            System.Reflection.Emit.DynamicMethod method = new System.Reflection.Emit.DynamicMethod("invoke_constructor", targetType, Type.EmptyTypes, false);
            var generator = method.GetILGenerator();
            generator.Emit(System.Reflection.Emit.OpCodes.Newobj, emptyConstructor); 
            if (targetType.IsValueType)
            { 
                generator.Emit(System.Reflection.Emit.OpCodes.Box); 
            }
 
            generator.Emit(System.Reflection.Emit.OpCodes.Ret);
            return method.CreateDelegate(typeof(Func<>).MakeGenericType(targetType));
        }
 
        /// Checks whether the specified type is a known primitive type.
        /// Type to check. 
        /// true if the specified type is known to be a primitive type; false otherwise. 
        internal static bool IsPrimitiveType(Type type)
        { 
            if (type == null)
            {
                return false;
            } 

            foreach (KeyValuePair primitiveTypeInfo in PrimitiveTypesEdmNameMapping) 
            { 
                if (type == primitiveTypeInfo.Key)
                { 
                    return true;
                }
            }
 
            return IsPrimitiveType(Nullable.GetUnderlyingType(type));
        } 
 
        /// 
        /// Checks whether the specified  
        /// is a valid MIME type with no parameters.
        /// 
        /// Simple MIME type.
        ///  
        /// true if the specified  is valid;
        /// false otherwise. 
        ///  
        /// 
        /// See http://tools.ietf.org/html/rfc2045#section-5.1 for futher details. 
        /// 
        internal static bool IsValidMimeType(string mimeType)
        {
            Debug.Assert(mimeType != null, "mimeType != null"); 
            const string Tspecials = "()<>@,;:\\\"/[]?=";
            bool partFound = false; 
            bool slashFound = false; 
            bool subTypeFound = false;
            foreach (char c in mimeType) 
            {
                Debug.Assert(partFound || !slashFound, "partFound || !slashFound -- slashFound->partFound");
                Debug.Assert(slashFound || !subTypeFound, "slashFound || !subTypeFound -- subTypeFound->slashFound");
 
                if (c == '/')
                { 
                    if (!partFound || slashFound) 
                    {
                        return false; 
                    }

                    slashFound = true;
                } 
                else if (c < '\x20' || c > '\x7F' || c == ' ' || Tspecials.IndexOf(c) >= 0)
                { 
                    return false; 
                }
                else 
                {
                    if (slashFound)
                    {
                        subTypeFound = true; 
                    }
                    else 
                    { 
                        partFound = true;
                    } 
                }
            }

            return subTypeFound; 
        }
 
        ///  
        /// Returns the name of the edm type given the clr type
        ///  
        /// clrType for whose edm type name needs to be returned
        /// returns the edm name for the given clrType
        internal static string GetEdmTypeName(Type type)
        { 
            Debug.Assert(type != null, "type != null");
            foreach (KeyValuePair primitiveTypeInfo in PrimitiveTypesEdmNameMapping) 
            { 
                if (type == primitiveTypeInfo.Key)
                { 
                    return primitiveTypeInfo.Value;
                }
            }
 
            Type elementType = Nullable.GetUnderlyingType(type);
            Debug.Assert(elementType != null, "elementType != null"); 
            return GetEdmTypeName(elementType); 
        }
 
        /// 
        /// Checks whether the specified element is an 
        /// of other elements.
        ///  
        /// Element to check (possibly null).
        /// , or null if  is not supported. 
        ///  
        /// true if  supports IEnumerable and is not
        /// a primitive type (strings and byte arrays are also enumerables, but 
        /// they shouldn't be iterated over, so they return false).
        /// 
        internal static bool IsElementIEnumerable(object element, out IEnumerable enumerable)
        { 
            enumerable = element as IEnumerable;
 
            if (enumerable == null) 
            {
                return false; 
            }

            // Primitive types are atomic, not enumerable, even if they implement IEnumerable.
            Type elementType = element.GetType(); 
            foreach (ResourceType type in GetPrimitiveTypes())
            { 
                if (type.Type == elementType) 
                {
                    return false; 
                }
            }

            return true; 
        }
 
        /// Returns the etag for the given resource. 
        /// Resource for which etag value needs to be returned.
        /// list of etag properties for the given resource 
        /// underlying provider to which the request was made.
        /// ETag value for the given resource, with values encoded for use in a URI.
        internal static string GetETagValue(object resource, ICollection etagProperties, IDataServiceProvider provider)
        { 
            Debug.Assert(etagProperties.Count != 0, "etagProperties.Count != 0");
 
            StringBuilder resultBuilder = new StringBuilder(); 
            bool firstKey = true;
            resultBuilder.Append(XmlConstants.HttpWeakETagPrefix); 
            foreach (ResourceProperty property in etagProperties)
            {
                object keyValue;
 
                // For GET operations, we cannot use GetMethod on IUpdatable. We need
                // to use reflection to get the property value. Hence passing provider 
                // as null in GET operation 
                if (provider == null)
                { 
                    keyValue = property.GetValue(resource);
                }
                else
                { 
                    keyValue = provider.GetValue(resource, property.Name);
                } 
 
                if (firstKey)
                { 
                    firstKey = false;
                }
                else
                { 
                    resultBuilder.Append(',');
                } 
 
                string keyValueText;
                if (keyValue == null) 
                {
                    keyValueText = XmlConstants.NullLiteralInETag;
                }
                else if (!System.Data.Services.Parsing.WebConvert.TryKeyPrimitiveToString(keyValue, out keyValueText)) 
                {
                    throw new InvalidOperationException(Strings.Serializer_CannotConvertValue(keyValue)); 
                } 

                Debug.Assert(keyValueText != null, "keyValueText != null - otherwise TryKeyPrimitiveToString returned true and null value"); 
                resultBuilder.Append(System.Uri.EscapeDataString(keyValueText));
            }

            resultBuilder.Append('"'); 
            return resultBuilder.ToString();
        } 
 
        /// Returns the etag for the given resource.
        /// Specific provider from which resource was obtained. 
        /// Resource for which etag value needs to be returned.
        /// Resource container to which the resource belongs to.
        /// ETag value for the given resource, with values encoded for use in a URI.
        internal static string GetETagValue(IDataServiceProvider provider, object resource, ResourceContainer container) 
        {
            ICollection etagProperties = provider.GetETagProperties(container.Name, resource.GetType()); 
            if (etagProperties.Count != 0) 
            {
                return WebUtil.GetETagValue(resource, etagProperties, null); 
            }
            else
            {
                return null; 
            }
        } 
 
        /// 
        /// Gets the type namespace of the specified , 
        /// appropriate as an externally-visible type name.
        /// 
        /// Type to get namespace for.
        /// The namespace for . 
        internal static string GetModelTypeNamespace(Type type)
        { 
            Debug.Assert(type != null, "type != null"); 
            return type.Namespace ?? "";
        } 

        /// Returns an array of primitive types supported.
        /// An array of primitive types supported
        internal static ResourceType[] GetPrimitiveTypes() 
        {
            if (primitiveResourceTypes == null) 
            { 
                ResourceType[] types = new ResourceType[PrimitiveTypesEdmNameMapping.Length];
                for (int i = 0; i < types.Length; i++) 
                {
                    string fullName = PrimitiveTypesEdmNameMapping[i].Value;
                    Debug.Assert(fullName.StartsWith(XmlConstants.EdmNamespace, StringComparison.Ordinal), "fullName.StartsWith(XmlConstants.EdmNamespace, StringComparison.Ordinal)");
                    string name = fullName.Substring(XmlConstants.EdmNamespace.Length + 1); 
                    types[i] = new ResourceType(PrimitiveTypesEdmNameMapping[i].Key, ResourceTypeKind.Primitive, null, fullName, name);
                } 
 
                System.Threading.Interlocked.CompareExchange(ref primitiveResourceTypes, types, null);
            } 

            Debug.Assert(primitiveResourceTypes != null, "primitiveResourceTypes != null");
            return primitiveResourceTypes;
        } 

        ///  
        /// Gets an  for the specified , 
        /// mapping well-known exceptions to the appropriate HTTP status code.
        ///  
        /// Request enumerable to get enumerator for.
        /// An  for the specified .
        internal static IEnumerator GetRequestEnumerator(IEnumerable enumerable)
        { 
            try
            { 
                return enumerable.GetEnumerator(); 
            }
            catch (NotImplementedException e) 
            {
                // 501: Not Implemented
                throw new DataServiceException(501, null, Strings.DataService_NotImplementedException, null, e);
            } 
            catch (NotSupportedException e)
            { 
                // 501: Not Implemented 
                throw new DataServiceException(501, null, Strings.DataService_NotImplementedException, null, e);
            } 
        }

        /// 
        /// Returns the container for the given resource cookie 
        /// 
        /// cookie for which resource container needs to be returned. 
        /// segment info containing the information about the resource cookie. 
        /// underlying data source provider instance.
        /// resource container for the resource represented by the resource cookie. 
#if !ASTORIA_OPEN_OBJECT
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "resource", Justification = "Required for open type support")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "provider", Justification = "Required for open type support")]
#endif 
        internal static ResourceContainer GetResourceContainer(object resource, SegmentInfo segmentInfo, IDataServiceProvider provider)
        { 
            Debug.Assert(resource != null, "resource != null"); 
            Debug.Assert(provider != null, "provider != null");
#if ASTORIA_OPEN_OBJECT 
            if (segmentInfo.TargetContainer == null)
            {
                Debug.Assert(
                    segmentInfo.TargetKind == RequestTargetKind.OpenProperty || 
                    segmentInfo.TargetKind == RequestTargetKind.OpenPropertyValue,
                    "its a open property target. Hence resource container must be null"); 
                return provider.GetContainerForResourceType(resource.GetType()); 
            }
#else 
            Debug.Assert(segmentInfo.TargetContainer != null, "segmentInfo.TargetContainer != null");
#endif

            return segmentInfo.TargetContainer; 
        }
 
        ///  
        /// Given the request description, query for the parent entity resource
        /// and compare the etag, if specified in the header 
        /// 
        /// entity resource for which etag needs to be checked.
        /// token as returned by the IUpdatable interface methods.
        /// container to which the entity resource belongs to. 
        /// Underlying provider to which the request was made to.
        /// Cached request headers 
        /// out bool which indicates whether response needs to be written for GET operations 
        /// current etag value for the given entity resource.
        internal static string CompareAndGetETag( 
            object parentEntityResource,
            object parentEntityToken,
            ResourceContainer container,
            IDataServiceProvider provider, 
            CachedRequestParams requestParams,
            out bool writeResponseForGetMethods) 
        { 
            // If this method is called for Update, we need to pass the token object as well as the actual instance.
            // The actual instance is used to determine the type that's necessary to find out the etag properties. 
            // The token is required to pass back to IUpdatable interface, if we need to get the values for etag properties.
            Debug.Assert(
                requestParams.AstoriaHttpVerb == AstoriaVerbs.GET || requestParams.AstoriaHttpVerb == AstoriaVerbs.PUT || requestParams.AstoriaHttpVerb == AstoriaVerbs.MERGE,
                "this method must be called for GET/PUT operations only"); 

            writeResponseForGetMethods = true; 
            string etag = null; 

            bool getMethod = requestParams.AstoriaHttpVerb == AstoriaVerbs.GET; 
            Debug.Assert(getMethod || String.IsNullOrEmpty(requestParams.IfNoneMatch), "IfNoneMatchHeader not allowed in PUT operations - checked in DataService.HandlePutOperation");

            // For .e.g when you are querying for /Customers(1)/BestFriend, the value can be null.
            // Hence in this case, if the If-Match header value is specified, we throw. 
            if (parentEntityResource == null)
            { 
                Debug.Assert(getMethod, "parent entity can be null only for GET"); 
                if (!String.IsNullOrEmpty(requestParams.IfMatch))
                { 
                    throw DataServiceException.CreatePreConditionFailedError(Strings.Serializer_ETagValueDoesNotMatch);
                }
            }
            else 
            {
                ICollection etagProperties = provider.GetETagProperties(container.Name, parentEntityResource.GetType()); 
                if (etagProperties.Count == 0) 
                {
                    // Cannot specify etag for types that don't have etag properties. 
                    if (!String.IsNullOrEmpty(requestParams.IfMatch))
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.Serializer_NoETagPropertiesForType);
                    } 
                }
                else if (String.IsNullOrEmpty(requestParams.IfMatch) && String.IsNullOrEmpty(requestParams.IfNoneMatch)) 
                { 
                    // For PUT operations, one needs to specify the etag value if the type has etag properties
                    if (!getMethod && etag != null) 
                    {
                        ResourceType resourceType = provider.GetResourceType(parentEntityResource.GetType());
                        throw DataServiceException.CreateBadRequestError(Strings.DataService_CannotPerformPutOperationWithoutETag(resourceType.FullName));
                    } 
                }
                else if (requestParams.IfMatch == XmlConstants.HttpAnyETag) 
                { 
                    // just return - for put, perform the operation and get, return the payload
                } 
                else if (getMethod && requestParams.IfNoneMatch == XmlConstants.HttpAnyETag)
                {
                    // If-None-Match is not allowed for PUT. Hence there is no point checking that
                    // For GET, return Not Modified 
                    writeResponseForGetMethods = false;
                } 
                else 
                {
                    etag = WebUtil.GetETagValue(parentEntityToken, etagProperties, getMethod ? null : provider); 
                    if (String.IsNullOrEmpty(requestParams.IfMatch))
                    {
                        if (!getMethod)
                        { 
                            // For PUT operations, one needs to specify the etag value if the type has etag properties
                            ResourceType resourceType = provider.GetResourceType(parentEntityResource.GetType()); 
                            throw DataServiceException.CreateBadRequestError(Strings.DataService_CannotPerformPutOperationWithoutETag(resourceType.FullName)); 
                        }
                        else 
                        {
                            Debug.Assert(!String.IsNullOrEmpty(requestParams.IfNoneMatch), "Both can't be null, otherwise it should have entered the first condition");
                            if (requestParams.IfNoneMatch == etag)
                            { 
                                writeResponseForGetMethods = false;
                            } 
                        } 
                    }
                    else 
                    {
                        if (etag != requestParams.IfMatch)
                        {
                            throw DataServiceException.CreatePreConditionFailedError(Strings.Serializer_ETagValueDoesNotMatch); 
                        }
                    } 
                } 

                if (getMethod && etag == null && etagProperties.Count != 0) 
                {
                    etag = WebUtil.GetETagValue(parentEntityResource, etagProperties, null);
                }
            } 

            return etag; 
        } 

        /// Writes an xml:space='preserve' attribute if the element value would need it. 
        /// XmlWriter to write to.
        /// Value that will be written after this call.
        internal static void WriteSpacePreserveAttributeIfNecessary(XmlWriter writer, string elementValue)
        { 
            if (elementValue.Length > 0 &&
                (Char.IsWhiteSpace(elementValue, 0) || 
                 Char.IsWhiteSpace(elementValue, elementValue.Length - 1))) 
            {
                WriteSpacePreserveAttribute(writer); 
            }
        }

        ///  
        /// If the specified reader is not on an element, advances to one, skipping document declaration
        /// nodes (typically at the beginning of a document), comments, processing instructions and 
        /// whitespace. 
        /// 
        /// Reader to reposition. 
        /// 
        /// true if the reader is left on an element; false otherwise.
        /// 
        internal static bool XmlReaderEnsureElement(XmlReader reader) 
        {
            Debug.Assert(reader != null, "reader != null"); 
            do 
            {
                switch (reader.NodeType) 
                {
                    case XmlNodeType.Element:
                        return true;
                    case XmlNodeType.Comment: 
                    case XmlNodeType.None:
                    case XmlNodeType.ProcessingInstruction: 
                    case XmlNodeType.XmlDeclaration: 
                    case XmlNodeType.Whitespace:
                        break; 
                    case XmlNodeType.Text:
                        if (WebUtil.IsWhitespace(reader.Value))
                        {
                            break; 
                        }
                        else 
                        { 
                            return false;
                        } 

                    default:
                        return false;
                } 
            }
            while (reader.Read()); 
 
            return false;
        } 

        /// Gets the text for a well-known status code.
        /// Status code to get text for.
        /// Text for the status code; an empty string if  is unknown. 
        internal static string GetStatusCodeText(int statusCode)
        { 
            #region Non-localized messages for status codes. 

            switch (statusCode) 
            {
                case 100:
                    return "Continue";
                case 101: 
                    return "Switching Protocols";
                case 200: 
                    return "OK"; 
                case 201:
                    return "Created"; 
                case 202:
                    return "Accepted";
                case 203:
                    return "Non-Authoritative Information"; 
                case 204:
                    return "No Content"; 
                case 205: 
                    return "Reset Content";
                case 206: 
                    return "Partial Content";
                case 300:
                    return "Multiple Choices";
                case 301: 
                    return "Moved Permanently";
                case 302: 
                    return "Found"; 
                case 303:
                    return "See Other"; 
                case 304:
                    return "Not Modified";
                case 305:
                    return "Use Proxy"; 
                case 307:
                    return "Temporary Redirect"; 
                case 400: 
                    return "Bad Request";
                case 401: 
                    return "Unauthorized";
                case 402:
                    return "Payment Required";
                case 403: 
                    return "Forbidden";
                case 404: 
                    return "Not Found"; 
                case 405:
                    return "Method Not Allowed"; 
                case 406:
                    return "Not Acceptable";
                case 407:
                    return "Proxy Authentication Required"; 
                case 408:
                    return "Request Time-out"; 
                case 409: 
                    return "Conflict";
                case 410: 
                    return "Gone";
                case 411:
                    return "Length Required";
                case 412: 
                    return "Precondition Failed";
                case 413: 
                    return "Request Entity Too Large"; 
                case 414:
                    return "Request-URI Too Large"; 
                case 415:
                    return "Unsupported Media Type";
                case 416:
                    return "Requested range not satisfiable"; 
                case 417:
                    return "Expectation Failed"; 
                case 500: 
                    return "Internal Server Error";
                case 501: 
                    return "Not Implemented";
                case 502:
                    return "Bad Gateway";
                case 503: 
                    return "Service Unavailable";
                case 504: 
                    return "Gateway Time-out"; 
                case 505:
                    return "HTTP Version not supported"; 
                default:
                    return "Unknown Status Code";
            }
 
            #endregion Non-localized messages for status codes.
        } 
 
        /// Gets the host and port parts of a Host header if they are both present.
        /// Host header value (non-null). 
        /// Scheme for the host and port values.
        /// If the result is true, the host part of the header.
        /// If the result is false, the port part of the header.
        /// true if the header has a host and port part, false otherwise. 
        private static bool GetHostAndPort(string hostHeader, string scheme, out string host, out int port)
        { 
            Debug.Assert(hostHeader != null, "hostHeader != null"); 

            if (scheme != null && !scheme.EndsWith("://", StringComparison.Ordinal)) 
            {
                scheme += "://";
            }
 
            Uri result;
            if (Uri.TryCreate(scheme + hostHeader, UriKind.Absolute, out result)) 
            { 
                host = result.Host;
                port = result.Port; 
                return true;
            }
            else
            { 
                host = null;
                port = default(int); 
                return false; 
            }
        } 

        /// Checks whether the specifies string is null or blank.
        /// Text to check.
        /// true if text is null, empty, or all whitespace characters. 
        private static bool IsWhitespace(string text)
        { 
            if (text == null) 
            {
                return true; 
            }
            else
            {
                foreach (char c in text) 
                {
                    if (!Char.IsWhiteSpace(c)) 
                    { 
                        return false;
                    } 
                }

                return true;
            } 
        }
 
        /// Writes an xml:space='preserve' attribute to the specified writer. 
        /// XmlWriter to write to.
        private static void WriteSpacePreserveAttribute(XmlWriter writer) 
        {
            Debug.Assert(writer != null, "writer != null");
            writer.WriteAttributeString(
                XmlConstants.XmlNamespacePrefix,        // prefix 
                XmlConstants.XmlSpaceAttributeName,     // localName
                null,                                   // ns 
                XmlConstants.XmlSpacePreserveValue);    // value 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides some utility functions for this project
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services
{
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Data.Linq; 
    using System.Data.Services.Providers;
    using System.Diagnostics; 
    using System.Globalization;
    using System.Reflection;
    using System.Text;
    using System.Xml; 
    using System.Xml.Linq;
 
    /// Utility methods for this project. 
    internal static class WebUtil
    { 
        /// Bindings Flags for public instance members.
        internal const BindingFlags PublicInstanceBindingFlags = BindingFlags.Public | BindingFlags.Instance;

        /// A zero-length object array. 
        internal static readonly object[] EmptyObjectArray = new object[0];
 
        /// A zero-length string array. 
        internal static readonly string[] EmptyStringArray = new string[0];
 
        // Only StackOverflowException & ThreadAbortException are sealed classes.

        /// Type of OutOfMemoryException.
        private static readonly Type OutOfMemoryType = typeof(System.OutOfMemoryException); 

        /// Type of StackOverflowException. 
        private static readonly Type StackOverflowType = typeof(System.StackOverflowException); 

        /// Type of ThreadAbortException. 
        private static readonly Type ThreadAbortType = typeof(System.Threading.ThreadAbortException);

        /// List of primitive types supported by Astoria and their corresponding edm names.
        private static readonly KeyValuePair[] PrimitiveTypesEdmNameMapping = 
            new KeyValuePair[]
            { 
                new KeyValuePair(typeof(string), XmlConstants.EdmStringTypeName), 
                new KeyValuePair(typeof(Boolean), XmlConstants.EdmBooleanTypeName),
                new KeyValuePair(typeof(Binary), XmlConstants.EdmBinaryTypeName), 
                new KeyValuePair(typeof(Byte), XmlConstants.EdmByteTypeName),
                new KeyValuePair(typeof(DateTime), XmlConstants.EdmDateTimeTypeName),
                new KeyValuePair(typeof(Decimal), XmlConstants.EdmDecimalTypeName),
                new KeyValuePair(typeof(Double), XmlConstants.EdmDoubleTypeName), 
                new KeyValuePair(typeof(Guid), XmlConstants.EdmGuidTypeName),
                new KeyValuePair(typeof(Int16), XmlConstants.EdmInt16TypeName), 
                new KeyValuePair(typeof(Int32), XmlConstants.EdmInt32TypeName), 
                new KeyValuePair(typeof(Int64), XmlConstants.EdmInt64TypeName),
                new KeyValuePair(typeof(SByte), XmlConstants.EdmSByteTypeName), 
                new KeyValuePair(typeof(Single), XmlConstants.EdmSingleTypeName),
                new KeyValuePair(typeof(byte[]), XmlConstants.EdmBinaryTypeName),
                new KeyValuePair(typeof(XElement), XmlConstants.EdmStringTypeName),
            }; 

        /// List of primitive types supported by Astoria and their corresponding default MIME types. 
        private static readonly KeyValuePair[] PrimitiveTypesMimeTypeMapping = 
            new KeyValuePair[]
            { 
                new KeyValuePair(typeof(byte[]), XmlConstants.MimeApplicationOctetStream),
                new KeyValuePair(typeof(Binary), XmlConstants.MimeApplicationOctetStream),
            };
 
        /// List of primitive types supported by Astoria and their corresponding default content format.
        private static readonly KeyValuePair[] PrimitiveTypesContentFormatMapping = 
            new KeyValuePair[] 
            {
                new KeyValuePair(typeof(byte[]), ContentFormat.Binary), 
                new KeyValuePair(typeof(Binary), ContentFormat.Binary),
            };

        /// List of primitive resource types. We don't want to create them again and again, so creating them once and caching them 
        private static ResourceType[] primitiveResourceTypes;
 
        ///  
        /// Applies the host specified in a request if available to the given .
        ///  
        /// URI to update with host (and port) information.
        /// Host header (possibly null or empty)
        /// The updated URI.
        internal static Uri ApplyHostHeader(Uri baseUri, string requestHost) 
        {
            Debug.Assert(baseUri != null, "baseUri"); 
            if (!String.IsNullOrEmpty(requestHost)) 
            {
                UriBuilder builder = new UriBuilder(baseUri); 
                string host;
                int port;
                if (GetHostAndPort(requestHost, baseUri.Scheme, out host, out port))
                { 
                    builder.Host = host;
                    builder.Port = port; 
                } 
                else
                { 
                    builder.Host = requestHost;
                }

                baseUri = builder.Uri; 
            }
 
            return baseUri; 
        }
 
        /// 
        /// Checks the argument value for null and throw ArgumentNullException if it is null
        /// 
        /// type of the argument 
        /// argument whose value needs to be checked
        /// name of the argument 
        /// returns the argument back 
        internal static T CheckArgumentNull(T value, string parameterName) where T : class
        { 
            if (null == value)
            {
                throw Error.ArgumentNull(parameterName);
            } 

            return value; 
        } 

        /// Checks that the  are valid and throws an exception otherwise. 
        /// Value to check.
        /// Name of parameter for the exception message.
        internal static void CheckResourceContainerRights(EntitySetRights rights, string parameterName)
        { 
            if (rights < 0 || rights > EntitySetRights.All)
            { 
                throw Error.ArgumentOutOfRange(parameterName); 
            }
        } 

        /// Checks that the  are valid and throws an exception otherwise.
        /// Value to check.
        /// Name of parameter for the exception message. 
        internal static void CheckServiceOperationRights(ServiceOperationRights rights, string parameterName)
        { 
            if (rights < 0 || rights > ServiceOperationRights.All) 
            {
                throw Error.ArgumentOutOfRange(parameterName); 
            }
        }

        /// Checks the specifid value for syntax validity. 
        /// Whether syntax is valid.
        /// segment indentifier for which the resource was null. 
        /// This helper method is used to keep syntax check code more terse. 
        internal static void CheckResourceExists(bool resourceExists, string identifier)
        { 
            if (!resourceExists)
            {
                throw DataServiceException.CreateResourceNotFound(identifier);
            } 
        }
 
        /// Checks the specifid value for syntax validity. 
        /// Whether syntax is valid.
        /// This helper method is used to keep syntax check code more terse. 
        internal static void CheckSyntaxValid(bool valid)
        {
            if (!valid)
            { 
                throw DataServiceException.CreateSyntaxError();
            } 
        } 

        /// Creates a new instance if the specified value is null. 
        /// Type of variable.
        /// Current value.
        internal static void CreateIfNull(ref T value) where T : new()
        { 
            if (value == null)
            { 
                value = new T(); 
            }
        } 

        /// 
        /// Debug.Assert(Enum.IsDefined(typeof(T), value))
        ///  
        /// type of enum
        /// enum value 
        [Conditional("DEBUG")] 
        internal static void DebugEnumIsDefined(T value)
        { 
            Debug.Assert(Enum.IsDefined(typeof(T), value), "enum value is not valid");
        }

        /// Disposes of  if it implements . 
        /// Object to dispose, possibly null.
        internal static void Dispose(object o) 
        { 
            IDisposable disposable = o as IDisposable;
            if (disposable != null) 
            {
                disposable.Dispose();
            }
        } 

        /// Adds an empty last segment as necessary to the specified . 
        /// An absolute URI. 
        ///  with an empty last segment (ie, "ending with '/'").
        internal static Uri EnsureLastSegmentEmpty(Uri absoluteUri) 
        {
            Debug.Assert(absoluteUri != null, "absoluteUri != null");
            Debug.Assert(absoluteUri.IsAbsoluteUri, "absoluteUri.IsAbsoluteUri");
            string[] segments = absoluteUri.Segments; 
            if (segments.Length > 0)
            { 
                string lastBaseSegment = segments[segments.Length - 1]; 
                if (lastBaseSegment.Length > 0 && lastBaseSegment[lastBaseSegment.Length - 1] != '/')
                { 
                    absoluteUri = new Uri(absoluteUri, lastBaseSegment + "/");
                }
            }
 
            return absoluteUri;
        } 
 
        /// 
        /// Get the expected responseFormat and the content type for the given primitive type 
        /// 
        /// type of the primitive
        /// expected content type for the given primitive type
        /// the expected response format for the given primitive type  
        internal static ContentFormat GetResponseFormatForPrimitiveValue(Type valueType, out string contentType)
        { 
            ContentFormat result = ContentFormat.Text; 
            contentType = XmlConstants.MimeTextPlain;
 
            foreach (KeyValuePair mapping in PrimitiveTypesMimeTypeMapping)
            {
                if (valueType == mapping.Key)
                { 
                    contentType = mapping.Value;
                    break; 
                } 
            }
 
            foreach (KeyValuePair mapping in PrimitiveTypesContentFormatMapping)
            {
                if (valueType == mapping.Key)
                { 
                    result = mapping.Value;
                    break; 
                } 
            }
 
            return result;
        }

        /// Gets the public name for the specified . 
        /// Metadata provider.
        /// Type to get name for. 
        /// A public name for the specified , empty if it cannot be found. 
        internal static string GetTypeName(IDataServiceProvider provider, Type type)
        { 
            Debug.Assert(provider != null, "provider != null");
            Debug.Assert(type != null, "type != null");

            // For open properties, we might not know the type - use a blank string instead. 
            ResourceType resourceType = provider.GetResourceType(type);
            type = Nullable.GetUnderlyingType(type) ?? type; 
            string resourceTypeName = (resourceType == null) ? String.Empty : resourceType.FullName; 
            return resourceTypeName;
        } 

        /// 
        /// Determines whether the specified exception can be caught and
        /// handled, or whether it should be allowed to continue unwinding. 
        /// 
        ///  to test. 
        ///  
        /// true if the specified exception can be caught and handled;
        /// false otherwise. 
        /// 
        internal static bool IsCatchableExceptionType(Exception e)
        {
            // a 'catchable' exception is defined by what it is not. 
            Debug.Assert(e != null, "Unexpected null exception!");
            Type type = e.GetType(); 
 
            return ((type != StackOverflowType) &&
                     (type != OutOfMemoryType) && 
                     (type != ThreadAbortType));
        }

#if ASTORIA_OPEN_OBJECT 

        ///  
        /// Checks whether the specified string is a valid C# identifier. 
        /// 
        /// Non-null value to check. 
        /// 
        /// true if  is a valid C# identifier;
        /// false otherwise.
        ///  
        /// 
        /// See section '2.4.2 Identifiers' of the C# specification at 
        /// http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/csharp%20language%20specification.doc. 
        /// These differences are by design, however:
        /// - An initial '@' character is disallowed rather than used for keywords. 
        /// - Unicode escape sequences are disallowed rather than processed for comparison.
        /// - Formatting characters are disallowed, rather than removed for comparison.
        /// 
        internal static bool IsIdentifier(string identifier) 
        {
            Debug.Assert(identifier != null, "identifier != null"); 
            if (identifier.Length == 0) 
            {
                return false; 
            }

            char startChar = identifier[0];
            if (startChar != '_' && !Char.IsLetter(startChar)) 
            {
                return false; 
            } 

            for (int i = 1; i < identifier.Length; i++) 
            {
                char c = identifier[i];
                System.Globalization.UnicodeCategory category = Char.GetUnicodeCategory(c);
 
                // identifier-part-character:
                // letter-character: A Unicode character of classes Lu, Ll, Lt, Lm, Lo, or Nl 
                // combining-character: A Unicode character of classes Mn or Mc 
                // decimal-digit-character: A Unicode character of the class Nd
                // connecting-character: A Unicode character of the class Pc 
                if (category != System.Globalization.UnicodeCategory.UppercaseLetter &&
                    category != System.Globalization.UnicodeCategory.LowercaseLetter &&
                    category != System.Globalization.UnicodeCategory.TitlecaseLetter &&
                    category != System.Globalization.UnicodeCategory.ModifierLetter && 
                    category != System.Globalization.UnicodeCategory.OtherLetter &&
                    category != System.Globalization.UnicodeCategory.LetterNumber && 
                    category != System.Globalization.UnicodeCategory.NonSpacingMark && 
                    category != System.Globalization.UnicodeCategory.SpacingCombiningMark &&
                    category != System.Globalization.UnicodeCategory.DecimalDigitNumber && 
                    category != System.Globalization.UnicodeCategory.ConnectorPunctuation)
                {
                    return false;
                } 
            }
 
            return true; 
        }
 
#endif

        /// Selects the request format type from the content type.
        /// content type as specified in the request header 
        /// request description for which the content type was specified.
        /// enum representing the response format for the given content type 
        internal static ContentFormat SelectRequestFormat(string contentType, RequestDescription description) 
        {
            ContentFormat contentFormat; 
            switch (contentType)
            {
                case XmlConstants.MimeApplicationJson:
                    contentFormat = ContentFormat.Json; 
                    break;
                case XmlConstants.MimeTextXml: 
                case XmlConstants.MimeApplicationXml: 
                    contentFormat = ContentFormat.PlainXml;
                    break; 
                case XmlConstants.MimeApplicationAtom:
                case XmlConstants.MimeAny:
                    contentFormat = ContentFormat.Atom;
                    break; 
                default:
                    return ContentFormat.Unsupported; 
            } 

            if (description.LinkUri) 
            {
                if (contentFormat == ContentFormat.Atom)
                {
                    throw new DataServiceException( 
                        415,
                        Strings.BadRequest_InvalidContentTypeForRequestUri(contentType, String.Format(CultureInfo.InvariantCulture, "'{0}', '{1}', '{2}'", XmlConstants.MimeApplicationJson, XmlConstants.MimeApplicationXml, XmlConstants.MimeTextXml))); 
                } 
            }
            else if (description.TargetKind == RequestTargetKind.Resource || 
                     description.LastSegmentInfo.HasKeyValues)
            {
                // If the target is a resource (for open properties, it must have key values or its a collection - nav properties)
                // For reference open properties, this check needs to be done in each deserializer 
                if (contentFormat == ContentFormat.PlainXml)
                { 
                    throw new DataServiceException( 
                        415,
                        Strings.BadRequest_InvalidContentTypeForRequestUri(contentType, String.Format(CultureInfo.InvariantCulture, "'{0}', '{1}', '{2}'", XmlConstants.MimeApplicationJson, XmlConstants.MimeApplicationAtom, XmlConstants.MimeAny))); 
                }
            }
            else if (
#if ASTORIA_OPEN_OBJECT 
                description.TargetKind != RequestTargetKind.OpenProperty &&
#endif 
                     contentFormat == ContentFormat.Atom) 
            {
                throw new DataServiceException( 
                    415,
                    Strings.BadRequest_InvalidContentTypeForRequestUri(contentType, String.Format(CultureInfo.InvariantCulture, "'{0}', '{1}', '{2}'", XmlConstants.MimeApplicationJson, XmlConstants.MimeApplicationXml, XmlConstants.MimeTextXml)));
            }
 
            return contentFormat;
        } 
 
#if ASTORIA_CONTAINMENT
 
        /// Converts a text array into comma-separated entries with no quotes.
        /// Strings to convert.
        /// A user-friendly string that represents the text array.
        /// This method can be used to provide a simpler API facade instead of identifier arrays. 
        internal static string SimpleArrayToString(string[] text)
        { 
            if (text == null || text.Length == 0) 
            {
                return String.Empty; 
            }
            else
            {
                return String.Join(",", text); 
            }
        } 
 
#endif
 
        /// Converts comma-separated entries with no quotes into a text array.
        /// Text to convert.
        /// A string array that represents the comma-separated values in the text.
        /// This method can be used to provide a simpler API facade instead of identifier arrays. 
        internal static string[] StringToSimpleArray(string text)
        { 
            if (String.IsNullOrEmpty(text)) 
            {
                return EmptyStringArray; 
            }
            else
            {
                return text.Split(new char[] { ',' }, StringSplitOptions.None); 
            }
        } 
 
        /// 
        /// Creates a delegate that when called creates a new instance of the specified . 
        /// 
        /// Type of the instance.
        /// full name of the given clr type.
        /// If the type name is not specified, it takes the full name from the clr type. 
        /// Type to return from the delegate.
        /// A delegate that when called creates a new instance of the specified . 
        internal static Delegate CreateNewInstanceConstructor(Type type, string fullName, Type targetType) 
        {
            Debug.Assert(type != null, "type != null"); 
            Debug.Assert(targetType != null, "targetType != null");

            // Create the new instance of the type
            ConstructorInfo emptyConstructor = type.GetConstructor(Type.EmptyTypes); 
            if (emptyConstructor == null)
            { 
                fullName = fullName ?? type.FullName; 
                throw new InvalidOperationException(Strings.NoEmptyConstructorFoundForType(fullName));
            } 

            System.Reflection.Emit.DynamicMethod method = new System.Reflection.Emit.DynamicMethod("invoke_constructor", targetType, Type.EmptyTypes, false);
            var generator = method.GetILGenerator();
            generator.Emit(System.Reflection.Emit.OpCodes.Newobj, emptyConstructor); 
            if (targetType.IsValueType)
            { 
                generator.Emit(System.Reflection.Emit.OpCodes.Box); 
            }
 
            generator.Emit(System.Reflection.Emit.OpCodes.Ret);
            return method.CreateDelegate(typeof(Func<>).MakeGenericType(targetType));
        }
 
        /// Checks whether the specified type is a known primitive type.
        /// Type to check. 
        /// true if the specified type is known to be a primitive type; false otherwise. 
        internal static bool IsPrimitiveType(Type type)
        { 
            if (type == null)
            {
                return false;
            } 

            foreach (KeyValuePair primitiveTypeInfo in PrimitiveTypesEdmNameMapping) 
            { 
                if (type == primitiveTypeInfo.Key)
                { 
                    return true;
                }
            }
 
            return IsPrimitiveType(Nullable.GetUnderlyingType(type));
        } 
 
        /// 
        /// Checks whether the specified  
        /// is a valid MIME type with no parameters.
        /// 
        /// Simple MIME type.
        ///  
        /// true if the specified  is valid;
        /// false otherwise. 
        ///  
        /// 
        /// See http://tools.ietf.org/html/rfc2045#section-5.1 for futher details. 
        /// 
        internal static bool IsValidMimeType(string mimeType)
        {
            Debug.Assert(mimeType != null, "mimeType != null"); 
            const string Tspecials = "()<>@,;:\\\"/[]?=";
            bool partFound = false; 
            bool slashFound = false; 
            bool subTypeFound = false;
            foreach (char c in mimeType) 
            {
                Debug.Assert(partFound || !slashFound, "partFound || !slashFound -- slashFound->partFound");
                Debug.Assert(slashFound || !subTypeFound, "slashFound || !subTypeFound -- subTypeFound->slashFound");
 
                if (c == '/')
                { 
                    if (!partFound || slashFound) 
                    {
                        return false; 
                    }

                    slashFound = true;
                } 
                else if (c < '\x20' || c > '\x7F' || c == ' ' || Tspecials.IndexOf(c) >= 0)
                { 
                    return false; 
                }
                else 
                {
                    if (slashFound)
                    {
                        subTypeFound = true; 
                    }
                    else 
                    { 
                        partFound = true;
                    } 
                }
            }

            return subTypeFound; 
        }
 
        ///  
        /// Returns the name of the edm type given the clr type
        ///  
        /// clrType for whose edm type name needs to be returned
        /// returns the edm name for the given clrType
        internal static string GetEdmTypeName(Type type)
        { 
            Debug.Assert(type != null, "type != null");
            foreach (KeyValuePair primitiveTypeInfo in PrimitiveTypesEdmNameMapping) 
            { 
                if (type == primitiveTypeInfo.Key)
                { 
                    return primitiveTypeInfo.Value;
                }
            }
 
            Type elementType = Nullable.GetUnderlyingType(type);
            Debug.Assert(elementType != null, "elementType != null"); 
            return GetEdmTypeName(elementType); 
        }
 
        /// 
        /// Checks whether the specified element is an 
        /// of other elements.
        ///  
        /// Element to check (possibly null).
        /// , or null if  is not supported. 
        ///  
        /// true if  supports IEnumerable and is not
        /// a primitive type (strings and byte arrays are also enumerables, but 
        /// they shouldn't be iterated over, so they return false).
        /// 
        internal static bool IsElementIEnumerable(object element, out IEnumerable enumerable)
        { 
            enumerable = element as IEnumerable;
 
            if (enumerable == null) 
            {
                return false; 
            }

            // Primitive types are atomic, not enumerable, even if they implement IEnumerable.
            Type elementType = element.GetType(); 
            foreach (ResourceType type in GetPrimitiveTypes())
            { 
                if (type.Type == elementType) 
                {
                    return false; 
                }
            }

            return true; 
        }
 
        /// Returns the etag for the given resource. 
        /// Resource for which etag value needs to be returned.
        /// list of etag properties for the given resource 
        /// underlying provider to which the request was made.
        /// ETag value for the given resource, with values encoded for use in a URI.
        internal static string GetETagValue(object resource, ICollection etagProperties, IDataServiceProvider provider)
        { 
            Debug.Assert(etagProperties.Count != 0, "etagProperties.Count != 0");
 
            StringBuilder resultBuilder = new StringBuilder(); 
            bool firstKey = true;
            resultBuilder.Append(XmlConstants.HttpWeakETagPrefix); 
            foreach (ResourceProperty property in etagProperties)
            {
                object keyValue;
 
                // For GET operations, we cannot use GetMethod on IUpdatable. We need
                // to use reflection to get the property value. Hence passing provider 
                // as null in GET operation 
                if (provider == null)
                { 
                    keyValue = property.GetValue(resource);
                }
                else
                { 
                    keyValue = provider.GetValue(resource, property.Name);
                } 
 
                if (firstKey)
                { 
                    firstKey = false;
                }
                else
                { 
                    resultBuilder.Append(',');
                } 
 
                string keyValueText;
                if (keyValue == null) 
                {
                    keyValueText = XmlConstants.NullLiteralInETag;
                }
                else if (!System.Data.Services.Parsing.WebConvert.TryKeyPrimitiveToString(keyValue, out keyValueText)) 
                {
                    throw new InvalidOperationException(Strings.Serializer_CannotConvertValue(keyValue)); 
                } 

                Debug.Assert(keyValueText != null, "keyValueText != null - otherwise TryKeyPrimitiveToString returned true and null value"); 
                resultBuilder.Append(System.Uri.EscapeDataString(keyValueText));
            }

            resultBuilder.Append('"'); 
            return resultBuilder.ToString();
        } 
 
        /// Returns the etag for the given resource.
        /// Specific provider from which resource was obtained. 
        /// Resource for which etag value needs to be returned.
        /// Resource container to which the resource belongs to.
        /// ETag value for the given resource, with values encoded for use in a URI.
        internal static string GetETagValue(IDataServiceProvider provider, object resource, ResourceContainer container) 
        {
            ICollection etagProperties = provider.GetETagProperties(container.Name, resource.GetType()); 
            if (etagProperties.Count != 0) 
            {
                return WebUtil.GetETagValue(resource, etagProperties, null); 
            }
            else
            {
                return null; 
            }
        } 
 
        /// 
        /// Gets the type namespace of the specified , 
        /// appropriate as an externally-visible type name.
        /// 
        /// Type to get namespace for.
        /// The namespace for . 
        internal static string GetModelTypeNamespace(Type type)
        { 
            Debug.Assert(type != null, "type != null"); 
            return type.Namespace ?? "";
        } 

        /// Returns an array of primitive types supported.
        /// An array of primitive types supported
        internal static ResourceType[] GetPrimitiveTypes() 
        {
            if (primitiveResourceTypes == null) 
            { 
                ResourceType[] types = new ResourceType[PrimitiveTypesEdmNameMapping.Length];
                for (int i = 0; i < types.Length; i++) 
                {
                    string fullName = PrimitiveTypesEdmNameMapping[i].Value;
                    Debug.Assert(fullName.StartsWith(XmlConstants.EdmNamespace, StringComparison.Ordinal), "fullName.StartsWith(XmlConstants.EdmNamespace, StringComparison.Ordinal)");
                    string name = fullName.Substring(XmlConstants.EdmNamespace.Length + 1); 
                    types[i] = new ResourceType(PrimitiveTypesEdmNameMapping[i].Key, ResourceTypeKind.Primitive, null, fullName, name);
                } 
 
                System.Threading.Interlocked.CompareExchange(ref primitiveResourceTypes, types, null);
            } 

            Debug.Assert(primitiveResourceTypes != null, "primitiveResourceTypes != null");
            return primitiveResourceTypes;
        } 

        ///  
        /// Gets an  for the specified , 
        /// mapping well-known exceptions to the appropriate HTTP status code.
        ///  
        /// Request enumerable to get enumerator for.
        /// An  for the specified .
        internal static IEnumerator GetRequestEnumerator(IEnumerable enumerable)
        { 
            try
            { 
                return enumerable.GetEnumerator(); 
            }
            catch (NotImplementedException e) 
            {
                // 501: Not Implemented
                throw new DataServiceException(501, null, Strings.DataService_NotImplementedException, null, e);
            } 
            catch (NotSupportedException e)
            { 
                // 501: Not Implemented 
                throw new DataServiceException(501, null, Strings.DataService_NotImplementedException, null, e);
            } 
        }

        /// 
        /// Returns the container for the given resource cookie 
        /// 
        /// cookie for which resource container needs to be returned. 
        /// segment info containing the information about the resource cookie. 
        /// underlying data source provider instance.
        /// resource container for the resource represented by the resource cookie. 
#if !ASTORIA_OPEN_OBJECT
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "resource", Justification = "Required for open type support")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "provider", Justification = "Required for open type support")]
#endif 
        internal static ResourceContainer GetResourceContainer(object resource, SegmentInfo segmentInfo, IDataServiceProvider provider)
        { 
            Debug.Assert(resource != null, "resource != null"); 
            Debug.Assert(provider != null, "provider != null");
#if ASTORIA_OPEN_OBJECT 
            if (segmentInfo.TargetContainer == null)
            {
                Debug.Assert(
                    segmentInfo.TargetKind == RequestTargetKind.OpenProperty || 
                    segmentInfo.TargetKind == RequestTargetKind.OpenPropertyValue,
                    "its a open property target. Hence resource container must be null"); 
                return provider.GetContainerForResourceType(resource.GetType()); 
            }
#else 
            Debug.Assert(segmentInfo.TargetContainer != null, "segmentInfo.TargetContainer != null");
#endif

            return segmentInfo.TargetContainer; 
        }
 
        ///  
        /// Given the request description, query for the parent entity resource
        /// and compare the etag, if specified in the header 
        /// 
        /// entity resource for which etag needs to be checked.
        /// token as returned by the IUpdatable interface methods.
        /// container to which the entity resource belongs to. 
        /// Underlying provider to which the request was made to.
        /// Cached request headers 
        /// out bool which indicates whether response needs to be written for GET operations 
        /// current etag value for the given entity resource.
        internal static string CompareAndGetETag( 
            object parentEntityResource,
            object parentEntityToken,
            ResourceContainer container,
            IDataServiceProvider provider, 
            CachedRequestParams requestParams,
            out bool writeResponseForGetMethods) 
        { 
            // If this method is called for Update, we need to pass the token object as well as the actual instance.
            // The actual instance is used to determine the type that's necessary to find out the etag properties. 
            // The token is required to pass back to IUpdatable interface, if we need to get the values for etag properties.
            Debug.Assert(
                requestParams.AstoriaHttpVerb == AstoriaVerbs.GET || requestParams.AstoriaHttpVerb == AstoriaVerbs.PUT || requestParams.AstoriaHttpVerb == AstoriaVerbs.MERGE,
                "this method must be called for GET/PUT operations only"); 

            writeResponseForGetMethods = true; 
            string etag = null; 

            bool getMethod = requestParams.AstoriaHttpVerb == AstoriaVerbs.GET; 
            Debug.Assert(getMethod || String.IsNullOrEmpty(requestParams.IfNoneMatch), "IfNoneMatchHeader not allowed in PUT operations - checked in DataService.HandlePutOperation");

            // For .e.g when you are querying for /Customers(1)/BestFriend, the value can be null.
            // Hence in this case, if the If-Match header value is specified, we throw. 
            if (parentEntityResource == null)
            { 
                Debug.Assert(getMethod, "parent entity can be null only for GET"); 
                if (!String.IsNullOrEmpty(requestParams.IfMatch))
                { 
                    throw DataServiceException.CreatePreConditionFailedError(Strings.Serializer_ETagValueDoesNotMatch);
                }
            }
            else 
            {
                ICollection etagProperties = provider.GetETagProperties(container.Name, parentEntityResource.GetType()); 
                if (etagProperties.Count == 0) 
                {
                    // Cannot specify etag for types that don't have etag properties. 
                    if (!String.IsNullOrEmpty(requestParams.IfMatch))
                    {
                        throw DataServiceException.CreateBadRequestError(Strings.Serializer_NoETagPropertiesForType);
                    } 
                }
                else if (String.IsNullOrEmpty(requestParams.IfMatch) && String.IsNullOrEmpty(requestParams.IfNoneMatch)) 
                { 
                    // For PUT operations, one needs to specify the etag value if the type has etag properties
                    if (!getMethod && etag != null) 
                    {
                        ResourceType resourceType = provider.GetResourceType(parentEntityResource.GetType());
                        throw DataServiceException.CreateBadRequestError(Strings.DataService_CannotPerformPutOperationWithoutETag(resourceType.FullName));
                    } 
                }
                else if (requestParams.IfMatch == XmlConstants.HttpAnyETag) 
                { 
                    // just return - for put, perform the operation and get, return the payload
                } 
                else if (getMethod && requestParams.IfNoneMatch == XmlConstants.HttpAnyETag)
                {
                    // If-None-Match is not allowed for PUT. Hence there is no point checking that
                    // For GET, return Not Modified 
                    writeResponseForGetMethods = false;
                } 
                else 
                {
                    etag = WebUtil.GetETagValue(parentEntityToken, etagProperties, getMethod ? null : provider); 
                    if (String.IsNullOrEmpty(requestParams.IfMatch))
                    {
                        if (!getMethod)
                        { 
                            // For PUT operations, one needs to specify the etag value if the type has etag properties
                            ResourceType resourceType = provider.GetResourceType(parentEntityResource.GetType()); 
                            throw DataServiceException.CreateBadRequestError(Strings.DataService_CannotPerformPutOperationWithoutETag(resourceType.FullName)); 
                        }
                        else 
                        {
                            Debug.Assert(!String.IsNullOrEmpty(requestParams.IfNoneMatch), "Both can't be null, otherwise it should have entered the first condition");
                            if (requestParams.IfNoneMatch == etag)
                            { 
                                writeResponseForGetMethods = false;
                            } 
                        } 
                    }
                    else 
                    {
                        if (etag != requestParams.IfMatch)
                        {
                            throw DataServiceException.CreatePreConditionFailedError(Strings.Serializer_ETagValueDoesNotMatch); 
                        }
                    } 
                } 

                if (getMethod && etag == null && etagProperties.Count != 0) 
                {
                    etag = WebUtil.GetETagValue(parentEntityResource, etagProperties, null);
                }
            } 

            return etag; 
        } 

        /// Writes an xml:space='preserve' attribute if the element value would need it. 
        /// XmlWriter to write to.
        /// Value that will be written after this call.
        internal static void WriteSpacePreserveAttributeIfNecessary(XmlWriter writer, string elementValue)
        { 
            if (elementValue.Length > 0 &&
                (Char.IsWhiteSpace(elementValue, 0) || 
                 Char.IsWhiteSpace(elementValue, elementValue.Length - 1))) 
            {
                WriteSpacePreserveAttribute(writer); 
            }
        }

        ///  
        /// If the specified reader is not on an element, advances to one, skipping document declaration
        /// nodes (typically at the beginning of a document), comments, processing instructions and 
        /// whitespace. 
        /// 
        /// Reader to reposition. 
        /// 
        /// true if the reader is left on an element; false otherwise.
        /// 
        internal static bool XmlReaderEnsureElement(XmlReader reader) 
        {
            Debug.Assert(reader != null, "reader != null"); 
            do 
            {
                switch (reader.NodeType) 
                {
                    case XmlNodeType.Element:
                        return true;
                    case XmlNodeType.Comment: 
                    case XmlNodeType.None:
                    case XmlNodeType.ProcessingInstruction: 
                    case XmlNodeType.XmlDeclaration: 
                    case XmlNodeType.Whitespace:
                        break; 
                    case XmlNodeType.Text:
                        if (WebUtil.IsWhitespace(reader.Value))
                        {
                            break; 
                        }
                        else 
                        { 
                            return false;
                        } 

                    default:
                        return false;
                } 
            }
            while (reader.Read()); 
 
            return false;
        } 

        /// Gets the text for a well-known status code.
        /// Status code to get text for.
        /// Text for the status code; an empty string if  is unknown. 
        internal static string GetStatusCodeText(int statusCode)
        { 
            #region Non-localized messages for status codes. 

            switch (statusCode) 
            {
                case 100:
                    return "Continue";
                case 101: 
                    return "Switching Protocols";
                case 200: 
                    return "OK"; 
                case 201:
                    return "Created"; 
                case 202:
                    return "Accepted";
                case 203:
                    return "Non-Authoritative Information"; 
                case 204:
                    return "No Content"; 
                case 205: 
                    return "Reset Content";
                case 206: 
                    return "Partial Content";
                case 300:
                    return "Multiple Choices";
                case 301: 
                    return "Moved Permanently";
                case 302: 
                    return "Found"; 
                case 303:
                    return "See Other"; 
                case 304:
                    return "Not Modified";
                case 305:
                    return "Use Proxy"; 
                case 307:
                    return "Temporary Redirect"; 
                case 400: 
                    return "Bad Request";
                case 401: 
                    return "Unauthorized";
                case 402:
                    return "Payment Required";
                case 403: 
                    return "Forbidden";
                case 404: 
                    return "Not Found"; 
                case 405:
                    return "Method Not Allowed"; 
                case 406:
                    return "Not Acceptable";
                case 407:
                    return "Proxy Authentication Required"; 
                case 408:
                    return "Request Time-out"; 
                case 409: 
                    return "Conflict";
                case 410: 
                    return "Gone";
                case 411:
                    return "Length Required";
                case 412: 
                    return "Precondition Failed";
                case 413: 
                    return "Request Entity Too Large"; 
                case 414:
                    return "Request-URI Too Large"; 
                case 415:
                    return "Unsupported Media Type";
                case 416:
                    return "Requested range not satisfiable"; 
                case 417:
                    return "Expectation Failed"; 
                case 500: 
                    return "Internal Server Error";
                case 501: 
                    return "Not Implemented";
                case 502:
                    return "Bad Gateway";
                case 503: 
                    return "Service Unavailable";
                case 504: 
                    return "Gateway Time-out"; 
                case 505:
                    return "HTTP Version not supported"; 
                default:
                    return "Unknown Status Code";
            }
 
            #endregion Non-localized messages for status codes.
        } 
 
        /// Gets the host and port parts of a Host header if they are both present.
        /// Host header value (non-null). 
        /// Scheme for the host and port values.
        /// If the result is true, the host part of the header.
        /// If the result is false, the port part of the header.
        /// true if the header has a host and port part, false otherwise. 
        private static bool GetHostAndPort(string hostHeader, string scheme, out string host, out int port)
        { 
            Debug.Assert(hostHeader != null, "hostHeader != null"); 

            if (scheme != null && !scheme.EndsWith("://", StringComparison.Ordinal)) 
            {
                scheme += "://";
            }
 
            Uri result;
            if (Uri.TryCreate(scheme + hostHeader, UriKind.Absolute, out result)) 
            { 
                host = result.Host;
                port = result.Port; 
                return true;
            }
            else
            { 
                host = null;
                port = default(int); 
                return false; 
            }
        } 

        /// Checks whether the specifies string is null or blank.
        /// Text to check.
        /// true if text is null, empty, or all whitespace characters. 
        private static bool IsWhitespace(string text)
        { 
            if (text == null) 
            {
                return true; 
            }
            else
            {
                foreach (char c in text) 
                {
                    if (!Char.IsWhiteSpace(c)) 
                    { 
                        return false;
                    } 
                }

                return true;
            } 
        }
 
        /// Writes an xml:space='preserve' attribute to the specified writer. 
        /// XmlWriter to write to.
        private static void WriteSpacePreserveAttribute(XmlWriter writer) 
        {
            Debug.Assert(writer != null, "writer != null");
            writer.WriteAttributeString(
                XmlConstants.XmlNamespacePrefix,        // prefix 
                XmlConstants.XmlSpaceAttributeName,     // localName
                null,                                   // ns 
                XmlConstants.XmlSpacePreserveValue);    // value 
        }
    } 
}

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