ErrorHandler.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 / ErrorHandler.cs / 2 / ErrorHandler.cs

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

namespace System.Data.Services
{
    #region Namespaces. 

    using System; 
    using System.Data.Services.Serializers; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Xml; 

    #endregion Namespaces. 
 
    /// 
    /// Provides support for orchestrating error handling at different points in the processing cycle and for 
    /// serializing structured errors.
    /// 
    internal class ErrorHandler
    { 
        #region Private fields.
 
        /// Arguments for the exception being handled. 
        private HandleExceptionArgs exceptionArgs;
 
        /// Encoding to created over stream; null if a higher-level writer will be provided.
        private Encoding encoding;

        #endregion Private fields. 

        #region Constructors. 
 
        /// Initializes a new  instance.
        /// Arguments for the exception being handled. 
        /// Encoding to created over stream; null if a higher-level writer will be provided.
        private ErrorHandler(HandleExceptionArgs args, Encoding encoding)
        {
            Debug.Assert(args != null, "args != null"); 
            this.exceptionArgs = args;
            this.encoding = encoding; 
        } 

        #endregion Constructors. 

        #region Internal methods.

        /// Handles an exception when processing a batch response. 
        /// Data service doing the processing.
        /// host to which we need to write the exception message 
        /// Exception thrown. 
        /// Output writer for the batch.
        internal static void HandleBatchProcessException(IDataService service, BatchServiceHost host, Exception exception, StreamWriter writer) 
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(host != null, "host != null");
            Debug.Assert(exception != null, "exception != null"); 
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(service.Configuration != null, "service.Configuration != null"); 
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception)"); 

            string contentType; 
            Encoding encoding;
            TryGetResponseFormatForError(host, out contentType, out encoding);

            HandleExceptionArgs args = new HandleExceptionArgs(exception, false, contentType, service.Configuration.UseVerboseErrors); 
            service.InternalHandleException(args);
            ((IDataServiceHost)host).ResponseVersion = ((IDataServiceHost)host).ResponseVersion ?? XmlConstants.DataServiceVersionCurrent; 
            ((IDataServiceHost)host).ProcessException(args); 

