Webapi: Concurrent requests with different $filters return invalid responses in OData 7.5+ (Including 8-prev3)

Created on 12 Jan 2021  路  5Comments  路  Source: OData/WebApi

Write a simple function which returns in memory fixed data
Call that function concurrently with different $fitlers
You'd expect results filtered based on the provided filter
But you'll see invalid responses

Assemblies affected

OData 7.5.4+ has this issue (including 8 prev3)
OData 7.5.2 and lower versions are fine

Reproduce steps

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddOData();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.Select().Filter().OrderBy().Count().Expand().MaxTop(100);
            endpoints.MapODataRoute("odata", "odata", GetEdmModel());
        });
    }

    IEdmModel GetEdmModel()
    {
        ODataConventionModelBuilder builder = new();

        builder.EntitySet<TestModel>("Test");

        return builder.GetEdmModel();
    }
}

public class TestModel
{
    public int Id { get; set; }
}

public class TestController : ODataController
{
    [HttpGet, EnableQuery, ODataRoute("Test")]
    public IQueryable<TestModel> Test()
    {
        return Enumerable.Range(1, 100)
            .Select(i => new TestModel
            {
                Id = i
            }).AsQueryable();
    }
}

[TestClass]
public class Test
{
    [TestMethod]
    public async Task Impl()
    {
        IHostBuilder hostBuilder = new HostBuilder()
            .ConfigureWebHost(webHost =>
            {
                webHost.UseTestServer();
                webHost.UseStartup<Startup>();
            });

        using IHost host = await hostBuilder.StartAsync();

        using HttpClient client = host.GetTestClient();

        var results = await Task.WhenAll(Enumerable.Range(1, 100).Select(i => client.GetCount(i)));

        foreach (var result in results)
        {
            Assert.AreEqual(100 - result.i, result.length);
        }
    }
}

public static class HttpClientExtensions
{
    public static async Task<(int i, int length)> GetCount(this HttpClient client, int i)
    {
        return (i, (await (await client.GetAsync($"odata/test?$filter=Id gt {i}")).EnsureSuccessStatusCode().Content.ReadFromJsonAsync<JsonElement>()).GetProperty("value").GetArrayLength());
    }
}

Expected result

The test should get passed all the time

Actual result

It gets passed on OData 7.5.2 and lower versions, but it fails on OData 7.5.4+

Additional detail

ODataConcurrentRequestsIssue.zip

Any time you switch between 7.5.4 and 7.5.2, perform clean/rebuild

regression

Most helpful comment

Fix has been made to both v7 and v8 repos.

All 5 comments

The user is asking for data in the following scenario:
Hey OData, please show me invoices of data on 01/05/2021, and OData is showing her data for 04/05/2020!
Why? Because another user is asking that period at the same time.
That broken nuget package (Version 7.5.4 should get unlist ASAP)
@xuzhg

@ysmoradi Thanks for reaching me.
I tested it. When I run request individually as:

image

And I changed the "Test()" method to return `IQueryable < TestModel >" as:

image

This change will hit the OData formatter and output the OData payload. Otherwise, it will go to the default ASP.NET Core Json formatter.

By the way, Is it related to the "Concurrent request"?

This has to be an effect of the same issue as https://github.com/OData/WebApi/issues/2390

The QueryOptions are no longer thread safe since PR #2362

Fix has been made to both v7 and v8 repos.

Thanks @RamjotSingh

Was this page helpful?
0 / 5 - 0 ratings

Related issues

davidmorissette picture davidmorissette  路  3Comments

LianwMS picture LianwMS  路  5Comments

johnhzhu picture johnhzhu  路  4Comments

abkmr picture abkmr  路  3Comments

christiannagel picture christiannagel  路  4Comments