{"id":3280,"date":"2019-04-27T17:32:22","date_gmt":"2019-04-28T00:32:22","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/odata\/?p=3280"},"modified":"2019-04-27T17:34:42","modified_gmt":"2019-04-28T00:34:42","slug":"supercharging-asp-net-core-api-with-odata","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/supercharging-asp-net-core-api-with-odata\/","title":{"rendered":"Supercharging ASP.NET Core API with OData"},"content":{"rendered":"<h3>Summary<\/h3>\n<p>In this article, I\u2019m going to show you how you can supercharge your existing ASP.NET Core APIs with OData to provide better experience for your API consumers with only 4 lines of code.<\/p>\n<p>For the purpose of this tutorial please clone our demo project WashingtonSchools so you can follow up and try the different features we are going to talk about in this article.<\/p>\n<p>You can clone the demo project from here:<\/p>\n<p><a href=\"https:\/\/github.com\/hassanhabib\/ODataDemo\">https:\/\/github.com\/hassanhabib\/ODataDemo<\/a><\/p>\n<p>&nbsp;<\/p>\n<h3>What is OData?<\/h3>\n<p>Let\u2019s talk about OData \u2026<\/p>\n<p>OData is an open source, open protocol technology that provides the ability to API developers to develop Queryable APIs, one of the most common things API developers need is pagination for instance.<\/p>\n<p>With OData you can enable pagination, ordering of data, reshaping and restructuring of the data and much more with only 4 lines of code.<\/p>\n<p>One of the most common scenarios today is when developers call an endpoint and pull out data that they are going to filter, reshape and order later on the client side.\nThis seems a bit wasteful. especially if the data is large enough that could cause latency and require further optimizations for a better user experience.<\/p>\n<p>&nbsp;<\/p>\n<h3>Getting Started<\/h3>\n<p>To get this started, this tutorial assumes you already have an API that provides some list of objects to your end users, for the purpose of this tutorial, we are going to use a sample WashingtonSchools API project that we built to demonstrate this feature.<\/p>\n<p>Our API endpoint api\/students returns all the students available in our database.<\/p>\n<p>To enable OData on that endpoint, we are going to need to install a nuget package for all OData binaries that\u2019ll enable us to turn our endpoint into a Queryable endpoint.<\/p>\n<p>The nuget package we are targeting here is:<\/p>\n<p><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData\">https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Once that\u2019s installed, let\u2019s go ahead and add OData services to our API.<\/p>\n<p>To do that, go to: Startup.cs file and add in this line of code in your ConfigureServices Function:<\/p>\n<pre class=\"lang:default decode:true\">services.AddOData();<\/pre>\n<p>Now we need to enable the dependency injection support for ALL HTTP routes.<\/p>\n<p>To do that, in the same file Startup.cs let\u2019s go to the Configure function and add these two lines of code:<\/p>\n<pre class=\"lang:default decode:true\">app.UseMvc(routeBuilder =&gt; {\r\n\r\n\u00a0\u00a0\u00a0\u00a0 routeBuilder.EnableDependencyInjection();\r\n\r\n     routeBuilder.Expand().Select().OrderBy().Filter();\r\n\r\n});<\/pre>\n<p>&nbsp;<\/p>\n<p>The first line of code enables the dependency injection to inject OData services into your existing API controller.<\/p>\n<p>The second line of code determines which OData functionality you would like to enable your API consumers to use, we will talk about Expand, Select and OrderBy in details shortly after we complete the setup of OData on your project.<\/p>\n<p>The last line of code we would want to add is an annotation on top of your API controller method, in our example here, we have a StudentsController class that has a GetStudents method to server all the available students in our database.<\/p>\n<p>Now all we need to do is to add this annotation on top of your GetStudents endpoint as follows:<\/p>\n<pre class=\"lang:default decode:true \">[EnableQuery]<\/pre>\n<p>&nbsp;<\/p>\n<p>So your controller method code should look like this:<\/p>\n<pre class=\"lang:default decode:true\">[HttpGet]\r\n\r\n[EnableQuery]\r\n\r\npublic IEnumerable&lt;Student&gt; GetStudents(){\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return this.context.Students;\r\n\r\n}<\/pre>\n<p>Now that the setup is done, let\u2019s test OData select, OrderBy and expand functionality.<\/p>\n<p>&nbsp;<\/p>\n<h3>Select<\/h3>\n<p>On your favorite API testing software or simply in the browser since this is a GET endpoint, let\u2019s try to select only the properties that we care about from the students objects.<\/p>\n<p>If the students object consists of an ID, Name and we care only about the Name, we could call our endpoint like this:<\/p>\n<pre class=\"lang:default decode:true\">api\/students?$select=Name<\/pre>\n<p>The results will be a json list of students that only has the Name property displayed. try different combinations such as:<\/p>\n<pre class=\"lang:default decode:true\">api\/students?$select=ID,Name<\/pre>\n<p>The select functionality enables you to control and reshape the data to fit just your need, it makes a big difference when your objects hold large amounts of data, like image data for instance that you don\u2019t really need for a specific API call, or rich text that is contained within the same object, using select could be a great optimization technique to expedite API calls and response time.<\/p>\n<p>&nbsp;<\/p>\n<h3>OrderBy<\/h3>\n<p>The next functionality here is the OrderBy, which allows you to order your students based on their names alphabetically or their scores, try to hit your endpoint as follows:<\/p>\n<pre class=\"lang:default decode:true\">api\/students?$orderby=Name<\/pre>\n<p>You can also do:<\/p>\n<pre class=\"lang:default decode:true \">api\/students?$orderby=Score desc<\/pre>\n<p>&nbsp;<\/p>\n<h3>Expand<\/h3>\n<p>One other functionality we want to test here is the expand. The expand functionality comes with a great advantage since it allows navigation across multiple entities.<\/p>\n<p>In our example here, Students and Schools are in a many-to-one relationship, we can pull the school every student belongs to by making an expand call like this:<\/p>\n<pre class=\"lang:default decode:true\">api\/students?$expand=School<\/pre>\n<p>Now we get to see both students and their schools nested within the same list of objects.<\/p>\n<p>&nbsp;<\/p>\n<h3>Filter<\/h3>\n<p>The last functionality here is the Filter. Filtering enables you to query for a specific data with a specific value, for instance, If I\u2019m looking for a student with the name Todd, all I have to do is to make an API call as follows:<\/p>\n<pre class=\"lang:default decode:true\">api\/students?$filter=Name eq \u2018Todd\u2019<\/pre>\n<p>The call will return all students that have the name Todd, you can be more specific with certain properties such as scores. For instance: if I want all students with scores greater than 100, I could make the following API call:<\/p>\n<pre class=\"lang:default decode:true\">api\/students?filter=Score gt 100<\/pre>\n<p>There are more features in OData that enables even more powerful API functionality that I urge you to explore such as MaxTop for pagination.<\/p>\n<p>&nbsp;<\/p>\n<h3>Final Notes<\/h3>\n<p>Here are few things to understand about OData:<\/p>\n<ol>\n<li>OData has no dependency whatsoever on the entity framework, it can come in handy with EF but it doesn\u2019t depend on it, here\u2019s a project that runs an OData API without EF: <a href=\"https:\/\/github.com\/hassanhabib\/ODataWithoutEF\">https:\/\/github.com\/hassanhabib\/ODataWithoutEF<\/a><\/li>\n<li>OData can give you more optimization with EF if you use IQueryable as a data return type that IEnumerable since IQueryable only evaluates after the query is built and ready to be executed.<\/li>\n<li>OData is much older than any other similar technology out there, it was released officially in 2007 and it has been around since then being used in large scale applications such as Microsoft Graph which feeds most of Microsoft Office products and XBOX in addition to Microsoft Windows.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h3>The Future of OData<\/h3>\n<p>OData team continues to improve the feature and make it even easier and simpler to use and consume on existing and new APIs with both ASP.NET Web API (classic) or ASP.NET Core and we are working on adding even more powerful features in the near future.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary In this article, I\u2019m going to show you how you can supercharge your existing ASP.NET Core APIs with OData to provide better experience for your API consumers with only 4 lines of code. For the purpose of this tutorial please clone our demo project WashingtonSchools so you can follow up and try the different [&hellip;]<\/p>\n","protected":false},"author":3348,"featured_media":3286,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,117],"tags":[],"class_list":["post-3280","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata","category-webapi"],"acf":[],"blog_post_summary":"<p>Summary In this article, I\u2019m going to show you how you can supercharge your existing ASP.NET Core APIs with OData to provide better experience for your API consumers with only 4 lines of code. For the purpose of this tutorial please clone our demo project WashingtonSchools so you can follow up and try the different [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/3280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/users\/3348"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=3280"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/3280\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media\/3286"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media?parent=3280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=3280"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=3280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}