{"id":364,"date":"2014-07-29T18:18:40","date_gmt":"2014-07-29T18:18:40","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2014\/07\/29\/profile-and-time-your-asp-net-mvc-app-all-the-way-to-azure\/"},"modified":"2022-08-08T05:06:05","modified_gmt":"2022-08-08T12:06:05","slug":"profile-and-time-your-asp-net-mvc-app-all-the-way-to-azure","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/profile-and-time-your-asp-net-mvc-app-all-the-way-to-azure\/","title":{"rendered":"Profile and Time your ASP.NET MVC app all the way to Azure"},"content":{"rendered":"<p><!--\nPerformance testing and monitoring ASP.NET MVC apps\n -->  <\/p>\n<p>Successful web app dev teams generally consider performance a requirement from the beginning,&#160; not an afterthought. Performance should be considered in all phases of a project, from design and into production, including updates to the app. That&#8217;s not to say you should try to optimize code before you&#8217;ve measured it, you really don&#8217;t know what needs to be optimized until you measure perf. This tutorial will primarily use a modified version of Tom Dykstra&#8217;s <a href=\"http:\/\/www.asp.net\/mvc\/tutorials\/getting-started-with-ef-using-mvc\/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application\">EF6\/MVC 5 Contoso University app <\/a> to introduce you to measuring and monitoring performance.<\/p>\n<p>This topic contains the following sections:<\/p>\n<ul>\n<li><a href=\"#sw\">Using the StopWatch filter to time every action method<\/a> <\/li>\n<li><a href=\"#ma\">Configure Azure settings from Visual Studio<\/a> <\/li>\n<li><a href=\"#ca\">Configure app settings for Azure<\/a> <\/li>\n<li><a href=\"#lp\">Limitations of the Perf filter<\/a> <\/li>\n<\/ul>\n<h2 id=\"sw\">Using the StopWatch filter to time every action method <\/h2>\n<p>Add the StopWatch NuGet package to your ASP.NET MVC app using the following command in the <a href=\"http:\/\/docs.nuget.org\/docs\/start-here\/using-the-package-manager-console\">Package Manager Console<\/a>:<\/p>\n<p><code>PM&gt; Install-Package StopWatch<\/code><\/p>\n<p>The StopWatch&#160; package will create a <em>Filter<\/em> directory and add a class containing the <code>UseStopwatch <\/code>attribute. You can apply this filter to controllers with the following syntax:<\/p>\n<pre class=\"code\"><span style=\"background: white;color: black\">[UseStopwatch]\r\n<\/span><span style=\"background: white;color: blue\">public class <\/span><span style=\"background: white;color: #2b91af\">HomeController <\/span><span style=\"background: white;color: black\">: <\/span><span style=\"background: white;color: #2b91af\">Controller\r\n<\/span><span style=\"background: white;color: black\">{<\/span><\/pre>\n<p><a href=\"http:\/\/11011.net\/software\/vspaste\"><\/a><\/p>\n<p>To apply it globally (that is to every controller), add the following code to the <em>App_StartFilterConfig.cs<\/em> file:<\/p>\n<pre class=\"code\"><span style=\"background: white;color: blue\">public class <\/span><span style=\"background: white;color: #2b91af\">FilterConfig\r\n<\/span><span style=\"background: white;color: black\">{\r\n    <\/span><span style=\"background: white;color: blue\">public static void <\/span><span style=\"background: white;color: black\">RegisterGlobalFilters(<\/span><span style=\"background: white;color: #2b91af\">GlobalFilterCollection <\/span><span style=\"background: white;color: black\">filters)\r\n    {\r\n        filters.Add(<\/span><span style=\"background: white;color: blue\">new <\/span><span style=\"background: white;color: #2b91af\">HandleErrorAttribute<\/span><span style=\"background: white;color: black\">());\r\n        filters.Add(<\/span><span style=\"background: yellow;color: blue\">new <\/span><span style=\"background: yellow;color: #2b91af\">UseStopwatchAttribute<\/span><span style=\"background: white;color: black\">());\r\n    }\r\n}<\/span><\/pre>\n<p><a href=\"http:\/\/11011.net\/software\/vspaste\"><\/a><\/p>\n<p>Add settings to the root <em>web.config<\/em> file to control how timing information is sent to the trace system. For development we want all requests to be under 250 MS. Action methods taking more than 500 MS are recorded at the warning level, and requests taking more than 2.5 seconds are considered errors. In the markup below, we&#8217;ve also set <code>ShowTimeInLayout <\/code>to 1 (true), so every page will display the elapsed time. We will show timing information for each page in development and test, but not in production. Later in the tutorial I\u2019ll show how to set these values outside of source code for the Azure environment.<\/p>\n<pre class=\"code\"><span style=\"background: white;color: blue\">&lt;\/<\/span><span style=\"background: white;color: #a31515\">connectionStrings<\/span><span style=\"background: white;color: blue\">&gt;\r\n&lt;<\/span><span style=\"background: white;color: #a31515\">appSettings<\/span><span style=\"background: white;color: blue\">&gt;\r\n   &lt;<\/span><span style=\"background: white;color: #a31515\">add <\/span><span style=\"background: white;color: red\">key<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">webpages:Version<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: red\">value<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">3.0.0.0<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: blue\">\/&gt;\r\n   &lt;!-- <\/span><span style=\"background: white;color: green\">Keys deleted for clarity.  <\/span><span style=\"background: white;color: blue\">--&gt;\r\n<\/span><span style=\"background: white;color: blue\">   &lt;<\/span><span style=\"background: white;color: #a31515\">add <\/span><span style=\"background: white;color: red\">key<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">TraceErrorTime<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: red\">value<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">2.5<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: blue\">\/&gt;\r\n   &lt;<\/span><span style=\"background: white;color: #a31515\">add <\/span><span style=\"background: white;color: red\">key<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">TraceWarningTime<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: red\">value<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">.5<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: blue\">\/&gt;\r\n   &lt;<\/span><span style=\"background: white;color: #a31515\">add <\/span><span style=\"background: white;color: red\">key<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">TraceInformationTime<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: red\">value<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">.25<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: blue\">\/&gt;\r\n   &lt;<\/span><span style=\"background: white;color: #a31515\">add <\/span><span style=\"background: white;color: red\">key<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">ShowTimeInLayout<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: red\">value<\/span><span style=\"background: white;color: blue\">=<\/span><span style=\"background: white;color: black\">&quot;<\/span><span style=\"background: white;color: blue\">1<\/span><span style=\"background: white;color: black\">&quot; <\/span><span style=\"background: white;color: blue\">\/&gt;\r\n&lt;\/<\/span><span style=\"background: white;color: #a31515\">appSettings<\/span><span style=\"background: white;color: blue\">&gt;\r\n&lt;<\/span><span style=\"background: white;color: #a31515\">system.web<\/span><span style=\"background: white;color: blue\">&gt;<\/span><\/pre>\n<p><a href=\"http:\/\/11011.net\/software\/vspaste\"><\/a><\/p>\n<p>The last change we need to make is to add the timing information to the <em>ViewsShared_Layout.cshtml<\/em> file:<\/p>\n<pre class=\"code\"><span style=\"background: white;color: blue\">&lt;<\/span><span style=\"background: white;color: maroon\">footer<\/span><span style=\"background: white;color: blue\">&gt;\r\n    &lt;<\/span><span style=\"background: white;color: maroon\">p<\/span><span style=\"background: white;color: blue\">&gt; <\/span><span style=\"background: white;color: black\">@<\/span><span style=\"background: yellow;color: black\">Html.Encode(ViewBag.elapsedTime) <\/span><span style=\"background: yellow;color: blue\">&lt;\/<\/span><span style=\"background: white;color: maroon\">p<\/span><span style=\"background: white;color: blue\">&gt;\r\n&lt;\/<\/span><span style=\"background: white;color: maroon\">footer<\/span><span style=\"background: white;color: blue\">&gt;<\/span><\/pre>\n<p><a href=\"http:\/\/11011.net\/software\/vspaste\"><\/a><\/p>\n<p>Run the app, each page shows the elapsed time for the action method.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/5367.r1_thumb-2.png\"><img decoding=\"async\" title=\"r1\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"r1\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/5367.r1_thumb-2.png\" width=\"646\" height=\"512\" \/><\/a> <\/p>\n<p>If you&#8217;re running in Visual Studio, you can see the trace data in the output window:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/6443.outputWinTrace_thumb-2.png\"><img decoding=\"async\" title=\"outputWinTrace\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"outputWinTrace\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/6443.outputWinTrace_thumb-2.png\" width=\"708\" height=\"302\" \/><\/a> <\/p>\n<h2 id=\"ma\">Configure Azure settings from Visual Studio<\/h2>\n<p>Deploy the app to Azure where you can see the page level timings. <\/p>\n<p>You can configure Azure settings in the Azure portal or in Visual Studio. Most of the steps in the following section will be done in Visual Studio, but they are easily done in the Azure portal. In <strong>Server Explorer<\/strong>,&#160; navigate to your web site (<strong>con2<\/strong> in the image below), right click &gt; <strong>View Settings<\/strong>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/8424.Avs_thumb-2.png\"><img decoding=\"async\" title=\"Avs\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"Avs\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/8424.Avs_thumb-2.png\" width=\"327\" height=\"585\" \/><\/a> <\/p>\n<p>Set the <strong>Application Logging<\/strong> level to <strong>Verbose<\/strong>. The <strong>Verbose<\/strong> level logs all trace message. Setting it to <strong>Information<\/strong> logs <strong>Information<\/strong>, <strong>Warning<\/strong> and <strong>Error<\/strong> levels.&#160; Setting it to <strong>Warning<\/strong>&#160; logs&#160; <strong>Warning<\/strong> and <strong>Error<\/strong> levels. You can set the logging level in the Azure portal on the <strong>Configure<\/strong> tab of the web site:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/3250.configPortal_thumb-2.png\"><img decoding=\"async\" title=\"configPortal\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"configPortal\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/3250.configPortal_thumb-2.png\" width=\"401\" height=\"335\" \/><\/a> <\/p>\n<p>Run the app on Azure, and in Visual Studio, navigate to your web site, right click &gt; <strong>View Streaming Logs:<\/strong><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/6470.avs2_thumb-2.png\"><img decoding=\"async\" title=\"avs2\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"avs2\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/6470.avs2_thumb-2.png\" width=\"338\" height=\"657\" \/><\/a> <\/p>\n<p>The output window in shows the trace data. Note the filter lists all the route data plus any query string data.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/7384.AzTrace_thumb-2.png\"><img decoding=\"async\" title=\"AzTrace\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"AzTrace\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/7384.AzTrace_thumb-2.png\" width=\"963\" height=\"328\" \/><\/a> <\/p>\n<p>Looking at trace data from Visual Studio is interesting, but it&#8217;s not a viable approach to production monitoring. A good way to save trace data on Azure is to connect the trace provider to Azure storage.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/2110.AcreateStorage_thumb-2.png\"><img decoding=\"async\" title=\"AcreateStorage\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"AcreateStorage\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/2110.AcreateStorage_thumb-2.png\" width=\"339\" height=\"311\" \/><\/a> <\/p>\n<p>In <strong>Server Explorer<\/strong>, right click <strong>Storage<\/strong> &gt; <strong>Create Storage Account<\/strong>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/8715.ACSA_thumb-2.png\"><img decoding=\"async\" title=\"ACSA\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"ACSA\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/8715.ACSA_thumb-2.png\" width=\"494\" height=\"323\" \/><\/a> <\/p>\n<p>In the Azure portal, click on your web site and select the <strong>Configure<\/strong> tab. Under <strong>application diagnostics <\/strong>set <strong>application logging (blob storage)<\/strong> to <strong>On<\/strong>. Set the logging level to <strong>Information<\/strong>. Click the manage blob storage button and enter the storage account you created. (Note: if you don&#8217;t see the storage account you created from Visual Studio, navigate to the storage account in the portal and force a full refresh of the browser (^F5)).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/0878.z_thumb-2.png\"><img decoding=\"async\" title=\"z\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"z\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/0878.z_thumb-2.png\" width=\"504\" height=\"428\" \/><\/a> <\/p>\n<p>Click <strong>Save<\/strong>. Test you web app so you can generate trace data. <\/p>\n<p>In <strong>Server Explorer<\/strong>,&#160; navigate to the blob storage you created and double click on the container.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/1070.z1_thumb-2.png\"><img decoding=\"async\" title=\"z1\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"z1\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/1070.z1_thumb-2.png\" width=\"340\" height=\"395\" \/><\/a> <\/p>\n<p>Double click on the trace data log to open it in Excel.<\/p>\n<p>You can use Excel to sort the data and hide columns you&#8217;re not interested in.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/4544.e_thumb-1.png\"><img decoding=\"async\" title=\"e\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"e\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/4544.e_thumb-1.png\" width=\"701\" height=\"478\" \/><\/a> <\/p>\n<h3 id=\"ca\">Configure app settings for Azure<\/h3>\n<p>In <strong>Server Explorer<\/strong>,&#160; navigate to your web site (<strong>con2<\/strong> in the image below), right click &gt; <strong>View Settings<\/strong>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/6710.Avs_thumb_1-1.png\"><img decoding=\"async\" title=\"Avs\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"Avs\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/6710.Avs_thumb_1-1.png\" width=\"327\" height=\"585\" \/><\/a> <\/p>\n<p>Under <strong>Application Settings<\/strong>, hit the <strong>Add<\/strong> button to add the app settings from the <em>web.config<\/em> file. The app settings here will override those in the <em>web.config<\/em> file. On a production app, we won&#8217;t want to show page timings.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/2437.zz_thumb-1.png\"><img decoding=\"async\" title=\"zz\" style=\"border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px\" border=\"0\" alt=\"zz\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2014\/07\/2437.zz_thumb-1.png\" width=\"739\" height=\"855\" \/><\/a> <\/p>\n<h3 id=\"lp\">Limitations of the Perf filter<\/h3>\n<p>The simple stopwatch filter misses the authorization portion of the ASP.NET pipeline (which can be expensive), and it stops timing after the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.web.mvc.actionfilterattribute.onresultexecuted(v=vs.118).aspx\">OnResultExecuted<\/a> completes. The filter completely ignores client side timing, which can be significant. <a href=\"http:\/\/getglimpse.com\/Docs\/\">Glimpse<\/a> is a much more powerful tool to profile and monitor your ASP.NET app &#8211; stay tuned, I&#8217;ll be blogging on that next.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Successful web app dev teams generally consider performance a requirement from the beginning,&#160; not an afterthought. Performance should be considered in all phases of a project, from design and into production, including updates to the app. That&#8217;s not to say you should try to optimize code before you&#8217;ve measured it, you really don&#8217;t know what [&hellip;]<\/p>\n","protected":false},"author":415,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[7333,37,46,7439,7295,108,7474,7475,7448,7476,7272,147,7415],"class_list":["post-364","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-asp-net-mvc","tag-azure","tag-c","tag-mvc-5","tag-perf","tag-performance","tag-pipelinestage","tag-profile","tag-routing","tag-time","tag-tips-and-tricks","tag-visual-studio","tag-windows-azure"],"acf":[],"blog_post_summary":"<p>Successful web app dev teams generally consider performance a requirement from the beginning,&#160; not an afterthought. Performance should be considered in all phases of a project, from design and into production, including updates to the app. That&#8217;s not to say you should try to optimize code before you&#8217;ve measured it, you really don&#8217;t know what [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/364","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\/415"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=364"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/364\/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=364"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=364"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=364"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}