            writer.Flush(); 
            Action errorWriter = CreateErrorSerializer(args, encoding);
            errorWriter(writer.BaseStream);
            writer.WriteLine();
        } 

        /// Handles an exception when processing a batch request. 
        /// Data service doing the processing. 
        /// Exception thrown.
        /// Output writer for the batch. 
        internal static void HandleBatchRequestException(IDataService service, Exception exception, StreamWriter writer)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(exception != null, "exception != null"); 
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(service.Configuration != null, "service.Configuration != null - it should have been initialized by now"); 
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception) - "); 

            string contentType; 
            Encoding encoding;
            TryGetResponseFormatForError(service.Host, out contentType, out encoding);
            encoding = writer.Encoding;
 
            HandleExceptionArgs args = new HandleExceptionArgs(exception, false, contentType, service.Configuration.UseVerboseErrors);
            service.InternalHandleException(args); 
            writer.Flush(); 

            Action errorWriter = CreateErrorSerializer(args, encoding); 
            errorWriter(writer.BaseStream);
            writer.WriteLine();
        }
 
        /// Handles an exception before the response has been written out.
        /// Exception thrown. 
        /// Data service doing the processing. 
        /// 'Accept' header value; possibly null.
        /// 'Accept-Charset' header; possibly null. 
        /// An action that can serialize the exception into a stream.
        internal static Action HandleBeforeWritingException(Exception exception, IDataService service, string accept, string acceptCharset)
        {
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception)"); 
            Debug.Assert(exception != null, "exception != null");
            Debug.Assert(service != null, "service != null"); 
 
            string contentType;
            Encoding encoding; 
            TryGetResponseFormatForError(accept, acceptCharset, out contentType, out encoding);

            bool verbose = (service.Configuration != null) ? service.Configuration.UseVerboseErrors : false;
            HandleExceptionArgs args = new HandleExceptionArgs(exception, false, contentType, verbose); 
            service.InternalHandleException(args);
            service.Host.ResponseVersion = service.Host.ResponseVersion ?? XmlConstants.DataServiceVersionCurrent; 
            service.Host.ProcessException(args); 

            return CreateErrorSerializer(args, encoding); 
        }

        /// Handles an exception while the response is being written out.
        /// Exception thrown. 
        /// Data service doing the processing.
        /// MIME type of output stream. 
        /// Serializer-specific exception writer. 
        internal static void HandleDuringWritingException(Exception exception, IDataService service, string contentType, IExceptionWriter exceptionWriter)
        { 
            Debug.Assert(service != null, "service != null");
            Debug.Assert(exception != null, "exception != null");
            Debug.Assert(exceptionWriter != null, "exceptionWriter != null");
            Debug.Assert(service.Configuration != null, "service.Configuration != null"); 
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception)");
 
            HandleExceptionArgs args = new HandleExceptionArgs(exception, true, contentType, service.Configuration.UseVerboseErrors); 
            service.InternalHandleException(args);
            service.Host.ProcessException(args); 
            exceptionWriter.WriteException(args);
        }

        /// Handles the specified . 
        /// Exception to handle
        /// The caller should re-throw the original exception if this method returns normally. 
        internal static void HandleTargetInvocationException(TargetInvocationException exception) 
        {
            Debug.Assert(exception != null, "exception != null"); 
            if (exception.InnerException == null || !WebUtil.IsCatchableExceptionType(exception.InnerException))
            {
                return;
            } 

            DataServiceException dataException = exception.InnerException as DataServiceException; 
            if (dataException == null) 
            {
                return; 
            }

            throw new DataServiceException(
                dataException.StatusCode, 
                dataException.ErrorCode,
                dataException.Message, 
                dataException.MessageLanguage, 
                exception);
        } 

        /// Serializes an error in JSON format.
        /// Arguments describing the error.
        /// Writer to which error should be serialized. 
        internal static void SerializeJsonError(HandleExceptionArgs args, JsonWriter writer)
        { 
            Debug.Assert(args != null, "args != null"); 
            Debug.Assert(writer != null, "writer != null");
            ErrorHandler serializer = new ErrorHandler(args, null); 
            serializer.SerializeJsonError(writer);
        }

        /// Serializes an error in XML format. 
        /// Arguments describing the error.
        /// Writer to which error should be serialized. 
        internal static void SerializeXmlError(HandleExceptionArgs args, XmlWriter writer) 
        {
            Debug.Assert(args != null, "args != null"); 
            Debug.Assert(writer != null, "writer != null");
            ErrorHandler serializer = new ErrorHandler(args, null);
            serializer.SerializeXmlError(writer);
        } 

        #endregion Internal methods. 
 
        #region Private methods.
 
        /// Creates a delegate that can serialize an error for the specified arguments.
        /// Arguments for the exception being handled.
        /// Encoding to created over stream.
        /// A delegate that can serialize an error for the specified arguments. 
        private static Action CreateErrorSerializer(HandleExceptionArgs args, Encoding encoding)
        { 
            Debug.Assert(args != null, "args != null"); 
            Debug.Assert(encoding != null, "encoding != null");
            ErrorHandler handler = new ErrorHandler(args, encoding); 
            if (args.ResponseContentType == XmlConstants.MimeApplicationJson)
            {
                return handler.SerializeJsonErrorToStream;
            } 
            else
            { 
                return handler.SerializeXmlErrorToStream; 
            }
        } 

        /// 
        /// Gets values describing the  if it's a DataServiceException;
        /// defaults otherwise. 
        /// 
        /// Exception to extract value from. 
        /// Error code from the ; blank if not available. 
        /// Message from the ; blank if not available.
        /// Message language from the ; current default if not available. 
        /// The cast DataServiceException; possibly null.
        private static DataServiceException ExtractErrorValues(Exception exception, out string errorCode, out string message, out string messageLang)
        {
            DataServiceException dataException = exception as DataServiceException; 
            if (dataException != null)
            { 
                errorCode = dataException.ErrorCode ?? ""; 
                message = dataException.Message ?? "";
                messageLang = dataException.MessageLanguage ?? CultureInfo.CurrentCulture.Name; 
                return dataException;
            }
            else
            { 
                errorCode = "";
                message = Strings.DataServiceException_GeneralError; 
                messageLang = CultureInfo.CurrentCulture.Name; 
                return null;
            } 
        }

        /// Serializes an exception in JSON format.
        /// Writer to which error should be serialized. 
        /// Exception to serialize.
        private static void SerializeJsonException(JsonWriter writer, Exception exception) 
        { 
            string elementName = XmlConstants.JsonErrorInner;
            int nestingDepth = 0; 
            while (exception != null)
            {
                writer.WriteName(elementName);
                writer.StartObjectScope(); 
                nestingDepth++;
 
                string exceptionMessage = exception.Message ?? String.Empty; 
                writer.WriteName(XmlConstants.JsonErrorMessage);
                writer.WriteValue(exceptionMessage); 

                string exceptionType = exception.GetType().FullName;
                writer.WriteName(XmlConstants.JsonErrorType);
                writer.WriteValue(exceptionType); 

                string exceptionStackTrace = exception.StackTrace ?? String.Empty; 
                writer.WriteName(XmlConstants.JsonErrorStackTrace); 
                writer.WriteValue(exceptionStackTrace);
 
                exception = exception.InnerException;
                elementName = XmlConstants.JsonErrorInternalException;
            }
 
            while (nestingDepth > 0)
            { 
                writer.EndScope();  //  
                nestingDepth--;
            } 
        }

        /// Serializes an exception in XML format.
        /// Writer to which error should be serialized. 
        /// Exception to serialize.
        private static void SerializeXmlException(XmlWriter writer, Exception exception) 
        { 
            string elementName = XmlConstants.XmlErrorInnerElementName;
            int nestingDepth = 0; 
            while (exception != null)
            {
                writer.WriteStartElement(elementName, XmlConstants.XmlnsNamespacePrefix);
                nestingDepth++; 

                string exceptionMessage = exception.Message ?? String.Empty; 
                writer.WriteStartElement(XmlConstants.XmlErrorMessageElementName, XmlConstants.XmlnsNamespacePrefix); 
                writer.WriteString(exceptionMessage);
                writer.WriteEndElement();   //  

                string exceptionType = exception.GetType().FullName;
                writer.WriteStartElement(XmlConstants.XmlErrorTypeElementName, XmlConstants.XmlnsNamespacePrefix);
                writer.WriteString(exceptionType); 
                writer.WriteEndElement();   // 
 
                string exceptionStackTrace = exception.StackTrace ?? String.Empty; 
                writer.WriteStartElement(XmlConstants.XmlErrorStackTraceElementName, XmlConstants.XmlnsNamespacePrefix);
                writer.WriteString(exceptionStackTrace); 
                writer.WriteEndElement();   // 

                exception = exception.InnerException;
                elementName = XmlConstants.XmlErrorInternalExceptionElementName; 
            }
 
            while (nestingDepth > 0) 
            {
                writer.WriteEndElement();   //  
                nestingDepth--;
            }
        }
 
        /// Gets content type and encoding information from the host if possible; defaults otherwise.
        /// Host to get headers from (possibly null). 
        /// After invocation, content type for the exception. 
        /// After invocation, encoding for the exception.
        private static void TryGetResponseFormatForError(IDataServiceHost host, out string contentType, out Encoding encoding) 
        {
            TryGetResponseFormatForError(
                (host != null) ? host.RequestAccept : null,
                (host != null) ? host.RequestAcceptCharSet : null, 
                out contentType,
                out encoding); 
        } 

        /// Gets content type and encoding information from the headers if possible; defaults otherwise. 
        /// A comma-separated list of client-supported MIME Accept types.
        /// The specification for the character set encoding that the client requested.
        /// After invocation, content type for the exception.
        /// After invocation, encoding for the exception. 
        private static void TryGetResponseFormatForError(string accept, string acceptCharset, out string contentType, out Encoding encoding)
        { 
            contentType = null; 
            encoding = null;
            if (accept != null) 
            {
                try
                {
                    string[] availableTypes = new string[] { XmlConstants.MimeApplicationXml, XmlConstants.MimeApplicationJson }; 
                    contentType = HttpProcessUtility.SelectMimeType(accept, availableTypes);
                } 
                catch (DataServiceException) 
                {
                    // Ignore formatting erros in Accept and rely on text. 
                }
            }

            if (acceptCharset != null) 
            {
                try 
                { 
                    encoding = HttpProcessUtility.EncodingFromAcceptCharset(acceptCharset);
                } 
                catch (DataServiceException)
                {
                    // Ignore formatting erros in Accept-Charset and rely on text.
                } 
            }
 
            contentType = contentType ?? XmlConstants.MimeApplicationXml; 
            encoding = encoding ?? HttpProcessUtility.FallbackEncoding;
        } 

        /// Serializes an error in JSON format.
        /// Writer to which error should be serialized.
        private void SerializeJsonError(JsonWriter writer) 
        {
            Debug.Assert(writer != null, "writer != null"); 
            writer.StartObjectScope();  // Wrapper for error. 
            writer.WriteName(XmlConstants.JsonError);
 
            string errorCode, message, messageLang;
            DataServiceException dataException = ExtractErrorValues(this.exceptionArgs.Exception, out errorCode, out message, out messageLang);
            writer.StartObjectScope();
 
            writer.WriteName(XmlConstants.JsonErrorCode);
            writer.WriteValue(errorCode); 
 
            writer.WriteName(XmlConstants.JsonErrorMessage);
            writer.StartObjectScope(); 
            writer.WriteName(XmlConstants.XmlLangAttributeName);
            writer.WriteValue(messageLang);
            writer.WriteName(XmlConstants.JsonErrorValue);
            writer.WriteValue(message); 
            writer.EndScope();  // 
 
            if (this.exceptionArgs.UseVerboseErrors) 
            {
                Exception exception = (dataException == null) ? this.exceptionArgs.Exception : dataException.InnerException; 
                SerializeJsonException(writer, exception);
            }

            writer.EndScope();  //  
            writer.EndScope();  // 
            writer.Flush(); 
        } 

        /// Serializes an error in XML format. 
        /// Writer to which error should be serialized.
        private void SerializeXmlError(XmlWriter writer)
        {
            Debug.Assert(writer != null, "writer != null"); 
            writer.WriteStartElement(XmlConstants.XmlErrorElementName, XmlConstants.DataWebMetadataNamespace);
            string errorCode, message, messageLang; 
            DataServiceException dataException = ExtractErrorValues(this.exceptionArgs.Exception, out errorCode, out message, out messageLang); 

            writer.WriteStartElement(XmlConstants.XmlErrorCodeElementName, XmlConstants.DataWebMetadataNamespace); 
            writer.WriteString(errorCode);
            writer.WriteEndElement();   // 

            writer.WriteStartElement(XmlConstants.XmlErrorMessageElementName, XmlConstants.DataWebMetadataNamespace); 
            writer.WriteAttributeString(
                XmlConstants.XmlNamespacePrefix,    // prefix 
                XmlConstants.XmlLangAttributeName,  // localName 
                null,                               // ns
                messageLang);                       // value 
            writer.WriteString(message);
            writer.WriteEndElement();   // 

            if (this.exceptionArgs.UseVerboseErrors) 
            {
                Exception exception = (dataException == null) ? this.exceptionArgs.Exception : dataException.InnerException; 
                SerializeXmlException(writer, exception); 
            }
 
            writer.WriteEndElement();   // 
            writer.Flush();
        }
 
        /// Serializes the current exception description to the specified .
        /// Stream to write to. 
        private void SerializeJsonErrorToStream(Stream stream) 
        {
            Debug.Assert(stream != null, "stream != null"); 
            using (StreamWriter streamWriter = new StreamWriter(stream, this.encoding))
            {
                JsonWriter jsonWriter = new JsonWriter(streamWriter);
                SerializeJsonError(jsonWriter); 
            }
        } 
 
        /// Serializes the current exception description to the specified .
        /// Stream to write to. 
        private void SerializeXmlErrorToStream(Stream stream)
        {
            Debug.Assert(stream != null, "stream != null");
            using (XmlWriter writer = XmlUtil.CreateXmlWriterAndWriteProcessingInstruction(stream, this.encoding)) 
            {
                SerializeXmlError(writer); 
            } 
        }
 
        #endregion Private methods.
    }
}

