/// <summary>
 /// Asynchronously writes the json value (primitive, IDictionary or IEnumerable) to the underlying json writer.
 /// </summary>
 /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param>
 /// <param name="propertyValue">value to write.</param>
 /// <returns>A task that represents the asynchronous write operation.</returns>
 private static async Task WriteJsonValueAsync(this IJsonWriterAsync jsonWriter, object propertyValue)
 {
     if (propertyValue == null)
     {
         await jsonWriter.WriteValueAsync((string)null).ConfigureAwait(false);
     }
     else if (EdmLibraryExtensions.IsPrimitiveType(propertyValue.GetType()))
     {
         await jsonWriter.WritePrimitiveValueAsync(propertyValue).ConfigureAwait(false);
     }
     else
     {
         IDictionary <string, object> objectValue = propertyValue as IDictionary <string, object>;
         if (objectValue != null)
         {
             await jsonWriter.WriteJsonObjectValueAsync(objectValue, null /*typeName */).ConfigureAwait(false);
         }
         else
         {
             IEnumerable arrayValue = propertyValue as IEnumerable;
             Debug.Assert(arrayValue != null, "arrayValue != null");
             await jsonWriter.WriteJsonArrayValueAsync(arrayValue).ConfigureAwait(false);
         }
     }
 }
        private async Task VerifyWriterPrimitiveValueWithIeee754CompatibleAsync <T>(T parameter, string expected, bool isIeee754Compatible)
        {
            this.writer = new JsonWriter(new StringWriter(builder), isIeee754Compatible);
            await this.writer.WritePrimitiveValueAsync(parameter);

            Assert.Equal(expected, this.builder.ToString());
        }
Exemple #3
0
 public ODataJsonWriterUtilsAsyncTests()
 {
     this.stringWriter = new StringWriter();
     this.jsonWriter   = new JsonWriter(this.stringWriter, isIeee754Compatible: true);
     this.settings     = new ODataMessageWriterSettings();
     this.writeInstanceAnnotationsDelegate = async(ICollection <ODataInstanceAnnotation> instanceAnnotations) => await TaskUtils.CompletedTask;
 }
        /// <summary>
        /// Write a JSON instance annotation name which represents a instance annotation.
        /// </summary>
        /// <param name="jsonWriter">The JSON writer to write to.</param>
        /// <param name="annotationName">The name of the instance annotation to write.</param>
        internal static Task WriteInstanceAnnotationNameAsync(this IJsonWriterAsync jsonWriter, string annotationName)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter != null");
            Debug.Assert(!string.IsNullOrEmpty(annotationName), "!string.IsNullOrEmpty(annotationName)");

            return(jsonWriter.WriteNameAsync(JsonLightConstants.ODataPropertyAnnotationSeparatorChar + annotationName));
        }
