{"id":1943,"date":"2009-02-05T19:46:00","date_gmt":"2009-02-05T19:46:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/dotnet\/2009\/02\/05\/catch-rethrow-and-filters-why-you-should-care\/"},"modified":"2021-10-04T16:06:32","modified_gmt":"2021-10-04T23:06:32","slug":"catch-rethrow-and-filters-why-you-should-care","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/catch-rethrow-and-filters-why-you-should-care\/","title":{"rendered":"Catch, Rethrow and Filters &#8211; Why you should care?"},"content":{"rendered":"<p class=\"MsoNormal\"><span><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">A very common pattern in the usage of managed exception handling is that of catching an exception, inspecting it&#8217;s type and rethrowing it once you realize it was not the exception you wanted to handle. Below is such an example (and should be avoided in preference to another approach described further below in the writeup) that uses <i>CustomBaseException <\/i>as the base type of an exception hierarchy and <i>CustomDontWantToCatchException <\/i>as a type that derives from the base class that you wouldn&rsquo;t want to catch:<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp; <\/span>private static void Foo()<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>try<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>\/\/ Set some program state<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>\/\/ Do some work that can possibly throw an exception<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>finally<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>\/\/ Reset the program state <\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp; <\/span><b><span>&nbsp;<\/span>public static void Main()<\/b><\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>try<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Foo();<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>catch (CustomBaseException ex)<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>if (ex is CustomDontWantToCatchException)<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>throw; \/\/ Rethrow since we dont want to handle exceptions we aren&rsquo;t interested in!<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>else<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>\/\/ handle the exception<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Managed exception handling comprises of two passes:<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span><font size=\"3\" face=\"Calibri\">1.<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><span><font size=\"3\"><font face=\"Calibri\">In the first pass, the CLR looks for a handler for the thrown exception. When one is found, it begins the second pass.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span><font size=\"3\" face=\"Calibri\">2.<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><span><font size=\"3\"><font face=\"Calibri\">In the second pass, also known as the <i>unwind pass<\/i>, it invokes all the <i>termination handlers<\/i> (e.g. managed finally\/fault blocks, along with the native counterparts like<i> __finally<\/i>, destructors of stack allocated objects) that lie between the handler of the exception and the point at which the exception was thrown.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Thus, if you use a pattern like the one above, <i>only to rethrow an exception <\/i>since it was decided not to deal with it, prior to your [catch] handler being invoked, the <i>termination handlers <\/i>will be invoked. These handlers would end up doing the cleanup (like reset program state) before control is returned to the handler that agreed to handle the exception. Hence, by the time you enter the <i>catch block, <\/i>like in the example above, program state would have been modified since the <i>finally <\/i>in <i>Foo <\/i>would have been invoked. Thus, <i>type handlers (like a catch clause) are invoked after the second pass has successfully been completed even though they are located in the first pass.<\/i><\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Assuming the exception was <i>CustomDontWantToCatchException<\/i>, the <i>catch block <\/i>proceeds to rethrow it, expecting it to go unhandled. When exceptions go unhandled, it is a good thing &#8211; and that is because we get the actual program state at the time when the exception was thrown. <i>However, <\/i>when pattern like the one above is used to rethrow conditionally, the program state gets modified and when the rethrown exception becomes unhandled, you will see actual program state from the point of rethrow and <i>not <\/i>the original throw.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><b><i><span><font face=\"Calibri\">So, how do we address such conditional exception processing without affecting program state for better diagnostics (in case the exception goes unhandled)?<\/p>\n<p><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Filters! Not really well known and not used a lot, <i>managed filters are invoked by the CLR in the first pass<\/i> when it is looking for a handler for an exception. While<span>&nbsp; <\/span>a <i>type handler is associated with a concrete type <\/i>based upon which <i>the CLR will decide<\/i> whether the handler is capable of handling the exception or not, a filter can have<i> custom logic<\/i> to determine whether it wants to handle the exception or not.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\" face=\"Calibri\">When a filter is found in the first pass, the CLR will pass it the exception object corresponding to the thrown exception. The filter can then decide whether it wants to handle the exception or not, by accessing the state on the exception object (<i>Note: accessing global program state from within a filter may lead to unexpected results. Thus, any such accesses should be avoided from within a filter)<\/i>. Once it has decided, a boolean is returned back to the CLR indicate its decision. If it agrees to handle the exception, the CLR will proceed to trigger the second (or unwind) pass. But if it decides <i>not <\/i>to handle the exception, the CLR will continue look further on the stack for any handler that may want to handle the exception. If none are found, the exception becomes unhandled and <\/font><\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/magazine\/cc793966.aspx\"><span><font size=\"3\" face=\"Calibri\">CLR&#8217;s unhandled exception processing<\/font><\/span><\/a><span><font size=\"3\"><font face=\"Calibri\"> kicks in. <\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Hence, instead of catching all exceptions as shown in the example above (or using base type of a given exception hierarchy) and then rethrowing the caught exception because you didn&rsquo;t want to handle it, write a filter that will enable you to do just that without triggering the second pass and modifying program state in the process.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><b><i><span><font face=\"Calibri\">And how does one write a managed filter?<\/p>\n<p><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><span><br><font size=\"3\"><font face=\"Calibri\">While the CLR support filters, not all managed languages support it &#8211; IL and VB, for instance, do support it but C# does not! Rewriting the <i>Main <\/i>method above in VB , we can see how easy it can be to inspect an exception on the fly without affecting the program state and conditionally deciding whether, or not, to handle the exception:<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;<\/span><b>Function ShouldCatch(ByVal exception As CustomBaseException) As Boolean<\/b><\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>If TypeOf (exception) Is CustomDontWantToCatchException Then<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Return False<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Else<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Return True<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>End If<br>&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\">End Function<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\">Sub Main()<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Try<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Foo()<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><i><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Catch ex As CustomBaseException When ShouldCatch(ex) = True<\/span><\/i><i><span><\/p>\n<p><\/span><\/i><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Console.WriteLine(&#8220;Caught exception!&#8221;)<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><i><span><font size=\"3\"><font face=\"Calibri\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>End Try<\/p>\n<p><\/font><\/font><\/span><\/i><\/p>\n<p class=\"MsoNormal\"><b><i><span><font size=\"3\"><font face=\"Calibri\">End Sub<\/p>\n<p><\/font><\/font><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"mso-bidi-font\"><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; A very common pattern in the usage of managed exception handling is that of catching an exception, inspecting it&#8217;s type and rethrowing it once you realize it was not the exception you wanted to handle. Below is such an example (and should be avoided in preference to another approach described further below in the [&hellip;]<\/p>\n","protected":false},"author":342,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[],"class_list":["post-1943","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet"],"acf":[],"blog_post_summary":"<p>&nbsp; A very common pattern in the usage of managed exception handling is that of catching an exception, inspecting it&#8217;s type and rethrowing it once you realize it was not the exception you wanted to handle. Below is such an example (and should be avoided in preference to another approach described further below in the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1943","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\/342"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=1943"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1943\/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=1943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=1943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=1943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}