// 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
{
    #region Namespaces. 

    using System; 
    using System.Data.Services.Serializers; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Xml; 

    #endregion Namespaces. 
 
    /// 
    /// Provides support for orchestrating error handling at different points in the processing cycle and for 
    /// serializing structured errors.
    /// 
    internal class ErrorHandler
    { 
        #region Private fields.
 
        /// Arguments for the exception being handled. 
        private HandleExceptionArgs exceptionArgs;
 
        /// Encoding to created over stream; null if a higher-level writer will be provided.
        private Encoding encoding;

        #endregion Private fields. 

        #region Constructors. 
 
        /// Initializes a new  instance.
        /// Arguments for the exception being handled. 
        /// Encoding to created over stream; null if a higher-level writer will be provided.
        private ErrorHandler(HandleExceptionArgs args, Encoding encoding)
        {
            Debug.Assert(args != null, "args != null"); 
            this.exceptionArgs = args;
            this.encoding = encoding; 
        } 

        #endregion Constructors. 

        #region Internal methods.

        /// Handles an exception when processing a batch response. 
        /// Data service doing the processing.
        /// host to which we need to write the exception message 
        /// Exception thrown. 
        /// Output writer for the batch.
        internal static void HandleBatchProcessException(IDataService service, BatchServiceHost host, Exception exception, StreamWriter writer) 
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(host != null, "host != null");
            Debug.Assert(exception != null, "exception != null"); 
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(service.Configuration != null, "service.Configuration != null"); 
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception)"); 

            string contentType; 
            Encoding encoding;
            TryGetResponseFormatForError(host, out contentType, out encoding);

            HandleExceptionArgs args = new HandleExceptionArgs(exception, false, contentType, service.Configuration.UseVerboseErrors); 
            service.InternalHandleException(args);
            ((IDataServiceHost)host).ResponseVersion = ((IDataServiceHost)host).ResponseVersion ?? XmlConstants.DataServiceVersionCurrent; 
            ((IDataServiceHost)host).ProcessException(args); 

            writer.Flush(); 
            Action errorWriter = CreateErrorSerializer(args, encoding);
            errorWriter(writer.BaseStream);
            writer.WriteLine();
        } 

        /// Handles an exception when processing a batch request. 
        /// Data service doing the processing. 
        /// Exception thrown.
        /// Output writer for the batch. 
        internal static void HandleBatchRequestException(IDataService service, Exception exception, StreamWriter writer)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(exception != null, "exception != null"); 
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(service.Configuration != null, "service.Configuration != null - it should have been initialized by now"); 
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception) - "); 

            string contentType; 
            Encoding encoding;
            TryGetResponseFormatForError(service.Host, out contentType, out encoding);
            encoding = writer.Encoding;
 
            HandleExceptionArgs args = new HandleExceptionArgs(exception, false, contentType, service.Configuration.UseVerboseErrors);
            service.InternalHandleException(args); 
            writer.Flush(); 

            Action errorWriter = CreateErrorSerializer(args, encoding); 
            errorWriter(writer.BaseStream);
            writer.WriteLine();
        }
 
        /// Handles an exception before the response has been written out.
        /// Exception thrown. 
        /// Data service doing the processing. 
        /// 'Accept' header value; possibly null.
        /// 'Accept-Charset' header; possibly null. 
        /// An action that can serialize the exception into a stream.
        internal static Action HandleBeforeWritingException(Exception exception, IDataService service, string accept, string acceptCharset)
        {
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception)"); 
            Debug.Assert(exception != null, "exception != null");
            Debug.Assert(service != null, "service != null"); 
 
            string contentType;
            Encoding encoding; 
            TryGetResponseFormatForError(accept, acceptCharset, out contentType, out encoding);

            bool verbose = (service.Configuration != null) ? service.Configuration.UseVerboseErrors : false;
            HandleExceptionArgs args = new HandleExceptionArgs(exception, false, contentType, verbose); 
            service.InternalHandleException(args);
            service.Host.ResponseVersion = service.Host.ResponseVersion ?? XmlConstants.DataServiceVersionCurrent; 
            service.Host.ProcessException(args); 

            return CreateErrorSerializer(args, encoding); 
        }

        /// Handles an exception while the response is being written out.
        /// Exception thrown. 
        /// Data service doing the processing.
        /// MIME type of output stream. 
        /// Serializer-specific exception writer. 
        internal static void HandleDuringWritingException(Exception exception, IDataService service, string contentType, IExceptionWriter exceptionWriter)
        { 
            Debug.Assert(service != null, "service != null");
            Debug.Assert(exception != null, "exception != null");
            Debug.Assert(exceptionWriter != null, "exceptionWriter != null");
            Debug.Assert(service.Configuration != null, "service.Configuration != null"); 
            Debug.Assert(WebUtil.IsCatchableExceptionType(exception), "WebUtil.IsCatchableExceptionType(exception)");
 
            HandleExceptionArgs args = new HandleExceptionArgs(exception, true, contentType, service.Configuration.UseVerboseErrors); 
            service.InternalHandleException(args);
            service.Host.ProcessException(args); 
            exceptionWriter.WriteException(args);
        }

        /// Handles the specified . 
        /// Exception to handle
        /// The caller should re-throw the original exception if this method returns normally. 
        internal static void HandleTargetInvocationException(TargetInvocationException exception) 
        {
            Debug.Assert(exception != null, "exception != null"); 
            if (exception.InnerException == null || !WebUtil.IsCatchableExceptionType(exception.InnerException))
            {
                return;
            } 

            DataServiceException dataException = exception.InnerException as DataServiceException; 
            if (dataException == null) 
            {
                return; 
            }

            throw new DataServiceException(
                dataException.StatusCode, 
                dataException.ErrorCode,
                dataException.Message, 
                dataException.MessageLanguage, 
                exception);
        } 

        /// Serializes an error in JSON format.
        /// Arguments describing the error.
        /// Writer to which error should be serialized. 
        internal static void SerializeJsonError(HandleExceptionArgs args, JsonWriter writer)
        { 
            Debug.Assert(args != null, "args != null"); 
            Debug.Assert(writer != null, "writer != null");
            ErrorHandler serializer = new ErrorHandler(args, null); 
            serializer.SerializeJsonError(writer);
        }

        /// Serializes an error in XML format. 
        /// Arguments describing the error.
        /// Writer to which error should be serialized. 
        internal static void SerializeXmlError(HandleExceptionArgs args, XmlWriter writer) 
        {
            Debug.Assert(args != null, "args != null"); 
            Debug.Assert(writer != null, "writer != null");
            ErrorHandler serializer = new ErrorHandler(args, null);
            serializer.SerializeXmlError(writer);
        } 

        #endregion Internal methods. 
 
        #region Private methods.
 
        /// Creates a delegate that can serialize an error for the specified arguments.
        /// Arguments for the exception being handled.
        /// Encoding to created over stream.
        /// A delegate that can serialize an error for the specified arguments. 
        private static Action CreateErrorSerializer(HandleExceptionArgs args, Encoding encoding)
        { 
            Debug.Assert(args != null, "args != null"); 
            Debug.Assert(encoding != null, "encoding != null");
            ErrorHandler handler = new ErrorHandler(args, encoding); 
            if (args.ResponseContentType == XmlConstants.MimeApplicationJson)
            {
                return handler.SerializeJsonErrorToStream;
            } 
            else
            { 
                return handler.SerializeXmlErrorToStream; 
            }
        } 

        /// 
        /// Gets values describing the  if it's a DataServiceException;
        /// defaults otherwise. 
        /// 
        /// Exception to extract value from. 
        /// Error code from the ; blank if not available. 
        /// Message from the ; blank if not available.
        /// Message language from the ; current default if not available. 
        /// The cast DataServiceException; possibly null.
        private static DataServiceException ExtractErrorValues(Exception exception, out string errorCode, out string message, out string messageLang)
        {
            DataServiceException dataException = exception as DataServiceException; 
            if (dataException != null)
            { 
                errorCode = dataException.ErrorCode ?? ""; 
                message = dataException.Message ?? "";
                messageLang = dataException.MessageLanguage ?? CultureInfo.CurrentCulture.Name; 
                return dataException;
            }
            else
            { 
                errorCode = "";
                message = Strings.DataServiceException_GeneralError; 
                messageLang = CultureInfo.CurrentCulture.Name; 
                return null;
            } 
        }

        /// Serializes an exception in JSON format.
        /// Writer to which error should be serialized. 
        /// Exception to serialize.
        private static void SerializeJsonException(JsonWriter writer, Exception exception) 
        { 
            string elementName = XmlConstants.JsonErrorInner;
            int nestingDepth = 0; 
            while (exception != null)
            {
                writer.WriteName(elementName);
                writer.StartObjectScope(); 
                nestingDepth++;
 
                string exceptionMessage = exception.Message ?? String.Empty; 
                writer.WriteName(XmlConstants.JsonErrorMessage);
                writer.WriteValue(exceptionMessage); 

                string exceptionType = exception.GetType().FullName;
                writer.WriteName(XmlConstants.JsonErrorType);
                writer.WriteValue(exceptionType); 

                string exceptionStackTrace = exception.StackTrace ?? String.Empty; 
                writer.WriteName(XmlConstants.JsonErrorStackTrace); 
                writer.WriteValue(exceptionStackTrace);
 
                exception = exception.InnerException;
                elementName = XmlConstants.JsonErrorInternalException;
            }
 
            while (nestingDepth > 0)
            { 
                writer.EndScope();  //  
                nestingDepth--;
            } 
        }

        /// Serializes an exception in XML format.
        /// Writer to which error should be serialized. 
        /// Exception to serialize.
        private static void SerializeXmlException(XmlWriter writer, Exception exception) 
        { 
            string elementName = XmlConstants.XmlErrorInnerElementName;
            int nestingDepth = 0; 
            while (exception != null)
            {
                writer.WriteStartElement(elementName, XmlConstants.XmlnsNamespacePrefix);
                nestingDepth++; 

                string exceptionMessage = exception.Message ?? String.Empty; 
                writer.WriteStartElement(XmlConstants.XmlErrorMessageElementName, XmlConstants.XmlnsNamespacePrefix); 
                writer.WriteString(exceptionMessage);
                writer.WriteEndElement();   //  

                string exceptionType = exception.GetType().FullName;
                writer.WriteStartElement(XmlConstants.XmlErrorTypeElementName, XmlConstants.XmlnsNamespacePrefix);
                writer.WriteString(exceptionType); 
                writer.WriteEndElement();   // 
 
                string exceptionStackTrace = exception.StackTrace ?? String.Empty; 
                writer.WriteStartElement(XmlConstants.XmlErrorStackTraceElementName, XmlConstants.XmlnsNamespacePrefix);
                writer.WriteString(exceptionStackTrace); 
                writer.WriteEndElement();   // 

                exception = exception.InnerException;
                elementName = XmlConstants.XmlErrorInternalExceptionElementName; 
            }
 
            while (nestingDepth > 0) 
            {
                writer.WriteEndElement();   //  
                nestingDepth--;
            }
        }
 
        /// Gets content type and encoding information from the host if possible; defaults otherwise.
        /// Host to get headers from (possibly null). 
        /// After invocation, content type for the exception. 
        /// After invocation, encoding for the exception.
        private static void TryGetResponseFormatForError(IDataServiceHost host, out string contentType, out Encoding encoding) 
        {
            TryGetResponseFormatForError(
                (host != null) ? host.RequestAccept : null,
                (host != null) ? host.RequestAcceptCharSet : null, 
                out contentType,
                out encoding); 
        } 

        /// Gets content type and encoding information from the headers if possible; defaults otherwise. 
        /// A comma-separated list of client-supported MIME Accept types.
        /// The specification for the character set encoding that the client requested.
        /// After invocation, content type for the exception.
        /// After invocation, encoding for the exception. 
        private static void TryGetResponseFormatForError(string accept, string acceptCharset, out string contentType, out Encoding encoding)
        { 
            contentType = null; 
            encoding = null;
            if (accept != null) 
            {
                try
                {
                    string[] availableTypes = new string[] { XmlConstants.MimeApplicationXml, XmlConstants.MimeApplicationJson }; 
                    contentType = HttpProcessUtility.SelectMimeType(accept, availableTypes);
                } 
                catch (DataServiceException) 
                {
                    // Ignore formatting erros in Accept and rely on text. 
                }
            }

            if (acceptCharset != null) 
            {
                try 
                { 
                    encoding = HttpProcessUtility.EncodingFromAcceptCharset(acceptCharset);
                } 
                catch (DataServiceException)
                {
                    // Ignore formatting erros in Accept-Charset and rely on text.
                } 
            }
 
            contentType = contentType ?? XmlConstants.MimeApplicationXml; 
            encoding = encoding ?? HttpProcessUtility.FallbackEncoding;
        } 

        /// Serializes an error in JSON format.
        /// Writer to which error should be serialized.
        private void SerializeJsonError(JsonWriter writer) 
        {
            Debug.Assert(writer != null, "writer != null"); 
            writer.StartObjectScope();  // Wrapper for error. 
            writer.WriteName(XmlConstants.JsonError);
 
            string errorCode, message, messageLang;
            DataServiceException dataException = ExtractErrorValues(this.exceptionArgs.Exception, out errorCode, out message, out messageLang);
            writer.StartObjectScope();
 
            writer.WriteName(XmlConstants.JsonErrorCode);
            writer.WriteValue(errorCode); 
 
            writer.WriteName(XmlConstants.JsonErrorMessage);
            writer.StartObjectScope(); 
            writer.WriteName(XmlConstants.XmlLangAttributeName);
            writer.WriteValue(messageLang);
            writer.WriteName(XmlConstants.JsonErrorValue);
            writer.WriteValue(message); 
            writer.EndScope();  // 
 
            if (this.exceptionArgs.UseVerboseErrors) 
            {
                Exception exception = (dataException == null) ? this.exceptionArgs.Exception : dataException.InnerException; 
                SerializeJsonException(writer, exception);
            }

            writer.EndScope();  //  
            writer.EndScope();  // 
            writer.Flush(); 
        } 

        /// Serializes an error in XML format. 
        /// Writer to which error should be serialized.
        private void SerializeXmlError(XmlWriter writer)
        {
            Debug.Assert(writer != null, "writer != null"); 
            writer.WriteStartElement(XmlConstants.XmlErrorElementName, XmlConstants.DataWebMetadataNamespace);
            string errorCode, message, messageLang; 
            DataServiceException dataException = ExtractErrorValues(this.exceptionArgs.Exception, out errorCode, out message, out messageLang); 

            writer.WriteStartElement(XmlConstants.XmlErrorCodeElementName, XmlConstants.DataWebMetadataNamespace); 
            writer.WriteString(errorCode);
            writer.WriteEndElement();   // 

            writer.WriteStartElement(XmlConstants.XmlErrorMessageElementName, XmlConstants.DataWebMetadataNamespace); 
            writer.WriteAttributeString(
                XmlConstants.XmlNamespacePrefix,    // prefix 
                XmlConstants.XmlLangAttributeName,  // localName 
                null,                               // ns
                messageLang);                       // value 
            writer.WriteString(message);
            writer.WriteEndElement();   // 

            if (this.exceptionArgs.UseVerboseErrors) 
            {
                Exception exception = (dataException == null) ? this.exceptionArgs.Exception : dataException.InnerException; 
                SerializeXmlException(writer, exception); 
            }
 
            writer.WriteEndElement();   // 
            writer.Flush();
        }
 
        /// Serializes the current exception description to the specified .
        /// Stream to write to. 
        private void SerializeJsonErrorToStream(Stream stream) 
        {
            Debug.Assert(stream != null, "stream != null"); 
            using (StreamWriter streamWriter = new StreamWriter(stream, this.encoding))
            {
                JsonWriter jsonWriter = new JsonWriter(streamWriter);
                SerializeJsonError(jsonWriter); 
            }
        } 
 
        /// Serializes the current exception description to the specified .
        /// Stream to write to. 
        private void SerializeXmlErrorToStream(Stream stream)
        {
            Debug.Assert(stream != null, "stream != null");
            using (XmlWriter writer = XmlUtil.CreateXmlWriterAndWriteProcessingInstruction(stream, this.encoding)) 
            {
                SerializeXmlError(writer); 
            } 
        }
 
        #endregion Private methods.
    }
}

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