Exemple #5
0
        /// <summary>
        /// Asynchronously writes an error message.
        /// </summary>
        /// <param name="jsonWriter">The JSON writer to write the error.</param>
        /// <param name="writeInstanceAnnotationsDelegate">Delegate to write the instance annotations.</param>
        /// <param name="error">The error instance to write.</param>
        /// <param name="includeDebugInformation">A flag indicating whether error details should be written (in debug mode only) or not.</param>
        /// <param name="maxInnerErrorDepth">The maximum number of nested inner errors to allow.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        internal static Task WriteErrorAsync(
            IJsonWriterAsync jsonWriter,
            Func <ICollection <ODataInstanceAnnotation>, Task> writeInstanceAnnotationsDelegate,
            ODataError error,
            bool includeDebugInformation,
            int maxInnerErrorDepth)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter != null");
            Debug.Assert(error != null, "error != null");

            ExceptionUtils.CheckArgumentNotNull(writeInstanceAnnotationsDelegate, "writeInstanceAnnotationsDelegate");

            string code, message;

            ErrorUtils.GetErrorDetails(error, out code, out message);

            ODataInnerError innerError = includeDebugInformation ? error.InnerError : null;

            return(WriteErrorAsync(
                       jsonWriter,
                       code,
                       message,
                       error.Target,
                       error.Details,
                       innerError,
                       error.GetInstanceAnnotations(),
                       writeInstanceAnnotationsDelegate,
                       maxInnerErrorDepth));
        }
 public ODataJsonLightWriterUtilsTests()
 {
     this.builder         = new StringBuilder();
     this.stringWriter    = new StringWriter(builder);
     this.jsonWriter      = new JsonWriter(this.stringWriter, isIeee754Compatible: true);
     this.asyncJsonWriter = new JsonWriter(this.stringWriter, isIeee754Compatible: true);
 }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="jsonWriter">The underlying JSON writer.</param>
        /// <param name="enableWritingODataAnnotationWithoutPrefix">Whether write odata annotation without "odata." prefix in name.</param>
        /// <param name="odataVersion">OData Version used when writing the annotations.</param>
        public JsonLightODataAnnotationWriter(IJsonWriterAsync asyncJsonWriter, bool enableWritingODataAnnotationWithoutPrefix, ODataVersion?odataVersion)
        {
            Debug.Assert(asyncJsonWriter != null, "asyncJsonWriter != null");

            this.asyncJsonWriter = asyncJsonWriter;
            this.enableWritingODataAnnotationWithoutPrefix = enableWritingODataAnnotationWithoutPrefix;
            this.odataVersion = odataVersion ?? ODataVersion.V4;
        }
 public JsonLightODataAnnotationWriterTests()
 {
     this.builder                    = new StringBuilder();
     this.stringWriter               = new StringWriter(builder);
     this.asyncJsonWriter            = (IJsonWriterAsync) new JsonWriter(this.stringWriter, isIeee754Compatible: true);
     this.asyncODataAnnotationWriter = new JsonLightODataAnnotationWriter(
         this.asyncJsonWriter, false, ODataVersion.V4);
 }
Exemple #9
0
        /// <summary>
        /// If we are writing a response and the given Json Padding function name is not null or empty
        /// this function will close the JSONP scope asynchronously.
        /// </summary>
        /// <param name="jsonWriter">JsonWriter to write to.</param>
        /// <param name="settings">Writer settings.</param>
        /// <returns>A task that represents the asynchronous operation.</returns>
        internal static Task EndJsonPaddingIfRequiredAsync(IJsonWriterAsync jsonWriter, ODataMessageWriterSettings settings)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter should not be null");

            if (settings.HasJsonPaddingFunction())
            {
                return(jsonWriter.EndPaddingFunctionScopeAsync());
            }

            return(TaskUtils.CompletedTask);
        }
Exemple #10
0
 /// <summary>
 /// Constructs a <see cref="JsonLightInstanceAnnotationWriter"/> that can write a collection of <see cref="ODataInstanceAnnotation"/>.
 /// </summary>
 /// <param name="valueSerializer">The <see cref="ODataJsonLightValueSerializer"/> to use for writing values of instance annotations.
 /// The <see cref="IJsonWriter"/> that is also used internally will be acquired from the this instance.</param>
 /// <param name="typeNameOracle">The oracle to use to determine the type name to write for entries and values.</param>
 internal JsonLightInstanceAnnotationWriter(ODataJsonLightValueSerializer valueSerializer, JsonLightTypeNameOracle typeNameOracle)
 {
     Debug.Assert(valueSerializer != null, "valueSerializer should not be null");
     this.valueSerializer                   = valueSerializer;
     this.typeNameOracle                    = typeNameOracle;
     this.jsonWriter                        = this.valueSerializer.JsonWriter;
     this.odataAnnotationWriter             = this.valueSerializer.ODataAnnotationWriter;
     this.asynchronousJsonWriter            = this.valueSerializer.AsynchronousJsonWriter;
     this.asynchronousODataAnnotationWriter = this.valueSerializer.AsynchronousODataAnnotationWriter;
     this.writerValidator                   = this.valueSerializer.MessageWriterSettings.Validator;
 }
