{"id":1534,"date":"2013-07-05T17:30:00","date_gmt":"2013-07-06T00:30:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2013\/07\/05\/introducing-select-and-expand-support-in-web-api-odata\/"},"modified":"2022-08-09T06:26:56","modified_gmt":"2022-08-09T13:26:56","slug":"introducing-select-and-expand-support-in-web-api-odata","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/introducing-select-and-expand-support-in-web-api-odata\/","title":{"rendered":"Introducing $select and $expand support in Web API OData"},"content":{"rendered":"<p>Last week Microsoft released the preview of Visual Studio 2013, and along with it came the ASP.NET and&nbsp;Web Tools for Visual Studio 2013 Preview. In this new release, we are expanding&nbsp;the OData support&nbsp;in Web API&nbsp;to include support for <a href=\"http:\/\/www.odata.org\/documentation\/odata-v3-documentation\/url-conventions\/#514_Select_System_Query_Option\">$select<\/a> and <a href=\"http:\/\/www.odata.org\/documentation\/odata-v3-documentation\/url-conventions\/#513_Expand_System_Query_Option\">$expand<\/a>, two of the most <a href=\"http:\/\/aspnet.uservoice.com\/forums\/147201-asp-net-web-api\/suggestions\/2683112-support-select-and-expand-odata-operators\">popular<\/a> OData query operators.&nbsp;In this blog post we&rsquo;ll cover the following topics:<\/p>\n<ul>\n<li>What are $select and $expand.<\/li>\n<li>How to use $select and $expand in an application.<\/li>\n<li>Configuration options and formatter support for $select and $expand.<\/li>\n<\/ul>\n<h2>What are $select and $expand<\/h2>\n<p>The $select operator allows a client to pick a subset of the properties of an entity to be retrieved when querying a feed or a single entity. The $expand operator allows a client to retrieve related entities for a given navigation property in line with the entities being retrieved.<\/p>\n<p>By using $select and $expand, we can make sure that we get the data we need in an optimal way.<\/p>\n<p>For example, we could use $select to return only the Id and Name properties of an entity, and we could use $expand to retrieve a customer and its related Orders on a single query.<\/p>\n<h2>How to use $select and $expand in an application<\/h2>\n<p>Let&rsquo;s see an example, we will start by retrieving only the Name property of a feed of customers. In order to do that, we need to do 3 things:<\/p>\n<ul>\n<li>Create a model like the one in the following diagram:<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2013\/07\/4212.image_thumb_57864337.png\"><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2013\/07\/4212.image_thumb_57864337.png\" alt=\"image\" width=\"584\" height=\"484\" border=\"0\" \/><\/a><\/p>\n<ul>\n<li>Write a CustomersController that returns a feed of Customers or a specific Customer for a given key:<\/li>\n<\/ul>\n<pre class=\"csharpcode\">[ODataNullValue]\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> CustomersController : ODataController\r\n{\r\n    ShoppingContext context;\r\n\r\n    <span class=\"kwrd\">public<\/span> CustomersController()\r\n    {\r\n        context = <span class=\"kwrd\">new<\/span> ShoppingContext();\r\n    }\r\n\r\n    [Queryable(MaxExpansionDepth = 5)]\r\n    <span class=\"kwrd\">public<\/span> IQueryable&lt;Customer&gt; Get()\r\n    {\r\n        <span class=\"kwrd\">return<\/span> context.Customers.AsQueryable();\r\n    }\r\n\r\n    [Queryable(MaxExpansionDepth = 5)]\r\n    <span class=\"kwrd\">public<\/span> SingleResult&lt;Customer&gt; Get(<span class=\"kwrd\">int<\/span> key)\r\n    {\r\n        <span class=\"kwrd\">return<\/span> SingleResult.Create(context.Customers.Where(c =&gt; c.Id == key));\r\n    }\r\n}\r\n<\/pre>\n<ul>\n<li>\n<pre class=\"csharpcode\">Setup the server and map the OData route as in the following code:<\/pre>\n<\/li>\n<\/ul>\n<pre class=\"csharpcode\"><span class=\"kwrd\">class<\/span> Program\r\n{\r\n    <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">void<\/span> Main(<span class=\"kwrd\">string<\/span>[] args)\r\n    {\r\n        <span class=\"kwrd\">string<\/span> serviceUrl = <span class=\"str\">\"http:\/\/localhost:12345\"<\/span>;\r\n        <span class=\"kwrd\">using<\/span> (WebApp.Start(serviceUrl, Configure))\r\n        {\r\n            Console.WriteLine(<span class=\"str\">\"Server listening on {0}\"<\/span>, serviceUrl);\r\n            Console.ReadKey();\r\n        }\r\n    }\r\n\r\n    <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">void<\/span> Configure(IAppBuilder builder)\r\n    {\r\n        HttpConfiguration configuration = <span class=\"kwrd\">new<\/span> HttpConfiguration();\r\n        IEdmModel model = ShoppingEdmModel.GetModel();\r\n        HttpServer server = <span class=\"kwrd\">new<\/span> HttpServer(configuration);\r\n        configuration.Routes.MapODataRoute(<span class=\"str\">\"odata\"<\/span>, <span class=\"str\">\"odata\"<\/span>, model, \r\n        <span class=\"kwrd\">new<\/span> DefaultODataBatchHandler(server));\r\n\r\n        builder.UseHttpMessageHandler(server);\r\n    }\r\n}<\/pre>\n<p>Once we have our server up and running, we only need to send the following request using fiddler in order to get just the Name property of the Customers feed.<\/p>\n<table style=\"width: 700px\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"700\">\n<p>GET <a href=\"http:\/\/localhost:12345\/odata\/Customers\">http:\/\/localhost:12345\/odata\/Customers?<\/a>$select=Name HTTP\/1.1 <br \/> Host: localhost:12345 <br \/> accept: application\/json<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Here is the response that we get:<\/p>\n<table style=\"width: 700px\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"700\">\n<p>HTTP\/1.1 200 OK <br \/> Content-Length: 415 <br \/> Content-Type: application\/json; charset=utf-8 <br \/> Server: Microsoft-HTTPAPI\/2.0 <br \/>DataServiceVersion: 3.0 <br \/> Date: Tue, 28 May 2013 23:58:17 GMT<\/p>\n<p>{ <br \/>&nbsp; &#8220;odata.metadata&#8221;:&#8221;<a href=\"http:\/\/localhost:12345\/odata\/\">http:\/\/localhost:12345\/odata\/<\/a>$metadata#Customers&#8221;,&#8221;value&#8221;:[ <br \/>&nbsp;&nbsp;&nbsp; { <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 1&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 2&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 3&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 4&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 5&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 6&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 7&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 8&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 9&#8243; <br \/>&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 0&#8243; <br \/>&nbsp;&nbsp;&nbsp; } <br \/>&nbsp; ] <br \/> }<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As we see on the response, we are still sending back a feed of customers, but we are only retuning their name, which allows us to improve the efficiency of our applications by reducing the amount of data returned from the database.<\/p>\n<p>We can see this if we see the query that Entity Framework sends to the database when we query just for the Ids of the customers:<\/p>\n<table style=\"width: 700px\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"700\">\n<p>SELECT <br \/> [Extent1].[Id] AS [Id], <br \/> N&#8217;bf436648-6bf3-4bd2-9639-2810e0a91f53&#8242; AS [C1], <br \/>N&#8217;Id&#8217; AS [C2] <br \/> FROM [dbo].[Customers] AS [Extent1]<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Aditionally, we can also apply $select when we are retrieving just a single entity. We could send the following request using fiddler:<\/p>\n<table style=\"width: 700px\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"700\">\n<p>GET <a href=\"http:\/\/localhost:12345\/odata\/Customers(5)\">http:\/\/localhost:12345\/odata\/Customers(5)?<\/a>$select=Name HTTP\/1.1 <br \/> Host: localhost:12345 <br \/> accept: application\/json<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As the following table shows, we get back a Customer, but we only get back its name property:<\/p>\n<table style=\"width: 700px\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"700\">\n<p>HTTP\/1.1 200 OK <br \/> Content-Length: 100 <br \/> Content-Type: application\/json; charset=utf-8 <br \/> Server: Microsoft-HTTPAPI\/2.0 <br \/>DataServiceVersion: 3.0 <br \/> Date: Wed, 29 May 2013 00:01:21 GMT<\/p>\n<p>{ <br \/>&nbsp; &#8220;odata.metadata&#8221;:&#8221;<a href=\"http:\/\/localhost:12345\/odata\/\">http:\/\/localhost:12345\/odata\/<\/a>$metadata#Customers\/@Element&#8221;,&#8221;Name&#8221;:&#8221;Name 5&#8243; <br \/> }<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Here is a more complex example in which we use $select and $expand together:<\/p>\n<table style=\"width: 700px\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"700\">\n<p>GET <a href=\"http:\/\/localhost:18340\/odata\/Customers\">http:\/\/localhost:18340\/odata\/Customers?<\/a>$select=Id,Name,Orders\/BillingAddress&amp;$expand=Orders HTTP\/1.1 <br \/> accept: application\/json <br \/> Host: localhost:18340<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In the example above, we are selecting the Id, Name, and the Billing Address property of the related Orders of a Customer.<\/p>\n<p>Here is the first entity of the associated response:<\/p>\n<table style=\"width: 700px\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"700\">\n<p>{ <br \/>&nbsp; &#8220;odata.metadata&#8221;:&#8221;<a href=\"http:\/\/localhost:18340\/odata\/\">http:\/\/localhost:18340\/odata\/<\/a>$metadata#Customers&#8221;,&#8221;value&#8221;:[ <br \/>&nbsp;&nbsp;&nbsp; { <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Orders&#8221;:[ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;BillingAddress&#8221;:{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;FirstLine&#8221;:&#8221;FirstLine 1&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;SecondLine&#8221;:&#8221;SecondLine 1&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;ZipCode&#8221;:214, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;City&#8221;:&#8221;City 1&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Country&#8221;:&#8221;Country 1&#8243; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;BillingAddress&#8221;:{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;FirstLine&#8221;:&#8221;FirstLine 2&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;SecondLine&#8221;:&#8221;SecondLine 2&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;ZipCode&#8221;:20, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;City&#8221;:&#8221;City 2&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;State&#8221;:&#8221;State 2&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Country&#8221;:&#8221;Country 2&#8243; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;BillingAddress&#8221;:{ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;FirstLine&#8221;:&#8221;FirstLine 3&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;SecondLine&#8221;:&#8221;SecondLine 3&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;ZipCode&#8221;:88, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;City&#8221;:&#8221;City 3&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;State&#8221;:&#8221;State 3&#8243;, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Country&#8221;:&#8221;Country 3&#8243; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ], &#8220;Id&#8221;:1, <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;Name&#8221;:&#8221;Name 1&#8243; <br \/>&nbsp;&nbsp;&nbsp; }, <br \/>&nbsp;&nbsp;&nbsp; &#8230; <br \/> }<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In order to apply a $select or $expand to a single entity, we can write our action method in two ways. If we just return an entity, like a customer and we apply the [Queryable] attribute on top of the action, $select and $expand will work, but the underlying query won&rsquo;t be optimized. Here is an example on how to do it.<\/p>\n<pre class=\"csharpcode\">[Queryable]\r\n<span class=\"kwrd\">public<\/span> Customer Get(<span class=\"kwrd\">int<\/span> key)\r\n{\r\n    <span class=\"kwrd\">return<\/span> context.Customers.Single(x =&gt; x.Id == key);\r\n}\r\n<\/pre>\n<p>This is not a problem if we are using Linq to objects as our backend, but it might cause a performance issue if we are using Entity Framework as the backend, as if we perform an $expand operation and lazy loading is enabled, we will be triggering an extra query for each navigation property we are expanding.<\/p>\n<p>In order to optimize queries to the backend when using $select and $expand, we can write a different version of this action that returns a special class, SingleResult, that allows the queryable attribute to access the query object, apply the $select and $expand operators, and that takes care of ensuring that only one entity is returned.<\/p>\n<pre class=\"csharpcode\">[Queryable]\r\n<span class=\"kwrd\">public<\/span> SingleResult&lt;Customer&gt; Get(<span class=\"kwrd\">int<\/span> key)\r\n{\r\n    <span class=\"kwrd\">return<\/span> SingleResult.Create(context.Customers.Where(x =&gt; x.Id == key));\r\n}\r\n<\/pre>\n<h2>Configuration options and formatter support for $select and $expand<\/h2>\n<p>When dealing with a real application, we need a way to configure operators like $expand so that a client (by mistake or maliciously, can&rsquo;t send an expensive query to the service). In the case of $expand, we can configure the depth of the expansions that we allow our clients to perform in their queries so that they don&rsquo;t cause a denial of service on the database. In order to do this, we can set the MaxExpansionDepth property on the ODataQueryOptions object or in the Queryable attribute.<\/p>\n<p>In this release of web API the OData formatter and the Json formatter support $select and $expand. An example of $select and $expand queries can be found at the ODataQueryableSample in the <a href=\"http:\/\/aspnet.codeplex.com\">aspnet samples<\/a> codeplex project, and this functionality is available with visual studio 2013 preview,&nbsp;on the official Nuget package feed or in the nightly build Nuget feed. For more information, please look at <a href=\"http:\/\/aspnetwebstack.codeplex.com\">http:\/\/aspnetwebstack.codeplex.com<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last week Microsoft released the preview of Visual Studio 2013, and along with it came the ASP.NET and&nbsp;Web Tools for Visual Studio 2013 Preview. In this new release, we are expanding&nbsp;the OData support&nbsp;in Web API&nbsp;to include support for $select and $expand, two of the most popular OData query operators.&nbsp;In this blog post we&rsquo;ll cover the [&hellip;]<\/p>\n","protected":false},"author":1866,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[7431,7436,7268,7230],"class_list":["post-1534","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-odata","tag-visual-studio-2013","tag-web","tag-web-api"],"acf":[],"blog_post_summary":"<p>Last week Microsoft released the preview of Visual Studio 2013, and along with it came the ASP.NET and&nbsp;Web Tools for Visual Studio 2013 Preview. In this new release, we are expanding&nbsp;the OData support&nbsp;in Web API&nbsp;to include support for $select and $expand, two of the most popular OData query operators.&nbsp;In this blog post we&rsquo;ll cover the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1534","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1866"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=1534"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1534\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=1534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=1534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=1534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}