Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ private static async Task<TransactionalBatchResponse> PopulateFromContentAsync(

HttpStatusCode responseStatusCode = responseMessage.StatusCode;
SubStatusCodes responseSubStatusCode = responseMessage.Headers.SubStatusCode;
string responseErrorMessage = responseMessage.ErrorMessage;

// Promote the operation error status as the Batch response error status if we have a MultiStatus response
// to provide users with status codes they are used to.
Expand All @@ -373,6 +374,16 @@ private static async Task<TransactionalBatchResponse> PopulateFromContentAsync(
{
responseStatusCode = result.StatusCode;
responseSubStatusCode = result.SubStatusCode;

if (result.ResourceStream != null)
{
using (StreamReader reader = new StreamReader(result.ResourceStream, encoding: System.Text.Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true))
{
responseErrorMessage = reader.ReadToEnd();
result.ResourceStream.Position = 0;
}
}

break;
}
}
Expand All @@ -381,7 +392,7 @@ private static async Task<TransactionalBatchResponse> PopulateFromContentAsync(
TransactionalBatchResponse response = new TransactionalBatchResponse(
responseStatusCode,
responseSubStatusCode,
responseMessage.ErrorMessage,
responseErrorMessage,
responseMessage.Headers,
trace,
serverRequest.Operations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,59 @@ public async Task BatchResponseDeserializationAsync()
Assert.IsTrue(comparer.Equals(results[1], batchResponse[1]));
}

private class ItemBatchOperationEqualityComparer : IEqualityComparer<ItemBatchOperation>
[TestMethod]
[Owner("nalutripician")]
public async Task BatchResponseDeserializationPromotesErrorMessageAsync()
{
string expectedErrorMessage = "{\"Errors\":[\"Resource with specified id or name already exists.\"]}";
byte[] errorBody = System.Text.Encoding.UTF8.GetBytes(expectedErrorMessage);

using CosmosClient cosmosClient = MockCosmosUtil.CreateMockCosmosClient();
ContainerInternal containerCore = (ContainerInlineCore)cosmosClient.GetDatabase("db").GetContainer("cont");
List<TransactionalBatchOperationResult> results = new List<TransactionalBatchOperationResult>
{
new TransactionalBatchOperationResult(HttpStatusCode.Conflict)
{
ResourceStream = new CloneableStream(
internalStream: new MemoryStream(errorBody, index: 0, count: errorBody.Length, writable: false, publiclyVisible: true),
allowUnsafeDataAccess: true),
},
new TransactionalBatchOperationResult(HttpStatusCode.FailedDependency)
};

MemoryStream responseContent = await new BatchResponsePayloadWriter(results).GeneratePayloadAsync();

SinglePartitionKeyServerBatchRequest batchRequest = await SinglePartitionKeyServerBatchRequest.CreateAsync(
partitionKey: Cosmos.PartitionKey.None,
operations: new ArraySegment<ItemBatchOperation>(
new ItemBatchOperation[]
{
new ItemBatchOperation(OperationType.Create, operationIndex: 0, id: "someId", containerCore: containerCore),
new ItemBatchOperation(OperationType.Create, operationIndex: 1, id: "someId2", containerCore: containerCore)
}),
serializerCore: MockCosmosUtil.Serializer,
trace: NoOpTrace.Singleton,
cancellationToken: CancellationToken.None);

ResponseMessage response = new ResponseMessage((HttpStatusCode)StatusCodes.MultiStatus) { Content = responseContent };
response.Headers.Session = Guid.NewGuid().ToString();
response.Headers.ActivityId = Guid.NewGuid().ToString();

TransactionalBatchResponse batchResponse = await TransactionalBatchResponse.FromResponseMessageAsync(
response,
batchRequest,
MockCosmosUtil.Serializer,
true,
NoOpTrace.Singleton,
CancellationToken.None);

Assert.IsNotNull(batchResponse);
Assert.AreEqual(HttpStatusCode.Conflict, batchResponse.StatusCode);
Assert.IsNotNull(batchResponse.ErrorMessage, "ErrorMessage should be promoted from the failing operation's ResourceStream");
Assert.AreEqual(expectedErrorMessage, batchResponse.ErrorMessage);
}

private class ItemBatchOperationEqualityComparer: IEqualityComparer<ItemBatchOperation>
{
public bool Equals(ItemBatchOperation x, ItemBatchOperation y)
{
Expand Down
Loading