Exemple #11
0
        /// <summary>
        /// Asynchronously writes the function's name and start the JSONP scope if we are writing a response and the
        /// JSONP function name is not null or empty.
        /// </summary>
        /// <param name="jsonWriter">JsonWriter to write to.</param>
        /// <param name="settings">Writer settings.</param>
        /// <returns>A task that represents the asynchronous operation.</returns>
        internal static async Task StartJsonPaddingIfRequiredAsync(IJsonWriterAsync jsonWriter, ODataMessageWriterSettings settings)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter should not be null");

            if (settings.HasJsonPaddingFunction())
            {
                await jsonWriter.WritePaddingFunctionNameAsync(settings.JsonPCallback).ConfigureAwait(false);

                await jsonWriter.StartPaddingFunctionScopeAsync().ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Asynchronously writes the json array value.
        /// </summary>
        /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="arrayValue">Writes the json array value to the underlying json writer.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        private static async Task WriteJsonArrayValueAsync(this IJsonWriterAsync jsonWriter, IEnumerable arrayValue)
        {
            Debug.Assert(arrayValue != null, "arrayValue != null");

            await jsonWriter.StartArrayScopeAsync().ConfigureAwait(false);

            foreach (object element in arrayValue)
            {
                await jsonWriter.WriteJsonValueAsync(element).ConfigureAwait(false);
            }

            await jsonWriter.EndArrayScopeAsync().ConfigureAwait(false);
        }
Exemple #13
0
        /// <summary>
        /// Write an inner error property and message.
        /// </summary>
        /// <param name="jsonWriter">The JSON writer to write the error to.</param>
        /// <param name="innerError">Inner error details.</param>
        /// <param name="innerErrorPropertyName">The property name for the inner error property.</param>
        /// <param name="recursionDepth">The number of times this method has been called recursively.</param>
        /// <param name="maxInnerErrorDepth">The maximum number of nested inner errors to allow.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        private static async Task WriteInnerErrorAsync(IJsonWriterAsync jsonWriter, ODataInnerError innerError,
                                                       string innerErrorPropertyName, int recursionDepth, int maxInnerErrorDepth)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter != null");
            Debug.Assert(innerErrorPropertyName != null, "innerErrorPropertyName != null");

            ValidationUtils.IncreaseAndValidateRecursionDepth(ref recursionDepth, maxInnerErrorDepth);

            // "innererror":
            await jsonWriter.WriteNameAsync(innerErrorPropertyName).ConfigureAwait(false);

            await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false);

            if (innerError.Properties != null)
            {
                foreach (KeyValuePair <string, ODataValue> pair in innerError.Properties)
                {
                    await jsonWriter.WriteNameAsync(pair.Key).ConfigureAwait(false);

                    if (pair.Value is ODataNullValue &&
                        (pair.Key == JsonConstants.ODataErrorInnerErrorMessageName ||
                         pair.Key == JsonConstants.ODataErrorInnerErrorStackTraceName ||
                         pair.Key == JsonConstants.ODataErrorInnerErrorTypeNameName))
                    {
                        // Write empty string for null values in stacktrace, type and message properties of inner error.
                        await jsonWriter.WriteODataValueAsync(new ODataPrimitiveValue(string.Empty)).ConfigureAwait(false);
                    }
                    else
                    {
                        await jsonWriter.WriteODataValueAsync(pair.Value).ConfigureAwait(false);
                    }
                }
            }

            if (innerError.InnerError != null)
            {
                // "internalexception": { <nested inner error> }
                await WriteInnerErrorAsync(jsonWriter, innerError.InnerError, JsonConstants.ODataErrorInnerErrorInnerErrorName,
                                           recursionDepth, maxInnerErrorDepth).ConfigureAwait(false);
            }

            // }
            await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false);
        }
