API hangs while building OData EdmModel, but only when deployed to Azure

82 Views Asked by At

I have a ASP.NET Web API with OData running on .NET 4.6.1 and in an Azure App Service. During startup, it builds and registers an OData EdmModel for a couple very simple entities. It hangs while building the EdmModel, CPU usage spikes to 100%, becomes unresponsive, and the AppService eventually kills and restarts the process. This is a recent issue.

I've reduced it down to this example:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration configuration)
{
    var odataBuilder = new ODataConventionModelBuilder();
    odataBuilder.EntitySet<Foo>("Foos");
    var edmModel = builder.GetEdmModel(); // hangs here

    app.UseMvc(builder => builder.MapODataServiceRoute("odata", "odata", edmModel, new DefaultODataBatchHandler());
}

Where Foo is a simple class with a handful of int, long, string, and DateTimeOffset fields. I've tried it with and without an associated controller at odata/Foos, with the same result either way.

Removing odataBuilder.EntitySet<Foo>("Foos"); avoids the issue, but is obviously not very useful.

Any ideas to further troubleshoot this?

I've also updated the OData packages to the latest 7.x version. I should also note that this is a recent issue, and there haven't been any changes that are obviously related to this code.

1

There are 1 best solutions below

0
Suresh Chikkam On

Thanks @Marc_s, yes as marc_s said Update the target framework in your project file to a more recent version, such as net6.0 or later.

<TargetFramework>net6.0</TargetFramework>

enter image description here

  • Integrated the GetEdmModel method to build and register the OData EdmModel. Build the EdmModel asynchronously to avoid blocking the main thread. The GetEdmModel method might be causing the hang due to synchronous execution.

Program.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.OData.Builder;
using Microsoft.AspNetCore.OData.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OData.Edm;

namespace WebApplication10
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddControllers();
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();
            app.UseAuthorization();

            // Build and register OData EdmModel
            var edmModel = GetEdmModel();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapODataRoute("odata", "odata", edmModel);
                endpoints.MapControllers();
            });

            app.Run();
        }

        private static IEdmModel GetEdmModel()
        {
            var odataBuilder = new ODataConventionModelBuilder();
            odataBuilder.EntitySet<Foo>("Foos");
            return odataBuilder.GetEdmModel();
        }
    }
}

OData message:

enter image description here

  • I also observed a typographical error in the variable names that you define the ODataConventionModelBuilder as odataBuilder, but then you attempt to get the EdmModel using builder.GetEdmModel();. This mismatch in variable names is likely causing the NullReferenceException, and the application hangs when trying to build the EdmModel.

Code:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration configuration)
{
    var odataBuilder = new ODataConventionModelBuilder();
    odataBuilder.EntitySet<Foo>("Foos");
    var edmModel = odataBuilder.GetEdmModel(); // Corrected variable name

    app.UseMvc(builder => builder.MapODataServiceRoute("odata", "odata", edmModel, new DefaultODataBatchHandler()));
}