public async Task <ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage, bool includeResourceTypeInEntryProperties = false) #endif { var readerSettings = new ODataMessageReaderSettings(); readerSettings.MessageQuotas.MaxReceivedMessageSize = Int32.MaxValue; using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind(); if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return(ODataResponse.FromStatusCode(responseMessage.StatusCode)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { #if SILVERLIGHT var text = Utils.StreamToString(responseMessage.GetStream()); #else var text = Client.Utils.StreamToString(await responseMessage.GetStreamAsync()); #endif return(ODataResponse.FromFeed(new[] { new Dictionary <string, object>() { { FluentCommand.ResultLiteral, text } } })); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return(await ReadResponse(messageReader.CreateODataBatchReader(), includeResourceTypeInEntryProperties)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Feed)) { return(ReadResponse(messageReader.CreateODataFeedReader(), includeResourceTypeInEntryProperties)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return(ReadResponse(messageReader.CreateODataCollectionReader(), includeResourceTypeInEntryProperties)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { var property = messageReader.ReadProperty(); return(ODataResponse.FromFeed(new[] { new Dictionary <string, object>() { { property.Name ?? FluentCommand.ResultLiteral, GetPropertyValue(property.Value) } } })); } else { return(ReadResponse(messageReader.CreateODataEntryReader(), includeResourceTypeInEntryProperties)); } } }
/// <inheritdoc/> public override async Task ProcessBatchAsync(HttpContext context, RequestDelegate nextHandler) { if (context == null) { throw Error.ArgumentNull("context"); } if (nextHandler == null) { throw Error.ArgumentNull("nextHandler"); } if (!await ValidateRequest(context.Request)) { return; } // This container is for the overall batch request. HttpRequest request = context.Request; IServiceProvider requestContainer = request.CreateRequestContainer(ODataRouteName); requestContainer.GetRequiredService <ODataMessageReaderSettings>().BaseUri = GetBaseUri(request); ODataMessageReader reader = request.GetODataMessageReader(requestContainer); ODataBatchReader batchReader = reader.CreateODataBatchReader(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); Guid batchId = Guid.NewGuid(); ODataOptions options = context.RequestServices.GetRequiredService <ODataOptions>(); bool enableContinueOnErrorHeader = (options != null) ? options.EnableContinueOnErrorHeader : false; SetContinueOnError(new WebApiRequestHeaders(request.Headers), enableContinueOnErrorHeader); while (batchReader.Read()) { ODataBatchResponseItem responseItem = null; if (batchReader.State == ODataBatchReaderState.ChangesetStart) { responseItem = await ExecuteChangeSetAsync(batchReader, batchId, request, nextHandler); } else if (batchReader.State == ODataBatchReaderState.Operation) { responseItem = await ExecuteOperationAsync(batchReader, batchId, request, nextHandler); } if (responseItem != null) { responses.Add(responseItem); if (responseItem.IsResponseSuccessful() == false && ContinueOnError == false) { break; } } } await CreateResponseMessageAsync(responses, request); }
/// <inheritdoc/> public override async Task <HttpResponseMessage> ProcessBatchAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw Error.ArgumentNull("request"); } ValidateRequest(request); ODataMessageReaderSettings oDataReaderSettings = new ODataMessageReaderSettings { DisableMessageStreamDisposal = true, MessageQuotas = MessageQuotas, BaseUri = GetBaseUri(request) }; ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(oDataReaderSettings, cancellationToken); request.RegisterForDispose(reader); ODataBatchReader batchReader = reader.CreateODataBatchReader(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); Guid batchId = Guid.NewGuid(); List <IDisposable> resourcesToDispose = new List <IDisposable>(); try { while (batchReader.Read()) { ODataBatchResponseItem responseItem = null; if (batchReader.State == ODataBatchReaderState.ChangesetStart) { responseItem = await ExecuteChangeSetAsync(batchReader, batchId, request, cancellationToken); } else if (batchReader.State == ODataBatchReaderState.Operation) { responseItem = await ExecuteOperationAsync(batchReader, batchId, request, cancellationToken); } if (responseItem != null) { responses.Add(responseItem); } } } catch { foreach (ODataBatchResponseItem response in responses) { if (response != null) { response.Dispose(); } } throw; } return(await CreateResponseMessageAsync(responses, request, cancellationToken)); }
public async Task <ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage) { if (responseMessage.StatusCode == (int)HttpStatusCode.NoContent) { return(ODataResponse.FromStatusCode(TypeCache, responseMessage.StatusCode, responseMessage.Headers)); } var readerSettings = _session.ToReaderSettings(); using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind().ToList(); if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return(ODataResponse.FromStatusCode(TypeCache, responseMessage.StatusCode, responseMessage.Headers)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { return(ODataResponse.FromValueStream(TypeCache, await responseMessage.GetStreamAsync().ConfigureAwait(false), responseMessage is ODataBatchOperationResponseMessage)); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return(await ReadResponse(messageReader.CreateODataBatchReader()).ConfigureAwait(false)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.ResourceSet)) { return(ReadResponse(messageReader.CreateODataResourceSetReader(), responseMessage)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return(ReadResponse(messageReader.CreateODataCollectionReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Resource)) { return(ReadResponse(messageReader.CreateODataResourceReader(), responseMessage)); } else { var property = messageReader.ReadProperty(); return(ODataResponse.FromProperty(TypeCache, property.Name, GetPropertyValue(property.Value))); } } else { return(ReadResponse(messageReader.CreateODataResourceReader(), responseMessage)); } } }
public async Task CanHandleSingleDeleteInBatch() { // Arrange var requestUri = string.Format("{0}/UnbufferedBatch/$batch", this.BaseAddress); // Act HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri); request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json")); HttpContent content = new StringContent(@" { ""requests"": [ { ""Id"": ""1"", ""method"": ""DELETE"", ""headers"": { ""odata-version"": ""4.01"", ""content-type"": ""application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false"" }, ""url"": ""DefaultBatchCustomer(5)"", ""body"": """" } ] }"); content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); request.Content = content; HttpResponseMessage response = await Client.SendAsync(request); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var stream = await response.Content.ReadAsStreamAsync(); Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType.ToString()); IODataResponseMessage odataResponseMessage = new ODataMessageWrapper(stream, response.Content.Headers); int subResponseCount = 0; using (var messageReader = new ODataMessageReader(odataResponseMessage, new ODataMessageReaderSettings(), GetEdmModel(new ODataConventionModelBuilder()))) { var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: var operationMessage = batchReader.CreateOperationResponseMessage(); subResponseCount++; break; } } } Assert.Equal(1, subResponseCount); }
/// <summary> /// Asynchronously parses the batch requests. /// </summary> /// <param name="request">The HTTP request that contains the batch requests.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task object that represents this asynchronous operation.</returns> public override async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync( HttpRequestMessage request, CancellationToken cancellationToken) { if (this.ApiFactory == null) { throw new InvalidOperationException(Resources.BatchHandlerRequiresApiContextFactory); } Ensure.NotNull(request, "request"); ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings { DisableMessageStreamDisposal = true, MessageQuotas = MessageQuotas, BaseUri = GetBaseUri(request) }; ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(readerSettings, cancellationToken); request.RegisterForDispose(reader); List <ODataBatchRequestItem> requests = new List <ODataBatchRequestItem>(); ODataBatchReader batchReader = reader.CreateODataBatchReader(); Guid batchId = Guid.NewGuid(); while (batchReader.Read()) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { IList <HttpRequestMessage> changeSetRequests = await batchReader.ReadChangeSetRequestAsync(batchId, cancellationToken); foreach (HttpRequestMessage changeSetRequest in changeSetRequests) { changeSetRequest.CopyBatchRequestProperties(request); } requests.Add(this.CreateChangeSetRequestItem(changeSetRequests)); } else if (batchReader.State == ODataBatchReaderState.Operation) { HttpRequestMessage operationRequest = await batchReader.ReadOperationRequestAsync( batchId, bufferContentStream : true, cancellationToken : cancellationToken); operationRequest.CopyBatchRequestProperties(request); requests.Add(new OperationRequestItem(operationRequest)); } } return(requests); }
public async Task<ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage, bool includeResourceTypeInEntryProperties = false) { var readerSettings = new ODataMessageReaderSettings(); readerSettings.MessageQuotas.MaxReceivedMessageSize = Int32.MaxValue; using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind(); if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return ODataResponse.FromStatusCode(responseMessage.StatusCode); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { var text = Utils.StreamToString(await responseMessage.GetStreamAsync()); return ODataResponse.FromFeed(new[] { new Dictionary<string, object>() { { FluentCommand.ResultLiteral, text } } }); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return await ReadResponse(messageReader.CreateODataBatchReader(), includeResourceTypeInEntryProperties); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Feed)) { return ReadResponse(messageReader.CreateODataFeedReader(), includeResourceTypeInEntryProperties); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return ReadResponse(messageReader.CreateODataCollectionReader(), includeResourceTypeInEntryProperties); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { var property = messageReader.ReadProperty(); return ODataResponse.FromFeed(new[] { new Dictionary<string, object>() { { property.Name ?? FluentCommand.ResultLiteral, GetPropertyValue(property.Value) } } }); } else { return ReadResponse(messageReader.CreateODataEntryReader(), includeResourceTypeInEntryProperties); } } }
public async Task <ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage) { var readerSettings = new ODataMessageReaderSettings(); // TODO ODataLib7 if (_session.Settings.IgnoreUnmappedProperties) { readerSettings.Validations &= ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; } readerSettings.MessageQuotas.MaxReceivedMessageSize = Int32.MaxValue; readerSettings.ShouldIncludeAnnotation = x => _session.Settings.IncludeAnnotationsInResults; using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind(); if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return(ODataResponse.FromStatusCode(responseMessage.StatusCode)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { return(ODataResponse.FromValueStream(await responseMessage.GetStreamAsync().ConfigureAwait(false), responseMessage is ODataBatchOperationResponseMessage)); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return(await ReadResponse(messageReader.CreateODataBatchReader()).ConfigureAwait(false)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.ResourceSet)) { return(ReadResponse(messageReader.CreateODataResourceSetReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return(ReadResponse(messageReader.CreateODataCollectionReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { var property = messageReader.ReadProperty(); return(ODataResponse.FromProperty(property.Name, GetPropertyValue(property.Value))); } else { return(ReadResponse(messageReader.CreateODataResourceReader())); } } }
public void ExecuteChangeSetAsync_CopiesPropertiesFromRequest_WithoutExcludedProperties() { MockHttpServer server = new MockHttpServer(request => { return(new HttpResponseMessage { RequestMessage = request }); }); UnbufferedODataBatchHandler batchHandler = new UnbufferedODataBatchHandler(server); HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, "http://example.com/$batch") { Content = new MultipartContent("mixed") { new MultipartContent("mixed") // ChangeSet { ODataBatchRequestHelper.CreateODataRequestContent(new HttpRequestMessage(HttpMethod.Post, "http://example.com/values") { Content = new StringContent("foo") }) } } }; batchRequest.Properties.Add("foo", "bar"); batchRequest.SetRouteData(new HttpRouteData(new HttpRoute())); batchRequest.RegisterForDispose(new StringContent(String.Empty)); ODataMessageReader reader = batchRequest.Content .GetODataMessageReaderAsync(new ODataMessageReaderSettings { BaseUri = new Uri("http://example.com") }, CancellationToken.None) .Result; ODataBatchReader batchReader = reader.CreateODataBatchReader(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); Guid batchId = Guid.NewGuid(); batchReader.Read(); var response = batchHandler.ExecuteChangeSetAsync(batchReader, Guid.NewGuid(), batchRequest, CancellationToken.None).Result; var changeSetResponses = ((ChangeSetResponseItem)response).Responses; foreach (var changeSetResponse in changeSetResponses) { var changeSetRequest = changeSetResponse.RequestMessage; Assert.Equal("bar", changeSetRequest.Properties["foo"]); Assert.Null(changeSetRequest.GetRouteData()); Assert.Same(changeSetRequest, changeSetRequest.GetUrlHelper().Request); Assert.Empty(changeSetRequest.GetResourcesForDisposal()); } }
public async Task ReadOperationRequest_InvalidState_Throws() { // Arrange StringContent httpContent = new StringContent(String.Empty, Encoding.UTF8, "multipart/mixed"); httpContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("boundary", Guid.NewGuid().ToString())); ODataMessageReader reader = await httpContent.GetODataMessageReaderAsync(new ODataMessageReaderSettings(), CancellationToken.None); Mock <HttpContext> mockContext = new Mock <HttpContext>(); // Act & Assert ExceptionAssert.Throws <InvalidOperationException>( () => ODataBatchReaderExtensions.ReadOperationRequestAsync(reader.CreateODataBatchReader(), mockContext.Object, Guid.NewGuid(), CancellationToken.None), "The current batch reader state 'Initial' is invalid. The expected state is 'Operation'."); }
public async Task ExecuteOperation_Throws_IfRequestIsNull() { // Arrange StringContent httpContent = new StringContent(string.Empty, Encoding.UTF8, "multipart/mixed"); httpContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("boundary", Guid.NewGuid().ToString())); ODataMessageReader reader = await httpContent.GetODataMessageReaderAsync(new ODataMessageReaderSettings(), CancellationToken.None); UnbufferedODataBatchHandler batchHandler = new UnbufferedODataBatchHandler(); // Act & Assert await ExceptionAssert.ThrowsArgumentNullAsync( () => batchHandler.ExecuteOperationAsync(reader.CreateODataBatchReader(), Guid.NewGuid(), null, null), "originalRequest"); }
public async Task <ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage) { var readerSettings = new ODataMessageReaderSettings(); readerSettings.MessageQuotas.MaxReceivedMessageSize = Int32.MaxValue; readerSettings.ShouldIncludeAnnotation = x => _session.Settings.IncludeAnnotationsInResults; using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind(); if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return(ODataResponse.FromStatusCode(responseMessage.StatusCode)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { return(ODataResponse.FromValueStream(await responseMessage.GetStreamAsync(), responseMessage is ODataBatchOperationResponseMessage)); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return(await ReadResponse(messageReader.CreateODataBatchReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Feed)) { return(ReadResponse(messageReader.CreateODataFeedReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return(ReadResponse(messageReader.CreateODataCollectionReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { var property = messageReader.ReadProperty(); return(ODataResponse.FromProperty(property.Name, GetPropertyValue(property.Value))); } else { return(ReadResponse(messageReader.CreateODataEntryReader())); } } }
private void ClientReadBatchResponse(byte[] responsePayload, string expectedAtomicGroupId, string expectedAtomicGroupAId) { IODataResponseMessage responseMessage = new InMemoryMessage() { Stream = new MemoryStream(responsePayload) }; responseMessage.SetHeader("Content-Type", batchContentTypeApplicationJson); using (var messageReader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), this.userModel)) { var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: ODataBatchOperationResponseMessage operationMessage = batchReader.CreateOperationResponseMessage(); string responseId = operationMessage.ContentId; if (responseId.Equals("1") || responseId.Equals("2")) { // Verify the group id of the responses is correlated to the group id from the data modification requests. Assert.Equal(operationMessage.GroupId, expectedAtomicGroupId); Assert.True(operationMessage.StatusCode == 201 || operationMessage.StatusCode == 204); } else if (responseId.Equals("1A") || responseId.Equals("2A")) { // Verify the group id of the responses is correlated to the group id from the data modification requests. Assert.Equal(operationMessage.GroupId, expectedAtomicGroupAId); Assert.True(operationMessage.StatusCode == 201 || operationMessage.StatusCode == 204); } else if (responseId.Equals("3") || responseId.Equals("3A")) { // Verify the group id of the query response. Assert.Null(operationMessage.GroupId); } else { Assert.True(false, "Unexpected response id received: " + responseId); } break; default: break; } } } }
/// <summary> /// Asynchronously parses the batch requests. /// </summary> /// <param name="request">The HTTP request that contains the batch requests.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task object that represents this asynchronous operation.</returns> public override async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync( HttpRequestMessage request, CancellationToken cancellationToken) { Ensure.NotNull(request, "request"); IServiceProvider requestContainer = request.CreateRequestContainer(ODataRouteName); requestContainer.GetRequiredService <ODataMessageReaderSettings>().BaseUri = GetBaseUri(request); ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(requestContainer, cancellationToken); request.RegisterForDispose(reader); List <ODataBatchRequestItem> requests = new List <ODataBatchRequestItem>(); ODataBatchReader batchReader = reader.CreateODataBatchReader(); Guid batchId = Guid.NewGuid(); while (batchReader.Read()) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { IList <HttpRequestMessage> changeSetRequests = await batchReader.ReadChangeSetRequestAsync(batchId, cancellationToken); foreach (HttpRequestMessage changeSetRequest in changeSetRequests) { changeSetRequest.CopyBatchRequestProperties(request); changeSetRequest.DeleteRequestContainer(false); } requests.Add(this.CreateRestierBatchChangeSetRequestItem(changeSetRequests)); } else if (batchReader.State == ODataBatchReaderState.Operation) { HttpRequestMessage operationRequest = await batchReader.ReadOperationRequestAsync( batchId, true, cancellationToken); operationRequest.CopyBatchRequestProperties(request); operationRequest.DeleteRequestContainer(false); requests.Add(new OperationRequestItem(operationRequest)); } } return(requests); }
private void ClientReadSingletonBatchResponse(byte[] responsePayload, string batchContentType) { IODataResponseMessage responseMessage = new InMemoryMessage() { Stream = new MemoryStream(responsePayload) }; responseMessage.SetHeader("Content-Type", batchContentType); using (ODataMessageReader messageReader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), this.userModel)) { ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a change set) ODataBatchOperationResponseMessage operationMessage = batchReader.CreateOperationResponseMessage(); if (operationMessage.StatusCode == 200) { using (ODataMessageReader innerMessageReader = new ODataMessageReader(operationMessage, new ODataMessageReaderSettings(), this.userModel)) { ODataReader reader = innerMessageReader.CreateODataResourceReader(); while (reader.Read()) { if (reader.State == ODataReaderState.ResourceEnd) { ODataResource entry = reader.Item as ODataResource; Assert.Equal(10, entry.Properties.Single(p => p.Name == "WebId").Value); Assert.Equal("WebSingleton", entry.Properties.Single(p => p.Name == "Name").Value); } } } // The only two messages with HTTP-200 response codes are the two GET requests with content id value of null. // Verify that: for multipart batch the content id of the response is matching that of the request; // for Json batch the content id of the response is not null. Assert.True( (batchReader is ODataJsonLightBatchReader && operationMessage.ContentId != null) || (batchReader is ODataMultipartMixedBatchReader && operationMessage.ContentId == null)); } break; } } } }
public virtual async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw Error.ArgumentNull("request"); } ODataMessageReaderSettings oDataReaderSettings = new ODataMessageReaderSettings { DisableMessageStreamDisposal = true, MessageQuotas = MessageQuotas, BaseUri = GetBaseUri(request) }; cancellationToken.ThrowIfCancellationRequested(); ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(oDataReaderSettings); request.RegisterForDispose(reader); List <ODataBatchRequestItem> requests = new List <ODataBatchRequestItem>(); ODataBatchReader batchReader = reader.CreateODataBatchReader(); Guid batchId = Guid.NewGuid(); while (batchReader.Read()) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { IList <HttpRequestMessage> changeSetRequests = await batchReader.ReadChangeSetRequestAsync(batchId, cancellationToken); foreach (HttpRequestMessage changeSetRequest in changeSetRequests) { changeSetRequest.CopyBatchRequestProperties(request); } requests.Add(new ChangeSetRequestItem(changeSetRequests)); } else if (batchReader.State == ODataBatchReaderState.Operation) { HttpRequestMessage operationRequest = await batchReader.ReadOperationRequestAsync(batchId, bufferContentStream : true, cancellationToken : cancellationToken); operationRequest.CopyBatchRequestProperties(request); requests.Add(new OperationRequestItem(operationRequest)); } } return(requests); }
private void ClientReadAsyncBatchResponse(byte[] responsePayload) { IODataResponseMessage responseMessage = new InMemoryMessage() { Stream = new MemoryStream(responsePayload) }; responseMessage.SetHeader("Content-Type", batchContentType); using (var messageReader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), this.userModel)) { var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a changeset) var operationMessage = batchReader.CreateOperationResponseMessage(); if (operationMessage.StatusCode == 200) { using (ODataMessageReader innerMessageReader = new ODataMessageReader(operationMessage, new ODataMessageReaderSettings(), this.userModel)) { var reader = innerMessageReader.CreateODataResourceReader(); while (reader.Read()) { if (reader.State == ODataReaderState.ResourceEnd) { ODataResource entry = reader.Item as ODataResource; Assert.Equal("ALFKI", entry.Properties.Single(p => p.Name == "Id").Value); Assert.Equal("John", entry.Properties.Single(p => p.Name == "Name").Value); } } } } else { Assert.Equal(202, operationMessage.StatusCode); } break; } } } }
public virtual async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync(HttpContext context) { if (context == null) { throw Error.ArgumentNull("context"); } HttpRequest request = context.Request; IServiceProvider requestContainer = request.CreateRequestContainer(ODataRouteName); requestContainer.GetRequiredService <ODataMessageReaderSettings>().BaseUri = GetBaseUri(request); ODataMessageReader reader = request.GetODataMessageReader(requestContainer); CancellationToken cancellationToken = context.RequestAborted; List <ODataBatchRequestItem> requests = new List <ODataBatchRequestItem>(); ODataBatchReader batchReader = reader.CreateODataBatchReader(); Guid batchId = Guid.NewGuid(); while (batchReader.Read()) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { IList <HttpContext> changeSetContexts = await batchReader.ReadChangeSetRequestAsync(context, batchId, cancellationToken); foreach (HttpContext changeSetContext in changeSetContexts) { changeSetContext.Request.CopyBatchRequestProperties(request); changeSetContext.Request.DeleteRequestContainer(false); } requests.Add(new ChangeSetRequestItem(changeSetContexts)); } else if (batchReader.State == ODataBatchReaderState.Operation) { HttpContext operationContext = await batchReader.ReadOperationRequestAsync(context, batchId, true, cancellationToken); operationContext.Request.CopyBatchRequestProperties(request); operationContext.Request.DeleteRequestContainer(false); requests.Add(new OperationRequestItem(operationContext)); } } return(requests); }
private void ClientReadBatchResponse(byte[] responsePayload, BodyContentType bodyContentType) { IODataResponseMessage responseMessage = new InMemoryMessage() { Stream = new MemoryStream(responsePayload) }; responseMessage.SetHeader(ODataConstants.ContentTypeHeader, batchContentTypeApplicationJson); using (ODataMessageReader messageReader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), null)) { ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a change set) ODataBatchOperationResponseMessage operationMessage = batchReader.CreateOperationResponseMessage(); if (operationMessage.StatusCode == 200) { using (Stream operationMessageBody = operationMessage.GetStream()) { // Verify the bytes in the response body. byte[] sampleBytes = bodyContentType == BodyContentType.Textual ? Encoding.UTF8.GetBytes("\"" + this.textualSampleStringB + "\"") : this.binarySampleBytesB; Assert.Equal(operationMessageBody.Length, sampleBytes.Length); foreach (byte samplebyte in sampleBytes) { Assert.Equal(samplebyte, operationMessageBody.ReadByte()); } } } else { Assert.True(201 == operationMessage.StatusCode); } break; } } } }
private void ClientReadBatchResponse(string batchContentType, byte[] responsePayload) { Debug.Assert(!string.IsNullOrEmpty(batchContentType), "!string.IsNullOrEmpty(batchContentType)"); IODataResponseMessage responseMessage = new InMemoryMessage() { Stream = new MemoryStream(responsePayload) }; responseMessage.SetHeader("Content-Type", batchContentType); using (var messageReader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), this.userModel)) { var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: ODataBatchOperationResponseMessage operationMessage = batchReader.CreateOperationResponseMessage(); if (operationMessage.StatusCode == 200) { using (ODataMessageReader innerMessageReader = new ODataMessageReader( operationMessage, new ODataMessageReaderSettings(), this.userModel)) { ODataReader reader = innerMessageReader.CreateODataResourceReader(); while (reader.Read()) { } } } break; default: break; } } } }
private void ServiceProcessBatchRequest(ODataJsonBatchPayloadTestCase testCase, ODataVersion version) { string requestPayload = testCase.RequestPayload; ODataJsonBatchPayloadTestCase.ValidateContentType requestMessageContentTypeVerifier = testCase.ContentTypeVerifier; IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(Encoding.ASCII.GetBytes(requestPayload)) }; requestMessage.SetHeader("Content-Type", batchContentTypeApplicationJson); using (ODataMessageReader messageReader = new ODataMessageReader(requestMessage, new ODataMessageReaderSettings() { Version = version, BaseUri = new Uri("http://odata.org") }, this.edmModel)) { ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); int operationIdx = 0; while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: ODataBatchOperationRequestMessage operationMessage = batchReader.CreateOperationRequestMessage(); // Verify operation message content type processing. requestMessageContentTypeVerifier.Invoke(operationMessage, operationIdx); operationIdx++; break; } } } }
public void ExecuteChangeSetAsync_ReturnsSingleErrorResponse() { MockHttpServer server = new MockHttpServer(request => { if (request.Method == HttpMethod.Post) { return(Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest))); } return(Task.FromResult(new HttpResponseMessage())); }); UnbufferedODataBatchHandler batchHandler = new UnbufferedODataBatchHandler(server); HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, "http://example.com/$batch") { Content = new MultipartContent("mixed") { new MultipartContent("mixed") // ChangeSet { ODataBatchRequestHelper.CreateODataRequestContent(new HttpRequestMessage(HttpMethod.Put, "http://example.com/values")), ODataBatchRequestHelper.CreateODataRequestContent(new HttpRequestMessage(HttpMethod.Post, "http://example.com/values")), ODataBatchRequestHelper.CreateODataRequestContent(new HttpRequestMessage(HttpMethod.Delete, "http://example.com/values")), } } }; ODataMessageReader reader = batchRequest.Content .GetODataMessageReaderAsync(new ODataMessageReaderSettings { BaseUri = new Uri("http://example.com") }, CancellationToken.None) .Result; ODataBatchReader batchReader = reader.CreateODataBatchReader(); var response = batchHandler.ExecuteChangeSetAsync(batchReader, Guid.NewGuid(), batchRequest, CancellationToken.None).Result; var changesetResponse = Assert.IsType <ChangeSetResponseItem>(response); Assert.Equal(1, changesetResponse.Responses.Count()); Assert.Equal(HttpStatusCode.BadRequest, changesetResponse.Responses.First().StatusCode); }
public static OeBatchMessage CreateBatchMessage(OeMessageContext context, Stream requestStream, String contentType) { IODataRequestMessage requestMessage = new OeInMemoryMessage(requestStream, contentType); var settings = new ODataMessageReaderSettings() { EnableMessageStreamDisposal = false }; using (var messageReader = new ODataMessageReader(requestMessage, settings)) { var batchMessage = new List <OeBatchMessage>(); ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { var operations = new List <OeOperationMessage>(); while (batchReader.Read() && batchReader.State != ODataBatchReaderState.ChangesetEnd) { if (batchReader.State == ODataBatchReaderState.Operation) { OeOperationMessage operation = OeOperationMessage.Create(context, batchReader); operations.Add(operation); } } return(new OeBatchMessage(contentType, operations)); } else if (batchReader.State == ODataBatchReaderState.Operation) { OeOperationMessage operation = OeOperationMessage.Create(context, batchReader); return(new OeBatchMessage(contentType, operation)); } } } throw new InvalidOperationException("batch not found"); }
public virtual async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync(HttpRequestMessage request) { if (request == null) { throw Error.ArgumentNull("request"); } ODataMessageReaderSettings oDataReaderSettings = new ODataMessageReaderSettings { DisableMessageStreamDisposal = true, MessageQuotas = MessageQuotas, BaseUri = GetBaseUri(request) }; ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(oDataReaderSettings); request.RegisterForDispose(reader); List <ODataBatchRequestItem> requests = new List <ODataBatchRequestItem>(); ODataBatchReader batchReader = reader.CreateODataBatchReader(); Guid batchId = Guid.NewGuid(); while (batchReader.Read()) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { requests.Add(new ChangeSetRequestItem(await batchReader.ReadChangeSetRequestAsync(batchId))); } else if (batchReader.State == ODataBatchReaderState.Operation) { requests.Add(new OperationRequestItem(await batchReader.ReadOperationRequestAsync(batchId, bufferContentStream: true))); } } return(requests); }
/// <inheritdoc/> public override async Task <HttpResponseMessage> ProcessBatchAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw Error.ArgumentNull("request"); } ValidateRequest(request); ODataMessageReaderSettings oDataReaderSettings = new ODataMessageReaderSettings { DisableMessageStreamDisposal = true, MessageQuotas = MessageQuotas, BaseUri = GetBaseUri(request) }; ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(oDataReaderSettings, cancellationToken); request.RegisterForDispose(reader); ODataBatchReader batchReader = reader.CreateODataBatchReader(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); Guid batchId = Guid.NewGuid(); List <IDisposable> resourcesToDispose = new List <IDisposable>(); string preferHeader = RequestPreferenceHelpers.GetRequestPreferHeader(request); if ((preferHeader != null && preferHeader.Contains(PreferenceContinueOnError)) || (!request.GetConfiguration().HasEnabledContinueOnErrorHeader())) { ContinueOnError = true; } else { ContinueOnError = false; } try { while (batchReader.Read()) { ODataBatchResponseItem responseItem = null; if (batchReader.State == ODataBatchReaderState.ChangesetStart) { responseItem = await ExecuteChangeSetAsync(batchReader, batchId, request, cancellationToken); } else if (batchReader.State == ODataBatchReaderState.Operation) { responseItem = await ExecuteOperationAsync(batchReader, batchId, request, cancellationToken); } if (responseItem != null) { responses.Add(responseItem); if (responseItem.IsResponseSuccessful() == false && ContinueOnError == false) { break; } } } } catch { foreach (ODataBatchResponseItem response in responses) { if (response != null) { response.Dispose(); } } throw; } return(await CreateResponseMessageAsync(responses, request, cancellationToken)); }
internal static IList <TableResult> TableBatchOperationPostProcess(IList <TableResult> result, TableBatchOperation batch, RESTCommand <IList <TableResult> > cmd, HttpWebResponse resp, OperationContext ctx, TableRequestOptions options, string accountName) { ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings(); readerSettings.MessageQuotas = new ODataMessageQuotas() { MaxPartsPerBatch = TableConstants.TableServiceMaxResults, MaxReceivedMessageSize = TableConstants.TableServiceMaxPayload }; using (ODataMessageReader responseReader = new ODataMessageReader(new HttpResponseAdapterMessage(resp, cmd.ResponseStream), readerSettings)) { // create a reader ODataBatchReader reader = responseReader.CreateODataBatchReader(); // Initial => changesetstart if (reader.State == ODataBatchReaderState.Initial) { reader.Read(); } if (reader.State == ODataBatchReaderState.ChangesetStart) { // ChangeSetStart => Operation reader.Read(); } int index = 0; bool failError = false; bool failUnexpected = false; while (reader.State == ODataBatchReaderState.Operation) { TableOperation currentOperation = batch[index]; TableResult currentResult = new TableResult() { Result = currentOperation.Entity }; result.Add(currentResult); ODataBatchOperationResponseMessage mimePartResponseMessage = reader.CreateOperationResponseMessage(); string contentType = mimePartResponseMessage.GetHeader(Constants.ContentTypeElement); currentResult.HttpStatusCode = mimePartResponseMessage.StatusCode; // Validate Status Code. if (currentOperation.OperationType == TableOperationType.Insert) { failError = mimePartResponseMessage.StatusCode == (int)HttpStatusCode.Conflict; if (currentOperation.EchoContent) { failUnexpected = mimePartResponseMessage.StatusCode != (int)HttpStatusCode.Created; } else { failUnexpected = mimePartResponseMessage.StatusCode != (int)HttpStatusCode.NoContent; } } else if (currentOperation.OperationType == TableOperationType.Retrieve) { if (mimePartResponseMessage.StatusCode == (int)HttpStatusCode.NotFound) { index++; // Operation => next reader.Read(); continue; } failUnexpected = mimePartResponseMessage.StatusCode != (int)HttpStatusCode.OK; } else { failError = mimePartResponseMessage.StatusCode == (int)HttpStatusCode.NotFound; failUnexpected = mimePartResponseMessage.StatusCode != (int)HttpStatusCode.NoContent; } if (failError) { // If the parse error is null, then don't get the extended error information and the StorageException will contain SR.ExtendedErrorUnavailable message. if (cmd.ParseError != null) { cmd.CurrentResult.ExtendedErrorInformation = cmd.ParseError(mimePartResponseMessage.GetStream(), resp, contentType); } cmd.CurrentResult.HttpStatusCode = mimePartResponseMessage.StatusCode; if (!string.IsNullOrEmpty(cmd.CurrentResult.ExtendedErrorInformation.ErrorMessage)) { string msg = cmd.CurrentResult.ExtendedErrorInformation.ErrorMessage; cmd.CurrentResult.HttpStatusMessage = msg.Substring(0, msg.IndexOf("\n", StringComparison.Ordinal)); } else { cmd.CurrentResult.HttpStatusMessage = mimePartResponseMessage.StatusCode.ToString(CultureInfo.InvariantCulture); } throw new StorageException( cmd.CurrentResult, cmd.CurrentResult.ExtendedErrorInformation != null ? cmd.CurrentResult.ExtendedErrorInformation.ErrorMessage : SR.ExtendedErrorUnavailable, null) { IsRetryable = false }; } if (failUnexpected) { // If the parse error is null, then don't get the extended error information and the StorageException will contain SR.ExtendedErrorUnavailable message. if (cmd.ParseError != null) { cmd.CurrentResult.ExtendedErrorInformation = cmd.ParseError(mimePartResponseMessage.GetStream(), resp, contentType); } cmd.CurrentResult.HttpStatusCode = mimePartResponseMessage.StatusCode; if (!string.IsNullOrEmpty(cmd.CurrentResult.ExtendedErrorInformation.ErrorMessage)) { string msg = cmd.CurrentResult.ExtendedErrorInformation.ErrorMessage; cmd.CurrentResult.HttpStatusMessage = msg.Substring(0, msg.IndexOf("\n", StringComparison.Ordinal)); } else { cmd.CurrentResult.HttpStatusMessage = mimePartResponseMessage.StatusCode.ToString(CultureInfo.InvariantCulture); } string indexString = Convert.ToString(index, CultureInfo.InvariantCulture); // Attempt to extract index of failing entity from extended error info if (cmd.CurrentResult.ExtendedErrorInformation != null && !string.IsNullOrEmpty(cmd.CurrentResult.ExtendedErrorInformation.ErrorMessage)) { string tempIndex = TableRequest.ExtractEntityIndexFromExtendedErrorInformation(cmd.CurrentResult); if (!string.IsNullOrEmpty(tempIndex)) { indexString = tempIndex; } } throw new StorageException(cmd.CurrentResult, string.Format(CultureInfo.CurrentCulture, SR.BatchErrorInOperation, indexString), null) { IsRetryable = true }; } // Update etag if (!string.IsNullOrEmpty(mimePartResponseMessage.GetHeader(Constants.HeaderConstants.EtagHeader))) { currentResult.Etag = mimePartResponseMessage.GetHeader(Constants.HeaderConstants.EtagHeader); if (currentOperation.Entity != null) { currentOperation.Entity.ETag = currentResult.Etag; } } // Parse Entity if needed if (currentOperation.OperationType == TableOperationType.Retrieve || (currentOperation.OperationType == TableOperationType.Insert && currentOperation.EchoContent)) { if (mimePartResponseMessage.GetHeader(Constants.ContentTypeElement).Contains(Constants.JsonNoMetadataAcceptHeaderValue)) { ReadEntityUsingJsonParser(currentResult, currentOperation, mimePartResponseMessage.GetStream(), ctx, options); } else { ReadOdataEntity(currentResult, currentOperation, mimePartResponseMessage, ctx, readerSettings, accountName, options); } } else if (currentOperation.OperationType == TableOperationType.Insert) { currentOperation.Entity.Timestamp = ParseETagForTimestamp(currentResult.Etag); } index++; // Operation => reader.Read(); } } return(result); }
public void BatchReaderNonContentIdTest() { const string truncatedBatchPayload = @"--batch_862fb28e-dc50-4af1-aad5-9608647761d1 Content-Type: multipart/mixed; boundary=changeset_18c8af6c-659f-4c95-bfd5-9d7bf1ee579b --changeset_18c8af6c-659f-4c95-bfd5-9d7bf1ee579b Content-Type: application/http Content-Transfer-Encoding: binary POST http://example.org/Products HTTP/1.1 --changeset_18c8af6c-659f-4c95-bfd5-9d7bf1ee579b-- --batch_862fb28e-dc50-4af1-aad5-9608647761d1-- "; using (var messageReader = new ODataMessageReader(new BatchReaderTestMessage(truncatedBatchPayload))) { ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); bool hitExpectedException = false; while (batchReader.State != ODataBatchReaderState.Exception && batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: try { batchReader.CreateOperationRequestMessage(); } catch (ODataException exception) { hitExpectedException = exception.Message == "The header with name 'Content-ID' was not present in the header collection of the batch operation."; } break; } } Assert.IsTrue(hitExpectedException, "Expected to fail with exception message about content ID not found for Changeset."); } }
/// <inheritdoc/> public override async Task <HttpResponseMessage> ProcessBatchAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw Error.ArgumentNull("request"); } ValidateRequest(request); // This container is for the overall batch request. IServiceProvider requestContainer = request.CreateRequestContainer(ODataRouteName); requestContainer.GetRequiredService <ODataMessageReaderSettings>().BaseUri = GetBaseUri(request); ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(requestContainer, cancellationToken); request.RegisterForDispose(reader); ODataBatchReader batchReader = reader.CreateODataBatchReader(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); Guid batchId = Guid.NewGuid(); HttpConfiguration configuration = request.GetConfiguration(); bool enableContinueOnErrorHeader = (configuration != null) ? configuration.HasEnabledContinueOnErrorHeader() : false; SetContinueOnError(new WebApiRequestHeaders(request.Headers), enableContinueOnErrorHeader); try { while (batchReader.Read()) { ODataBatchResponseItem responseItem = null; if (batchReader.State == ODataBatchReaderState.ChangesetStart) { responseItem = await ExecuteChangeSetAsync(batchReader, batchId, request, cancellationToken); } else if (batchReader.State == ODataBatchReaderState.Operation) { responseItem = await ExecuteOperationAsync(batchReader, batchId, request, cancellationToken); } if (responseItem != null) { responses.Add(responseItem); if (responseItem.IsResponseSuccessful() == false && ContinueOnError == false) { break; } } } } catch { foreach (ODataBatchResponseItem response in responses) { if (response != null) { response.Dispose(); } } throw; } return(await CreateResponseMessageAsync(responses, request, cancellationToken)); }
public async Task<ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage) { var readerSettings = new ODataMessageReaderSettings(); readerSettings.MessageQuotas.MaxReceivedMessageSize = Int32.MaxValue; using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind(); if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return ODataResponse.FromStatusCode(responseMessage.StatusCode); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { return ODataResponse.FromValueStream(await responseMessage.GetStreamAsync()); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return await ReadResponse(messageReader.CreateODataBatchReader()); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Feed)) { return ReadResponse(messageReader.CreateODataFeedReader()); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return ReadResponse(messageReader.CreateODataCollectionReader()); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { var property = messageReader.ReadProperty(); return ODataResponse.FromProperty(property.Name, GetPropertyValue(property.Value)); } else { return ReadResponse(messageReader.CreateODataEntryReader()); } } }
private byte[] ServiceReadRequestAndWriterResponseForMultipartBatchVerifyDependsOnIds(string requestPayload, ODataVersion maxVersion) { byte[] responseBytes = null; IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(requestPayload)) }; requestMessage.SetHeader("Content-Type", batchContentTypeMultipartMime); ODataMessageReaderSettings settings = new ODataMessageReaderSettings { Version = maxVersion }; using (ODataMessageReader messageReader = new ODataMessageReader(requestMessage, settings, this.userModel)) { MemoryStream responseStream = new MemoryStream(); IODataResponseMessage responseMessage = new InMemoryMessage { Stream = responseStream }; // Client is expected to receive the response message in the same format as that is used in the request sent. responseMessage.SetHeader("Content-Type", batchContentTypeMultipartMime); using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage)) { ODataBatchWriter batchWriter = messageWriter.CreateODataBatchWriter(); batchWriter.WriteStartBatch(); ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a change set) ODataBatchOperationRequestMessage operationMessage = batchReader.CreateOperationRequestMessage(); // Verify DependsOnIds are set correctly IEnumerable <string> dependsOnIds = operationMessage.DependsOnIds; switch (operationMessage.ContentId) { case "1": case "2A": Assert.True(dependsOnIds.Count() == 0); break; case "2B": Assert.True(dependsOnIds.SequenceEqual(new List <string> { "2A" })); break; case "2C": Assert.True(dependsOnIds.SequenceEqual(new List <string> { "2A", "2B" })); break; case "3": Assert.True(dependsOnIds.SequenceEqual(new List <string> { "1" })); break; default: break; } ODataBatchOperationResponseMessage response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId); if (operationMessage.Method == "PATCH") { response.StatusCode = 204; response.SetHeader("Content-Type", "application/json;odata.metadata=none"); } else if (operationMessage.Method == "PUT") { response.StatusCode = 201; response.SetHeader("Content-Type", "application/json;"); } break; case ODataBatchReaderState.ChangesetStart: batchWriter.WriteStartChangeset(); break; case ODataBatchReaderState.ChangesetEnd: batchWriter.WriteEndChangeset(); break; } } batchWriter.WriteEndBatch(); responseStream.Position = 0; responseBytes = responseStream.ToArray(); } return(responseBytes); } }
private byte[] ServiceReadAsyncBatchRequestAndWriteAsyncResponse(byte[] requestPayload) { IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(requestPayload) }; requestMessage.SetHeader("Content-Type", batchContentType); using (var messageReader = new ODataMessageReader(requestMessage, new ODataMessageReaderSettings { BaseUri = new Uri(serviceDocumentUri) }, this.userModel)) { var responseStream = new MemoryStream(); IODataResponseMessage responseMessage = new InMemoryMessage { Stream = responseStream }; responseMessage.SetHeader("Content-Type", batchContentType); var messageWriter = new ODataMessageWriter(responseMessage); var batchWriter = messageWriter.CreateODataBatchWriter(); batchWriter.WriteStartBatch(); var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a changeset) var operationMessage = batchReader.CreateOperationRequestMessage(); if (operationMessage.Method == "GET" && operationMessage.Url.AbsolutePath.Contains("ALFKI")) { var response = batchWriter.CreateOperationResponseMessage(null); response.StatusCode = 200; response.SetHeader("Content-Type", "application/json;"); var settings = new ODataMessageWriterSettings(); settings.SetServiceDocumentUri(new Uri(serviceDocumentUri)); using (var operationMessageWriter = new ODataMessageWriter(response, settings, this.userModel)) { var entryWriter = operationMessageWriter.CreateODataResourceWriter(this.customers, this.customerType); var entry = new ODataResource() { TypeName = "MyNS.Customer", Properties = new[] { new ODataProperty() { Name = "Id", Value = "ALFKI" }, new ODataProperty() { Name = "Name", Value = "John" } } }; entryWriter.WriteStart(entry); entryWriter.WriteEnd(); } } break; } } var asyncResponse = batchWriter.CreateOperationResponseMessage(null); asyncResponse.StatusCode = 202; asyncResponse.SetHeader("Location", "http://service/async-monitor"); asyncResponse.SetHeader("Retry-After", "10"); batchWriter.WriteEndBatch(); responseStream.Position = 0; return(responseStream.ToArray()); } }
private byte[] ServiceReadAsyncBatchRequestAndWriteAsyncResponse(byte[] requestPayload) { IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(requestPayload) }; requestMessage.SetHeader("Content-Type", batchContentType); using (var messageReader = new ODataMessageReader(requestMessage, new ODataMessageReaderSettings(), this.userModel)) { var responseStream = new MemoryStream(); IODataResponseMessage responseMessage = new InMemoryMessage { Stream = responseStream }; responseMessage.SetHeader("Content-Type", batchContentType); var messageWriter = new ODataMessageWriter(responseMessage); var batchWriter = messageWriter.CreateODataBatchWriter(); batchWriter.WriteStartBatch(); var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a changeset) var operationMessage = batchReader.CreateOperationRequestMessage(); if (operationMessage.Method == "GET" && operationMessage.Url.AbsolutePath.Contains("ALFKI")) { var response = batchWriter.CreateOperationResponseMessage(null); response.StatusCode = 200; response.SetHeader("Content-Type", "application/json;"); var settings = new ODataMessageWriterSettings(); settings.SetServiceDocumentUri(new Uri(serviceDocumentUri)); using (var operationMessageWriter = new ODataMessageWriter(response, settings, this.userModel)) { var entryWriter = operationMessageWriter.CreateODataEntryWriter(this.customers, this.customerType); var entry = new ODataEntry() { TypeName = "MyNS.Customer", Properties = new[] { new ODataProperty() { Name = "Id", Value = "ALFKI" }, new ODataProperty() { Name = "Name", Value = "John" } } }; entryWriter.WriteStart(entry); entryWriter.WriteEnd(); } } break; } } var asyncResponse = batchWriter.CreateOperationResponseMessage(null); asyncResponse.StatusCode = 202; asyncResponse.SetHeader("Location", "http://service/async-monitor"); asyncResponse.SetHeader("Retry-After", "10"); batchWriter.WriteEndBatch(); responseStream.Position = 0; return responseStream.ToArray(); } }
protected void Button4_Click(object sender, EventArgs e) { string accessToken = ((Button)sender).CommandArgument; Int16 operationCount = 0; if (IsPostBack) { // Get the host web's URL. sharepointUrl = new Uri(Request.QueryString["SPHostUrl"]); } // Create the parent request var batchRequest = new BatchODataRequest(String.Format("{0}/_api/", sharepointUrl)); // ctor adds "$batch" batchRequest.SetHeader("Authorization", "Bearer " + accessToken); using (var oDataMessageWriter = new ODataMessageWriter(batchRequest)) { var oDataBatchWriter = oDataMessageWriter.CreateODataBatchWriter(); oDataBatchWriter.WriteStartBatch(); oDataBatchWriter.WriteStartChangeset(); // Create the list deleting operation var deleteOperation = oDataBatchWriter.CreateOperationRequestMessage( "DELETE", new Uri(sharepointUrl.ToString() + "/_api/Web/lists/getbytitle(\'" +OldList.Text+ "\')")); deleteOperation.SetHeader("If-Match", "\"1\""); oDataBatchWriter.WriteEndChangeset(); operationCount++; // Create the query operation var queryOperationMessage3 = oDataBatchWriter.CreateOperationRequestMessage( "GET", new Uri(sharepointUrl.ToString() + "/_api/Web/lists")); operationCount++; oDataBatchWriter.WriteEndBatch(); oDataBatchWriter.Flush(); } // Parse the response and bind the data to the UI controls var oDataResponse = batchRequest.GetResponse(); using (var oDataReader = new ODataMessageReader(oDataResponse)) { var oDataBatchReader = oDataReader.CreateODataBatchReader(); while (oDataBatchReader.Read()) { switch (oDataBatchReader.State) { case ODataBatchReaderState.Initial: // Optionally, handle the start of a batch payload. break; case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a changeset) var operationResponse = oDataBatchReader.CreateOperationResponseMessage(); // Response ATOM markup parsing and presentation using (var stream = operationResponse.GetStream()) { switch (operationCount) { case 2: // The "delete list" operation if (operationResponse.StatusCode == 200) { DeleteListResponse.Text = "Your list was deleted!"; } else { DeleteListResponse.Text = "Your list was not deleted. Status returned: " + operationResponse.StatusCode.ToString(); } operationCount--; break; case 1: // The "List of Lists" operation // Bind data to the grid on the page. // In a production app, check operationResponse.StatusCode and handle non-200 statuses. // For simplicity, this sample assumes status 200 (the list items are returned). List<XElement> entries = SharePointDataHelpers.ListDataHelper.ExtractListItemsFromATOMResponse(stream); var itemTitles = SharePointDataHelpers.ListDataHelper.GetItemTitles(entries); GridView4.DataSource = itemTitles; GridView4.DataBind(); operationCount--; break; } }; break; case ODataBatchReaderState.ChangesetStart: // Optionally, handle the start of a change set. break; case ODataBatchReaderState.ChangesetEnd: // When this sample was created, SharePoint did not support "all or nothing" transactions. // If that changes in the future this is where you would commit the transaction. break; case ODataBatchReaderState.Exception: // In a producition app handle exeception. Omitted for simplicity in this sample app. break; } } } GridView3.Visible = false; }
public async Task<ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage) #endif { var readerSettings = new ODataMessageReaderSettings(); readerSettings.MessageQuotas.MaxReceivedMessageSize = Int32.MaxValue; using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind(); if (payloadKind.Any(x => x.PayloadKind != ODataPayloadKind.Property)) _hasResponse = true; if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return ODataResponse.FromStatusCode(responseMessage.StatusCode); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { #if SILVERLIGHT var stream = responseMessage.GetStream(); #else var stream = await responseMessage.GetStreamAsync(); #endif return ODataResponse.FromValueStream(stream); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return await ReadResponse(messageReader.CreateODataBatchReader()); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Feed)) { return ReadResponse(messageReader.CreateODataFeedReader()); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return ReadResponse(messageReader.CreateODataCollectionReader()); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { var property = messageReader.ReadProperty(); if (property.Value != null && (property.Value.GetType() != typeof(string) || !string.IsNullOrEmpty(property.Value.ToString()))) _hasResponse = true; if (_hasResponse) { return ODataResponse.FromProperty(property.Name, GetPropertyValue(property.Value)); } else { return ODataResponse.EmptyFeed; } } else { return ReadResponse(messageReader.CreateODataEntryReader()); } } }
private byte[] ServiceReadSingletonBatchRequestAndWriterBatchResponse(byte[] requestPayload) { IODataRequestMessage requestMessage = new InMemoryMessage() { Stream = new MemoryStream(requestPayload) }; requestMessage.SetHeader("Content-Type", batchContentType); using (var messageReader = new ODataMessageReader(requestMessage, new ODataMessageReaderSettings(), this.userModel)) { var responseStream = new MemoryStream(); IODataResponseMessage responseMessage = new InMemoryMessage { Stream = responseStream }; responseMessage.SetHeader("Content-Type", batchContentType); var messageWriter = new ODataMessageWriter(responseMessage); var batchWriter = messageWriter.CreateODataBatchWriter(); batchWriter.WriteStartBatch(); var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a changeset) var operationMessage = batchReader.CreateOperationRequestMessage(); if (operationMessage.Method == "PATCH") { var response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId); response.StatusCode = 204; response.SetHeader("Content-Type", "application/json;odata.metadata=none"); } else if (operationMessage.Method == "GET") { var response = batchWriter.CreateOperationResponseMessage(null); response.StatusCode = 200; response.SetHeader("Content-Type", "application/json;"); var settings = new ODataMessageWriterSettings(); settings.SetServiceDocumentUri(new Uri(serviceDocumentUri)); using (var operationMessageWriter = new ODataMessageWriter(response, settings, this.userModel)) { var entryWriter = operationMessageWriter.CreateODataEntryWriter(this.singleton, this.webType); var entry = new ODataEntry() { TypeName = "NS.Web", Properties = new[] { new ODataProperty() { Name = "WebId", Value = 10 }, new ODataProperty() { Name = "Name", Value = "WebSingleton" } } }; entryWriter.WriteStart(entry); entryWriter.WriteEnd(); } } else if (operationMessage.Method == "DELETE") { var response = batchWriter.CreateOperationResponseMessage(operationMessage.ContentId); response.StatusCode = 500; } break; case ODataBatchReaderState.ChangesetStart: batchWriter.WriteStartChangeset(); break; case ODataBatchReaderState.ChangesetEnd: batchWriter.WriteEndChangeset(); break; } } batchWriter.WriteEndBatch(); responseStream.Position = 0; return responseStream.ToArray(); } }
protected void Button3_Click(object sender, EventArgs e) { string accessToken = ((Button)sender).CommandArgument; Int16 operationCount = 0; if (IsPostBack) { // Get the host web's URL. sharepointUrl = new Uri(Request.QueryString["SPHostUrl"]); } // Create the parent request var batchRequest = new BatchODataRequest(String.Format("{0}/_api/", sharepointUrl)); // ctor adds "$batch" batchRequest.SetHeader("Authorization", "Bearer " + accessToken); using (var oDataMessageWriter = new ODataMessageWriter(batchRequest)) { var oDataBatchWriter = oDataMessageWriter.CreateODataBatchWriter(); oDataBatchWriter.WriteStartBatch(); oDataBatchWriter.WriteStartChangeset(); // Create the list adding operation var addListOperation = oDataBatchWriter.CreateOperationRequestMessage( "POST", new Uri(sharepointUrl.ToString() + "/_api/lists")); addListOperation.SetHeader("Content-Type", "application/json;odata=verbose"); // Write the body of the operation using (var oDataInsertWriter = new ODataMessageWriter(addListOperation)) { var entryWriter = oDataInsertWriter.CreateODataEntryWriter(); var insertionBody = new ODataEntry() { Properties = new[] { new ODataProperty() {Name = "Title", Value = NewList.Text}, new ODataProperty() {Name = "BaseTemplate", Value = "100"} } }; // Set the "__metadata" type property insertionBody.TypeName = "SP.List"; entryWriter.WriteStart(insertionBody); entryWriter.WriteEnd(); } oDataBatchWriter.WriteEndChangeset(); operationCount++; // Create the query operation var queryOperationMessage3 = oDataBatchWriter.CreateOperationRequestMessage( "GET", new Uri(sharepointUrl.ToString() + "/_api/Web/lists")); operationCount++; oDataBatchWriter.WriteEndBatch(); oDataBatchWriter.Flush(); } // Parse the response and bind the data to the UI controls var oDataResponse = batchRequest.GetResponse(); using (var oDataReader = new ODataMessageReader(oDataResponse)) { var oDataBatchReader = oDataReader.CreateODataBatchReader(); while (oDataBatchReader.Read()) { switch (oDataBatchReader.State) { case ODataBatchReaderState.Initial: // Optionally, handle the start of a batch payload. break; case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a changeset) var operationResponse = oDataBatchReader.CreateOperationResponseMessage(); // Response ATOM markup parsing and presentation using (var stream = operationResponse.GetStream()) { switch (operationCount) { case 2: // The "add new list" operation if (operationResponse.StatusCode == 201) { AddListResponse.Text = "Your list was created!"; } else { AddListResponse.Text = "Your list was not created. Status returned: " + operationResponse.StatusCode.ToString(); } operationCount--; break; case 1: // The "List of Lists" operation // Bind data to the grid on the page. // In a production app, check operationResponse.StatusCode and handle non-200 statuses. // For simplicity, this sample assumes status 200 (the list items are returned). List<XElement> entries = SharePointDataHelpers.ListDataHelper.ExtractListItemsFromATOMResponse(stream); var itemTitles = SharePointDataHelpers.ListDataHelper.GetItemTitles(entries); GridView3.DataSource = itemTitles; GridView3.DataBind(); operationCount--; break; } }; break; case ODataBatchReaderState.ChangesetStart: // Optionally, handle the start of a change set. break; case ODataBatchReaderState.ChangesetEnd: // When this sample was created, SharePoint did not support "all or nothing" transactions. // If that changes in the future this is where you would commit the transaction. break; case ODataBatchReaderState.Exception: // In a producition app handle exeception. Omitted for simplicity in this sample app. break; } } } GridView3.Visible = true; TwoLists.Visible = false; }
private void ClientReadAsyncBatchResponse(byte[] responsePayload) { IODataResponseMessage responseMessage = new InMemoryMessage() { Stream = new MemoryStream(responsePayload) }; responseMessage.SetHeader("Content-Type", batchContentType); using (var messageReader = new ODataMessageReader(responseMessage, new ODataMessageReaderSettings(), this.userModel)) { var batchReader = messageReader.CreateODataBatchReader(); while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // Encountered an operation (either top-level or in a changeset) var operationMessage = batchReader.CreateOperationResponseMessage(); if (operationMessage.StatusCode == 200) { using (ODataMessageReader innerMessageReader = new ODataMessageReader(operationMessage, new ODataMessageReaderSettings(), this.userModel)) { var reader = innerMessageReader.CreateODataEntryReader(); while (reader.Read()) { if (reader.State == ODataReaderState.EntryEnd) { ODataEntry entry = reader.Item as ODataEntry; Assert.AreEqual("ALFKI", entry.Properties.Single(p => p.Name == "Id").Value); Assert.AreEqual("John", entry.Properties.Single(p => p.Name == "Name").Value); } } } } else { Assert.AreEqual(202, operationMessage.StatusCode); } break; } } } }
public async Task <ODataResponse> GetResponseAsync(IODataResponseMessageAsync responseMessage) #endif { var readerSettings = new ODataMessageReaderSettings(); readerSettings.MessageQuotas.MaxReceivedMessageSize = Int32.MaxValue; using (var messageReader = new ODataMessageReader(responseMessage, readerSettings, _model)) { var payloadKind = messageReader.DetectPayloadKind(); if (payloadKind.Any(x => x.PayloadKind != ODataPayloadKind.Property)) { _hasResponse = true; } if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Error)) { return(ODataResponse.FromStatusCode(responseMessage.StatusCode)); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Value)) { if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { throw new NotImplementedException(); } else { #if SILVERLIGHT var stream = responseMessage.GetStream(); #else var stream = await responseMessage.GetStreamAsync(); #endif return(ODataResponse.FromValueStream(stream, responseMessage is ODataBatchOperationResponseMessage)); } } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Batch)) { return(await ReadResponse(messageReader.CreateODataBatchReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Feed)) { return(ReadResponse(messageReader.CreateODataFeedReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Collection)) { return(ReadResponse(messageReader.CreateODataCollectionReader())); } else if (payloadKind.Any(x => x.PayloadKind == ODataPayloadKind.Property)) { var property = messageReader.ReadProperty(); if (property.Value != null && (property.Value.GetType() != typeof(string) || !string.IsNullOrEmpty(property.Value.ToString()))) { _hasResponse = true; } if (_hasResponse) { return(ODataResponse.FromProperty(property.Name, GetPropertyValue(property.Value))); } else { return(ODataResponse.EmptyFeed); } } else { return(ReadResponse(messageReader.CreateODataEntryReader())); } } }
protected void Button2_Click(object sender, EventArgs e) { string accessToken = ((Button)sender).CommandArgument; Int16 listRetrievalCount = 0; if (IsPostBack) { // Get the host web's URL. sharepointUrl = new Uri(Request.QueryString["SPHostUrl"]); } // Create the parent request var batchRequest = new BatchODataRequest(String.Format("{0}/_api/", sharepointUrl)); // ctor adds "$batch" batchRequest.SetHeader("Authorization", "Bearer " + accessToken); using (var oDataMessageWriter = new ODataMessageWriter(batchRequest)) { var oDataBatchWriter = oDataMessageWriter.CreateODataBatchWriter(); oDataBatchWriter.WriteStartBatch(); // Create the two child query operations. oDataBatchWriter.CreateOperationRequestMessage( "GET", new Uri(sharepointUrl.ToString() + "/_api/Web/lists/getbytitle('Composed Looks')/items?$select=Title")); listRetrievalCount++; oDataBatchWriter.CreateOperationRequestMessage( "GET", new Uri(sharepointUrl.ToString() + "/_api/Web/lists/getbytitle('User Information List')/items?$select=Title")); listRetrievalCount++; oDataBatchWriter.WriteEndBatch(); oDataBatchWriter.Flush(); } // Parse the response and bind the data to the UI controls var oDataResponse = batchRequest.GetResponse(); using (var oDataReader = new ODataMessageReader(oDataResponse)) { var oDataBatchReader = oDataReader.CreateODataBatchReader(); while (oDataBatchReader.Read()) { switch (oDataBatchReader.State) { case ODataBatchReaderState.Initial: // Optionally, handle the start of a batch payload. break; case ODataBatchReaderState.Operation: // Start of an operation (either top-level or in a changeset) var operationResponse = oDataBatchReader.CreateOperationResponseMessage(); // Response's ATOM markup parsing and presentation section using (var stream = operationResponse.GetStream()) { List<XElement> entries = SharePointDataHelpers.ListDataHelper.ExtractListItemsFromATOMResponse(stream); var itemTitles = SharePointDataHelpers.ListDataHelper.GetItemTitles(entries); // Bind data to the grid on the page. // In a production app, check operationResponse.StatusCode and handle non-200 statuses. // For simplicity, this sample assumes status 200 (the list items are returned). switch (listRetrievalCount) { case 2: GridView2.DataSource = itemTitles; GridView2.DataBind(); listRetrievalCount--; break; case 1: GridView1.DataSource = itemTitles; GridView1.DataBind(); listRetrievalCount--; break; } }; break; case ODataBatchReaderState.ChangesetStart: // Optionally, handle the start of a change set. break; case ODataBatchReaderState.ChangesetEnd: // When this sample was created, SharePoint did not support "all or nothing" transactions. // If that changes in the future this is where you would commit the transaction. break; case ODataBatchReaderState.Exception: // In a producition app handle exeception. Omitted for simplicity in this sample app. break; } } } TwoLists.Visible = true; }
private void BatchRequestWithPayloadUriWritingOption(BatchPayloadUriOption option) { var writerSettings = new ODataMessageWriterSettings(); writerSettings.BaseUri = ServiceBaseUri; ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings() { BaseUri = ServiceBaseUri }; var accountType = Model.FindDeclaredType(NameSpacePrefix + "Account") as IEdmEntityType; var accountSet = Model.EntityContainer.FindEntitySet("Accounts"); var paymentInstrumentType = Model.FindDeclaredType(NameSpacePrefix + "PaymentInstrument") as IEdmEntityType; IEdmNavigationProperty navProp = accountType.FindProperty("MyPaymentInstruments") as IEdmNavigationProperty; var myPaymentInstrumentSet = accountSet.FindNavigationTarget(navProp); var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri + "$batch")); requestMessage.SetHeader("Content-Type", "multipart/mixed;boundary=batch_01AD6766-4A45-47CC-9463-94D4591D8DA9"); requestMessage.SetHeader("OData-Version", "4.0"); requestMessage.Method = "POST"; using (var messageWriter = new ODataMessageWriter(requestMessage, writerSettings, Model)) { var batchWriter = messageWriter.CreateODataBatchWriter(); //Batch start. batchWriter.WriteStartBatch(); //A Get request. var batchOperation1 = batchWriter.CreateOperationRequestMessage("GET", new Uri(ServiceBaseUri + "Accounts(101)/MyPaymentInstruments"), null, option); batchOperation1.SetHeader("Accept", "application/json;odata.metadata=full"); //Get request ends. //Changeset start. batchWriter.WriteStartChangeset(); //The first operation in changeset is a Create request. ODataBatchOperationRequestMessage batchChangesetOperation1 = batchWriter.CreateOperationRequestMessage("POST", new Uri(ServiceBaseUri + "Accounts(102)/MyPaymentInstruments"), "1", option); batchChangesetOperation1.SetHeader("Content-Type", "application/json;odata.metadata=full"); batchChangesetOperation1.SetHeader("Accept", "application/json;odata.metadata=full"); var paymentInstrumentEntry = new ODataResource() { TypeName = NameSpacePrefix + "PaymentInstrument" }; var paymentInstrumentEntryP1 = new ODataProperty { Name = "PaymentInstrumentID", Value = 102910 }; var paymentInstrumentEntryP2 = new ODataProperty { Name = "FriendlyName", Value = "102 batch new PI" }; var paymentInstrumentEntryP3 = new ODataProperty { Name = "CreatedDate", Value = new DateTimeOffset(new DateTime(2013, 12, 29, 11, 11, 57)) }; paymentInstrumentEntry.Properties = new[] { paymentInstrumentEntryP1, paymentInstrumentEntryP2, paymentInstrumentEntryP3 }; using (var entryMessageWriter = new ODataMessageWriter(batchChangesetOperation1, writerSettings, Model)) { var odataEntryWriter = entryMessageWriter.CreateODataResourceWriter(myPaymentInstrumentSet, paymentInstrumentType); odataEntryWriter.WriteStart(paymentInstrumentEntry); odataEntryWriter.WriteEnd(); } //Changeset end. batchWriter.WriteEndChangeset(); //Another Get request. var batchOperation2 = batchWriter.CreateOperationRequestMessage("GET", new Uri(ServiceBaseUri + "Accounts(103)/MyPaymentInstruments(103901)/BillingStatements(103901001)"), null, option); batchOperation2.SetHeader("Accept", "application/json;odata.metadata=full"); //Batch end. batchWriter.WriteEndBatch(); } var responseMessage = requestMessage.GetResponse(); Assert.AreEqual(200, responseMessage.StatusCode); using (var innerMessageReader = new ODataMessageReader(responseMessage, readerSettings, Model)) { var batchReader = innerMessageReader.CreateODataBatchReader(); int batchOperationId = 0; while (batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Initial: break; case ODataBatchReaderState.ChangesetStart: break; case ODataBatchReaderState.ChangesetEnd: break; case ODataBatchReaderState.Operation: ODataBatchOperationResponseMessage operationResponse = batchReader.CreateOperationResponseMessage(); using (var operationResponseReader = new ODataMessageReader(operationResponse, readerSettings, Model)) { if (batchOperationId == 0) { // the first response message is a feed var feedReader = operationResponseReader.CreateODataResourceSetReader(); Assert.AreEqual(200, operationResponse.StatusCode); List <ODataResource> pis = new List <ODataResource>(); while (feedReader.Read()) { switch (feedReader.State) { case ODataReaderState.ResourceEnd: ODataResource entry = feedReader.Item as ODataResource; Assert.IsNotNull(entry); pis.Add(entry); break; } } Assert.AreEqual(ODataReaderState.Completed, feedReader.State); Assert.AreEqual(3, pis.Count); } else if (batchOperationId == 1) { // the second response message is a creation response var entryReader = operationResponseReader.CreateODataResourceReader(); Assert.AreEqual(201, operationResponse.StatusCode); List <ODataResource> pis = new List <ODataResource>(); while (entryReader.Read()) { switch (entryReader.State) { case ODataReaderState.ResourceEnd: ODataResource entry = entryReader.Item as ODataResource; Assert.IsNotNull(entry); pis.Add(entry); break; } } Assert.AreEqual(ODataReaderState.Completed, entryReader.State); Assert.AreEqual(1, pis.Count); Assert.AreEqual(102910, pis[0].Properties.Single(p => p.Name == "PaymentInstrumentID").Value); } else if (batchOperationId == 2) { // the third response message is an entry var entryReader = operationResponseReader.CreateODataResourceReader(); Assert.AreEqual(200, operationResponse.StatusCode); List <ODataResource> statements = new List <ODataResource>(); while (entryReader.Read()) { switch (entryReader.State) { case ODataReaderState.ResourceEnd: ODataResource entry = entryReader.Item as ODataResource; Assert.IsNotNull(entry); statements.Add(entry); break; } } Assert.AreEqual(ODataReaderState.Completed, entryReader.State); Assert.AreEqual(1, statements.Count); Assert.AreEqual(103901001, statements[0].Properties.Single(p => p.Name == "StatementID").Value); } } batchOperationId++; break; } } Assert.AreEqual(ODataBatchReaderState.Completed, batchReader.State); } }
public void BatchReaderShouldNotLoopInfinitelyIfStreamEndsUnexpectedly() { const string truncatedBatchPayload = @"--batch_862fb28e-dc50-4af1-aad5-9608647761d1 Content-Type: multipart/mixed; boundary=changeset_18c8af6c-659f-4c95-bfd5-9d7bf1ee579b --changeset_18c8af6c-659f-4c95-bfd5-9d7bf1ee579b Content-Type: application/http Content-Transfer-Encoding: binary Content-Id: 1 "; using (var messageReader = new ODataMessageReader(new BatchReaderTestMessage(truncatedBatchPayload))) { ODataBatchReader batchReader = messageReader.CreateODataBatchReader(); bool hitExpectedException = false; while (batchReader.State != ODataBatchReaderState.Exception && batchReader.Read()) { switch (batchReader.State) { case ODataBatchReaderState.Operation: // In the original bug, this would cause an infinite loop. try { batchReader.CreateOperationRequestMessage(); } catch (ODataException exception) { hitExpectedException = exception.Message == "Encountered an unexpected end of input while reading the batch payload."; } break; } } Assert.IsTrue(hitExpectedException, "Expected to fail with exception message about end of input being reached."); } }