{"id":2685,"date":"2018-07-03T23:38:18","date_gmt":"2018-07-03T23:38:18","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/?p=2685"},"modified":"2020-04-06T16:01:00","modified_gmt":"2020-04-06T23:01:00","slug":"asp-net-core-odata-now-available","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/asp-net-core-odata-now-available\/","title":{"rendered":"ASP.NET Core OData now Available"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>The Microsoft OData Team is proud to announce general availability (GA) of OData (<a href=\"https:\/\/odata.org\">Open OData Protocol<\/a>) on ASP.NET Core 2.0. It is now available through Nuget package at <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData\">https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData<\/a>, current its version is 7.0.0.<\/p>\n<p>Along this release, it will allow customers to create OData v4.0 endpoints and leverage the OData query syntax easily on multiple platforms, not only on Windows.<\/p>\n<p>This blog is intended to give you a tutorial about how to build\/consume OData service through ASP.NET Core OData package. Let\u2019s getting started.<\/p>\n<h2>ASP.NET Core Web Application<\/h2>\n<p>For simplicity, we will start by creating a simple ASP.NET Core Web Application called\u00a0<strong>BookStore<\/strong>.<\/p>\n<h2>Create Visual Studio Project<\/h2>\n<p>In Visual studio 2017, from the \u201c<strong>File<\/strong>\u201d menu, select \u201c<strong>New<\/strong> &gt; <strong>Project \u2026<\/strong>\u201d.<\/p>\n<p>In the \u201c<strong>New Project<\/strong>\u201d dialog, select \u201c<strong>.NET Core<\/strong>\u201d and pick \u201c<strong>ASP.NET Core Web Application<\/strong>\u201d template, give a name as \u201c<strong>BookStore<\/strong>\u201d and set up the location, see the following picture:<\/p>\n<p><a href=\"http:\/\/devblogs.microsoft.com\/odatateam\/wp-content\/uploads\/sites\/23\/2018\/07\/newdialog.png\"><img decoding=\"async\" class=\"aligncenter wp-image-2695 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newdialog.png\" alt=\"\" width=\"939\" height=\"651\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newdialog.png 939w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newdialog-300x208.png 300w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newdialog-768x532.png 768w\" sizes=\"(max-width: 939px) 100vw, 939px\" \/><\/a><\/p>\n<p>Click &#8220;<strong>OK<\/strong>&#8221; button, then in the \u201c<strong>New ASP.NET Core Web Application \u2013 BookStore<\/strong>\u201d dialog, select \u201cAPI\u201d and\u00a0un-check the &#8220;<strong>Configure for HTTPs<\/strong>&#8221; for simplicity as below:<\/p>\n<p><a href=\"http:\/\/devblogs.microsoft.com\/odatateam\/wp-content\/uploads\/sites\/23\/2018\/07\/newAspnetWeb.png\"><img decoding=\"async\" class=\"aligncenter wp-image-2705 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newAspnetWeb.png\" alt=\"\" width=\"787\" height=\"551\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newAspnetWeb.png 787w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newAspnetWeb-300x210.png 300w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2018\/07\/newAspnetWeb-768x538.png 768w\" sizes=\"(max-width: 787px) 100vw, 787px\" \/><\/a><\/p>\n<p>Click \u201c<strong>Ok<\/strong>\u201d button, we will get an empty ASP.NET Core Web Application project.<\/p>\n<h2>Install the Nuget Package<\/h2>\n<p>Once the empty application has been created, the first thing is to install the ASP.NET Core OData Nuget package from <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData\">Nuget.org<\/a>. In the solution explorer, right click on \u201c<strong>Dependencies<\/strong>\u201d in the <strong>BookStore<\/strong> project and select \u201c<strong>Manage Nuget Packages<\/strong>\u201d into the Nuget packages Management dialog. In this dialog, Search and select \u201c<strong>Microsoft.AspNetCore.OData<\/strong>\u201d package and click the install button to install the package into the Web application.See the below picture:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-2715 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odatateam\/wp-content\/uploads\/sites\/23\/2018\/07\/nugetpackage-1.png\" alt=\"\" width=\"1227\" height=\"501\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/\">EF Core<\/a> is also used in this tutorial, so do the same process to install \u201c<strong>Microsoft.EntityFrameworkCore.InMemory<\/strong>\u201d and its dependencies (for simplicity, we use <em>In Memory<\/em> data source).<\/p>\n<p>Now, we have the following project configuration:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/43e2a08244c464804a8dfe5d945b3acf.js\"><span class=\"mce_SELRES_end\" style=\"width: 0px; line-height: 0; overflow: hidden; display: inline-block;\" data-mce-type=\"bookmark\">\ufeff<\/span><\/script><\/p>\n<h2>Add the Model classes<\/h2>\n<p>A model is an object representing the data in the application. In this tutorial, we use the POCOs (<strong>P<\/strong>lain <strong>O<\/strong>ld <strong>C<\/strong>LR <strong>O<\/strong>bject) classes to represent our book store models.<\/p>\n<p>Right click <strong>BookStore<\/strong> project in the solution explorer, from the popup menu, select <strong>Add<\/strong> &gt; <strong>New Folder<\/strong>. Name the folder as <em>Models<\/em>. Add the following classes into the <em>Models<\/em> folder:<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/871e540a3f7e9634c374398b68655523.js\"><\/script><\/p>\n<p>Where:<\/p>\n<ul>\n<li><strong>Book, Press<\/strong> will be served as <em>Entity<\/em> types<\/li>\n<li><strong>Address<\/strong> will be served as a <em>Complex<\/em> type.<\/li>\n<li><strong>Category<\/strong> will be served as an <em>Enum<\/em> type.<\/li>\n<\/ul>\n<h2>Build the Edm Model<\/h2>\n<p>OData uses the Entity Data Model (EDM) to describe the structure of data. In ASP.NET Core OData, it\u2019s easily to build the EDM Model based on the above CLR types. So, add the following private static method at the end of class \u201c<strong>Startup<\/strong>\u201d.<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/2528597c2c9d81ba81a64a6f06d0fd1e.js\"><\/script><\/p>\n<p>Where, we define two entity set named \u201c<strong>Books<\/strong>\u201d and \u201c<strong>Presses<\/strong>\u201d.<\/p>\n<h2>Register Services through Dependency Injection<\/h2>\n<h2>Register the OData Services<\/h2>\n<p>ASP.NET Core OData requires some services registered ahead to provide its functionality. The library provides an extension method called \u201c<strong>AddOData()<\/strong>\u201d to register the required OData services through the built-in dependency injection. So, add the following codes into \u201cConfigureServices\u201d method in the \u201cStartup\u201d class:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/0ecdf7e1527d04641eda4cb18b18fa07.js\"><\/script><\/p>\n<h2>Register the OData Endpoint<\/h2>\n<p>We also need to add OData route to register the OData endpoint. We are going to add an OData route named \u201c<strong>odata<\/strong>\u201d with \u201c<strong>odata<\/strong>\u201d prefix to the MVC routes, and call the \u201c<strong>GetEdmModel()<\/strong>\u201d to bind the Edm model to the endpoint. So, change the \u201c<strong>Configure()<\/strong>\u201d method in \u201c<strong>Startup<\/strong>\u201d class as:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/7237d61af59ae31bf1eb63311de3baf4.js\"><\/script><\/p>\n<h3>Query the metadata<\/h3>\n<p>The OData service is ready to run and can provide basic functionalities, for example to query the metadata (XML representation of the EDM). So, let\u2019s build and run the Web Application. Once it\u2019s running, we can use any client tools (for example, <a href=\"https:\/\/www.getpostman.com\/\"><em>Postman<\/em><\/a>) to issue the following request (<em>remember to change the port in the URI<\/em>):<\/p>\n<p><em><strong>GET<\/strong> http:\/\/localhost:<span style=\"color: #ff0000;\">5000<\/span>\/odata\/$metadata<\/em><\/p>\n<p>Then, you can get the metadata as following xml:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/a17c8f098ba08cacbbe0ee310af9d3e9.js\"><\/script><\/p>\n<h2>Create the Database Context<\/h2>\n<p>Now, it\u2019s ready to add more real functionalities. First, let\u2019s introduce the database context into the Web Application.\u00a0The <em>database context<\/em> is the main class that maps Entity Framework Core database to a given data model (CLR classes).<\/p>\n<p>In the \u201c<em>Models<\/em>\u201d folder, add a new class named \u201c<strong>BookStoreContext<\/strong>\u201d with the following contents:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/f2e9d6d1f66c4f82be1e4d4824277cd3.js\"><\/script><\/p>\n<p>The code in \u201c<strong>OnModelCreating<\/strong>\u201d maps the \u201c<strong>Address<\/strong>\u201d as complex type.<\/p>\n<h2>Register the Database Context<\/h2>\n<p>Second, we should register the database context through built-in dependency injection at service configuration. So, change the \u201c<strong>ConfigureServices<\/strong>\u201d method in \u201c<strong>Startup<\/strong>\u201d class as:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/5a6cfc1971f9ce448e1f0135a57339fc.js\"><\/script><\/p>\n<h2>Inline Model Data<\/h2>\n<p>For simplicity, we build a class to contain the inline model data. In the following codes, I add two books in this container.\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/d40d70ecdaa9054f0ae8e92ba80746da.js\"><\/script><\/p>\n<h2>Manipulate Resources<\/h2>\n<h2>Build the Controller<\/h2>\n<p>In the \u201c<strong>Controllers<\/strong>\u201d folder, rename \u201c<strong>ValuesController<\/strong>.cs\u201d to \u201c<strong>BooksController<\/strong>.cs\u201d and replace its content with:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/61edc7b6beffbfdd3fe7f1fe5d4ae55c.js\"><\/script>\nIn this class, we add a private instance of <strong>BookStoreContext<\/strong> to play the DB role and inherit it from &#8220;<strong>ODataController<\/strong>&#8221; class.<\/p>\n<h2>Retrieve the Resources<\/h2>\n<p>Add the following methods to the \u201c<strong>BooksController<\/strong>\u201d:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/6bfdd5a3e43b3d684a68234df7a1edb0.js\"><\/script>\nWhere,<\/p>\n<ol>\n<li><strong><em>Get()<\/em><\/strong> returns the entire books<\/li>\n<li><strong><em>Get(int key)<\/em><\/strong> returns a certain book by its key.<\/li>\n<\/ol>\n<p>Now, we can query the whole books as \u201c<em><strong>GET<\/strong> http:\/\/localhost:<span style=\"color: #ff0000;\">5000<\/span>\/odata\/Books<\/em>\u201d, the result should be:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/19edf781022da7d0fd3617410455ccf8.js\"><\/script>\nYou can try issue a request as \u201c<em><strong>GET<\/strong>\u00a0http:\/\/localhost:<span style=\"color: #ff0000;\">5000<\/span>\/odata\/Books(2)<\/em>\u201d to get the book with Id equal to 2.<\/p>\n<h2>Create the Resources<\/h2>\n<p>Adding the following lines of code into \u201c<strong>BooksController<\/strong>\u201d will allow to create book to the service:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/cc82560b01a2d5453c581b33d2fa8ed1.js\"><\/script>\nWhere, [<strong>FromBody<\/strong>] is necessary in ASP.NET Core.<\/p>\n<p>As an example, we can issue a post request as follows to create a new Book:<\/p>\n<p><strong><em>POST<\/em><\/strong><em> http:\/\/localhost:5000\/odata\/Books<\/em><\/p>\n<p><em>Content-Type: application\/json<\/em><\/p>\n<p><em>Content:<\/em>\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/8bb0401d415284341efaae4490fb1461.js\"><\/script><\/p>\n<h2>Query the Resources<\/h2>\n<p>Adding the following line of code in <strong>Startup.cs<\/strong> enables all OData query options, for example <em>$filter, $orderby, $expand<\/em>, etc.\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/865ea3efdb7bf085d4c6a4d652681e80.js\"><\/script>\nHere&#8217;s a basic <em>$filter<\/em> example:<\/p>\n<p><em><strong>GET<\/strong>\u00a0http:\/\/localhost:<span style=\"color: #ff0000;\">5000<\/span>\/odata\/Books?$filter=Price le 50<\/em><\/p>\n<p>The response content is:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/e9fd30e41701802aaad1500ef81d2c85.js\"><\/script><\/p>\n<p>It also supports complex query option, for example:<\/p>\n<p><em><strong>GET<\/strong> http:\/\/localhost:<span style=\"color: #ff0000;\">5000<\/span>\/odata\/Books?$filter=Price le 50&amp;$expand=Press($select=Name)&amp;$select=ISBN<\/em><\/p>\n<p>The response content is:\n<script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/xuzhg\/ab91c6722f86bbf6c88ef9bd4d6a02fd.js\"><\/script><\/p>\n<h2>Summary<\/h2>\n<p>Thanks to the OData Community for their feedbacks, questions, issues, and contributions on <a href=\"https:\/\/github.com\/OData\">GitHub<\/a>. Without their help, we can&#8217;t deliver this version.<\/p>\n<p>We encourage you to download the latest\u00a0package from <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData\">Nuget.org<\/a>\u00a0and start building amazing OData service\u00a0running on ASP.NET Core.\u00a0 Enjoy it!<\/p>\n<p>You can refer to the below links for other detail information:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li><a href=\"https:\/\/www.odata.org\/documentation\/\">Open Data Protocol (OData) Specification<\/a><\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/?view=aspnetcore-2.1\">ASP.NET Core<\/a> &amp; <a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/\">EF Core<\/a><\/li>\n<li>OData .NET Open Source (<a href=\"https:\/\/github.com\/OData\/odata.net\">ODL<\/a> &amp; <a href=\"https:\/\/github.com\/OData\/WebApi\">Web API<\/a>)<\/li>\n<li>OData <a href=\"http:\/\/odata.github.io\/\">Tutorials<\/a> &amp; <a href=\"https:\/\/github.com\/OData\/ODataSamples\">Samples<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/xuzhg\/MyAspNetCore\/tree\/master\/src\/BookStore\">This blog&#8217;s sample project<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Introduction The Microsoft OData Team is proud to announce general availability (GA) of OData (Open OData Protocol) on ASP.NET Core 2.0. It is now available through Nuget package at https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData, current its version is 7.0.0. Along this release, it will allow customers to create OData v4.0 endpoints and leverage the OData query syntax easily on [&hellip;]<\/p>\n","protected":false},"author":514,"featured_media":3253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,116,117],"tags":[],"class_list":["post-2685","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata","category-odl","category-webapi"],"acf":[],"blog_post_summary":"<p>Introduction The Microsoft OData Team is proud to announce general availability (GA) of OData (Open OData Protocol) on ASP.NET Core 2.0. It is now available through Nuget package at https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.OData, current its version is 7.0.0. Along this release, it will allow customers to create OData v4.0 endpoints and leverage the OData query syntax easily on [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/2685","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\/514"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=2685"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/2685\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media\/3253"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media?parent=2685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=2685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=2685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}