private QueryResponse( IReadOnlyList <CosmosElement> result, int count, long responseLengthBytes, CosmosQueryResponseMessageHeaders responseHeaders, HttpStatusCode statusCode, RequestMessage requestMessage, CosmosDiagnosticsContext diagnostics, string errorMessage, Error error, Lazy <MemoryStream> memoryStream, CosmosSerializationFormatOptions serializationOptions) : base( statusCode: statusCode, requestMessage: requestMessage, errorMessage: errorMessage, error: error, headers: responseHeaders, diagnostics: diagnostics) { this.CosmosElements = result; this.Count = count; this.ResponseLengthBytes = responseLengthBytes; this.memoryStream = memoryStream; this.CosmosSerializationOptions = serializationOptions; }
internal static QueryResponse CreateSuccess( IReadOnlyList <CosmosElement> result, int count, long responseLengthBytes, CosmosQueryResponseMessageHeaders responseHeaders, CosmosDiagnosticsContext diagnostics, CosmosSerializationFormatOptions serializationOptions) { if (count < 0) { throw new ArgumentOutOfRangeException("count must be positive"); } if (responseLengthBytes < 0) { throw new ArgumentOutOfRangeException("responseLengthBytes must be positive"); } Lazy <MemoryStream> memoryStream = new Lazy <MemoryStream>(() => CosmosElementSerializer.ToStream( responseHeaders.ContainerRid, result, responseHeaders.ResourceType, serializationOptions)); QueryResponse cosmosQueryResponse = new QueryResponse( result: result, count: count, responseLengthBytes: responseLengthBytes, responseHeaders: responseHeaders, diagnostics: diagnostics, statusCode: HttpStatusCode.OK, errorMessage: null, error: null, requestMessage: null, memoryStream: memoryStream, serializationOptions: serializationOptions); return(cosmosQueryResponse); }
private QueryResponse( IReadOnlyList <CosmosElement> result, int count, long responseLengthBytes, CosmosQueryResponseMessageHeaders responseHeaders, HttpStatusCode statusCode, RequestMessage requestMessage, CosmosException cosmosException, Lazy <MemoryStream> memoryStream, CosmosSerializationFormatOptions serializationOptions, ITrace trace) : base( statusCode: statusCode, requestMessage: requestMessage, cosmosException: cosmosException, headers: responseHeaders, trace: trace) { this.CosmosElements = result; this.Count = count; this.ResponseLengthBytes = responseLengthBytes; this.memoryStream = memoryStream; this.CosmosSerializationOptions = serializationOptions; }
/// <summary> /// Converts a list of CosmosElements into a memory stream. /// </summary> /// <param name="stream">The memory stream response for the query REST response Azure Cosmos</param> /// <param name="resourceType">The resource type</param> /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param> /// <returns>An array of CosmosElements parsed from the response body.</returns> public static CosmosArray ParseElementsFromRestStream( Stream stream, ResourceType resourceType, CosmosSerializationFormatOptions cosmosSerializationOptions) { if (!(stream is MemoryStream memoryStream)) { memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); } if (!memoryStream.CanRead) { throw new InvalidDataException("Stream can not be read"); } // Parse out the document from the REST response like this: // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // You want to create a CosmosElement for each document in "Documents". ReadOnlyMemory <byte> content; if (memoryStream.TryGetBuffer(out ArraySegment <byte> buffer)) { content = buffer; } else { content = memoryStream.ToArray(); } IJsonNavigator jsonNavigator; if (cosmosSerializationOptions != null) { // Use the users custom navigator jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = resourceType switch { ResourceType.Collection => "DocumentCollections", _ => resourceType.ToResourceTypeString() + "s", }; if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } if (!(CosmosElement.Dispatch( jsonNavigator, objectProperty.ValueNode) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } return(cosmosArray); }
/// <summary> /// Converts a list of CosmosElements into a memory stream. /// </summary> /// <param name="memoryStream">The memory stream response for the query REST response Azure Cosmos</param> /// <param name="resourceType">The resource type</param> /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param> /// <returns>An array of CosmosElements parsed from the response body.</returns> private static CosmosArray ParseElementsFromRestStream( MemoryStream memoryStream, ResourceType resourceType, CosmosSerializationFormatOptions cosmosSerializationOptions) { if (!memoryStream.CanRead) { throw new InvalidDataException("Stream can not be read"); } // Parse out the document from the REST response this: // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // You want to create a CosmosElement for each document in "Documents". ReadOnlyMemory <byte> content; if (memoryStream.TryGetBuffer(out ArraySegment <byte> buffer)) { content = buffer; } else { content = memoryStream.ToArray(); } IJsonNavigator jsonNavigator; if (cosmosSerializationOptions != null) { // Use the users custom navigator jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = resourceType switch { ResourceType.Collection => "DocumentCollections", _ => resourceType.ToResourceTypeString() + "s", }; CosmosArray documents; if ((jsonNavigator.SerializationFormat == JsonSerializationFormat.Binary) && jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), "stringDictionary", out ObjectProperty stringDictionaryProperty)) { // Payload is string dictionary encode so we have to decode using the string dictionary. IJsonNavigatorNode stringDictionaryNode = stringDictionaryProperty.ValueNode; JsonStringDictionary jsonStringDictionary = JsonStringDictionary.CreateFromStringArray( jsonNavigator .GetArrayItems(stringDictionaryNode) .Select(item => jsonNavigator.GetStringValue(item)) .ToList()); if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty resourceProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } IJsonNavigatorNode resources = resourceProperty.ValueNode; if (!jsonNavigator.TryGetBufferedBinaryValue(resources, out ReadOnlyMemory <byte> resourceBinary)) { resourceBinary = jsonNavigator.GetBinaryValue(resources); } IJsonNavigator navigatorWithStringDictionary = JsonNavigator.Create(resourceBinary, jsonStringDictionary); if (!(CosmosElement.Dispatch( navigatorWithStringDictionary, navigatorWithStringDictionary.GetRootNode()) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } documents = cosmosArray; } else { // Payload is not string dictionary encoded so we can just do for the documents as is. if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } if (!(CosmosElement.Dispatch( jsonNavigator, objectProperty.ValueNode) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } documents = cosmosArray; } return(documents); }