{"id":60537,"date":"2026-08-06T10:05:00","date_gmt":"2026-08-06T17:05:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=60537"},"modified":"2026-08-06T10:05:00","modified_gmt":"2026-08-06T17:05:00","slug":"microsoft-testing-platform-reporting","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/microsoft-testing-platform-reporting\/","title":{"rendered":"Test reporting in Microsoft.Testing.Platform: from red build to root cause"},"content":{"rendered":"<p>When a test fails in CI, &#8220;the build is red&#8221; is only the starting point. The useful questions are whether this\nchange caused the failure, whether the test has failed before, and where to find the evidence. If answering\nthem means searching a job log, downloading an artifact, and finding the teammate who remembers how that test\nbehaved last month, the report has not done enough.<\/p>\n<p>MTP reporting shortens the path from a failed build to the decision a developer or reviewer needs to make.<\/p>\n<p><a href=\"https:\/\/aka.ms\/mtp-overview\">Microsoft.Testing.Platform (MTP)<\/a> powers\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/unit-testing-with-dotnet-test\"><code>dotnet test<\/code><\/a>, the Test Explorer\nin Visual Studio and Visual Studio Code, and test runs in CI. Over the past year its reporting has been closing\nthat gap \u2014 putting failures where reviewers already work, and preserving the evidence when a run falls over.<\/p>\n<p>This works on whichever test framework you already use: MTP is supported by\n<a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/mtp-adoption-frameworks\/\">MSTest, NUnit, xUnit.net, TUnit and Expecto<\/a>.\nMost capabilities in this post require MTP 2.3.0 or later. The examples were validated with <code>MSTest.Sdk<\/code> 4.3.3\nand MTP 2.3.3; the GitHub Actions, JUnit and CTRF reporters currently ship as preview packages.\nMost of what follows is provider-independent, but two of the strongest features read your build history, and\nthat part is Azure DevOps only today:<\/p>\n<table>\n<thead>\n<tr>\n<th>Capability<\/th>\n<th>GitHub Actions<\/th>\n<th>Azure DevOps<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Inline failure annotations and job summary<\/td>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Live result publishing while the run is going<\/td>\n<td>Not yet<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Flaky-vs-regression history, quarantine, slow-test history<\/td>\n<td>Not yet<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Crash-resilient reports, report formats, JSON discovery<\/td>\n<td>Provider-independent<\/td>\n<td>Provider-independent<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Start with inline reporting on either provider: it moves the next failure out of the raw log. If you use Azure\nDevOps, add history-based triage next so reviewers can distinguish a new regression from a recurring failure.<\/p>\n<h2>Put the failure where the author is already looking<\/h2>\n<p>A report that lands in an artifact is a report someone has to go and fetch. Both providers can surface results\ninline instead, and MTP now emits the annotation format each one understands natively.<\/p>\n<p>Enable <a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports#github-actions-reports\"><code>--report-gh<\/code><\/a>\nin a GitHub Actions job and a failing test becomes an annotation on the line of code that failed. Skipped tests\nappear as warnings, each assembly is collapsed into its own log group, and the same run writes a summary straight\nto the workflow page:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2026\/08\/github-actions-test-summary.webp\" alt=\"A failed GitHub Actions test job with the MTP test run summary\" \/><\/p>\n<p>The failure is visible from the job page and the pull request without downloading a report artifact.\nAnnotations, log groups, the summary and slow-test notices can each be configured independently.<\/p>\n<p>Azure DevOps has the same shape behind\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports#azure-devops-reports\"><code>--report-azdo<\/code><\/a>,\nand it offers something GitHub Actions doesn&#8217;t have yet. With <code>--publish-azdo-test-results<\/code>, results stream into\nthe Tests tab <em>while the run is still going<\/em> \u2014 instead of arriving from a separate publish step that only runs if\nthe job survives to reach it. The two are independent: <code>--report-azdo<\/code> handles annotations and logging,\n<code>--publish-azdo-test-results<\/code> handles the Tests tab, and either works alone.<\/p>\n<h2>Azure DevOps: tell a genuine regression from a known flake<\/h2>\n<p>This is the central decision that build history unlocks: not only <em>which<\/em> test failed, but whether the current\nchange is likely to have caused it.<\/p>\n<p>In a large suite, intermittently failing tests train reviewers to read red as background noise. Once &#8220;probably\njust flaky&#8221; is the reasonable first guess, real regressions inherit the same shrug \u2014 and the cost isn&#8217;t the\nflaky tests, it&#8217;s the response time on everything else.<\/p>\n<p><div class=\"alert alert-primary\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Azure DevOps only<\/strong><\/p>The build-history annotations, known-flaky demotion, quarantine and history-based slow-test detection in this section are Azure DevOps-only. The GitHub Actions reporter doesn&#8217;t offer them yet.<\/div><\/p>\n<p>Azure DevOps already exposes this evidence in the Tests tab. In this testfx run, the current build reported no\nfailures across 86,406 tests, while the 14-day history still called out one unique failing test:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2026\/08\/azure-devops-test-history.webp\" alt=\"Azure DevOps Tests tab showing current results and a failing test in the 14-day history\" \/><\/p>\n<p>For the testfx team, that context narrows the first investigation step: a failure with no history gets immediate\nregression attention, while a recurring failure starts with its existing flaky record.<\/p>\n<p>Pass that same 14-day window to the reporter, and it queries the pipeline history and attaches the context to\neach failure:<\/p>\n<pre><code class=\"language-bash\">dotnet test --report-azdo --report-azdo-flaky-history 14<\/code><\/pre>\n<p>A test that has been failing on and off for two weeks is labelled with its record:<\/p>\n<pre><code class=\"language-text\">[flaky: failed 3\/20 in last 14d]<\/code><\/pre>\n<p>A test with no such history gets the label that matters:<\/p>\n<pre><code class=\"language-text\">[REGRESSION]<\/code><\/pre>\n<p>That turns &#8220;someone should look at this eventually&#8221; into &#8220;this pull request broke something,&#8221; and it reaches\nthe reviewer at the point of decision instead of depending on who remembers what. If you want CI to act on it\nrather than merely say it, <code>--report-azdo-demote-known-flaky<\/code> turns known-flaky failures into warnings while\nregressions stay errors.<\/p>\n<p>In the testfx pipeline we use the history annotations but leave automatic demotion off, so every failure stays\nblocking and history only guides triage. Other teams will reasonably choose to demote. The decision worth\nmaking explicitly is whether history should inform a reviewer or change CI severity on its own.<\/p>\n<p>The same history powers slow-test detection. Instead of one threshold that is wrong for every project,\n<code>--report-azdo-slow-test-history<\/code> compares each test against its own past. The threshold is a configurable\nmultiple over a minimum number of runs, so a single cold start won&#8217;t trip it.<\/p>\n<h2>Keep the evidence when the run crashes<\/h2>\n<p>History helps determine whether a failure is new, but triage still stalls if the run loses the evidence needed\nto investigate it. The run you most need a report from is the one that died. That used to be the run that\nproduced nothing, because results were serialized at the end.<\/p>\n<p>TRX results are now streamed to disk as they are produced, so a hard crash no longer takes the whole report\nwith it. Pair <code>--report-trx<\/code> with the\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-crash-hang-dumps\">crash-dump extension<\/a>\nand the run is supervised by a controller process that finalises the partial report when the host dies:<\/p>\n<pre><code class=\"language-bash\">dotnet test --report-trx --crashdump<\/code><\/pre>\n<p>You get a valid TRX containing every test that completed, plus a console list of the ones that didn&#8217;t:<\/p>\n<pre><code class=\"language-text\">The following tests were still running when the test host crashed:\n[00:00:00] D_crash_the_host<\/code><\/pre>\n<p>That names the test that took the process down, without rerunning the suite to find it. The extension also\nwrites a <code>*.crash.sequence.log<\/code> recording every test start and end, so a test that started and never finished\nis unambiguous even when several were running in parallel.<\/p>\n<p>Attachments got the same treatment. Crash dumps, hang dumps and extension artifacts are no longer silently\ndropped on .NET Framework when the path exceeds the Windows <code>MAX_PATH<\/code> limit, and an attachment that can&#8217;t be\ncopied is now surfaced on the console rather than only inside the TRX file. An incomplete run is now <em>visibly<\/em>\nincomplete, instead of a green-looking report with the evidence quietly missing.<\/p>\n<h2>One run, reports for people and tools<\/h2>\n<p>Choose the output based on who consumes it. Use TRX for .NET tooling, HTML for direct inspection, and JUnit or\nCTRF for dashboards and cross-stack automation. A single run can enable any combination, removing the\nformat-conversion step teams often wire into their pipelines.<\/p>\n<table>\n<thead>\n<tr>\n<th>Format<\/th>\n<th>Enable with<\/th>\n<th>Package<\/th>\n<th>Status<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>TRX<\/td>\n<td><code>--report-trx<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.TrxReport\"><code>Microsoft.Testing.Extensions.TrxReport<\/code><\/a><\/td>\n<td>Stable<\/td>\n<\/tr>\n<tr>\n<td>HTML<\/td>\n<td><code>--report-html<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.HtmlReport\"><code>Microsoft.Testing.Extensions.HtmlReport<\/code><\/a><\/td>\n<td>Stable<\/td>\n<\/tr>\n<tr>\n<td>JUnit XML<\/td>\n<td><code>--report-junit<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.JUnitReport\"><code>Microsoft.Testing.Extensions.JUnitReport<\/code><\/a><\/td>\n<td>Preview<\/td>\n<\/tr>\n<tr>\n<td>CTRF JSON<\/td>\n<td><code>--report-ctrf<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.CtrfReport\"><code>Microsoft.Testing.Extensions.CtrfReport<\/code><\/a><\/td>\n<td>Preview<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><a href=\"https:\/\/ctrf.io\/\">CTRF<\/a> is worth knowing about if you aggregate results across languages: it&#8217;s a shared JSON\nschema, so .NET reports into the same shape as the rest of a polyglot estate.<\/p>\n<p>Only TRX and JUnit are formats a CI system parses into a results view. HTML and CTRF are for people and\ndashboards, so they show up as downloadable artifacts instead \u2014 and on Azure DevOps,\n<code>--report-azdo-upload-artifacts files<\/code> collects them automatically. Pick TRX or JUnit when something downstream\nreads the results; add HTML or CTRF for whoever has to look at them.<\/p>\n<p>Report names no longer collide either. Each reporter takes a <code>--report-&lt;format&gt;-filename<\/code> accepting\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports#report-file-names\">build-specific placeholders<\/a>\nsuch as <code>{asm}<\/code> and <code>{tfm}<\/code>, resolved under the results directory:<\/p>\n<pre><code class=\"language-bash\">dotnet test --report-trx --report-trx-filename \"reports\/{asm}_{tfm}_{time}.trx\"<\/code><\/pre>\n<p>Left alone, TRX, HTML and JUnit now default to a deterministic <code>&lt;asm&gt;_&lt;tfm&gt;_&lt;arch&gt;<\/code> name. If you multi-target,\n<code>net8.0<\/code> and <code>net8.0-windows<\/code> write separate files instead of reporting over each other \u2014 a quiet data-loss bug\nin matrix builds that is worth checking for in your current setup.<\/p>\n<h2>Stable output for automation<\/h2>\n<p>People need actionable context in the pull request; automation needs the same context in a stable, structured\nformat. Scripts, dashboards, IDE integrations and coding agents cannot reliably consume terminal prose.<\/p>\n<p><code>--list-tests json<\/code> emits a schema-versioned document describing every discovered test, down to its source\nlocation:<\/p>\n<pre><code class=\"language-json\">{\n  \"schemaVersion\": 1,\n  \"tests\": [\n    {\n      \"uid\": \"11a3aade-7a31-8389-89ce-eab6ff0db7f3\",\n      \"displayName\": \"Total_includes_shipping\",\n      \"location\": { \"file\": \"CheckoutTests.cs\", \"lineStart\": 13, \"lineEnd\": 13 }\n    }\n  ]\n}<\/code><\/pre>\n<p>That schema is a stable input for test selection, impact analysis or IDE integration, instead of scraping\nconsole text that changes between releases.<\/p>\n<p>MTP also adapts its own output for these consumers. In an agent or LLM environment it suppresses the banner,\nANSI escapes and progress animation, and defaults <code>--show-stdout<\/code> and <code>--show-stderr<\/code> to <code>failed<\/code>, so what\ncomes back is results rather than redrawn progress bars. You can set the same behaviour by hand \u2014 the platform\nhonors <code>NO_COLOR<\/code>, and exposes <code>--ansi<\/code> and <code>--progress<\/code> for the rest.<\/p>\n<h2>Try it today<\/h2>\n<ol>\n<li>Confirm that one test project runs MTP 2.3 or later.<\/li>\n<li>Enable the reporter for your CI provider through <code>MSTest.Sdk<\/code> or a direct package reference.<\/li>\n<li>Add <code>dotnet test --report-gh<\/code> in GitHub Actions or <code>dotnet test --report-azdo<\/code> in Azure DevOps.<\/li>\n<li>Use the next failure to check whether the report reduced the time you spent searching logs.<\/li>\n<\/ol>\n<h3>Scale it across a repository<\/h3>\n<p>Once you have chosen a reporting policy, keep it in the repository rather than everyone&#8217;s shell history. Every\noption in the\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-cli-options\">MTP CLI reference<\/a> can\nlive in a checked-in\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-config#cli-options-in-testconfigjson\"><code>testconfig.json<\/code><\/a>\nbeside your test project, under <code>commandLineOptions<\/code>:<\/p>\n<pre><code class=\"language-json\">{\n  \"commandLineOptions\": {\n    \"report-trx\": true,\n    \"report-html\": true,\n    \"report-azdo\": true,\n    \"report-azdo-flaky-history\": 14\n  }\n}<\/code><\/pre>\n<p>Local and CI runs then produce the same reports by default, and a developer can still override any of it from\nthe command line. Misspelled settings fail at startup with a message naming the file, rather than being\nsilently ignored:<\/p>\n<pre><code class=\"language-text\">In testconfig.json under 'commandLineOptions': Unknown option '--report-trxx'<\/code><\/pre>\n<p>For a repo-wide rollout:<\/p>\n<ul>\n<li>\n<p><strong>Centralize once you&#8217;ve decided.<\/strong> With <code>MSTest.Sdk<\/code> each reporter is an MSBuild property, so one\n<code>Directory.Build.props<\/code> applies your policy to every test project in the repo:<\/p>\n<pre><code class=\"language-xml\">&lt;Project&gt;\n&lt;PropertyGroup&gt;\n  &lt;EnableMicrosoftTestingExtensionsHtmlReport&gt;true&lt;\/EnableMicrosoftTestingExtensionsHtmlReport&gt;\n  &lt;EnableMicrosoftTestingExtensionsAzureDevOpsReport&gt;true&lt;\/EnableMicrosoftTestingExtensionsAzureDevOpsReport&gt;\n&lt;\/PropertyGroup&gt;\n&lt;\/Project&gt;<\/code><\/pre>\n<p>The properties follow one pattern (<code>EnableMicrosoftTestingExtensions<\/code> + reporter name), and\n<code>&lt;TestingExtensionsProfile&gt;AllMicrosoft&lt;\/TestingExtensionsProfile&gt;<\/code> switches on the stable set in one line \u2014\nTRX, HTML, Azure DevOps, GitHub Actions, crash dump, hang dump and retry. JUnit and CTRF stay opt-in.<\/p>\n<\/li>\n<li><strong>On other frameworks, check the version.<\/strong> Outside <code>MSTest.Sdk<\/code> you reference the reporter package\ndirectly, and it has to match the MTP version your framework targets. These reporters are built on MTP 2.x,\nso adding one to a project on an older framework release fails at startup with a <code>MissingMethodException<\/code>.\nMTP 2.x support arrives in <code>MSTest.TestAdapter<\/code> 4.0.0, <code>NUnit3TestAdapter<\/code> 6.0.1, <code>TUnit<\/code> 1.7.16,\n<code>YoloDev.Expecto.TestSdk<\/code> 0.16.0, and the <code>xunit.v3<\/code> 4.0 prereleases.<\/li>\n<li><strong>Set the runner opt-in once, at the repo level.<\/strong> Whether <code>dotnet test<\/code> runs your solution through MTP is a\nsingle switch \u2014 put it in <code>Directory.Build.props<\/code> so a new project can&#8217;t drift out of it. Mixing MTP and\nVSTest projects in one solution isn&#8217;t supported; on the .NET 10 SDK, running an MTP project through the old\nVSTest path fails the build with a link to the opt-in, so any drift surfaces immediately. The\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/migrating-vstest-microsoft-testing-platform\">migration guide<\/a>\ncovers that switch.<\/li>\n<li><strong>The Azure DevOps history options need a token.<\/strong> <code>--report-azdo-flaky-history<\/code> and\n<code>--report-azdo-slow-test-history<\/code> call the Azure DevOps REST API, so pass\n<code>SYSTEM_ACCESSTOKEN: $(System.AccessToken)<\/code> to the step. Without it the run continues and simply skips the\nhistory annotations.<\/li>\n<\/ul>\n<h3>Replacing your existing publish tasks<\/h3>\n<p>If you own an existing Azure DevOps pipeline, this section shows which publishing tasks you can replace.\nLive publishing sends the results it already holds in memory straight to the REST API \u2014 it doesn&#8217;t read a TRX,\nso there&#8217;s no report file to produce or glob for. Together with <code>--report-azdo-upload-artifacts files<\/code>, which\npublishes the test results directory as a build artifact, that replaces the tasks most pipelines carry today:<\/p>\n<table>\n<thead>\n<tr>\n<th>Classic task<\/th>\n<th>Replaced by<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>PublishTestResults@2<\/code><\/td>\n<td><code>--publish-azdo-test-results<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>PublishBuildArtifacts@1<\/code> \/ <code>PublishPipelineArtifact@1<\/code><\/td>\n<td><code>--report-azdo-upload-artifacts files<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>PublishCodeCoverageResults@2<\/code><\/td>\n<td>Not replaced \u2014 keep it for the pipeline&#8217;s Code Coverage tab<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Coverage is the one to watch. Live publishing does attach <code>.coverage<\/code>, <code>.cobertura.xml<\/code> and <code>.opencover.xml<\/code>\nto the test run, and failing tests carry their own attachments \u2014 dumps, plus captured stdout and stderr. But\nnothing here populates the pipeline&#8217;s Code Coverage tab, so keep the step that does that today.<\/p>\n<p><div class=\"alert alert-info\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Avoid duplicate test runs<\/strong><\/p>Live publishing and a <code>PublishTestResults@2<\/code> task are independent publishers, not two views of one run. If you enable both, Azure DevOps creates two test runs for the build, so pick one.<\/div><\/p>\n<h2>Where reporting goes next<\/h2>\n<p>Line these changes up and a direction appears. Two years ago MTP was a lighter way to execute tests. Today it\nputs failures directly into GitHub Actions and Azure DevOps, and publishes results live in Azure DevOps as the\nrun happens. It interprets a failure against your own build history, preserves evidence when the host crashes,\nand exposes a stable schema to tools that hadn&#8217;t been written when the platform shipped. The next round \u2014 live\npublishing for GitHub Actions, richer artifact handling, and stable releases for the preview reporters \u2014\ncontinues the same shift: from producing a result file to helping a team decide what to do next.<\/p>\n<p>Reporting is a practical place to evaluate MTP, because developers, reviewers and build owners all see the\ndifference on day one. Pick the smallest version of it: turn on <code>--report-gh<\/code> or <code>--report-azdo<\/code> in one test\nproject and watch where your next failure shows up.<\/p>\n<p>Then tell us what still sends you back to the logs. Several of the options in this post exist because somebody\nopened an issue on <a href=\"https:\/\/github.com\/microsoft\/testfx\">the testfx repository<\/a> describing a bad afternoon.<\/p>\n<p><div  class=\"d-flex justify-content-center\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports\" target=\"_blank\">Add MTP reporting to your CI run<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microsoft.Testing.Platform brings failures into GitHub Actions and Azure DevOps, uses pipeline history to separate regressions from flakes, and preserves usable reports when a test host crashes.<\/p>\n","protected":false},"author":140087,"featured_media":60538,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,756],"tags":[6766,7605,8197,7784,136],"class_list":["post-60537","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-csharp","tag-ci","tag-devops","tag-microsoft-testing-platform","tag-mstest","tag-testing"],"acf":[],"blog_post_summary":"<p>Microsoft.Testing.Platform brings failures into GitHub Actions and Azure DevOps, uses pipeline history to separate regressions from flakes, and preserves usable reports when a test host crashes.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60537","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\/140087"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=60537"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60537\/revisions"}],"predecessor-version":[{"id":60543,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60537\/revisions\/60543"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/60538"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=60537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=60537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=60537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}