Skip to content

Commit

Permalink
Fixes #1190: Enable case insensitive by default for query (#1192)
Browse files Browse the repository at this point in the history
* Fixes #1190: Enable case insensitive by default for query

* upate the test cases

* The Json string switches randomly, so change the codes to avoid random ordering.

* Address the comment and rebase to main
  • Loading branch information
xuzhg authored May 13, 2024
1 parent 9e2756f commit 1c029ad
Showing 9 changed files with 145 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/Microsoft.AspNetCore.OData/Query/ODataQueryContext.cs
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@ namespace Microsoft.AspNetCore.OData.Query
/// </summary>
public class ODataQueryContext
{
internal static readonly ODataUriResolver DefaultCaseInsensitiveResolver = new ODataUriResolver { EnableCaseInsensitive = true };

private DefaultQueryConfigurations _defaultQueryConfigurations;

/// <summary>
9 changes: 8 additions & 1 deletion src/Microsoft.AspNetCore.OData/Query/ODataQueryOptions.cs
Original file line number Diff line number Diff line change
@@ -843,6 +843,13 @@ internal void AddAutoSelectExpandProperties()
Context.NavigationSource,
queryParameters,
Context.RequestContainer); // the Context.RequestContainer could be null for non-edm model

if (Context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}

var originalSelectExpand = SelectExpand;
SelectExpand = new SelectExpandQueryOption(
autoSelectRawValue,
@@ -1160,7 +1167,7 @@ private void Initialize(ODataQueryContext context)
else
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = new ODataUriResolver { EnableCaseInsensitive = true };
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}

BuildQueryOptions(normalizedQueryParameters);
Original file line number Diff line number Diff line change
@@ -77,6 +77,12 @@ internal ComputeQueryOption(string rawValue, ODataQueryContext context)
context.NavigationSource,
new Dictionary<string, string> { { "$compute", rawValue } },
context.RequestContainer);

if (context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}
}

/// <summary>
Original file line number Diff line number Diff line change
@@ -73,6 +73,12 @@ internal CountQueryOption(string rawValue, ODataQueryContext context)
context.NavigationSource,
new Dictionary<string, string> { { "$count", rawValue } },
context.RequestContainer);

if (context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}
}

/// <summary>
Original file line number Diff line number Diff line change
@@ -83,6 +83,12 @@ internal FilterQueryOption(string rawValue, ODataQueryContext context)
context.NavigationSource,
new Dictionary<string, string> { { "$filter", rawValue } },
context.RequestContainer);

if (context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}
}

/// <summary>
13 changes: 13 additions & 0 deletions src/Microsoft.AspNetCore.OData/Query/Query/OrderByQueryOption.cs
Original file line number Diff line number Diff line change
@@ -82,6 +82,13 @@ internal OrderByQueryOption(string rawValue, ODataQueryContext context, string a
context.NavigationSource,
new Dictionary<string, string> { { "$orderby", rawValue }, { "$apply", applyRaw } },
context.RequestContainer);

if (context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}

_queryOptionParser.ParseApply();
}

@@ -107,6 +114,12 @@ internal OrderByQueryOption(string rawValue, ODataQueryContext context)
context.NavigationSource,
new Dictionary<string, string> { { "$orderby", rawValue } },
context.RequestContainer);

if (context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver.EnableCaseInsensitive = true;
}
}

internal OrderByQueryOption(OrderByQueryOption orderBy)
Original file line number Diff line number Diff line change
@@ -76,6 +76,12 @@ internal SearchQueryOption(string rawValue, ODataQueryContext context)
context.NavigationSource,
new Dictionary<string, string> { { "$search", rawValue } },
context.RequestContainer);

if (context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}
}

/// <summary>
Original file line number Diff line number Diff line change
@@ -94,6 +94,11 @@ internal SelectExpandQueryOption(string select, string expand, ODataQueryContext
context.RequestContainer)
: null)
{
if (_queryOptionParser != null && context.RequestContainer == null)
{
// By default, let's enable the property name case-insensitive
_queryOptionParser.Resolver = ODataQueryContext.DefaultCaseInsensitiveResolver;
}
}

/// <summary>
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//-----------------------------------------------------------------------------
// <copyright file="ODataOrderByMoreTest.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.E2E.Tests.Extensions;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.TestCommon;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Linq;
using Xunit;

namespace Microsoft.AspNetCore.OData.E2E.Tests.ODataOrderByTest
{
public class ODataOrderByMoreTest : WebApiTestBase<ODataOrderByMoreTest>
{
public ODataOrderByMoreTest(WebApiTestFixture<ODataOrderByMoreTest> fixture)
:base(fixture)
{
}

protected static void UpdateConfigureServices(IServiceCollection services)
{
services.ConfigureControllers(typeof(BooksController));
services.AddControllers()
.AddOData(); // without any configuration
}

[Theory]
[InlineData("/books?orderby=ISBN&top=1")]
[InlineData("/books?orderby=isbn&top=1")]
[InlineData("/books?$orderby=ISBN&top=1")]
[InlineData("/books?$orderby=isbn&top=1")]
public async Task TestOrderBy_WithDifferentPropertyCase(string requestUri)
{
// Arrange
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri);
HttpClient client = CreateClient();

// Act
HttpResponseMessage response = await client.SendAsync(request);

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var resultArray = await response.Content.ReadAsObject<JArray>();

JObject objectItem = Assert.IsType<JObject>(Assert.Single(resultArray));
Assert.Equal(2, objectItem.Properties().Count());
Assert.Equal("063-6-920-02371-5", objectItem["isbn"]);
Assert.Equal(2, objectItem["id"]);
}
}

[ApiController]
[Route("[controller]")]
public class BooksController : ControllerBase
{
private static IList<Book> _books = new List<Book>
{
new Book
{
Id = 1,
ISBN = "978-0-321-87758-1"
},
new Book
{
Id = 2,
ISBN = "063-6-920-02371-5",
}
};

[HttpGet]
public IEnumerable<Book> Get(ODataQueryOptions<Book> queryOptions)
{
var queryable = (IQueryable<Book>)queryOptions.ApplyTo(_books.AsQueryable());
return queryable.ToList();
}
}

public class Book
{
public int Id { get; set; }
public string ISBN { get; set; }
}
}

1 comment on commit 1c029ad

@jholovacs
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not being merged into 8.2? The last 8.2 is broken.

Please sign in to comment.