Build with an Azure free account. Get USD200 credit for 30 days and 12 months of free services.

Start free today

Supercharging your Web APIs with OData and ASP.NET Core

Sign in to queue

Description

OData (Open Data Protocol) is an ISO/IEC approvedOASIS standard that defines a set of best practices for building and consuming Web APIs.

In this episode, Hassan Habib joins Jeremy to show us how we can easily add OData support to an existing Web API built with ASP.NET Core.

  • [01:26] - What is OData?
  • [04:38] - Demo
  • [07:18] - How can you add OData to an existing Web API?
  • [12:54] - How can you shape the results of a Web API call?
  • [14:13] - How can you define ordering with OData?
  • [15:07] - How can you include related entities?
  • [16:04] - How can you enable filtering?

 

Useful Links

 

Embed

Download

The Discussion

  • User profile image
    Pankaj Nikam
    Hi Hassan,

    Your demo was super cool and as promised it was really four lines of code :) I was a bit sceptical when I heard this first, however, you proved me wrong. Thanks!

    One small question, how do you compare OData with GraphQL. What would be the best use case to use OData over GraphQL?

    Thanks.
  • User profile image
    Rich

    Here is one comparison of GraphQL and OData: https://jeffhandley.com/2018-09-13/graphql-is-not-odata

  • User profile image
    lucianoc
    Is OData magically using the DbContext on the controller? Or is it performing all those operation with what is returned from the method?
  • User profile image
    lucianoc
    just tried it, it looks like is using the response of the method as data source. This is great. So no matter your back-end you can expose server side query operations.
  • User profile image
    Tom

    @lucianoc I was wondering the same. I'm not sure what I would prefer. If the EF queries are altered it wont work with repositories (only demo implementations query their db context in the api controller methods). On the other hand if odata works on the response then you have quite a substantial overhead on the sql compared to specialized methods. If you have a complex or large data set you cannot return everything and filter it after it is loaded.

  • User profile image
    fabianorosa
    Hi Hassan, could you share the sample source code?
  • User profile image
    hassanhabib
    Of course this is the source code:
    https://github.com/hassanhabib/ODataDemo
  • User profile image
    Gagandeep

    Awesome!

  • User profile image
    hassanhabib
  • User profile image
    Richard

    How would you see this working in scenarios where you don't use your dbContext in your controller and you map to DTO's (in our case using automapper).

    Your public contracts/models will look very different to your DB model and you would want the user to use your public models properties in their odata operations - but you would need to pass your DB queries using the db entity properties.

    Many people never use dbcontexts directly in controllers, either using a Repository/UnitOfWork or Service type pattern.

  • User profile image
    dotman007
    This is wonderful
    Nice Presentation
  • User profile image
    Hans

    Thanks very much for the demo Hassanhabib. I have used odata a few years ago with the dotnet framework and even though it did a good job for us at the time I didn't like that it wasn't well integrated into our existing webapi controllers. This seem to have changed now - which is great! I was wondering about the missing EDM setup in your demo. Could you speak to that a bit? Also, I didn't see any ODATA related tags, e.g. @odata.context: "..." , coming through in the JSON that is being returned from your controller. Is that because you didn't setup EDM for your entities?

  • User profile image
    hassanhabib
    @Richard - OData isn't really dependent on EF, you don't have to use a context in your controller to have OData work, all you have to have in your controller is returning a list of IQueryable or IEnumerable and OData does the work of filtering and selecting ...etc.
  • User profile image
    hassanhabib
    @Hans - so this video was just an introduction for OData to integrate it with an existing API, in the next few videos we are going to build OData from scratch with EDM and tags ... etc.
    The idea of this video was simply to show to things:
    1. How simple is integrating OData with an existing API.
    2. How OData works from a request/response perspective.
    We will follow up with more videos around OData on .NET Framework existing APIs, OData with EDM and many other subjects in depth.
  • User profile image
    Doron Grinzaig

    Curious why one would prefer OData over GraphQL.
    OData was adopted by only a tiny portion of the industry, unlike GraphQL.

  • User profile image
    silky01
    amazing , made me happy!
  • User profile image
    aspleo
    Nice demo Hassan. Just curious as to why the Odata 'select' operator performs a proper casing on the db field names. So firstName comes back as FirstName. 'filter' operator doesn't do that.
  • User profile image
    Luciano Evaristo Guerche

    Just noted when using $select, "Name" and "Score" have their names capitalized on the json result. On a javascript client it may cause a lot of headache to figure out why client stopped working.

  • User profile image
    Luciano Evaristo Guerche

    Actually, I guess the problem is that after adding $select to the URL json serialization change behaviour and stopped using camelCase in favor of PascalCase. As javascript is case sensitive, on code like {{ student.name }} there won't be shown any values afterwards. Moreover, no error will be displayed on console.

  • User profile image
    OzBobWa
    Could you please explain how to limit the object graph of the dependant children when using $expand, in this example returning only the ProductIds?:
    https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/using-select-expand-and-value#using-expand

    Filtered EF Includes is a big long discussion going back to 2015 with Rowan Miller: https://github.com/aspnet/EntityFrameworkCore/issues/1833#issuecomment-475905184

    Where is the extension point for Microsoft.AspnetCore.OData that would allow $expand to make use a Global Query(https://docs.microsoft.com/en-au/ef/core/querying/filters)?
  • User profile image
    dynamite

    Great demo. Is it possible to make this demo work with Cosmos database back end? If so, how do I go about it?
  • User profile image
    dunder

    What about Dapper? How do you construct Dapper queries based on the OData context?

  • User profile image
    Dzivo

    @hassanhabib

    For us who are using

    @Richard - OData isn't really dependent on EF, you don't have to use a context in your controller to have OData work, all you have to have in your controller is returning a list of IQueryable or IEnumerable and OData does the work of filtering and selecting ...etc.

    So is there an example where we can pass query strings to odata and IQuer<able and get the dynamic response back so that we can use API wrapper and IActionResult and DTO to BAL mapping.
    Since we would really like to keep our controlles without any logic.

    We already did something with exsiting odata:
    Behind this ODataQuery is a whole library but we would like to stop developing it since it is obsolete
    now if we could find out how to do something similar this way.

    public IActionResult Get(int offset, int limit, string orderBy = null, string filter = null)
    {
    var oDataQuery = new ODataQuery(filter: filter, orderBy: orderBy, skip: offset, top: limit);
    var (dalResponse, count) = this._productOdataService.GetPage(oDataQuery, null, _include, null);
    var mappedResponse = MapToList(dalResponse);
    var response = new ApiPaginatedResponse<IEnumerable<API.Product>>(mappedResponse, count, true);
    return new ApiObjectResult(response);
    }


  • User profile image
    Michael_​Lechthaler
    Hi Hassan,
    Thanks for the great demo. I implemented OData in one of my existing controllers - works great so far! Unfortunately now my Swagger documentation page is broken (System.InvalidOperationException: No media types found in 'Microsoft.AspNet.OData.Formatter.ODataOutputFormatter.SupportedMediaTypes'. Add at least one media type to the list of supported media types.). Any ideas of how to fix this?

  • User profile image
    Brendan Knowles

    Hassan - this was *EXACTLY* what I needed after thinking I couldn't add OData to my existing endpoints in a simplistic way. Thanks so much!

  • User profile image
    LawrenceFej

    @Hassanhabib First of all thanks for video, 4 lines of code was surprising but it actually works. I am however having an issue with the count. $count=true does not return the count and using $count throws an exception "ExceptionMessage": "The value for OData query '$count' cannot be empty.". am i doing something wrong or is this just a limitation of the 4 lines of code implementation you showed. PS I made sure to add .count() to the routebuilder.

  • User profile image
    kix

    Hi Hassan,

    This is a great tool and video. Just a quick question, will this be supported in the upcoming Asp.Net Core 3.0? and how will it be implemented in the startup using VS2019.


    Thanks!

  • User profile image
    kix

    Here's the default startup.cs once you create a new project from VS2019.

    public void ConfigureServices(IServiceCollection services)
    {
    services.AddControllers()
    .AddNewtonsoftJson();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    else
    {
    app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    });
    }

  • User profile image
    sachana
    Hi Hasan,
    Is there any way we can apply this OData filters through request body instead of query parameters for get method?

  • User profile image
    flipdoubt
    @hassanhabib, thanks for the great intro. Still waiting for the followups and details on using OData with Dapper and other data-access methods in AspNet Core.
  • User profile image
    olamidejame​s007
    Hello Hassan,

    Please as this issue, https://github.com/aspnet/EntityFrameworkCore/issues/8531 been fixed?.

    Loading related entities using ODATA causes Database RoundTrip.

    Regards
  • User profile image
    flipdoubt
    Can anyone point to an example of how to get the unfiltered count back so I can page the data?
  • User profile image
    Sally

    Hi Hasan,
    I am consuming OData web services published by Microsoft NAV with "Add service reference" tool on (VS c#.net 20015 web application).
    upgrading to vs 2019 I am struggling to map the services tried Connected services Unchase OData with no success services have username/password and it fail on The OData service requires authentication for accessing it.

    Any recommendation on how to add service reference?

  • User profile image
    Keerthi

    Hi,

    I have created a Web Api using Asp.net core 2.2 , I am using swagger for documentation of Api's , When I tried to integrate the OData with Swagger configured api it is throwing error what could be the issue ..

    BR, Keerthi

Add Your 2 Cents