public static async Task <IList <HttpRequestMessage> > ReadChangeSetRequestAsync(this ODataBatchReader reader, Guid batchId, CancellationToken cancellationToken) { if (reader == null) { throw Error.ArgumentNull("reader"); } if (reader.State != ODataBatchReaderState.ChangesetStart) { throw Error.InvalidOperation( SRResources.InvalidBatchReaderState, reader.State.ToString(), ODataBatchReaderState.ChangesetStart.ToString()); } Guid changeSetId = Guid.NewGuid(); List <HttpRequestMessage> requests = new List <HttpRequestMessage>(); while (await reader.ReadAsync() && reader.State != ODataBatchReaderState.ChangesetEnd) { if (reader.State == ODataBatchReaderState.Operation) { requests.Add(await ReadOperationInternalAsync(reader, batchId, changeSetId, cancellationToken)); } } return(requests); }
/// <summary> /// Reads a ChangeSet request. /// </summary> /// <param name="reader">The <see cref="ODataBatchReader"/>.</param> /// <param name="context">The context containing the batch request messages.</param> /// <param name="batchId">The Batch Id.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>A collection of <see cref="HttpRequest"/> in the ChangeSet.</returns> public static async Task <IList <HttpContext> > ReadChangeSetRequestAsync( this ODataBatchReader reader, HttpContext context, Guid batchId, CancellationToken cancellationToken) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (reader.State != ODataBatchReaderState.ChangesetStart) { throw Error.InvalidOperation( SRResources.InvalidBatchReaderState, reader.State.ToString(), ODataBatchReaderState.ChangesetStart.ToString()); } Guid changeSetId = Guid.NewGuid(); List <HttpContext> contexts = new List <HttpContext>(); while (await reader.ReadAsync().ConfigureAwait(false) && reader.State != ODataBatchReaderState.ChangesetEnd) { if (reader.State == ODataBatchReaderState.Operation) { contexts.Add(await ReadOperationInternalAsync(reader, context, batchId, changeSetId, cancellationToken).ConfigureAwait(false)); } } return(contexts); }
/// <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 = await reader.CreateODataBatchReaderAsync(); 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 (await batchReader.ReadAsync()) { 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); }
/// <summary> /// Executes the ChangeSet. /// </summary> /// <param name="batchReader">The batch reader.</param> /// <param name="batchId">The batch id.</param> /// <param name="originalRequest">The original request containing all the batch requests.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>The response for the ChangeSet.</returns> public virtual async Task <ODataBatchResponseItem> ExecuteChangeSetAsync(ODataBatchReader batchReader, Guid batchId, HttpRequestMessage originalRequest, CancellationToken cancellationToken) { if (batchReader == null) { throw Error.ArgumentNull("batchReader"); } if (originalRequest == null) { throw Error.ArgumentNull("originalRequest"); } Guid changeSetId = Guid.NewGuid(); List <HttpResponseMessage> changeSetResponse = new List <HttpResponseMessage>(); Dictionary <string, string> contentIdToLocationMapping = new Dictionary <string, string>(); try { while (await batchReader.ReadAsync() && batchReader.State != ODataBatchReaderState.ChangesetEnd) { if (batchReader.State == ODataBatchReaderState.Operation) { HttpRequestMessage changeSetOperationRequest = await batchReader.ReadChangeSetOperationRequestAsync(batchId, changeSetId, bufferContentStream : false); changeSetOperationRequest.CopyBatchRequestProperties(originalRequest); changeSetOperationRequest.DeleteRequestContainer(false); try { HttpResponseMessage response = await ODataBatchRequestItem.SendMessageAsync(Invoker, changeSetOperationRequest, cancellationToken, contentIdToLocationMapping); if (response.IsSuccessStatusCode) { changeSetResponse.Add(response); } else { ChangeSetRequestItem.DisposeResponses(changeSetResponse); changeSetResponse.Clear(); changeSetResponse.Add(response); return(new ChangeSetResponseItem(changeSetResponse)); } } finally { originalRequest.RegisterForDispose(changeSetOperationRequest.GetResourcesForDisposal()); originalRequest.RegisterForDispose(changeSetOperationRequest); } } } } catch { ChangeSetRequestItem.DisposeResponses(changeSetResponse); throw; } return(new ChangeSetResponseItem(changeSetResponse)); }
/// <summary> /// Converts the incoming OData batch request into a collection of request messages. /// </summary> /// <param name="context">The context containing the batch request messages.</param> /// <returns>A collection of <see cref="ODataBatchRequestItem"/>.</returns> public virtual async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync(HttpContext context) { if (context == null) { throw Error.ArgumentNull(nameof(context)); } HttpRequest request = context.Request; IServiceProvider requestContainer = request.CreateRouteServices(PrefixName); requestContainer.GetRequiredService <ODataMessageReaderSettings>().BaseUri = GetBaseUri(request); using (ODataMessageReader reader = request.GetODataMessageReader(requestContainer)) { CancellationToken cancellationToken = context.RequestAborted; List <ODataBatchRequestItem> requests = new List <ODataBatchRequestItem>(); ODataBatchReader batchReader = await reader.CreateODataBatchReaderAsync().ConfigureAwait(false); Guid batchId = Guid.NewGuid(); Dictionary <string, string> contentToLocationMapping = new Dictionary <string, string>(); while (await batchReader.ReadAsync().ConfigureAwait(false)) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { IList <HttpContext> changeSetContexts = await batchReader.ReadChangeSetRequestAsync(context, batchId, cancellationToken).ConfigureAwait(false); foreach (HttpContext changeSetContext in changeSetContexts) { changeSetContext.Request.ClearRouteServices(); } ChangeSetRequestItem requestItem = new ChangeSetRequestItem(changeSetContexts); requestItem.ContentIdToLocationMapping = contentToLocationMapping; requests.Add(requestItem); } else if (batchReader.State == ODataBatchReaderState.Operation) { HttpContext operationContext = await batchReader.ReadOperationRequestAsync(context, batchId, cancellationToken).ConfigureAwait(false); operationContext.Request.ClearRouteServices(); OperationRequestItem requestItem = new OperationRequestItem(operationContext); requestItem.ContentIdToLocationMapping = contentToLocationMapping; requests.Add(requestItem); } } return(requests); } }
public async Task ExecuteOperationAsync_CopiesPropertiesFromRequest_WithoutExcludedProperties() { // Arrange RequestDelegate handler = context => { context.Features[typeof(UnbufferedODataBatchHandlerTest)] = "foo"; return(Task.FromResult(context.Response)); }; UnbufferedODataBatchHandler batchHandler = new UnbufferedODataBatchHandler(); string batchRequest = @"--75148e61-e67a-4bb7-ac0f-78fa30d0da30 Content-Type: application/http Content-Transfer-Encoding: binary Content-ID: 318941389 GET / HTTP/1.1 Host: example.com --75148e61-e67a-4bb7-ac0f-78fa30d0da30-- "; HttpRequest request = RequestFactory.Create("Post", "http://example.com/$batch", opt => opt.AddModel(EdmCoreModel.Instance)); HttpContext httpContext = request.HttpContext; byte[] requestBytes = Encoding.UTF8.GetBytes(batchRequest); request.Body = new MemoryStream(requestBytes); request.ContentType = "multipart/mixed;boundary=\"75148e61-e67a-4bb7-ac0f-78fa30d0da30\""; request.ContentLength = 431; httpContext.ODataFeature().PrefixName = ""; IServiceProvider sp = request.GetSubServiceProvider(); IODataRequestMessage oDataRequestMessage = ODataMessageWrapperHelper.Create(httpContext.Request.Body, request.Headers, sp); ODataMessageReader oDataMessageReader = new ODataMessageReader(oDataRequestMessage, new ODataMessageReaderSettings { BaseUri = new Uri("http://example.com") }); ODataBatchReader batchReader = await oDataMessageReader.CreateODataBatchReaderAsync(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); await batchReader.ReadAsync(); // Act var response = await batchHandler.ExecuteOperationAsync(batchReader, Guid.NewGuid(), httpContext.Request, handler); // Assert OperationResponseItem operationResponseItem = Assert.IsType <OperationResponseItem>(response); Assert.Equal("foo", operationResponseItem.Context.Features[typeof(UnbufferedODataBatchHandlerTest)]); }
public async Task 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 = await batchRequest.Content .GetODataMessageReaderAsync(new ODataMessageReaderSettings { BaseUri = new Uri("http://example.com") }, CancellationToken.None); ODataBatchReader batchReader = await reader.CreateODataBatchReaderAsync(); List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>(); Guid batchId = Guid.NewGuid(); await batchReader.ReadAsync(); var response = await batchHandler.ExecuteChangeSetAsync(batchReader, Guid.NewGuid(), batchRequest, CancellationToken.None); 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()); } }
/// <summary> /// Executes the ChangeSet. /// </summary> /// <param name="batchReader">The batch reader.</param> /// <param name="batchId">The batch id.</param> /// <param name="originalRequest">The original request containing all the batch requests.</param> /// <param name="handler">The handler for processing a message.</param> /// <returns>The response for the ChangeSet.</returns> public virtual async Task <ODataBatchResponseItem> ExecuteChangeSetAsync(ODataBatchReader batchReader, Guid batchId, HttpRequest originalRequest, RequestDelegate handler) { if (batchReader == null) { throw new ArgumentNullException(nameof(batchReader)); } if (originalRequest == null) { throw new ArgumentNullException(nameof(originalRequest)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } Guid changeSetId = Guid.NewGuid(); List <HttpContext> changeSetResponse = new List <HttpContext>(); Dictionary <string, string> contentIdToLocationMapping = new Dictionary <string, string>(); while (await batchReader.ReadAsync().ConfigureAwait(false) && batchReader.State != ODataBatchReaderState.ChangesetEnd) { if (batchReader.State == ODataBatchReaderState.Operation) { CancellationToken cancellationToken = originalRequest.HttpContext.RequestAborted; HttpContext changeSetOperationContext = await batchReader.ReadChangeSetOperationRequestAsync(originalRequest.HttpContext, batchId, changeSetId, cancellationToken).ConfigureAwait(false); changeSetOperationContext.Request.CopyBatchRequestProperties(originalRequest); //changeSetOperationContext.Request.DeleteRequestContainer(false); await ODataBatchRequestItem.SendRequestAsync(handler, changeSetOperationContext, contentIdToLocationMapping).ConfigureAwait(false); if (changeSetOperationContext.Response.IsSuccessStatusCode()) { changeSetResponse.Add(changeSetOperationContext); } else { changeSetResponse.Clear(); changeSetResponse.Add(changeSetOperationContext); return(new ChangeSetResponseItem(changeSetResponse)); } } } return(new ChangeSetResponseItem(changeSetResponse)); }
/// <summary> /// Converts the incoming OData batch request into a collection of request messages. /// </summary> /// <param name="context">The context containing the batch request messages.</param> /// <returns>A collection of <see cref="ODataBatchRequestItem"/>.</returns> public virtual async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } HttpRequest request = context.Request; IServiceProvider requestContainer = request.CreateSubServiceProvider(PrefixName); requestContainer.GetRequiredService <ODataMessageReaderSettings>().BaseUri = GetBaseUri(request); using (ODataMessageReader reader = request.GetODataMessageReader(requestContainer)) { CancellationToken cancellationToken = context.RequestAborted; List <ODataBatchRequestItem> requests = new List <ODataBatchRequestItem>(); ODataBatchReader batchReader = await reader.CreateODataBatchReaderAsync().ConfigureAwait(false); Guid batchId = Guid.NewGuid(); while (await batchReader.ReadAsync().ConfigureAwait(false)) { if (batchReader.State == ODataBatchReaderState.ChangesetStart) { IList <HttpContext> changeSetContexts = await batchReader.ReadChangeSetRequestAsync(context, batchId, cancellationToken).ConfigureAwait(false); foreach (HttpContext changeSetContext in changeSetContexts) { changeSetContext.Request.CopyBatchRequestProperties(request); changeSetContext.Request.DeleteSubRequestProvider(false); } requests.Add(new ChangeSetRequestItem(changeSetContexts)); } else if (batchReader.State == ODataBatchReaderState.Operation) { HttpContext operationContext = await batchReader.ReadOperationRequestAsync(context, batchId, cancellationToken).ConfigureAwait(false); operationContext.Request.CopyBatchRequestProperties(request); operationContext.Request.DeleteSubRequestProvider(false); requests.Add(new OperationRequestItem(operationContext)); } } return(requests); } }
public virtual async Task <IList <ODataBatchRequestItem> > ParseBatchRequestsAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw Error.ArgumentNull("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 = await reader.CreateODataBatchReaderAsync(); Guid batchId = Guid.NewGuid(); while (await batchReader.ReadAsync()) { 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(new ChangeSetRequestItem(changeSetRequests)); } else if (batchReader.State == ODataBatchReaderState.Operation) { HttpRequestMessage operationRequest = await batchReader.ReadOperationRequestAsync(batchId, bufferContentStream : true, cancellationToken : cancellationToken); operationRequest.CopyBatchRequestProperties(request); operationRequest.DeleteRequestContainer(false); requests.Add(new OperationRequestItem(operationRequest)); } } return(requests); }
/// <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 = await reader.CreateODataBatchReaderAsync(); 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 (await batchReader.ReadAsync()) { 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)); }