Skip to content

Conversation

xuzhg
Copy link
Member

@xuzhg xuzhg commented Dec 15, 2023

Fixes #578

Minimal APIs are a simplified approach for building fast HTTP APIs with ASP.NET Core. You can build fully functioning REST endpoints with minimal code and configuration. Skip traditional scaffolding and avoid unnecessary controllers by fluently declaring API routes and actions. For example, the following code creates an API at the root of the web app that returns the text, "Hello World!".

var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();

Customer want to get the OData query options functionalities. We can provide couple solutions

  1. Get OData JSON payload for minimal API

  2. Enable customer to apply OData query to IQueryable explicitly.

  3. Enable customers to apply OData query to IQueryable implicitly.

@habbes
Copy link
Contributor

habbes commented Jan 4, 2024

Happy to see some progress on minimal API support @xuzhg
Would you consider adding more context or a more detailed breakdown of the PR implementation?

Also can you clarify the extent of OData features we support in this PR and what do not support (and do not plan to support).
I assume OData routing is not supported at all. Does this support model binding? Delta? Or is support restricted to only ODataQueryOptions<T>?

@xuzhg
Copy link
Member Author

xuzhg commented Jan 4, 2024

Happy to see some progress on minimal API support @xuzhg Would you consider adding more context or a more detailed breakdown of the PR implementation?

Also can you clarify the extent of OData features we support in this PR and what do not support (and do not plan to support). I assume OData routing is not supported at all. Does this support model binding? Delta? Or is support restricted to only ODataQueryOptions<T>?

Happy to see some progress on minimal API support @xuzhg Would you consider adding more context or a more detailed breakdown of the PR implementation?

Also can you clarify the extent of OData features we support in this PR and what do not support (and do not plan to support). I assume OData routing is not supported at all. Does this support model binding? Delta? Or is support restricted to only ODataQueryOptions<T>?

Thanks for your feedback. Actually, the product codes in the PR changed less.

OData routing

In my understanding, most of customers only want to get the 'OData Query functionalities" when building the minimal API. They don't want to know "Entity Type, Complex Type", or "Entity set, Singleton, Navigation Source, Navigation Property", concepts like these. Even thought they don't want to know about "Key Segement" and It should come after "Collection Segement". So, there's no "OData routing" at all. However, we can add "OData routing" mechanise, for example:

app.MapOData<ODataServiceContext>(EdmModel);

Where, ODataServiceContext is a class containing OData routings.

Does this support model binding?

In my understanding, ASP.NET Core doesn't add model binding for minimal API. So we can't add it. In the minimal API, it only contains the parameter binding, it's same as "model binding" and most of logics are same. For example, You can put [FromBody] on the parameter to bind the parameter from request body. There's new solution to customize the parameter binding. That's what I used in my PR to binding the ODataQueryOptiont< T >.

Delta< T > ? DeltaSet< T >

I think we should support to bind those types. I also added the comments in my PR to support them. It could be a little bit same as ODataQueryOption< T > implementation. It's not complicated but I think let's do it step by step. Before implementing it, let's finish our first BrainStorm on the initial design.

To Be Discussion

OData payload is JSON payload. I think it's time to consider to use Default Json serializer/deserializer. The only thing is to implement the JsonConverter on the OData object. We can sync it more later.

@julealgon
Copy link
Contributor

OData payload is JSON payload. I think it's time to consider to use Default Json serializer/deserializer. The only thing is to implement the JsonConverter on the OData object. We can sync it more later.

AntonioBanderasOhGIF

Honestly... this would be the biggest improvement to OData in years and would avoid so many problems.

At the same time... seems ambitious to consider that alongside the Minimal API changes 😅. As much as I want that, I'd avoid doing them together, or potentially even in the same release.

@robertmclaws
Copy link
Contributor

It would be ABSOLUTELY AMAZING if OData switched to out-of-the-box System.Text.Json serialization with converters. I think it would improve perf by at least 50%, and I wouldn't be surprised if you saw a 200-400% improvement.

Probably needs a separate work branch tho. Hopefully the unit tests are designed to be able to handle this.

Happy to help wherever possible.

@habbes
Copy link
Contributor

habbes commented Jan 17, 2024

I agree we stand to gain a lot from leveraging System.Text.Json. But it's not a trivial change given all the scenarios that OData's current serialization supports as well as adherence to the OData spec. However, this is something we're currently looking into. I'll share results from the progress soon. (see: OData/odata.net#2798)

Copy link
Contributor

@habbes habbes left a comment

Choose a reason for hiding this comment

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

Will you add tests?


namespace ODataMiniApi;

public class MetadataHandler
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that this is in the sample project, does this mean this is something the customer will have to write, or does this work out of the box?

SkipValidation = false
};

// we can't use response body directly since ODL writes the JSON CSDL using Synchronous operations.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we prioritize making this async in ODL?

app.MapGet("/customized/schools", (AppDb db, ODataQueryOptions<School> options) => {
db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
return options.ApplyTo(db.Schools);
}).UseOData("customized"); // In customized OData, MailAddress and Student are complex types, you can also use 'IODataModelConfiguration'
Copy link
Contributor

Choose a reason for hiding this comment

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

How would you use IODataModelConfiguration?

/// </summary>
/// <param name="context">The HttpContext.</param>
/// <param name="builder">The <see cref="ODataModelBuilder">builder</see> used to apply configurations.</param>
void Apply(HttpContext context, ODataModelBuilder builder);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we envision that more arguments could be needed in the future, such that we could use an ODataModelConfiguratonOptions class to encapsulate the options, or is an ODataModelBuilder sufficient?

/// Supports converting <see cref="SelectExpandWrapper{T}"/> types by using a factory pattern.
/// </summary>
internal class SelectExpandWrapperConverter : JsonConverterFactory
public class SelectExpandWrapperConverter : JsonConverterFactory
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this made public?

/// A cache for <see cref="Endpoint"/> and <see cref="IEdmModel"/> mapping.
/// It's typically used for minimal API scenario.
/// </summary>
public interface IODataEndpointModelMapper
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the likelihood that the customer will want to customize this? Maybe we should make it internal until there's explicit/clear demand from the customer to make it extensible, that way it can give us room to change the design without breaking changes.

@danielpastoor
Copy link

Is there any update on this pull-request?

@cbrianball
Copy link

Can this please be merged?! I would really like to use minimal API with OData!

@cbrianball
Copy link

One thing I have noticed is that the response from the minimal API endpoints just have the "bare" data. Meaning it doesn't have "@odata.context" field and then the result in a "value" field. If there is a way to have this, please include an example.

@julealgon
Copy link
Contributor

One thing I have noticed is that the response from the minimal API endpoints just have the "bare" data. Meaning it doesn't have "@odata.context" field and then the result in a "value" field. If there is a way to have this, please include an example.

That's likely unintentional. That response body is a critical part of the OData protocol and needs to be kept intact.

@asyncoder
Copy link

Any updates on this?

@mike-bagheri
Copy link

mike-bagheri commented Oct 8, 2024

Any new on this one? Is there any plan to release this?

@mguinness
Copy link

mguinness commented Jan 31, 2025

@xuzhg It's been a year since you last worked on this PR, are there any blockers? @mikepizzo The original issue has 28 upvotes, is this something that is considered?

EDIT: See new PR #1431

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ASP.NET Core OData 8.x does not work with Minimal API

10 participants