OData / AspNetCoreOData

ASP.NET Core OData: A server library built upon ODataLib and ASP.NET Core
Other
454 stars 160 forks source link

No EDM model in action request #356

Open Robelind opened 2 years ago

Robelind commented 2 years ago

Microsoft.AspNetCore.OData 8.0.3

EDM model

builder.EntitySet<TestA>("TestAs");
builder.EntityType<TestA>().Action("Test")
    .ReturnsCollectionFromEntitySet<TestA>("TestAs");

Controller

public class TestAsController : ODataController
{
    [HttpPost]
    public IActionResult Test()
    {
        return (Created(new[] { new TestA(), new TestA() }));
    }
}

Request

POST /api/TestAs/Test HTTP/1.1
OData-MaxVersion: 4.0
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8

Result

HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Wed, 03 Nov 2021 12:35:05 GMT

System.InvalidOperationException: The request must have an associated EDM model. Consider registering Edm model calling AddOData().
   at Microsoft.AspNetCore.OData.Results.ResultHelpers.GenerateODataLink(HttpRequest request, Object entity, Boolean isEntityId)
   at Microsoft.AspNetCore.OData.Results.CreatedODataResult`1.GenerateLocationHeader(HttpRequest request)
   at Microsoft.AspNetCore.OData.Results.CreatedODataResult`1.ExecuteResultAsync(ActionContext context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|28_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)

HEADERS
=======
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
OData-MaxVersion: 4.0

What am I doing wrong here?

xuzhg commented 2 years ago

@Robelind I am a little bit confusing.

Since you said it's non-Edm, but you create the Edm model.

Since you have the Edm model created, do you config it in the startup.cs?

Please take a look the samples in sample folder.

Robelind commented 2 years ago

Yes, I config it in startup.cs, as displayed under the header EDM model. I do not say it's non-Edm. It's ASP.Net that says the request doesn't have an associated EDM model. Please read again.

xuzhg commented 2 years ago

@Robelind How can you route to IActionResult Test(), since it cannot meet conventional routing and I don't see 'attribute routing template` on the action.

Can you share with me your repo or repro?

Robelind commented 2 years ago

Repro.zip

qwertie commented 2 years ago

I got this error message when I switched from "endpoint routing" (whatever that means) to "UseMvc" (whatever that means).

i.e. OData is set up like this

        mvc.AddOData(opt => opt.AddRouteComponents("odata", OurDataModel.Get())
           .Select().Filter().OrderBy().Count().Expand().SkipToken());

and then I commented out this in Startup.cs...

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "api/{apiVersion}/{controller}/{action=Index}/{id?}");
        });

and introduced this...

        // in ConfigureServices
        IMvcBuilder mvc = services.AddControllers(options => {
            options.EnableEndpointRouting = false; // this line is new
        });

        // in Configure()
        app.UseMvc(routeBuilder => { });

After that, regular controllers kept working, but OData broke; /odata/$metadata says "The request must have an associated EDM model. Consider registering Edm model calling AddOData()."

xuzhg commented 2 years ago

@qwertie let's forget UseMvc?

surajrautela commented 8 months ago

Any update on this @qwertie . I am still facing the same issue

julealgon commented 8 months ago

@qwertie / @Robelind / @surajrautela a suggestion to all of you is to always double check your endpoints are actively being detected as OData endpoints using the route debug view with $odata. Please check the readme for more information on that debug endpoint.

If they are not being detected as OData, you are either not properly using expected conventions, or you are using non-matching attribute-based routes.

qwertie commented 7 months ago

Sorry @surajrautela, I don't understand this stuff, I'm simply not using UseMvc although I have a call to IServiceCollection.AddMvcCore. My Configure looks like this (but I don't need to serve pages, only APIs):

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) {
        app.UseResponseCompression();
        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
            app.UseOpenApi();
            app.UseSwaggerUi3();
        }
        app.UseCors();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints => {
            // Unknown purpose. Without this, all controllers report 404
            endpoints.MapControllerRoute(name: "default", pattern: "api/{apiVersion}/{controller}/{action=Index}/{id?}");
        });
    }