{"id":14175,"date":"2017-10-05T10:20:46","date_gmt":"2017-10-05T17:20:46","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudio\/?p=14175"},"modified":"2019-10-24T17:36:40","modified_gmt":"2019-10-25T00:36:40","slug":"7-hidden-gems-in-visual-studio-2017","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/visualstudio\/7-hidden-gems-in-visual-studio-2017\/","title":{"rendered":"7 Hidden Gems in Visual Studio 2017"},"content":{"rendered":"<p>I\u2019ve been working on developer tooling for over 16 years, and I still love it when I find a new tip or trick that shaves seconds off a repetitive task. The set below are features that I see infrequently used but can save loads of time!<\/p>\n<h2>Gem #1 &#8211; Expression Evaluator Format Specifiers<\/h2>\n<p>The part of the debugger that processes the language being debugged is known as the expression evaluator (EE). A different expression evaluator is used for each language, though a default is selected if the language cannot be determined. The expression evaluators have some lesser-known features, and though they aren\u2019t always standardized across languages, they come in handy now and then.<\/p>\n<p>A format specifier, in the debugger, is a special syntax to tell the EE how to interpret the expression being examined. There are many format specifiers that are understood by the C++ EE, and a smaller set understood by the C# and VB EEs.<\/p>\n<p>As an example, imagine that you want to call a method every time you step to see what the updated value is. You\u2019re probably used to seeing this and having to click on the refresh icon:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem1-Expression-Evaluator-Format-Specifiers-Refresh.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Expression Evaluator Format Specifiers - Refresh\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem1-Expression-Evaluator-Format-Specifiers-Refresh.png\" alt=\"Expression Evaluator Format Specifiers - Refresh\" \/><\/a><\/p>\n<p>However, you can use the \u2018ac\u2019 (always calculate) format specifier to force evaluation on every step.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem1-Expression-Evaluator-Format-Specifiers-ac.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Expression Evaluator Format Specifiers - ac\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem1-Expression-Evaluator-Format-Specifiers-ac.png\" alt=\"Expression Evaluator Format Specifiers - ac\" \/><\/a><\/p>\n<p>I also find the \u2018h\u2019 (hexadecimal) format specifier useful. You can leave the global display of the debugger alone, but update a single watch item to report in hex by using \u2018value,h\u2019.<\/p>\n<p>You can read about all of the different format specifiers for both <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/debugger\/format-specifiers-in-cpp\">C++<\/a> and <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/debugger\/format-specifiers-in-csharp\">C#\/VB<\/a>.<\/p>\n<h2>Gem #2 &#8211; Controlling the value column of the debugger<\/h2>\n<p>The measure of a modern debugger is its ability to display runtime object data in a simple and meaningful way. As such, when the debugger displays this information, it needs to show the most interesting values prominently. Unfortunately, it is difficult for the debugger to analyze arbitrary objects and figure out what is \u2018most important\u2019. The only generic solution is for <i>you<\/i> to control what the debugger displays; which leads us quite nicely into attributed debugging.<\/p>\n<p>Attributed debugging gives the author of the type the ability to specify what it looks like when being debugged. The simplest form of this is the DebuggerDisplayAttribute. Imagine debugging the following code:<\/p>\n<pre class=\"lang:default decode:true \">class Person\r\n{\r\n    public string FirstName;\r\n    public string LastName;\r\n\r\n    public Person(string first, string last)\r\n    {\r\n        this.FirstName = first;\r\n        this.LastName = last;\r\n    }\r\n\r\n    public string FullName { get =&gt; $\"{LastName}, {FirstName}\"; }\r\n}\r\n\r\n\r\nclass Program\r\n{\r\n    static void Main(string[] args)\r\n    {\r\n        List&lt;Person&gt; presidents = new List&lt;Person&gt;\r\n        {\r\n            new Person(\"George\", \"Washington\"),\r\n            new Person(\"John\", \"Adams\"),\r\n            new Person(\"Thomas\", \"Jefferson\"),\r\n            new Person(\"James\", \"Madison\"),\r\n            new Person(\"James\", \"Monroe\")\r\n        };\r\n    }\r\n}<\/pre>\n<p>If you set a breakpoint on the closing brace of Main, and examine presidents, you\u2019ll see something like this:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-2-Controlling-the-value-column-of-the-debugger-Closing-brace-of-Main.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Controlling the value column of the debugger - Closing brace of Main\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-2-Controlling-the-value-column-of-the-debugger-Closing-brace-of-Main.png\" alt=\"Controlling the value column of the debugger - Closing brace of Main\" \/><\/a><\/p>\n<p>If you want to examine the properties of James Madison, then you must know that he was the 4<sup>th<\/sup> president. You could override ToString in Person; the EE will call ToString if it\u2019s overridden. However, that causes a function evaluation, which can be hundreds of times slower than normal data inspection, and it may be that the debug \u2018view\u2019 of the data should be different than the ToString view. For those cases you can use DebuggerDisplay as follows:<\/p>\n<pre class=\"lang:default decode:true\">[DebuggerDisplay(\"Name: {FullName,nq}\")]\r\nclassPerson<\/pre>\n<p>This updates the display, to the more scannable:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-2-Controlling-the-value-column-of-the-debugger-Debugger-Display.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Controlling the value column of the debugger - Debugger Display \" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-2-Controlling-the-value-column-of-the-debugger-Debugger-Display.png\" alt=\"Controlling the value column of the debugger - Debugger Display \" \/><\/a><\/p>\n<p>You can include format specifiers in the expression to evaluate. In this case \u2018nq\u2019 means \u2018no quotes\u2019 when displaying the string.<\/p>\n<h2>Gem #3 &#8211; Showing important values when an object is expanded<\/h2>\n<p>We now have an easier time finding James Madison without expanding every node; however, after we expand, we see the following view:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-3-Showing-important-values-when-an-object-is-expanded-Watch-Window.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Showing important values when an object is expanded - Watch Window\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-3-Showing-important-values-when-an-object-is-expanded-Watch-Window.png\" alt=\"Showing important values when an object is expanded - Watch Window\" \/><\/a><\/p>\n<p>This shows a lot of duplicative information, and in this case, we don\u2019t really need it. Not only that, but it consumes 3 full rows of the watch window, where vertical space is precious. Since we know how FullName is calculated we\u2019re comfortable never seeing FirstName or LastName when a Person is expanded. This is achieved through the DebuggerBrowsableAttribute. For example, if we add the following attributes:<\/p>\n<pre class=\"lang:default decode:true\">[DebuggerBrowsable(DebuggerBrowsableState.Never)] \r\npublic string FirstName; \r\n[DebuggerBrowsable(DebuggerBrowsableState.Never)] \r\npublic string LastName;<\/pre>\n<p>Our view updates to:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-3-Showing-important-values-when-an-object-is-expanded-Debugger-Browsable-Attribute.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Showing important values when an object is expanded - Debugger Browsable Attribute\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-3-Showing-important-values-when-an-object-is-expanded-Debugger-Browsable-Attribute.png\" alt=\"Showing important values when an object is expanded - Debugger Browsable Attribute\" \/><\/a><\/p>\n<p>You can learn more about attributes that control the debugger data window views <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/framework\/debug-trace-profile\/enhancing-debugging-with-the-debugger-display-attributes\">here<\/a>. There are several other attributes that can control the behavior and look of the debugger, that we\u2019ll likely talk about in future posts!<\/p>\n<h2>Gem #4 \u2013 Applying view customizations to framework types<\/h2>\n<p>You may not always control the source for the types that you\u2019d like to make easier to view. Imagine you have the following:<\/p>\n<pre class=\"lang:default decode:true \">class Program\r\n{\r\n    static void Main(string[] args)\r\n    {\r\n        IPHostEntry hostEntry = Dns.GetHostEntry(\"bing.com\");\r\n    }\r\n}<\/pre>\n<p>It sure would be nice if IPHostEntry showed the HostName property in the value column, without having to expand it.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-4-Applying-view-customizations-to-framework-types.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Applying view customizations to framework types\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-4-Applying-view-customizations-to-framework-types.png\" alt=\"Applying view customizations to framework types\" width=\"1024\" height=\"103\" \/><\/a><\/p>\n<p>The DebuggerDisplayAttribute has an optional parameter for TargetType. This can be used in conjunction with setting the DebuggerDisplayAttribute at the assembly level, to customize types even when you cannot modify their source.<\/p>\n<p>Visual Studio ships with a file called autoexp.cs &amp; autoexp.dll (auto expand) in &lt;visual studio install location&gt;\\Common7\\Packages\\Debugger\\Visualizers\\Original. This file already has several DebuggerDisplay attributes that customize common framework types. We can modify it from an elevated command prompt and add the following:<code><\/code><\/p>\n<pre class=\"lang:default decode:true\">[assembly: DebuggerDisplay(\"Host: {HostName}\", Target = typeof(IPHostEntry))]<\/pre>\n<p>We then compile it, again from an elevated developer command prompt, with the command line \u201ccsc \/t:library autoexp.cs\u201d. The next time we debug our program, we\u2019ll now see:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-4-Applying-view-customizations-to-framework-types-Debugger-Display.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Applying view customizations to framework types - Debugger Display\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-4-Applying-view-customizations-to-framework-types-Debugger-Display.png\" alt=\"Applying view customizations to framework types - Debugger Display\" width=\"1024\" height=\"110\" \/><\/a><\/p>\n<p>This allows for powerful, time-saving, customizations of your own types, frameworks you ship to others, and any code on which you depend.<\/p>\n<p>Although the examples above focus on managed code, similar customizations can be made to the C++ debugging experience, including global view modifications via autoexp.dat, as <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/debugger\/create-custom-views-of-native-objects\">documented here<\/a>.<\/p>\n<h2>Gem #5 \u2013 Snippets<\/h2>\n<p>The tips above are focused on debugging code that\u2019s already been written. What about when you need to pump out new code quickly? I expect many of you may already be familiar with the built-in Code Snippets, but it\u2019s worth mentioning that Snippets are extensible. There are default directories that are registered where you can store your own code snippets. For example, for C#, that location is %userprofile%\\Documents\\Visual Studio 2017\\Code Snippets\\Visual C#\\My Code Snippets.<\/p>\n<p>In 2005, when Snippets were first introduced, a common demo of adding a new snippet for C# was to create a \u2018dim\u2019 snippet, so that you wouldn\u2019t have to enter the type name twice when instantiating a type in C#. The introduction of implicitly typed local variables via \u2018var\u2019 somewhat eliminated the need for such a snippet; however, some coding guidelines preclude using var as it can impact readability. So, let\u2019s introduce a new \u2018var\u2019 snippet, called var.snippet, of the following form:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\" encoding=\"utf-8\" ?&gt; \r\n&lt;CodeSnippets  xmlns=\"http:\/\/schemas.microsoft.com\/VisualStudio\/2005\/CodeSnippet\"&gt; \r\n  &lt;CodeSnippet Format=\"1.0.0\"&gt; \r\n    &lt;Header&gt; \r\n      &lt;Title&gt;Var&lt;\/Title&gt; \r\n      &lt;Shortcut&gt;var&lt;\/Shortcut&gt; \r\n      &lt;Description&gt;Code snippet for instantiating an object with full type info&lt;\/Description&gt; \r\n      &lt;Author&gt;Anson Horton&lt;\/Author&gt; \r\n      &lt;SnippetTypes&gt; \r\n        &lt;SnippetType&gt;Expansion&lt;\/SnippetType&gt; \r\n      &lt;\/SnippetTypes&gt; \r\n    &lt;\/Header&gt; \r\n    &lt;Snippet&gt; \r\n      &lt;Declarations&gt; \r\n        &lt;Literal&gt; \r\n          &lt;ID&gt;type&lt;\/ID&gt; \r\n          &lt;Default&gt;Example&lt;\/Default&gt; \r\n          &lt;ToolTip&gt;The type to construct&lt;\/ToolTip&gt; \r\n        &lt;\/Literal&gt; \r\n        &lt;Literal&gt; \r\n          &lt;ID&gt;variable&lt;\/ID&gt; \r\n          &lt;Default&gt;example&lt;\/Default&gt; \r\n          &lt;ToolTip&gt;The variable name&lt;\/ToolTip&gt; \r\n        &lt;\/Literal&gt; \r\n        &lt;Literal&gt; \r\n          &lt;ID&gt;args&lt;\/ID&gt; \r\n          &lt;Default&gt;&lt;\/Default&gt; \r\n          &lt;ToolTip&gt;The constructor arguments&lt;\/ToolTip&gt; \r\n        &lt;\/Literal&gt; \r\n      &lt;\/Declarations&gt; \r\n      &lt;Code Language=\"csharp\"&gt; \r\n        &lt;![CDATA[$type$ $variable$ = new $type$($args$);$end$]]&gt; \r\n      &lt;\/Code&gt; \r\n    &lt;\/Snippet&gt; \r\n  &lt;\/CodeSnippet&gt; \r\n&lt;\/CodeSnippets&gt;<\/pre>\n<p>Now if we type var in a C# file, and hit &lt;tab&gt;&lt;tab&gt;, the following will be inserted:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-5.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Gem 5 - Snippets\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-5.png\" alt=\"Gem 5 - Snippets\" width=\"320\" height=\"77\" \/><\/a><\/p>\n<p>We can tab through the literals, and as we update the type name, any other reference to that same literal will be updated!<\/p>\n<p>Code snippets are supported in many Visual Studio languages including Visual Basic, C#, CSS, HTML, JavaScript, TSQL, TypeScript, Visual C++, XAML and XML. You can read more about that support <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/ide\/code-snippets\">here<\/a>.<\/p>\n<h2>Gem #6 \u2013 Derived types<\/h2>\n<p>In some cases, when exploring a codebase, it\u2019s useful to be able to see all the types that derive from a base class. This can be particularly true for large, heavily factored frameworks, like Universal Windows or the .NET Framework. It\u2019s possible to use Object Browser to do this for you!<\/p>\n<p>Object Browser is extensible, by creating a library manager. This is important for this tip because different library managers support different functionality. The C# Library Manager does not support locating Derived Types, so if you use the \u2018My Solution\u2019 component set, then you will not see this option. The \u2018My Solution\u2019 component set is the default, but you can change it by the drop-down that appears at the top of the Object Browser (there are many options). Let\u2019s select the .NET Framework 4.6.1:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/clip_image018.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Gem 6 - Devired Types\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/clip_image018.png\" alt=\"Gem 6 - Devired Types\" width=\"438\" height=\"592\" \/><\/a><\/p>\n<p>Now, if you want to locate all the derived types of System.IO.Stream, you simply navigate to the type and expand the \u2018Derived Types\u2019 folder. This is an expensive operation, so expect to wait a fair bit of time for the result to come back.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-6.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Gem-6-Derived Types Folder\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/Gem-6.png\" alt=\"Gem-6-Derived Types Folder\" width=\"380\" height=\"386\" \/><\/a><\/p>\n<p>This works for any assembly or framework; however, to use it for items that you have referenced in your solution, you must first add them to a separate \u2018custom component set\u2019 (the \u2026 next to the drop-down), so that the correct library manager is used.<\/p>\n<h2>Gem #7 \u2013 Find combo<\/h2>\n<p>There is a little-known toolbar combobox called \u2018Find\u2019. It\u2019s on the standard toolbar, but in most settings files its hidden by default. You can show it by clicking on the drop-down of the standard toolbar, the down arrow at the far right of the toolbar that has the back and forward buttons on it, and selecting Add or Remove Buttons and then the Find option.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/clip_image020.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Gem 7 - Combo box\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/clip_image020.png\" alt=\"Gem 7 - Combo box\" width=\"565\" height=\"480\" \/><\/a><\/p>\n<p>This will cause a new combobox to appear on the toolbar, usually to the far right. Depending on your settings choice, the keybinding for this combobox is Ctrl+\/.<\/p>\n<p>The combobox is deceptively named. It\u2019s true that if you type in text and hit enter, then the combo will do essentially the same thing as Quick Find within the current document (and successive enters \u2018Find Next\u2019). However, this combo does so much more!<\/p>\n<p>The combobox doubles as a small viewport into the command window. So, if you prefix your text with the greater than symbol, you can enter in any command! If you want to open a file, with completion, you could type \u2018&gt;of &lt;filename&gt;\u2019, where of is an alias for File.OpenFile:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/clip_image021.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" title=\"Gem 7 - Combo box in Toolbar\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/clip_image021.png\" alt=\"Gem 7 - Combo box in Toolbar\" width=\"260\" height=\"107\" \/><\/a><\/p>\n<p>Similarly, you could type \u2018&gt;GotoLn 20\u2019 to go to the 20<sup>th<\/sup> line in the current document.<\/p>\n<p>The combobox will also pass the text entered to any command that\u2019s bound to a shortcut. For example, it\u2019s possible to open App.Config (without completion) by typing in App.Config and hitting Ctrl+O. Or, you could set a breakpoint on a function by typing in the function name, like \u2018Program.Main\u2019, and hitting F9.<\/p>\n<h2>Conclusion<\/h2>\n<p>I hope you\u2019ve found a few of these hidden gems useful, either as reminders of lesser used functionality, or as discovering something new!<\/p>\n<p>Do you have hidden gems of your own? Share in the comments below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019ve been working on developer tooling for over 16 years, and I still love it when I find a new tip or trick that shaves seconds off a repetitive task. The set below are features that I see infrequently used but can save loads of time! Gem #1 &#8211; Expression Evaluator Format Specifiers The part [&hellip;]<\/p>\n","protected":false},"author":3216,"featured_media":255385,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1085,4980,155],"tags":[237,242,1383,136,9,137,376,124,185,357,287,125,653,156,133],"class_list":["post-14175","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cloud","category-java","category-visual-studio","tag-net","tag-azure","tag-c","tag-css","tag-debug","tag-html","tag-java","tag-javascript","tag-node-js","tag-sql","tag-tips-and-tricks","tag-typescript","tag-visual-basic","tag-visual-studio-2017","tag-xaml"],"acf":[],"blog_post_summary":"<p>I\u2019ve been working on developer tooling for over 16 years, and I still love it when I find a new tip or trick that shaves seconds off a repetitive task. The set below are features that I see infrequently used but can save loads of time! Gem #1 &#8211; Expression Evaluator Format Specifiers The part [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/14175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/users\/3216"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/comments?post=14175"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/14175\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media\/255385"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media?parent=14175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/categories?post=14175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/tags?post=14175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}