Skip to content

Commit

Permalink
Issue 1594: DefaultODataBatchHandler doesn't handle urls relative to the
Browse files Browse the repository at this point in the history
batch endpoint properly.
The root cause is that the base uri of ODataMessageReaderSettings doesn't
end with slash.
The fix is only for v3 and v4 works well for all kinds of urls because
ODL v4 will append a slash in the end of the base uri if there isn't one.
  • Loading branch information
fenzhao committed Jul 4, 2014
1 parent 6c5cc2c commit 142f4ff
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public virtual async Task<IList<ODataBatchRequestItem>> ParseBatchRequestsAsync(
{
DisableMessageStreamDisposal = true,
MessageQuotas = MessageQuotas,
BaseUri = GetBaseUri(request)
BaseUri = EnsureTrailingSlash(GetBaseUri(request))
};

ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(oDataReaderSettings, cancellationToken);
Expand Down
13 changes: 13 additions & 0 deletions src/System.Web.Http.OData/OData/Batch/ODataBatchHandler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System.Diagnostics.Contracts;
using System.Web.Http.Batch;
using Microsoft.Data.OData;

Expand Down Expand Up @@ -34,5 +35,17 @@ public ODataMessageQuotas MessageQuotas
/// Gets or sets the name of the OData route associated with this batch handler.
/// </summary>
public string ODataRouteName { get; set; }

internal static Uri EnsureTrailingSlash(Uri uri)
{
Contract.Assert(uri != null);

if (!uri.OriginalString.EndsWith("/", StringComparison.Ordinal))
{
return new Uri(uri.OriginalString + "/");
}

return uri;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public override async Task<HttpResponseMessage> ProcessBatchAsync(HttpRequestMes
{
DisableMessageStreamDisposal = true,
MessageQuotas = MessageQuotas,
BaseUri = GetBaseUri(request)
BaseUri = EnsureTrailingSlash(GetBaseUri(request))
};

ODataMessageReader reader = await request.Content.GetODataMessageReaderAsync(oDataReaderSettings, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Web.Http.OData;
using System.Web.Http.OData.Batch;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Extensions;
using System.Web.Http.Routing;
using Microsoft.Data.Edm;
using Microsoft.TestCommon;

namespace System.Web.Http
Expand Down Expand Up @@ -324,5 +328,68 @@ public void ValidateRequest_Throws_IfRequestContentTypeDoesNotHaveBoundary()
Assert.Equal("The batch request must have a boundary specification in the \"Content-Type\" header.",
errorResponse.Response.Content.ReadAsAsync<HttpError>().Result.Message);
}

[Fact]
public void BatchRequest_Works_AbsoluteAndRelativeUri()
{
// Arrange
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<BatchCustomer>("BatchCustomers");
IEdmModel model = builder.GetEdmModel();

HttpConfiguration configuration = new HttpConfiguration();
HttpServer server = new HttpServer(configuration);
HttpClient client = new HttpClient(server);
configuration.Routes.MapODataServiceRoute("odata", "odata", model, new DefaultODataBatchHandler(server));

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/odata/$batch");
request.Content = new StringContent(
@"--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET http://localhost/odata/BatchCustomers(5) HTTP/1.1
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET /odata/BatchCustomers(6) HTTP/1.1
Host: localhost
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET BatchCustomers(7) HTTP/1.1
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--
");
request.Content.Headers.ContentType =
MediaTypeHeaderValue.Parse("multipart/mixed;boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b");

// Act
HttpResponseMessage response = client.SendAsync(request).Result;
string responseString = response.Content.ReadAsStringAsync().Result;

// Assert
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
Assert.Contains("\"odata.metadata\":\"http://localhost/odata/$metadata#BatchCustomers/@Element\",\"ID\":5", responseString);
Assert.Contains("\"odata.metadata\":\"http://localhost/odata/$metadata#BatchCustomers/@Element\",\"ID\":6", responseString);
Assert.Contains("\"odata.metadata\":\"http://localhost/odata/$metadata#BatchCustomers/@Element\",\"ID\":7", responseString);
}

public class BatchCustomersController : ODataController
{
public IHttpActionResult Get(int key)
{
return Ok(new BatchCustomer { ID = key });
}
}

public class BatchCustomer
{
public int ID { get; set; }
}
}
}

0 comments on commit 142f4ff

Please sign in to comment.