Exemple #14
0
        /// <summary>
        /// Asynchronously writes the error details.
        /// </summary>
        /// <param name="jsonWriter">JSON writer.</param>
        /// <param name="details">The details of the error.</param>
        /// <param name="odataErrorDetailsName">The property name for the error details property.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        private static async Task WriteErrorDetailsAsync(IJsonWriterAsync jsonWriter, IEnumerable <ODataErrorDetail> details,
                                                         string odataErrorDetailsName)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter != null");
            Debug.Assert(details != null, "details != null");
            Debug.Assert(odataErrorDetailsName != null, "odataErrorDetailsName != null");

            // "details": [
            await jsonWriter.WriteNameAsync(odataErrorDetailsName).ConfigureAwait(false);

            await jsonWriter.StartArrayScopeAsync().ConfigureAwait(false);

            foreach (var detail in details.Where(d => d != null))
            {
                // {
                await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false);

                // "code": "301",
                await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorCodeName).ConfigureAwait(false);

                await jsonWriter.WriteValueAsync(detail.ErrorCode ?? string.Empty).ConfigureAwait(false);

                if (detail.Target != null)
                {
                    // "target": "$search"
                    await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorTargetName).ConfigureAwait(false);

                    await jsonWriter.WriteValueAsync(detail.Target).ConfigureAwait(false);
                }

                // "message": "$search query option not supported",
                await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorMessageName).ConfigureAwait(false);

                await jsonWriter.WriteValueAsync(detail.Message ?? string.Empty).ConfigureAwait(false);

                // }
                await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false);
            }

            // ]
            await jsonWriter.EndArrayScopeAsync().ConfigureAwait(false);
        }
        /// <summary>
        /// Asynchronously writes the json object value to the <paramref name="jsonWriter"/>.
        /// </summary>
        /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="jsonObjectValue">Writes the given json object value to the underlying json writer.</param>
        /// <param name="injectPropertyDelegate">Called when the top-level object is started to possibly inject first property into the object.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        internal static async Task WriteJsonObjectValueAsync(
            this IJsonWriterAsync jsonWriter,
            IDictionary <string, object> jsonObjectValue,
            Func <IJsonWriterAsync, Task> injectPropertyDelegate)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter != null");
            Debug.Assert(jsonObjectValue != null, "jsonObjectValue != null");

            await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false);

            if (injectPropertyDelegate != null)
            {
                await injectPropertyDelegate(jsonWriter).ConfigureAwait(false);
            }

            foreach (KeyValuePair <string, object> property in jsonObjectValue)
            {
                await jsonWriter.WriteNameAsync(property.Key).ConfigureAwait(false);

                await jsonWriter.WriteJsonValueAsync(property.Value).ConfigureAwait(false);
            }

            await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false);
        }
        /// <summary>
        /// Asynchronously writes the ODataValue (primitive, collection or resource value) to the underlying json writer.
        /// </summary>
        /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="odataValue">value to write.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        internal static async Task WriteODataValueAsync(this IJsonWriterAsync jsonWriter, ODataValue odataValue)
        {
            if (odataValue == null || odataValue is ODataNullValue)
            {
                await jsonWriter.WriteValueAsync((string)null).ConfigureAwait(false);

                return;
            }

            object objectValue = odataValue.FromODataValue();

            if (EdmLibraryExtensions.IsPrimitiveType(objectValue.GetType()))
            {
                await jsonWriter.WritePrimitiveValueAsync(objectValue).ConfigureAwait(false);

                return;
            }

            ODataResourceValue resourceValue = odataValue as ODataResourceValue;

            if (resourceValue != null)
            {
                await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false);

                foreach (ODataProperty property in resourceValue.Properties)
                {
                    await jsonWriter.WriteNameAsync(property.Name).ConfigureAwait(false);

                    await jsonWriter.WriteODataValueAsync(property.ODataValue).ConfigureAwait(false);
                }

                await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false);

                return;
            }

            ODataCollectionValue collectionValue = odataValue as ODataCollectionValue;

            if (collectionValue != null)
            {
                await jsonWriter.StartArrayScopeAsync().ConfigureAwait(false);

                foreach (object item in collectionValue.Items)
                {
                    // Will not be able to accurately serialize complex objects unless they are ODataValues.
                    ODataValue collectionItem = item as ODataValue;
                    if (item != null)
                    {
                        await jsonWriter.WriteODataValueAsync(collectionItem).ConfigureAwait(false);
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.ODataJsonWriter_UnsupportedValueInCollection);
                    }
                }

                await jsonWriter.EndArrayScopeAsync().ConfigureAwait(false);

                return;
            }

            throw new ODataException(
                      ODataErrorStrings.ODataJsonWriter_UnsupportedValueType(odataValue.GetType().FullName));
        }
        /// <summary>
        /// Asynchronously writes the current Json object.
        /// </summary>
        /// <param name="reader">The Json reader providing the data.</param>
        /// <param name="jsonWriter">The Json writer writes data into memory stream.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        private static async Task WriteCurrentJsonObjectAsync(IJsonReaderAsync reader, IJsonWriterAsync jsonWriter)
        {
            Stack <JsonNodeType> nodeTypes = new Stack <JsonNodeType>();

            do
            {
                switch (reader.NodeType)
                {
                case JsonNodeType.PrimitiveValue:
                    object primitiveValue;

                    if ((primitiveValue = await reader.GetValueAsync().ConfigureAwait(false)) != null)
                    {
                        await jsonWriter.WritePrimitiveValueAsync(primitiveValue)
                        .ConfigureAwait(false);
                    }
                    else
                    {
                        await jsonWriter.WriteValueAsync((string)null)
                        .ConfigureAwait(false);
                    }

                    break;

                case JsonNodeType.Property:
                    object propertyName = await reader.GetValueAsync()
                                          .ConfigureAwait(false);

                    await jsonWriter.WriteNameAsync(propertyName.ToString())
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.StartObject:
                    nodeTypes.Push(reader.NodeType);
                    await jsonWriter.StartObjectScopeAsync()
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.StartArray:
                    nodeTypes.Push(reader.NodeType);
                    await jsonWriter.StartArrayScopeAsync()
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.EndObject:
                    Debug.Assert(nodeTypes.Peek() == JsonNodeType.StartObject);
                    nodeTypes.Pop();
                    await jsonWriter.EndObjectScopeAsync()
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.EndArray:
                    Debug.Assert(nodeTypes.Peek() == JsonNodeType.StartArray);
                    nodeTypes.Pop();
                    await jsonWriter.EndArrayScopeAsync()
                    .ConfigureAwait(false);

                    break;

                default:
                    throw new ODataException(Strings.ODataJsonLightBatchBodyContentReaderStream_UnexpectedNodeType(reader.NodeType));
                }

                await reader.ReadNextAsync()
                .ConfigureAwait(false);     // This can be EndOfInput, where nodeTypes should be empty.
            }while (nodeTypes.Count != 0);

            await jsonWriter.FlushAsync()
            .ConfigureAwait(false);
        }
        /// <summary>
        /// Writes the 'value' property name asynchronously.
        /// </summary>
        /// <param name="jsonWriter">The JSON writer to write to.</param>
        internal static Task WriteValuePropertyNameAsync(this IJsonWriterAsync jsonWriter)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter != null");

            return(jsonWriter.WriteNameAsync(JsonLightConstants.ODataValuePropertyName));
        }
 public JsonWriterAsyncTests()
 {
     this.builder = new StringBuilder();
     this.writer  = new JsonWriter(new StringWriter(builder), isIeee754Compatible: true);
 }
        /// <summary>
        /// Asynchronously writes a primitive value.
        /// </summary>
        /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="value">The value to write.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        internal static async Task WritePrimitiveValueAsync(this IJsonWriterAsync jsonWriter, object value)
        {
            if (value is bool)
            {
                await jsonWriter.WriteValueAsync((bool)value).ConfigureAwait(false);

                return;
            }

            if (value is byte)
            {
                await jsonWriter.WriteValueAsync((byte)value).ConfigureAwait(false);

                return;
            }

            if (value is decimal)
            {
                await jsonWriter.WriteValueAsync((decimal)value).ConfigureAwait(false);

                return;
            }

            if (value is double)
            {
                await jsonWriter.WriteValueAsync((double)value).ConfigureAwait(false);

                return;
            }

            if (value is Int16)
            {
                await jsonWriter.WriteValueAsync((Int16)value).ConfigureAwait(false);

                return;
            }

            if (value is Int32)
            {
                await jsonWriter.WriteValueAsync((Int32)value).ConfigureAwait(false);

                return;
            }

            if (value is Int64)
            {
                await jsonWriter.WriteValueAsync((Int64)value).ConfigureAwait(false);

                return;
            }

            if (value is sbyte)
            {
                await jsonWriter.WriteValueAsync((sbyte)value).ConfigureAwait(false);

                return;
            }

            if (value is Single)
            {
                await jsonWriter.WriteValueAsync((Single)value).ConfigureAwait(false);

                return;
            }

            var str = value as string;

            if (str != null)
            {
                await jsonWriter.WriteValueAsync(str).ConfigureAwait(false);

                return;
            }

            byte[] valueAsByteArray = value as byte[];
            if (valueAsByteArray != null)
            {
                await jsonWriter.WriteValueAsync(valueAsByteArray).ConfigureAwait(false);

                return;
            }

            if (value is DateTimeOffset)
            {
                await jsonWriter.WriteValueAsync((DateTimeOffset)value).ConfigureAwait(false);

                return;
            }

            if (value is Guid)
            {
                await jsonWriter.WriteValueAsync((Guid)value).ConfigureAwait(false);

                return;
            }

            if (value is TimeSpan)
            {
                await jsonWriter.WriteValueAsync((TimeSpan)value).ConfigureAwait(false);

                return;
            }

            if (value is Date)
            {
                await jsonWriter.WriteValueAsync((Date)value).ConfigureAwait(false);

                return;
            }

            if (value is TimeOfDay)
            {
                await jsonWriter.WriteValueAsync((TimeOfDay)value).ConfigureAwait(false);

                return;
            }

            throw new ODataException(ODataErrorStrings.ODataJsonWriter_UnsupportedValueType(value.GetType().FullName));
        }
Exemple #21
0
        /// <summary>
        /// Asynchronously writes an error message.
        /// </summary>
        /// <param name="jsonWriter">JSON writer.</param>
        /// <param name="code">The code of the error.</param>
        /// <param name="message">The message of the error.</param>
        /// <param name="target">The target of the error.</param>
        /// <param name="details">The details of the error.</param>
        /// <param name="innerError">Inner error details that will be included in debug mode (if present).</param>
        /// <param name="instanceAnnotations">Instance annotations for this error.</param>
        /// <param name="writeInstanceAnnotationsDelegate">Delegate to write the instance annotations.</param>
        /// <param name="maxInnerErrorDepth">The maximum number of nested inner errors to allow.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        private static async Task WriteErrorAsync(
            IJsonWriterAsync jsonWriter,
            string code,
            string message,
            string target,
            IEnumerable <ODataErrorDetail> details,
            ODataInnerError innerError,
            ICollection <ODataInstanceAnnotation> instanceAnnotations,
            Func <ICollection <ODataInstanceAnnotation>, Task> writeInstanceAnnotationsDelegate,
            int maxInnerErrorDepth)
        {
            Debug.Assert(jsonWriter != null, "jsonWriter != null");
            Debug.Assert(code != null, "code != null");
            Debug.Assert(message != null, "message != null");
            Debug.Assert(instanceAnnotations != null, "instanceAnnotations != null");

            ExceptionUtils.CheckArgumentNotNull(writeInstanceAnnotationsDelegate, "writeInstanceAnnotationsDelegate");

            // "error": {
            await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false);

            await jsonWriter.WriteNameAsync(JsonLightConstants.ODataErrorPropertyName).ConfigureAwait(false);

            await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false);

            // "code": "<code>"
            await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorCodeName).ConfigureAwait(false);

            await jsonWriter.WriteValueAsync(code).ConfigureAwait(false);

            // "message": "<message string>"
            await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorMessageName).ConfigureAwait(false);

            await jsonWriter.WriteValueAsync(message).ConfigureAwait(false);

            // For example, "target": "query",
            if (target != null)
            {
                await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorTargetName).ConfigureAwait(false);

                await jsonWriter.WriteValueAsync(target).ConfigureAwait(false);
            }

            // Such as, "details": [
            //  {
            //   "code": "301",
            //   "target": "$search",
            //   "message": "$search query option not supported"
            //  }]
            if (details != null)
            {
                await WriteErrorDetailsAsync(jsonWriter, details, JsonConstants.ODataErrorDetailsName).ConfigureAwait(false);
            }

            if (innerError != null)
            {
                await WriteInnerErrorAsync(jsonWriter, innerError, JsonConstants.ODataErrorInnerErrorName,
                                           /* recursionDepth */ 0, maxInnerErrorDepth).ConfigureAwait(false);
            }

            await writeInstanceAnnotationsDelegate(instanceAnnotations).ConfigureAwait(false);

            // } }
            await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false);

            await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false);
        }