[{"data":1,"prerenderedAt":4909},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-vscode":397},[4,192,200],{"title":5,"_path":6,"children":7,"icon":191},"Blog","/posts",[8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59,62,65,68,71,74,77,80,83,86,89,92,95,98,101,104,107,110,113,116,119,122,125,128,131,134,137,140,143,146,149,152,155,158,161,164,167,170,173,176,179,182,185,188],{"title":9,"_path":10},"Testing your API with REST Client","/posts/testing-your-api-with-rest-client",{"title":12,"_path":13},"HTML templating in Xamarin","/posts/html-templating-in-xamarin",{"title":15,"_path":16},"Goodbye Azure Portal, Welcome Azure CLI","/posts/welcome-azure-cli",{"title":18,"_path":19},"Coming across Gitpod","/posts/gitpod",{"title":21,"_path":22},"Handle token retrieval while querying an API","/posts/delegating-handler",{"title":24,"_path":25},"Clean up your local git branches.","/posts/cleaning-git-branches",{"title":27,"_path":28},"Automate configuration of Teams Tab SSO with PowerShell.","/posts/teams-sso-powershell",{"title":30,"_path":31},"How to do a technology watch? - Part 1","/posts/technology-watch-part1",{"title":33,"_path":34},"How to do a technology watch? - Part 2","/posts/technology-watch-part2",{"title":36,"_path":37},"You almost no longer need Key Vault references for Azure Functions.","/posts/azure-functions-custom-configuration",{"title":39,"_path":40},"How to do a technology watch? - Part 3","/posts/technology-watch-part3",{"title":42,"_path":43},"Forget DevOps, the future is already here!","/posts/devops-future",{"title":45,"_path":46},"Week 9, 2021 - Tips I learned this week","/posts/w09-2021-tips-learned-this-week",{"title":48,"_path":49},"Week 12, 2021 - Tips I learned this week","/posts/w12-2021-tips-learned-this-week",{"title":51,"_path":52},"Week 14, 2021 - Tips I learned this week","/posts/w14-2021-tips-learned-this-week",{"title":54,"_path":55},"Once upon a time in .NET","/posts/once-upon-a-time-in-dotnet",{"title":57,"_path":58},"Install your applications with winget","/posts/winget-import",{"title":60,"_path":61},"Customize your applications when installing them with winget","/posts/winget-override",{"title":63,"_path":64},"Week 22, 2021 - Tips I learned this week","/posts/w22-2021-tips-learned-this-week",{"title":66,"_path":67},"How to connect to an Azure SQL Database from C# using Azure AD","/posts/sqlclient-active-directory-authent",{"title":69,"_path":70},"Producing packages for Windows Package Manager","/posts/wingetcreate",{"title":72,"_path":73},"4 tips about GitHub Actions environment variables and contexts","/posts/github-actions-var-and-context",{"title":75,"_path":76},"AzureWebJobsStorage, the secret you don't need in your Function App.","/posts/azure-functions-without-azurewebjobsstorage",{"title":78,"_path":79},"ASP.NET Core - Lost in configuration","/posts/lost-in-configuration",{"title":81,"_path":82},"Week 39, 2021 - Tips I learned this week","/posts/w39-2021-tips-learned-this-week",{"title":84,"_path":85},"Week 41, 2021 - Tips I learned this week","/posts/w41-2021-tips-learned-this-week",{"title":87,"_path":88},"Migrating and open-sourcing my blog","/posts/migrating-blog",{"title":90,"_path":91},"Week 45, 2021 - Tips I learned this week","/posts/w45-2021-tips-learned-this-week",{"title":93,"_path":94},"Organize your GitHub stars with Astral","/posts/astral",{"title":96,"_path":97},"Pulumi with an Azure Blob Storage backend","/posts/pulumi-azure-backend",{"title":99,"_path":100},"IaC Hot Reload with Pulumi Watch","/posts/pulumi-watch",{"title":102,"_path":103},"Week 2, 2022 - Tips I learned this week","/posts/w02-2022-tips-learned-this-week",{"title":105,"_path":106},"Week 3, 2022 - Tips I learned this week","/posts/w03-2022-tips-learned-this-week",{"title":108,"_path":109},"Week 5, 2022 - Tips I learned this week","/posts/w05-2022-tips-learned-this-week",{"title":111,"_path":112},"How to provision an Azure SQL Database with Active Directory authentication","/posts/sqldatabase-active-directory-authent",{"title":114,"_path":115},"Why will I choose Pulumi over Terraform for my next project?","/posts/pulumi-vs-terraform",{"title":117,"_path":118},"Week 19, 2022 - Tips I learned this week","/posts/w19-2022-tips-learned-this-week",{"title":120,"_path":121},"Week 20, 2022 - Tips I learned this week","/posts/w20-2022-tips-learned-this-week",{"title":123,"_path":124},"Keeping secrets secure when using API Clients","/posts/http-clients-secrets",{"title":126,"_path":127},"What made me want to be a developer?","/posts/be-a-developer",{"title":129,"_path":130},"What can we do when stuck with a programming problem?","/posts/get-unstuck",{"title":132,"_path":133},"How did I automate the setup of my developer Windows laptop?","/posts/automate-developer-machine",{"title":135,"_path":136},"Discussion about API clients","/posts/http-clients",{"title":138,"_path":139},"Week 46, 2022 - Tips I learned this week","/posts/w46-2022-tips-learned-this-week",{"title":141,"_path":142},"When Pulumi met Nuke: a .NET love story","/posts/when-pulumi-met-nuke",{"title":144,"_path":145},"A year of learning and sharing - Dev Retro 2022","/posts/2022-retro",{"title":147,"_path":148},"Perform Dynamic Execution of an npm Package","/posts/pnpm-dlx",{"title":150,"_path":151},"Manage multiple Node.js versions","/posts/pnpm-env",{"title":153,"_path":154},"Introducing the Vue.js CI/CD series","/posts/vuecicd-introduction",{"title":156,"_path":157},"Execute commands using your project dependencies","/posts/pnpm-exec",{"title":159,"_path":160},"Vue.js CI/CD: Continuous Integration","/posts/vuecicd-ci",{"title":162,"_path":163},"Who is using pnpm?","/posts/pnpm-who-is-using",{"title":165,"_path":166},"Create an Azure-Ready GitHub Repository using Pulumi","/posts/azure-ready-github-repository",{"title":168,"_path":169},"Deploying to Azure from Azure DevOps without secrets","/posts/ado-workload-identity-federation",{"title":171,"_path":172},"Effortlessly Configure GitHub Repositories for Azure Deployment via OIDC","/posts/scripting-azure-ready-github-repository",{"title":174,"_path":175},"Playing with the .NET 8 Web API template","/posts/playing-with-dotnet8",{"title":177,"_path":178},"Another year of sharing and learning - Dev Retro 2023","/posts/2023-retro",{"title":180,"_path":181},"Week 4, 2024 - Tips I learned this week","/posts/w04-2024-tips-learned-this-week",{"title":183,"_path":184},"Using dependency injection with Azure .NET SDK","/posts/azure-sdk-di",{"title":186,"_path":187},"Having Fun With IT Event Calendars","/posts/it-event-calendars",{"title":189,"_path":190},"Call your Azure AD B2C protected API with authenticated HTTP requests from your JetBrains IDE","/posts/http-clients-oauth2","i-heroicons-newspaper",{"title":193,"_path":194,"children":195,"icon":199},"Goodies","/goodies",[196],{"title":197,"_path":198},"My Git Cheat Sheet","/goodies/gitcheatsheet","i-heroicons-gift-solid",{"title":201,"_path":202,"icon":203},"About","/about","i-heroicons-user-circle-solid",[205,207,209,211,214,217,220,223,226,229,231,234,237,240,242,244,247,250,253,255,258,261,264,267,270,273,276,279,282,285,287,289,292,294,297,300,303,305,308,310,313,316,319,322,325,327,329,332,335,338,341,344,347,350,353,356,359,361,363,366,369,372,375,377,380,383,385,388,391,394],[206,206],"tooling",[208,208],"vscode",[210,210],"rest",[212,213],"http","HTTP",[215,216],"razor","Razor",[218,219],"xamarin","Xamarin",[221,222],"templating","Templating",[224,225],"azure-cli","Azure CLI",[227,228],"azure","Azure",[230,230],"shell",[232,233],"github","GitHub",[235,236],"asp-net-core","ASP.NET Core",[238,239],"net",".NET",[241,241],"git",[243,243],"nushell",[245,246],"microsoft-teams","Microsoft Teams",[248,249],"powershell","PowerShell",[251,252],"azure-active-directory","Azure Active Directory",[254,254],"learning",[256,257],"azure-functions","Azure Functions",[259,260],"azure-key-vault","Azure Key Vault",[262,263],"configuration","Configuration",[265,266],"devops","DevOps",[268,269],"it","IT",[271,272],"tips-learned-this-week","tips learned this week",[274,275],"windows-terminal","Windows Terminal",[277,278],"azure-pipelines","Azure Pipelines",[280,281],"application-insights","Application Insights",[283,284],"azure-iot","Azure IoT",[286,286],"records",[288,288],"refit",[290,291],"development-box-setup","development box setup",[293,293],"winget",[295,296],"package-manager","package manager",[298,299],"azure-sql-database","Azure SQL Database",[301,302],"azure-sdk","Azure SDK",[304,304],"wingetcreate",[306,307],"github-actions","GitHub Actions",[309,309],"jq",[311,312],"pulumi","Pulumi",[314,315],"iac","IaC",[317,318],"azure-storage","Azure Storage",[320,321],"azure-signalr","Azure SignalR",[323,324],"visio","Visio",[326,326],"csharp",[328,328],"jest",[330,331],"statiq","Statiq",[333,334],"open-source","open source",[336,337],"visual-studio","Visual Studio",[339,340],"vue-js","Vue.js",[342,343],"azure-devops","Azure DevOps",[345,346],"vite","Vite",[348,349],"code-analysis","Code analysis",[351,352],"diagram","Diagram",[354,355],"terraform","Terraform",[357,358],"typescript","TypeScript",[360,360],"thoughts",[362,362],"pnpm",[364,365],"nuke","Nuke",[367,368],"pipelines","Pipelines",[370,371],"cicd","CI/CD",[373,374],"openid-connect","OpenID Connect",[376,376],"security",[378,379],"github-cli","GitHub CLI",[381,382],"microsoft-entra-id","Microsoft Entra ID",[384,384],"advent",[386,387],"finops","FinOps",[389,390],"anglesharp","AngleSharp",[392,393],"oauth2","OAuth2",[395,396],"azure-ad-b2c","Azure AD B2C",[398,683,905,1211,1657,1900,3199,3564,3743,4014],{"_path":139,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":138,"description":402,"lead":402,"date":403,"image":404,"badge":406,"tags":408,"body":409,"_type":678,"_id":679,"_source":680,"_file":681,"_extension":682},"posts",false,"","Some tips about .NET, pnpm, and Azure DevOps.","2022-11-20T00:00:00.000Z",{"src":405},"/images/surface_1.jpg",{"label":407},"Tips",[272,239,293,362,296,208,343,206],{"type":410,"children":411,"toc":673},"root",[412,421,438,466,489,495,526,531,541,555,567,576,581,591,600,614,620,625,635,653,662,667],{"type":413,"tag":414,"props":415,"children":417},"element","h2",{"id":416},"net-tip-of-the-week-install-net-7-using-winget",[418],{"type":419,"value":420},"text",".NET tip of the week: install .NET 7 using winget",{"type":413,"tag":422,"props":423,"children":424},"p",{},[425,427,436],{"type":419,"value":426},"This week, I installed .NET 7 on my laptop and I used ",{"type":413,"tag":428,"props":429,"children":433},"a",{"href":430,"rel":431},"https://learn.microsoft.com/en-us/windows/package-manager/",[432],"nofollow",[434],{"type":419,"value":435},"Windows Package Manager",{"type":419,"value":437}," for that:",{"type":413,"tag":439,"props":440,"children":443},"pre",{"className":441,"code":442,"language":248,"meta":401,"style":401},"language-powershell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","winget install Microsoft.DotNet.SDK.7\n",[444],{"type":413,"tag":445,"props":446,"children":447},"code",{"__ignoreMap":401},[448],{"type":413,"tag":449,"props":450,"children":453},"span",{"class":451,"line":452},"line",1,[454,460],{"type":413,"tag":449,"props":455,"children":457},{"style":456},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[458],{"type":419,"value":459},"winget install Microsoft.DotNet.SDK.",{"type":413,"tag":449,"props":461,"children":463},{"style":462},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[464],{"type":419,"value":465},"7\n",{"type":413,"tag":422,"props":467,"children":468},{},[469,471,478,480,487],{"type":419,"value":470},"I like winget, I have already written a few articles about it (you can find them ",{"type":413,"tag":428,"props":472,"children":475},{"href":473,"rel":474},"https://www.techwatching.dev/tags/winget/",[432],[476],{"type":419,"value":477},"here",{"type":419,"value":479},") so I am really glad to see that we can now use winget to install .NET (whether it be the SDKs or the runtimes). You can check ",{"type":413,"tag":428,"props":481,"children":484},{"href":482,"rel":483},"https://devblogs.microsoft.com/dotnet/dotnet-now-on-windows-package-manager/",[432],[485],{"type":419,"value":486},"Microsoft's article",{"type":419,"value":488}," announcing it for more information.",{"type":413,"tag":414,"props":490,"children":492},{"id":491},"tool-of-the-week-pnpm",[493],{"type":419,"value":494},"Tool of the week: pnpm",{"type":413,"tag":422,"props":496,"children":497},{},[498,500,506,508,515,517,524],{"type":419,"value":499},"I don't know which JavaScript package manager you are using but since I tried ",{"type":413,"tag":428,"props":501,"children":504},{"href":502,"rel":503},"https://pnpm.io/",[432],[505],{"type":419,"value":362},{"type":419,"value":507}," I don't want to use anything else because it's so fast! If you are interested to know why it's so fast and better than npm for instance, you can watch the talk ",{"type":413,"tag":428,"props":509,"children":512},{"href":510,"rel":511},"https://viteconf.org/2022/replay/pnpm",[432],[513],{"type":419,"value":514},"\"What makes pnpm performant\"",{"type":419,"value":516}," that Zoltan Kochan gave at Vite Conf. Many ",{"type":413,"tag":428,"props":518,"children":521},{"href":519,"rel":520},"https://pnpm.io/workspaces#usage-examples",[432],[522],{"type":419,"value":523},"popular open-source projects",{"type":419,"value":525}," like Vite and Vue are using pnpm.",{"type":413,"tag":422,"props":527,"children":528},{},[529],{"type":419,"value":530},"Here are some tips about pnpm:",{"type":413,"tag":532,"props":533,"children":534},"ol",{},[535],{"type":413,"tag":536,"props":537,"children":538},"li",{},[539],{"type":419,"value":540},"You can use pnpm to manage Node.js versions on your machine",{"type":413,"tag":422,"props":542,"children":543},{},[544,546,553],{"type":419,"value":545},"Previously, I was using ",{"type":413,"tag":428,"props":547,"children":550},{"href":548,"rel":549},"https://github.com/coreybutler/nvm-windows",[432],[551],{"type":419,"value":552},"nvm-windows",{"type":419,"value":554}," to manage multiple installation of Node.js on my laptop and it worked fine. Yet I can now do that directly using pnpm env command:",{"type":413,"tag":422,"props":556,"children":557},{},[558],{"type":413,"tag":559,"props":560,"children":566},"img",{"alt":561,"className":562,"src":565},"Output of the pnpm env command in a terminal.",[563,564],"rounded-lg","mx-auto","/posts/images/w462022tips_pnpm_env.png",[],{"type":413,"tag":532,"props":568,"children":570},{"start":569},2,[571],{"type":413,"tag":536,"props":572,"children":573},{},[574],{"type":419,"value":575},"You can configure vscode to run npm scripts using pnpm",{"type":413,"tag":422,"props":577,"children":578},{},[579],{"type":419,"value":580},"A lot of the people I know don't use the scripts explorer of vscode to run the scripts contained in the package.json file of the project opened in vscode. It's a pity because it is an handy feature. And you can configure it in your settings to run scripts using a specific package manager, pnpm in my case.",{"type":413,"tag":422,"props":582,"children":583},{},[584],{"type":413,"tag":559,"props":585,"children":590},{"alt":586,"className":587,"src":588,"width":589},"Npm scripts view in vscode editor.",[563,564],"/posts/images/w462022tips_pnpm_scripts.png",600,[],{"type":413,"tag":532,"props":592,"children":594},{"start":593},3,[595],{"type":413,"tag":536,"props":596,"children":597},{},[598],{"type":419,"value":599},"With pnpm, you can use aliases for packages you install",{"type":413,"tag":422,"props":601,"children":602},{},[603,605,612],{"type":419,"value":604},"Check the ",{"type":413,"tag":428,"props":606,"children":609},{"href":607,"rel":608},"https://pnpm.io/aliases",[432],[610],{"type":419,"value":611},"documentation",{"type":419,"value":613}," to see why and how to use this feature.",{"type":413,"tag":414,"props":615,"children":617},{"id":616},"the-gitlensazure-devops-tip-you-did-not-know-about-autolinks",[618],{"type":419,"value":619},"The GitLens/Azure DevOps tip you did not know about: autolinks",{"type":413,"tag":422,"props":621,"children":622},{},[623],{"type":419,"value":624},"GitLens, the awesome extension for vscode has a nice feature called \"autolinks\" that can make external references in your commit messages clickable links.",{"type":413,"tag":422,"props":626,"children":627},{},[628],{"type":413,"tag":559,"props":629,"children":634},{"alt":630,"className":631,"src":632,"width":633},"Autolinks GitLens settings view in vscode.",[563,564],"/posts/images/w462022tips_gitlens_autolink_1.png",1000,[],{"type":413,"tag":422,"props":636,"children":637},{},[638,640,647],{"type":419,"value":639},"If you are using Azure DevOps, this feature can become very handy for you commit messages that contain references to work items (usually an hasjtag followed by the work item number). You just have to configure # as the prefix and ",{"type":413,"tag":428,"props":641,"children":644},{"href":642,"rel":643},"https://dev.azure.com/%7BorganizationName%7D/%7BprojectName%7D/_workitems/edit/",[432],[645],{"type":419,"value":646},"https://dev.azure.com/{organizationName}/{projectName}/_workitems/edit/",{"type":413,"tag":648,"props":649,"children":650},"num",{},[651],{"type":419,"value":652}," as the URL) to make it work.",{"type":413,"tag":422,"props":654,"children":655},{},[656],{"type":413,"tag":559,"props":657,"children":661},{"alt":658,"className":659,"src":660,"width":633},"A commit GitLens popin in vscode with an Azure DevOps link.",[563,564],"/posts/images/w462022tips_gitlens_autolink_2.png",[],{"type":413,"tag":422,"props":663,"children":664},{},[665],{"type":419,"value":666},"And that's it for this week, happy learning!",{"type":413,"tag":668,"props":669,"children":670},"style",{},[671],{"type":419,"value":672},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":401,"searchDepth":569,"depth":569,"links":674},[675,676,677],{"id":416,"depth":569,"text":420},{"id":491,"depth":569,"text":494},{"id":616,"depth":569,"text":619},"markdown","content:1.posts:44.w46-2022-tips-learned-this-week.md","content","1.posts/44.w46-2022-tips-learned-this-week.md","md",{"_path":118,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":117,"description":684,"lead":684,"date":685,"image":686,"badge":687,"tags":688,"body":689,"_type":678,"_id":903,"_source":680,"_file":904,"_extension":682},"Git commands in vscode, a nice tool for Vue developers and a must-have Visual Studio extension.","2022-05-14T00:00:00.000Z",{"src":405},{"label":407},[272,208,241,340,337,206],{"type":410,"children":690,"toc":898},[691,697,729,738,743,752,765,771,820,829,842,851,857,871,880,885,894],{"type":413,"tag":414,"props":692,"children":694},{"id":693},"git-tip-of-the-week",[695],{"type":419,"value":696},"Git tip of the week",{"type":413,"tag":422,"props":698,"children":699},{},[700,702,709,711,718,720,727],{"type":419,"value":701},"If you have read my ",{"type":413,"tag":428,"props":703,"children":706},{"href":704,"rel":705},"https://www.techwatching.dev/gitcheatsheet",[432],[707],{"type":419,"value":708},"git cheat sheet",{"type":419,"value":710},", you know that I am a big fan of the ",{"type":413,"tag":428,"props":712,"children":715},{"href":713,"rel":714},"https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens",[432],[716],{"type":419,"value":717},"GitLens",{"type":419,"value":719}," vscode extension. I have been using it for a while now but just discovered recently that there is a ",{"type":413,"tag":428,"props":721,"children":724},{"href":722,"rel":723},"https://github.com/gitkraken/vscode-gitlens#git-command-palette-",[432],[725],{"type":419,"value":726},"Git Command Palette",{"type":419,"value":728}," that gives access to most common Git commands.",{"type":413,"tag":422,"props":730,"children":731},{},[732],{"type":413,"tag":559,"props":733,"children":737},{"alt":734,"className":735,"src":736,"width":633},"GitLens Command Palette in vscode",[563,564],"/posts/images/w192022tips_gitlens_1.png",[],{"type":413,"tag":422,"props":739,"children":740},{},[741],{"type":419,"value":742},"Usually, I prefer typing the git commands rather than using a visual tool. This way, I know exactly what I am doing (no magic commands done by a tool behind the scene), and I improve my knowledge of git. However, I think that with Git Command Palette, I get the best of both worlds. The UI helps me to use the git command I need without having to type everything and remember the exact syntax of the command. Yet, this is not a UI with buttons that hide from me the git commands being run. I am still aware of the exact git commands I am using and how.",{"type":413,"tag":422,"props":744,"children":745},{},[746],{"type":413,"tag":559,"props":747,"children":751},{"alt":748,"className":749,"src":750,"width":633},"Doing a Git fetch in GitLens Command Palette.",[563,564],"/posts/images/w192022tips_gitlens_2.png",[],{"type":413,"tag":422,"props":753,"children":754},{},[755,757,763],{"type":419,"value":756},"On Windows, the default shortcut to use the Git Command Palette is ",{"type":413,"tag":445,"props":758,"children":760},{"className":759},[],[761],{"type":419,"value":762},"Ctrl + Shift + G : ",{"type":419,"value":764},".",{"type":413,"tag":414,"props":766,"children":768},{"id":767},"tool-of-the-week-vue-telescope",[769],{"type":419,"value":770},"Tool of the week: Vue Telescope",{"type":413,"tag":422,"props":772,"children":773},{},[774,776,783,785,792,794,801,803,810,812,818],{"type":419,"value":775},"If you are a Vue developer and don't know this tool yet, this is going to make your day! When browsing a website, you are probably wondering if it has been made with Vue.js and if so what is the technology stack behind it. Personally, I find it very interesting to know which frameworks, libraries, or plugins have been used to create a website in Vue. And that's what ",{"type":413,"tag":428,"props":777,"children":780},{"href":778,"rel":779},"https://vuetelescope.com/",[432],[781],{"type":419,"value":782},"Vue Telescope",{"type":419,"value":784}," is about. It's an open source tool made by ",{"type":413,"tag":428,"props":786,"children":789},{"href":787,"rel":788},"https://nuxtlabs.com/",[432],[790],{"type":419,"value":791},"NuxtLabs",{"type":419,"value":793}," (the team behind the ",{"type":413,"tag":428,"props":795,"children":798},{"href":796,"rel":797},"https://nuxtjs.org/",[432],[799],{"type":419,"value":800},"Nuxt",{"type":419,"value":802}," framework) that detects the Vue technologies used in a website. It can be used from a browser ",{"type":413,"tag":428,"props":804,"children":807},{"href":805,"rel":806},"https://chrome.google.com/webstore/detail/vue-telescope/neaebjphlfplgdhedjdhcnpjkndddbpd",[432],[808],{"type":419,"value":809},"extension",{"type":419,"value":811}," or from Vue Telescope's ",{"type":413,"tag":428,"props":813,"children":815},{"href":778,"rel":814},[432],[816],{"type":419,"value":817},"website",{"type":419,"value":819}," to search a analyze a specific website.",{"type":413,"tag":422,"props":821,"children":822},{},[823],{"type":413,"tag":559,"props":824,"children":828},{"alt":825,"className":826,"src":827,"width":633},"Vue Telescope extension showing Vue Telescope stack on its website.",[563,564],"/posts/images/w192022tips_vuetelescope_1.png",[],{"type":413,"tag":422,"props":830,"children":831},{},[832,834,840],{"type":419,"value":833},"You can explore the Vue.js websites already scanned by VueTelescope ",{"type":413,"tag":428,"props":835,"children":838},{"href":836,"rel":837},"https://vuetelescope.com/explore",[432],[839],{"type":419,"value":477},{"type":419,"value":841}," and filter on the frameworks, UI Frameworks you are interested in.",{"type":413,"tag":422,"props":843,"children":844},{},[845],{"type":413,"tag":559,"props":846,"children":850},{"alt":847,"className":848,"src":849,"width":633},"Vue Telescope search.",[563,564],"/posts/images/w192022tips_vuetelescope_2.png",[],{"type":413,"tag":414,"props":852,"children":854},{"id":853},"the-visual-studio-extension-you-should-try-add-new-file",[855],{"type":419,"value":856},"The Visual Studio extension you should try: Add New File",{"type":413,"tag":422,"props":858,"children":859},{},[860,862,869],{"type":419,"value":861},"Sometimes the simplest IDE extensions are the best. That's the case for the ",{"type":413,"tag":428,"props":863,"children":866},{"href":864,"rel":865},"https://marketplace.visualstudio.com/items?itemName=MadsKristensen.AddNewFile64",[432],[867],{"type":419,"value":868},"\"Add New\"",{"type":419,"value":870}," Visual Studio extension which allows you to quickly create a new file by hitting \"Shift+F2\" and writing the name of the file with its extension. Nothing fancy, but it saves you a lot of time compared to adding a new file using the default dialog.",{"type":413,"tag":422,"props":872,"children":873},{},[874],{"type":413,"tag":559,"props":875,"children":879},{"alt":876,"className":877,"src":878,"width":633},"Website of Add New File Visual Studio extension.",[563,564],"/posts/images/w192022tips_addnewfile_1.png",[],{"type":413,"tag":422,"props":881,"children":882},{},[883],{"type":419,"value":884},"As you can see you can even create the missing folders where the file is placed.",{"type":413,"tag":422,"props":886,"children":887},{},[888],{"type":413,"tag":559,"props":889,"children":893},{"alt":890,"className":891,"src":892,"width":633},"Usage of Add New File in Visual Studio.",[563,564],"/posts/images/w192022tips_addnewfile.gif",[],{"type":413,"tag":422,"props":895,"children":896},{},[897],{"type":419,"value":666},{"title":401,"searchDepth":569,"depth":569,"links":899},[900,901,902],{"id":693,"depth":569,"text":696},{"id":767,"depth":569,"text":770},{"id":853,"depth":569,"text":856},"content:1.posts:37.w19-2022-tips-learned-this-week.md","1.posts/37.w19-2022-tips-learned-this-week.md",{"_path":109,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":108,"description":906,"lead":907,"date":908,"image":909,"badge":910,"tags":911,"body":912,"_type":678,"_id":1209,"_source":680,"_file":1210,"_extension":682},"This week we talk about code analysis in .NET, cron expressions with crontab guru, diagrams in Azure DevOps wikis, and sending HTTP requests in VS Code.","Tooling around .NET, Azure DevOps and VS Code.","2022-02-04T00:00:00.000Z",{"src":405},{"label":407},[272,239,349,343,352,208,206],{"type":410,"children":913,"toc":1203},[914,918,924,971,984,993,1006,1015,1027,1036,1049,1055,1068,1077,1090,1096,1101,1144,1149,1158,1164,1176,1185,1199],{"type":413,"tag":422,"props":915,"children":916},{},[917],{"type":419,"value":906},{"type":413,"tag":414,"props":919,"children":921},{"id":920},"net-tip-of-the-week-configuring-code-analysis-on-your-project",[922],{"type":419,"value":923},".NET tip of the week: configuring code analysis on your project",{"type":413,"tag":422,"props":925,"children":926},{},[927,929,935,937,944,946,953,955,961,963,969],{"type":419,"value":928},"Static code analysis is great because it helps you to have a better code quality, and it allows you to detect potential issues or bad practices in your code directly from your IDE. I knew about Roslyn Analyzers and the possibility to configure which rules are enabled or not (with their level of severity) through an ",{"type":413,"tag":445,"props":930,"children":932},{"className":931},[],[933],{"type":419,"value":934},".editorconfig",{"type":419,"value":936}," file. However, until I read this ",{"type":413,"tag":428,"props":938,"children":941},{"href":939,"rel":940},"https://endjin.com/blog/2022/01/raising-coding-standard-dotnet-analyzers.html",[432],[942],{"type":419,"value":943},"article",{"type":419,"value":945}," a few days ago, I did not know that you could set a ",{"type":413,"tag":428,"props":947,"children":950},{"href":948,"rel":949},"https://docs.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysismode",[432],[951],{"type":419,"value":952},"predefined code analysis configuration",{"type":419,"value":954}," just by setting an ",{"type":413,"tag":445,"props":956,"children":958},{"className":957},[],[959],{"type":419,"value":960},"AnalysisMode",{"type":419,"value":962}," property in your project file. This is great, especially if you don't want to lose time configuring all the rules individually in an ",{"type":413,"tag":445,"props":964,"children":966},{"className":965},[],[967],{"type":419,"value":968},"editorconfig",{"type":419,"value":970}," file. You can just choose the analysis mode you feel more appropriate and eventually disable a few rules that you don't want.",{"type":413,"tag":422,"props":972,"children":973},{},[974,976,982],{"type":419,"value":975},"For instance, in this ASP.NET Core 6 project I created from the built-in template, I added an empty interface in the ",{"type":413,"tag":445,"props":977,"children":979},{"className":978},[],[980],{"type":419,"value":981},"Program.cs",{"type":419,"value":983}," file.\nBy default I see a message indicating that I should declare my interface in a namespace.",{"type":413,"tag":422,"props":985,"children":986},{},[987],{"type":413,"tag":559,"props":988,"children":992},{"alt":989,"className":990,"src":991},"Program in vscode with default analysis mode.",[563,564],"/posts/images/w052022tips_analysismode_1.png",[],{"type":413,"tag":422,"props":994,"children":995},{},[996,998,1004],{"type":419,"value":997},"If I set the analysis mode to ",{"type":413,"tag":445,"props":999,"children":1001},{"className":1000},[],[1002],{"type":419,"value":1003},"Recommended",{"type":419,"value":1005},", the code analysis indicates to me the same thing but this time as a warning.",{"type":413,"tag":422,"props":1007,"children":1008},{},[1009],{"type":413,"tag":559,"props":1010,"children":1014},{"alt":1011,"className":1012,"src":1013},"Program in vscode with 'Recommended' analysis mode.",[563,564],"/posts/images/w052022tips_analysismode_2.png",[],{"type":413,"tag":422,"props":1016,"children":1017},{},[1018,1019,1025],{"type":419,"value":997},{"type":413,"tag":445,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":419,"value":1024},"All",{"type":419,"value":1026},", then not only do I have the previous warning but I also have a warning to tell me I should not have an empty interface.",{"type":413,"tag":422,"props":1028,"children":1029},{},[1030],{"type":413,"tag":559,"props":1031,"children":1035},{"alt":1032,"className":1033,"src":1034},"Program in vscode with 'All' analysis mode.",[563,564],"/posts/images/w052022tips_analysismode_3.png",[],{"type":413,"tag":422,"props":1037,"children":1038},{},[1039,1041,1047],{"type":419,"value":1040},"There are also properties to only apply rules specific to a category (security for instance). You can check the ",{"type":413,"tag":428,"props":1042,"children":1045},{"href":1043,"rel":1044},"https://docs.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysismodecategory",[432],[1046],{"type":419,"value":611},{"type":419,"value":1048}," to learn more about these.",{"type":413,"tag":414,"props":1050,"children":1052},{"id":1051},"tool-of-the-week-crontab-guru",[1053],{"type":419,"value":1054},"Tool of the week: crontab guru",{"type":413,"tag":422,"props":1056,"children":1057},{},[1058,1060,1066],{"type":419,"value":1059},"You are probably using cron expressions in a lot of different contexts whether it be to schedule an Azure Function or to trigger periodically a CI/CD pipeline (GitHub Actions or Azure DevOps for instance). Cron expressions are useful but you might not use them often, which makes it hard to remember the syntax. ",{"type":413,"tag":445,"props":1061,"children":1063},{"className":1062},[],[1064],{"type":419,"value":1065},"crontab guru",{"type":419,"value":1067}," is a tool that helps you create cron schedule expressions or understand what existing cron expressions mean.",{"type":413,"tag":422,"props":1069,"children":1070},{},[1071],{"type":413,"tag":559,"props":1072,"children":1076},{"alt":1073,"className":1074,"src":1075},"Crontab Guru website.",[563,564],"/posts/images/w052022tips_crontab_guru.png",[],{"type":413,"tag":422,"props":1078,"children":1079},{},[1080,1082,1089],{"type":419,"value":1081},"It's really helpful, so add it to your ",{"type":413,"tag":428,"props":1083,"children":1086},{"href":1084,"rel":1085},"https://crontab.guru/",[432],[1087],{"type":419,"value":1088},"bookmarks",{"type":419,"value":764},{"type":413,"tag":414,"props":1091,"children":1093},{"id":1092},"the-azure-devops-tip-you-did-not-know-about-creating-diagrams-in-markdown-with-mermaidjs",[1094],{"type":419,"value":1095},"The Azure DevOps tip you did not know about: creating diagrams in markdown with Mermaid.js",{"type":413,"tag":422,"props":1097,"children":1098},{},[1099],{"type":419,"value":1100},"If you are using Azure DevOps, you are probably writing your technical documentation in markdown in a wiki. I like the idea of having \"documentation as code\" with markdown stored in a git repository that keeps the history of changes. Yet, sometimes documentation is not just about text, you want to have diagrams to properly illustrate what your text is explaining. And you don't want to have these diagrams just stored as images in your repository but you want them within the markdown to be modified as easily as the text.",{"type":413,"tag":422,"props":1102,"children":1103},{},[1104,1106,1112,1114,1120,1122,1127,1129,1134,1136,1143],{"type":419,"value":1105},"And guess what, that's possible thanks to ",{"type":413,"tag":445,"props":1107,"children":1109},{"className":1108},[],[1110],{"type":419,"value":1111},"Mermaid.js",{"type":419,"value":1113},". As you can read on its website, ",{"type":413,"tag":428,"props":1115,"children":1118},{"href":1116,"rel":1117},"https://mermaid-js.github.io/",[432],[1119],{"type":419,"value":1111},{"type":419,"value":1121}," is a \"JavaScript based diagramming and charting tool that renders Markdown-inspired text definitions to create and modify diagrams dynamically\". It means that you can write in your markdown file some text that describes a diagram and it will be rendered by ",{"type":413,"tag":445,"props":1123,"children":1125},{"className":1124},[],[1126],{"type":419,"value":1111},{"type":419,"value":1128},". There are a lot of types of diagrams that you can create using ",{"type":413,"tag":445,"props":1130,"children":1132},{"className":1131},[],[1133],{"type":419,"value":1111},{"type":419,"value":1135}," but Azure DevOps only ",{"type":413,"tag":428,"props":1137,"children":1140},{"href":1138,"rel":1139},"https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page",[432],[1141],{"type":419,"value":1142},"supports Sequence diagrams, Gantt Charts, and Flowcharts",{"type":419,"value":764},{"type":413,"tag":422,"props":1145,"children":1146},{},[1147],{"type":419,"value":1148},"Here is an example of a diagram I created in an Azure DevOps wiki:",{"type":413,"tag":422,"props":1150,"children":1151},{},[1152],{"type":413,"tag":559,"props":1153,"children":1157},{"alt":1154,"className":1155,"src":1156},"Mermaid.js diagram in Azure DevOps wiki.",[563,564],"/posts/images/w052022tips_mermaid_1.png",[],{"type":413,"tag":414,"props":1159,"children":1161},{"id":1160},"the-vs-code-extension-you-should-try-rest-client",[1162],{"type":419,"value":1163},"The VS Code extension you should try: Rest Client",{"type":413,"tag":422,"props":1165,"children":1166},{},[1167,1174],{"type":413,"tag":428,"props":1168,"children":1171},{"href":1169,"rel":1170},"https://github.com/Huachao/vscode-restclient",[432],[1172],{"type":419,"value":1173},"REST Client",{"type":419,"value":1175}," is an open source VS Code extension that allows you to send HTTP requests and view the responses as you would do with Postman. But I prefer using REST Client over Postman because with REST Client you write the HTTP requests in text files (using the RFC 2616 standard) that you can version in your git repository along with your code. REST Client is not something I discovered this week, I have been using it for quite a long time but it's still very useful to me so I thought this post was a good opportunity to tell you to try it if you have not yet.",{"type":413,"tag":422,"props":1177,"children":1178},{},[1179],{"type":413,"tag":559,"props":1180,"children":1184},{"alt":1181,"className":1182,"src":1183},"REST Client vscode extension.",[563,564],"/posts/images/w052022tips_restclient.png",[],{"type":413,"tag":422,"props":1186,"children":1187},{},[1188,1190,1197],{"type":419,"value":1189},"In fact, it's quite funny because the ",{"type":413,"tag":428,"props":1191,"children":1194},{"href":1192,"rel":1193},"https://www.techwatching.dev/posts/testing-your-api-with-rest-client",[432],[1195],{"type":419,"value":1196},"first article",{"type":419,"value":1198}," I wrote here on my blog was an article about REST Client, how to use it and why you should use it instead of Postman.",{"type":413,"tag":422,"props":1200,"children":1201},{},[1202],{"type":419,"value":666},{"title":401,"searchDepth":569,"depth":569,"links":1204},[1205,1206,1207,1208],{"id":920,"depth":569,"text":923},{"id":1051,"depth":569,"text":1054},{"id":1092,"depth":569,"text":1095},{"id":1160,"depth":569,"text":1163},"content:1.posts:34.w05-2022-tips-learned-this-week.md","1.posts/34.w05-2022-tips-learned-this-week.md",{"_path":106,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":105,"description":1212,"lead":1213,"date":1214,"image":1215,"badge":1216,"tags":1217,"body":1218,"_type":678,"_id":1655,"_source":680,"_file":1656,"_extension":682},".NET configuration providers, Vite vscode extension, Azure DevOps pull request templates, and degit.","Tooling around .NET, Azure DevOps, and VS Code.","2022-01-24T00:00:00.000Z",{"src":405},{"label":407},[272,239,263,343,208,346,241,206],{"type":410,"children":1219,"toc":1649},[1220,1226,1278,1287,1300,1403,1425,1431,1454,1459,1468,1474,1479,1493,1506,1519,1524,1533,1538,1543,1548,1557,1574,1580,1585,1620,1629,1641,1645],{"type":413,"tag":414,"props":1221,"children":1223},{"id":1222},"net-tip-of-the-week-the-new-way-to-add-a-configuration-source",[1224],{"type":419,"value":1225},".NET tip of the week: the new way to add a configuration source",{"type":413,"tag":422,"props":1227,"children":1228},{},[1229,1231,1237,1239,1245,1247,1253,1255,1260,1262,1267,1269,1276],{"type":419,"value":1230},".NET 6 introduced a new way to build a .NET application using the new ",{"type":413,"tag":445,"props":1232,"children":1234},{"className":1233},[],[1235],{"type":419,"value":1236},"WebApplication",{"type":419,"value":1238}," and ",{"type":413,"tag":445,"props":1240,"children":1242},{"className":1241},[],[1243],{"type":419,"value":1244},"WebApplicationBuilder",{"type":419,"value":1246}," classes. One thing I like about it is how configuration is handled. Instead of using the ",{"type":413,"tag":445,"props":1248,"children":1250},{"className":1249},[],[1251],{"type":419,"value":1252},"ConfigureAppConfiguration",{"type":419,"value":1254}," method to add a new configuration source, you can directly use the ",{"type":413,"tag":445,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":419,"value":263},{"type":419,"value":1261}," property on the ",{"type":413,"tag":445,"props":1263,"children":1265},{"className":1264},[],[1266],{"type":419,"value":1244},{"type":419,"value":1268}," instance. You can see an example of this change on this screenshot of the ",{"type":413,"tag":428,"props":1270,"children":1273},{"href":1271,"rel":1272},"https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-6.0#add-configuration-providers",[432],[1274],{"type":419,"value":1275},"ASP.NET Core documentation",{"type":419,"value":1277},":",{"type":413,"tag":422,"props":1279,"children":1280},{},[1281],{"type":413,"tag":559,"props":1282,"children":1286},{"alt":1283,"className":1284,"src":1285},"Using configuration provider in ASP.NET 5 versus ASP.NET 6.",[563,564],"/posts/images/w032022tips_net_configuration_1.png",[],{"type":413,"tag":422,"props":1288,"children":1289},{},[1290,1292,1298],{"type":419,"value":1291},"You may think this way of adding a new configuration source does not bring much apart from making the code shorter. I thought it too until I discovered that it enables you to access configuration in the builder from previously registered configuration sources. For instance, if you want to load secrets from an Azure Key Vault into your configuration, you will need to retrieve the Key Vault URI from your configuration (that you may have set in your ",{"type":413,"tag":445,"props":1293,"children":1295},{"className":1294},[],[1296],{"type":419,"value":1297},"appsettings.Development.json",{"type":419,"value":1299}," file). Before you would have to partially build your configuration to get the value of a setting, now you can just access it.",{"type":413,"tag":439,"props":1301,"children":1304},{"className":1302,"code":1303,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","builder.Configuration.AddAzureKeyVault(new Uri(builder.Configuration[\"KeyVault:VaultUri\"]), new DefaultAzureCredential());\n",[1305],{"type":413,"tag":445,"props":1306,"children":1307},{"__ignoreMap":401},[1308],{"type":413,"tag":449,"props":1309,"children":1310},{"class":451,"line":452},[1311,1316,1321,1325,1329,1335,1340,1346,1351,1355,1359,1363,1368,1373,1379,1383,1388,1393,1398],{"type":413,"tag":449,"props":1312,"children":1313},{"style":456},[1314],{"type":419,"value":1315},"builder",{"type":413,"tag":449,"props":1317,"children":1319},{"style":1318},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1320],{"type":419,"value":764},{"type":413,"tag":449,"props":1322,"children":1323},{"style":456},[1324],{"type":419,"value":263},{"type":413,"tag":449,"props":1326,"children":1327},{"style":1318},[1328],{"type":419,"value":764},{"type":413,"tag":449,"props":1330,"children":1332},{"style":1331},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[1333],{"type":419,"value":1334},"AddAzureKeyVault",{"type":413,"tag":449,"props":1336,"children":1337},{"style":1318},[1338],{"type":419,"value":1339},"(new",{"type":413,"tag":449,"props":1341,"children":1343},{"style":1342},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1344],{"type":419,"value":1345}," Uri",{"type":413,"tag":449,"props":1347,"children":1348},{"style":1318},[1349],{"type":419,"value":1350},"(",{"type":413,"tag":449,"props":1352,"children":1353},{"style":456},[1354],{"type":419,"value":1315},{"type":413,"tag":449,"props":1356,"children":1357},{"style":1318},[1358],{"type":419,"value":764},{"type":413,"tag":449,"props":1360,"children":1361},{"style":456},[1362],{"type":419,"value":263},{"type":413,"tag":449,"props":1364,"children":1365},{"style":1318},[1366],{"type":419,"value":1367},"[",{"type":413,"tag":449,"props":1369,"children":1370},{"style":1318},[1371],{"type":419,"value":1372},"\"",{"type":413,"tag":449,"props":1374,"children":1376},{"style":1375},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1377],{"type":419,"value":1378},"KeyVault:VaultUri",{"type":413,"tag":449,"props":1380,"children":1381},{"style":1318},[1382],{"type":419,"value":1372},{"type":413,"tag":449,"props":1384,"children":1385},{"style":1318},[1386],{"type":419,"value":1387},"]),",{"type":413,"tag":449,"props":1389,"children":1390},{"style":1318},[1391],{"type":419,"value":1392}," new",{"type":413,"tag":449,"props":1394,"children":1395},{"style":1342},[1396],{"type":419,"value":1397}," DefaultAzureCredential",{"type":413,"tag":449,"props":1399,"children":1400},{"style":1318},[1401],{"type":419,"value":1402},"());\n",{"type":413,"tag":422,"props":1404,"children":1405},{},[1406,1408,1415,1417,1423],{"type":419,"value":1407},"Configuration from previously registered sources is already available because configuration sources are directly loaded once they are added. If you want to learn more about the behind-the-scenes, Andrew Lock has a ",{"type":413,"tag":428,"props":1409,"children":1412},{"href":1410,"rel":1411},"https://andrewlock.net/exploring-dotnet-6-part-1-looking-inside-configurationmanager-in-dotnet-6/",[432],[1413],{"type":419,"value":1414},"very interesting article",{"type":419,"value":1416}," about ",{"type":413,"tag":445,"props":1418,"children":1420},{"className":1419},[],[1421],{"type":419,"value":1422},"ConfigurationManager",{"type":419,"value":1424}," that I suggest you read.",{"type":413,"tag":414,"props":1426,"children":1428},{"id":1427},"the-vs-code-extension-you-should-try-vite",[1429],{"type":419,"value":1430},"The VS Code extension you should try: Vite",{"type":413,"tag":422,"props":1432,"children":1433},{},[1434,1436,1443,1445,1452],{"type":419,"value":1435},"If you are developing a front-end using Vite (and there are ",{"type":413,"tag":428,"props":1437,"children":1440},{"href":1438,"rel":1439},"https://vitejs.dev/guide/why.html",[432],[1441],{"type":419,"value":1442},"good reasons",{"type":419,"value":1444}," why you should), there is a ",{"type":413,"tag":428,"props":1446,"children":1449},{"href":1447,"rel":1448},"https://marketplace.visualstudio.com/items?itemName=antfu.vite",[432],[1450],{"type":419,"value":1451},"Vite extension for VS Code",{"type":419,"value":1453}," currently in preview.",{"type":413,"tag":422,"props":1455,"children":1456},{},[1457],{"type":419,"value":1458},"You can see the main features of this extension below: little things that make you always more productive.",{"type":413,"tag":422,"props":1460,"children":1461},{},[1462],{"type":413,"tag":559,"props":1463,"children":1467},{"alt":1464,"className":1465,"src":1466},"Vs code vite exension.",[563,564],"/posts/images/w032022tips_vscode_vite_1.png",[],{"type":413,"tag":414,"props":1469,"children":1471},{"id":1470},"the-azure-devops-tip-you-did-not-know-about-creating-pull-requests-templates",[1472],{"type":419,"value":1473},"The Azure DevOps tip you did not know about: creating pull requests templates",{"type":413,"tag":422,"props":1475,"children":1476},{},[1477],{"type":419,"value":1478},"As a developer working with Azure DevOps, you probably spend a lot of time reviewing your colleagues pull requests and what helps you to have a good context (of what problem a pull request solves or what new feature it brings) are having a work item associated to the pull request, and having a good description. You can enforce the pull request to have an associated work item by setting it to mandatory in your branch policies, but \"having a good description\" is not something you can enforce.",{"type":413,"tag":422,"props":1480,"children":1481},{},[1482,1484,1491],{"type":419,"value":1483},"However, you can provide some guidance on what the description should tell, how it should be organized, what are the key points to verify before submitting the pull request... How do you do that? By creating a pull request template in your repository which will be a markdown file that will be automatically added to a pull request description when the pull request is created. You can read the ",{"type":413,"tag":428,"props":1485,"children":1488},{"href":1486,"rel":1487},"https://docs.microsoft.com/en-us/azure/devops/repos/git/pull-request-templates?view=azure-devops",[432],[1489],{"type":419,"value":1490},"official documentation",{"type":419,"value":1492}," but let me show you quickly how it works:",{"type":413,"tag":422,"props":1494,"children":1495},{},[1496,1498,1504],{"type":419,"value":1497},"1- You create a ",{"type":413,"tag":445,"props":1499,"children":1501},{"className":1500},[],[1502],{"type":419,"value":1503},".azuredevops",{"type":419,"value":1505}," folder in the root of your git repository",{"type":413,"tag":422,"props":1507,"children":1508},{},[1509,1511,1517],{"type":419,"value":1510},"2- You create a markdown file ",{"type":413,"tag":445,"props":1512,"children":1514},{"className":1513},[],[1515],{"type":419,"value":1516},"pull_request_template.md",{"type":419,"value":1518}," containing the description you want",{"type":413,"tag":422,"props":1520,"children":1521},{},[1522],{"type":419,"value":1523},"You can see below an example of a template I created:",{"type":413,"tag":422,"props":1525,"children":1526},{},[1527],{"type":413,"tag":559,"props":1528,"children":1532},{"alt":1529,"className":1530,"src":1531},"Pull request markdown template file.",[563,564],"/posts/images/w032022tips_pr_template_1.png",[],{"type":413,"tag":422,"props":1534,"children":1535},{},[1536],{"type":419,"value":1537},"3- You commit this file and push it in your main branch",{"type":413,"tag":422,"props":1539,"children":1540},{},[1541],{"type":419,"value":1542},"4- Now when someone creates a pull request, he will have a pre-filled description to complete before submitting his pull request",{"type":413,"tag":422,"props":1544,"children":1545},{},[1546],{"type":419,"value":1547},"This is what it looks like for my template:",{"type":413,"tag":422,"props":1549,"children":1550},{},[1551],{"type":413,"tag":559,"props":1552,"children":1556},{"alt":1553,"className":1554,"src":1555},"Pull request template in Azure DevOps.",[563,564],"/posts/images/w032022tips_pr_template_2.png",[],{"type":413,"tag":1558,"props":1559,"children":1561},"callout",{"icon":1560},"i-heroicons-chat-bubble-left-20-solid",[1562],{"type":413,"tag":422,"props":1563,"children":1564},{},[1565,1567,1573],{"type":419,"value":1566},"If you are using GitHub and not Azure DevOps, just know that there are also pull requests templates in ",{"type":413,"tag":428,"props":1568,"children":1571},{"href":1569,"rel":1570},"https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository",[432],[1572],{"type":419,"value":233},{"type":419,"value":764},{"type":413,"tag":414,"props":1575,"children":1577},{"id":1576},"tool-of-the-week-degit",[1578],{"type":419,"value":1579},"Tool of the week: degit",{"type":413,"tag":422,"props":1581,"children":1582},{},[1583],{"type":419,"value":1584},"Sometimes you find an interesting open source git repository that could help you save some time when starting a new project. That can be a project template or a sample, it's a repository that you want to start coding from. You can clone it or fork it but you will retrieve the whole git history and that is something that you probably don't want.",{"type":413,"tag":422,"props":1586,"children":1587},{},[1588,1595,1597,1603,1605,1611,1613,1619],{"type":413,"tag":428,"props":1589,"children":1592},{"href":1590,"rel":1591},"https://github.com/Rich-Harris/degit",[432],[1593],{"type":419,"value":1594},"degit",{"type":419,"value":1596}," is a helpful tool that solves this issue. When you run this tool on a git repository, it retrieves locally the latest version of this repository without its git history. It's an ",{"type":413,"tag":445,"props":1598,"children":1600},{"className":1599},[],[1601],{"type":419,"value":1602},"npm",{"type":419,"value":1604}," tool so you can install it globally with ",{"type":413,"tag":445,"props":1606,"children":1608},{"className":1607},[],[1609],{"type":419,"value":1610},"npm install -g degit",{"type":419,"value":1612}," or directly run it using ",{"type":413,"tag":445,"props":1614,"children":1616},{"className":1615},[],[1617],{"type":419,"value":1618},"npx",{"type":419,"value":764},{"type":413,"tag":422,"props":1621,"children":1622},{},[1623],{"type":413,"tag":559,"props":1624,"children":1628},{"alt":1625,"className":1626,"src":1627},"Ouput when using degit package on a repository.",[563,564],"/posts/images/w032022tips_degit_1.png",[],{"type":413,"tag":422,"props":1630,"children":1631},{},[1632,1634,1639],{"type":419,"value":1633},"Don't hesitate to give the project a star on ",{"type":413,"tag":428,"props":1635,"children":1637},{"href":1590,"rel":1636},[432],[1638],{"type":419,"value":233},{"type":419,"value":1640}," if you find it useful.",{"type":413,"tag":422,"props":1642,"children":1643},{},[1644],{"type":419,"value":666},{"type":413,"tag":668,"props":1646,"children":1647},{},[1648],{"type":419,"value":672},{"title":401,"searchDepth":569,"depth":569,"links":1650},[1651,1652,1653,1654],{"id":1222,"depth":569,"text":1225},{"id":1427,"depth":569,"text":1430},{"id":1470,"depth":569,"text":1473},{"id":1576,"depth":569,"text":1579},"content:1.posts:33.w03-2022-tips-learned-this-week.md","1.posts/33.w03-2022-tips-learned-this-week.md",{"_path":103,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":102,"description":1658,"lead":1659,"date":1660,"image":1661,"badge":1662,"tags":1663,"body":1664,"_type":678,"_id":1898,"_source":680,"_file":1899,"_extension":682},"This is my first article of the series Tips I learned this week for 2022 🚀! And today we are going to see some tips about .NET, Azure, GitHub, and VS Code.","Tooling around .NET, Azure, Github and VS Code.","2022-01-14T00:00:00.000Z",{"src":405},{"label":407},[272,239,225,233,208,206],{"type":410,"children":1665,"toc":1891},[1666,1680,1686,1699,1708,1713,1725,1738,1768,1777,1783,1797,1810,1823,1832,1845,1851,1865,1874,1887],{"type":413,"tag":422,"props":1667,"children":1668},{},[1669,1671,1678],{"type":419,"value":1670},"This is my first article of the series ",{"type":413,"tag":428,"props":1672,"children":1675},{"href":1673,"rel":1674},"https://www.techwatching.dev/tags/tips-learned-this-week/",[432],[1676],{"type":419,"value":1677},"Tips I learned this week",{"type":419,"value":1679}," for 2022 🚀! And today we are going to see some tips about .NET, Azure, GitHub, and VS Code.",{"type":413,"tag":414,"props":1681,"children":1683},{"id":1682},"net-tip-of-the-week-changing-the-net-cli-language",[1684],{"type":419,"value":1685},".NET tip of the week: changing the .NET CLI language",{"type":413,"tag":422,"props":1687,"children":1688},{},[1689,1691,1697],{"type":419,"value":1690},"Did you know that you could change the language of the .NET CLI to the one you find most appropriate? By default, the dotnet CLI messages you see when running a dotnet program are your language OS (French in my case). However, by setting the \"DOTNET_CLI_UI_LANGUAGE\" variable environment to ",{"type":413,"tag":445,"props":1692,"children":1694},{"className":1693},[],[1695],{"type":419,"value":1696},"en",{"type":419,"value":1698}," for instance I can change it to English.",{"type":413,"tag":422,"props":1700,"children":1701},{},[1702],{"type":413,"tag":559,"props":1703,"children":1707},{"alt":1704,"className":1705,"src":1706},".NET CLI language change in terminal.",[563,564],"/posts/images/w022022tips_dotnet_cli.png",[],{"type":413,"tag":422,"props":1709,"children":1710},{},[1711],{"type":419,"value":1712},"Why is it useful? Let's imagine I have an issue with a dotnet CLI command and that I want to get some help from the community by posting a question to a Q&A website with a screenshot of my error. If all the messages are in French I will probably not get many answers whereas if it's in English everyone will be able to understand what my commands are doing. There is also the fact that sometimes French accents and special characters are not well displayed by some terminals.",{"type":413,"tag":414,"props":1714,"children":1716},{"id":1715},"the-azure-tip-you-did-not-know-about-simplify-your-azure-cli-configuration-with-azure-init",[1717,1719],{"type":419,"value":1718},"The Azure tip you did not know about: simplify your Azure CLI configuration with ",{"type":413,"tag":445,"props":1720,"children":1722},{"className":1721},[],[1723],{"type":419,"value":1724},"azure init",{"type":413,"tag":422,"props":1726,"children":1727},{},[1728,1730,1736],{"type":419,"value":1729},"I don't know if you use a lot Azure CLI but it's a very nice tool! Each time I use Azure CLI, I think \"it's awesome 🤩 I should use it more often instead of using Azure Portal\". I even wrote a post about that 2 years ago: \"",{"type":413,"tag":428,"props":1731,"children":1734},{"href":1732,"rel":1733},"https://www.techwatching.dev/posts/welcome-azure-cli",[432],[1735],{"type":419,"value":15},{"type":419,"value":1737},"\".",{"type":413,"tag":422,"props":1739,"children":1740},{},[1741,1743,1749,1751,1758,1760,1766],{"type":419,"value":1742},"However, if you want to configure your Azure CLI, it can be sometimes a bit boring and slow to configure it using the ",{"type":413,"tag":445,"props":1744,"children":1746},{"className":1745},[],[1747],{"type":419,"value":1748},"az config",{"type":419,"value":1750}," command. That is why Microsoft has ",{"type":413,"tag":428,"props":1752,"children":1755},{"href":1753,"rel":1754},"https://techcommunity.microsoft.com/t5/azure-tools-blog/streamline-configuring-azure-cli-with-az-init/ba-p/3051810",[432],[1756],{"type":419,"value":1757},"released in preview",{"type":419,"value":1759}," an Azure CLI extension called ",{"type":413,"tag":445,"props":1761,"children":1763},{"className":1762},[],[1764],{"type":419,"value":1765},"az init",{"type":419,"value":1767}," to simplify this configuration. For example you can quickly configure the output of the commands or the syntax highlighting, things like that.",{"type":413,"tag":422,"props":1769,"children":1770},{},[1771],{"type":413,"tag":559,"props":1772,"children":1776},{"alt":1773,"className":1774,"src":1775},"azure init command output.",[563,564],"/posts/images/w022022tips_az_init.png",[],{"type":413,"tag":414,"props":1778,"children":1780},{"id":1779},"tool-of-the-week-github-code-search",[1781],{"type":419,"value":1782},"Tool of the week: GitHub Code Search",{"type":413,"tag":422,"props":1784,"children":1785},{},[1786,1788,1795],{"type":419,"value":1787},"Have you ever wished you could easily search code on GitHub in multiple repositories without cloning anything? That is now possible with ",{"type":413,"tag":428,"props":1789,"children":1792},{"href":1790,"rel":1791},"https://cs.github.com/",[432],[1793],{"type":419,"value":1794},"GitHub Code Search",{"type":419,"value":1796},". It is still in preview but looks promising! You have access to nice filters to find exactly the code you are looking for, and once you get it you can navigate in and across files.",{"type":413,"tag":422,"props":1798,"children":1799},{},[1800,1802,1808],{"type":419,"value":1801},"For a long time, I have kept a bookmark to the \"",{"type":413,"tag":428,"props":1803,"children":1806},{"href":1804,"rel":1805},"https://source.dot.net/",[432],[1807],{"type":419,"value":1804},{"type":419,"value":1809},"\" website for the times when I needed to understand how something was implemented in the .NET Core framework. But with GitHub Code Search I think I don't need it anymore. .NET Core is open source and all the source code is on GitHub so I can quickly find everything I need just by searching it on GitHub.",{"type":413,"tag":422,"props":1811,"children":1812},{},[1813,1815,1821],{"type":419,"value":1814},"For instance, let's say I don't remember exactly what configuration is injected by default in a dotnet project when you use the ",{"type":413,"tag":445,"props":1816,"children":1818},{"className":1817},[],[1819],{"type":419,"value":1820},"Host.CreateDefaultBuilder",{"type":419,"value":1822}," method. I will scope my search to dotnet organization repositories and a few keystrokes later, I can see all the configuration providers used to load some default configuration in a project.",{"type":413,"tag":422,"props":1824,"children":1825},{},[1826],{"type":413,"tag":559,"props":1827,"children":1831},{"alt":1828,"className":1829,"src":1830},"GitHub search usage.",[563,564],"/posts/images/w022022tips_githu_cs.gif",[],{"type":413,"tag":422,"props":1833,"children":1834},{},[1835,1837,1844],{"type":419,"value":1836},"You can read more about GitHub Code Search on ",{"type":413,"tag":428,"props":1838,"children":1841},{"href":1839,"rel":1840},"https://github.blog/2021-12-08-improving-github-code-search/",[432],[1842],{"type":419,"value":1843},"GitHub's blog",{"type":419,"value":764},{"type":413,"tag":414,"props":1846,"children":1848},{"id":1847},"the-vs-code-extension-you-should-try-i18n-ally",[1849],{"type":419,"value":1850},"The VS Code extension you should try: i18n ally",{"type":413,"tag":422,"props":1852,"children":1853},{},[1854,1856,1863],{"type":419,"value":1855},"When you are developing an application that supports several languages, it can quickly become annoying to go in every translation file when you need to check or modify a translation. If you are developing your application using VS Code, you probably should check out the extension ",{"type":413,"tag":428,"props":1857,"children":1860},{"href":1858,"rel":1859},"https://github.com/lokalise/i18n-ally",[432],[1861],{"type":419,"value":1862},"i18n ally",{"type":419,"value":1864}," because it will save you a lot of time.",{"type":413,"tag":422,"props":1866,"children":1867},{},[1868],{"type":413,"tag":559,"props":1869,"children":1873},{"alt":1870,"className":1871,"src":1872},"i18n ally extension in vscode.",[563,564],"/posts/images/w222021tips_i18n_ally.png",[],{"type":413,"tag":422,"props":1875,"children":1876},{},[1877,1879,1885],{"type":419,"value":1878},"It is very handy and I like the fact the extension support lots of frameworks like Vue.js, Angular, React, Svelte, and Flutter (you can find the complete list of supported frameworks ",{"type":413,"tag":428,"props":1880,"children":1883},{"href":1881,"rel":1882},"https://github.com/lokalise/i18n-ally/wiki/Supported-Frameworks",[432],[1884],{"type":419,"value":477},{"type":419,"value":1886},"). My only regret with this extension is not to have heard about it sooner.",{"type":413,"tag":422,"props":1888,"children":1889},{},[1890],{"type":419,"value":666},{"title":401,"searchDepth":569,"depth":569,"links":1892},[1893,1894,1896,1897],{"id":1682,"depth":569,"text":1685},{"id":1715,"depth":569,"text":1895},"The Azure tip you did not know about: simplify your Azure CLI configuration with azure init",{"id":1779,"depth":569,"text":1782},{"id":1847,"depth":569,"text":1850},"content:1.posts:32.w02-2022-tips-learned-this-week.md","1.posts/32.w02-2022-tips-learned-this-week.md",{"_path":85,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":84,"description":1901,"lead":1902,"date":1903,"image":1904,"badge":1905,"tags":1906,"body":1907,"_type":678,"_id":3197,"_source":680,"_file":3198,"_extension":682},"This week I worked mainly in vs code to do some web development so tips will mostly be about vscode.","vscode, vscode Jest extension, csharp attributes for nullables.","2021-10-18T00:00:00.000Z",{"src":405},{"label":407},[272,208,326,328],{"type":410,"children":1908,"toc":3190},[1909,1913,1919,1924,1933,1946,1955,1967,1987,2002,2022,2031,2044,2049,2055,2060,2069,2090,2192,2200,2205,2214,2259,2264,2270,2275,2283,2288,2311,2324,2337,2964,2976,3108,3182,3186],{"type":413,"tag":422,"props":1910,"children":1911},{},[1912],{"type":419,"value":1901},{"type":413,"tag":414,"props":1914,"children":1916},{"id":1915},"work-on-different-parts-of-your-file-with-the-new-split-in-group-command",[1917],{"type":419,"value":1918},"Work on different parts of your file with the new \"split in group\" command",{"type":413,"tag":422,"props":1920,"children":1921},{},[1922],{"type":419,"value":1923},"When you are developing a component in Vue.js, it is convenient to be able to work at the same time on the HTML template and the TypeScript code which happen to be in the same file.",{"type":413,"tag":422,"props":1925,"children":1926},{},[1927],{"type":413,"tag":559,"props":1928,"children":1932},{"alt":1929,"className":1930,"src":1931},"Split in Group option in vscode.",[563,564],"/posts/images/w412021tips_vscode_1.png",[],{"type":413,"tag":422,"props":1934,"children":1935},{},[1936,1938,1944],{"type":419,"value":1937},"The latest release of vscode allows you to do that easily by introducing a new command \"Split in Group\" (the shortcut is ",{"type":413,"tag":445,"props":1939,"children":1941},{"className":1940},[],[1942],{"type":419,"value":1943},"Ctrl+K Ctrl+Shift+*",{"type":419,"value":1945}," on Windows)\" that splits an editor into two sides.",{"type":413,"tag":422,"props":1947,"children":1948},{},[1949],{"type":413,"tag":559,"props":1950,"children":1954},{"alt":1951,"className":1952,"src":1953},"Vue component split in 2 in vscode.",[563,564],"/posts/images/w412021tips_vscode_2.png",[],{"type":413,"tag":414,"props":1956,"children":1958},{"id":1957},"vscode-jest-a-must-have-extension-when-using-jest",[1959,1965],{"type":413,"tag":445,"props":1960,"children":1962},{"className":1961},[],[1963],{"type":419,"value":1964},"vscode-jest",{"type":419,"value":1966},", a must-have extension when using Jest",{"type":413,"tag":422,"props":1968,"children":1969},{},[1970,1972,1978,1980,1985],{"type":419,"value":1971},"Many projects are using ",{"type":413,"tag":445,"props":1973,"children":1975},{"className":1974},[],[1976],{"type":419,"value":1977},"Jest",{"type":419,"value":1979}," as their testing framework for the frontend. But I was quite surprised to see that by default there is no test explorer in vscode to run or debug your ",{"type":413,"tag":445,"props":1981,"children":1983},{"className":1982},[],[1984],{"type":419,"value":1977},{"type":419,"value":1986}," tests. I like the command line but for some things, like debugging a specific test, a UI is way more convenient.",{"type":413,"tag":1558,"props":1988,"children":1989},{"icon":1560},[1990],{"type":413,"tag":422,"props":1991,"children":1992},{},[1993,1995,2001],{"type":419,"value":1994},"From what I understood, there is a native API/UI in vscode that extensions can use to help you managed your tests. You can learn about that ",{"type":413,"tag":428,"props":1996,"children":1999},{"href":1997,"rel":1998},"https://code.visualstudio.com/api/extension-guides/testing",[432],[2000],{"type":419,"value":477},{"type":419,"value":764},{"type":413,"tag":422,"props":2003,"children":2004},{},[2005,2007,2012,2014,2020],{"type":419,"value":2006},"So we have to install the ",{"type":413,"tag":445,"props":2008,"children":2010},{"className":2009},[],[2011],{"type":419,"value":1964},{"type":419,"value":2013}," ",{"type":413,"tag":428,"props":2015,"children":2018},{"href":2016,"rel":2017},"https://github.com/jest-community/vscode-jest",[432],[2019],{"type":419,"value":809},{"type":419,"value":2021}," to be able to discover our tests, run them and debug them.",{"type":413,"tag":422,"props":2023,"children":2024},{},[2025],{"type":413,"tag":559,"props":2026,"children":2030},{"alt":2027,"className":2028,"src":2029},"Jest vscoe extension.",[563,564],"/posts/images/w412021tips_jest_1.png",[],{"type":413,"tag":422,"props":2032,"children":2033},{},[2034,2036,2042],{"type":419,"value":2035},"If you are familiar with full-featured IDEs, you will like this extension that gives you a nice test explorer as well as other interesting features such as automatically running tests when code changes are made (similar to ",{"type":413,"tag":445,"props":2037,"children":2039},{"className":2038},[],[2040],{"type":419,"value":2041},"Live Unit Testing",{"type":419,"value":2043}," in Visual Studio )",{"type":413,"tag":422,"props":2045,"children":2046},{},[2047],{"type":419,"value":2048},"That brings me to talking about sharing your vs code extensions with your colleagues.",{"type":413,"tag":414,"props":2050,"children":2052},{"id":2051},"share-to-your-colleagues-the-vscode-extensions-to-use-on-your-project",[2053],{"type":419,"value":2054},"Share to your colleagues the vscode extensions to use on your project",{"type":413,"tag":422,"props":2056,"children":2057},{},[2058],{"type":419,"value":2059},"When you start working on a new project, you often have to find out which extensions your colleagues are using so that you install everything you need to work on the project. If your colleagues are nice, they would have written this kind of information in the README or the wiki of the project. But what if vscode could directly suggest to you which extensions to install when you open the project on your computer.",{"type":413,"tag":422,"props":2061,"children":2062},{},[2063],{"type":413,"tag":559,"props":2064,"children":2068},{"alt":2065,"className":2066,"src":2067},"Suggested extensions popin in vscode.",[563,564],"/posts/images/w412021tips_vscode_3.png",[],{"type":413,"tag":422,"props":2070,"children":2071},{},[2072,2074,2080,2082,2088],{"type":419,"value":2073},"As you can see on the screenshot above that is exactly what vscode can do for you if someone has specified the recommended vscode extensions of the workspace in the ",{"type":413,"tag":445,"props":2075,"children":2077},{"className":2076},[],[2078],{"type":419,"value":2079},"extensions.json",{"type":419,"value":2081}," file of the ",{"type":413,"tag":445,"props":2083,"children":2085},{"className":2084},[],[2086],{"type":419,"value":2087},".vscode",{"type":419,"value":2089}," folder.\nHere is an example of such a file:",{"type":413,"tag":439,"props":2091,"children":2095},{"className":2092,"code":2093,"language":2094,"meta":401,"style":401},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n    \"recommendations\": [\n        \"orta.vscode-jest\",\n        \"sdras.vue-vscode-extensionpack\"\n    ]\n}\n","json",[2096],{"type":413,"tag":445,"props":2097,"children":2098},{"__ignoreMap":401},[2099,2107,2134,2156,2174,2183],{"type":413,"tag":449,"props":2100,"children":2101},{"class":451,"line":452},[2102],{"type":413,"tag":449,"props":2103,"children":2104},{"style":1318},[2105],{"type":419,"value":2106},"{\n",{"type":413,"tag":449,"props":2108,"children":2109},{"class":451,"line":569},[2110,2115,2121,2125,2129],{"type":413,"tag":449,"props":2111,"children":2112},{"style":1318},[2113],{"type":419,"value":2114},"    \"",{"type":413,"tag":449,"props":2116,"children":2118},{"style":2117},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[2119],{"type":419,"value":2120},"recommendations",{"type":413,"tag":449,"props":2122,"children":2123},{"style":1318},[2124],{"type":419,"value":1372},{"type":413,"tag":449,"props":2126,"children":2127},{"style":1318},[2128],{"type":419,"value":1277},{"type":413,"tag":449,"props":2130,"children":2131},{"style":1318},[2132],{"type":419,"value":2133}," [\n",{"type":413,"tag":449,"props":2135,"children":2136},{"class":451,"line":593},[2137,2142,2147,2151],{"type":413,"tag":449,"props":2138,"children":2139},{"style":1318},[2140],{"type":419,"value":2141},"        \"",{"type":413,"tag":449,"props":2143,"children":2144},{"style":1375},[2145],{"type":419,"value":2146},"orta.vscode-jest",{"type":413,"tag":449,"props":2148,"children":2149},{"style":1318},[2150],{"type":419,"value":1372},{"type":413,"tag":449,"props":2152,"children":2153},{"style":1318},[2154],{"type":419,"value":2155},",\n",{"type":413,"tag":449,"props":2157,"children":2159},{"class":451,"line":2158},4,[2160,2164,2169],{"type":413,"tag":449,"props":2161,"children":2162},{"style":1318},[2163],{"type":419,"value":2141},{"type":413,"tag":449,"props":2165,"children":2166},{"style":1375},[2167],{"type":419,"value":2168},"sdras.vue-vscode-extensionpack",{"type":413,"tag":449,"props":2170,"children":2171},{"style":1318},[2172],{"type":419,"value":2173},"\"\n",{"type":413,"tag":449,"props":2175,"children":2177},{"class":451,"line":2176},5,[2178],{"type":413,"tag":449,"props":2179,"children":2180},{"style":1318},[2181],{"type":419,"value":2182},"    ]\n",{"type":413,"tag":449,"props":2184,"children":2186},{"class":451,"line":2185},6,[2187],{"type":413,"tag":449,"props":2188,"children":2189},{"style":1318},[2190],{"type":419,"value":2191},"}\n",{"type":413,"tag":1558,"props":2193,"children":2194},{"icon":1560},[2195],{"type":413,"tag":422,"props":2196,"children":2197},{},[2198],{"type":419,"value":2199},"If you don't want vscode to recommend you some extensions, you can also specify a list of unwanted recommendations in this file.",{"type":413,"tag":422,"props":2201,"children":2202},{},[2203],{"type":419,"value":2204},"This is just a list of vscode extensions identifiers. You can find the identifier of an extension on its details page in vscode. You will also find there a button to directly add the extension to your recommended list of extensions.",{"type":413,"tag":422,"props":2206,"children":2207},{},[2208],{"type":413,"tag":559,"props":2209,"children":2213},{"alt":2210,"className":2211,"src":2212},"Add to workspace recommendation example.",[563,564],"/posts/images/w412021tips_vscode_4.png",[],{"type":413,"tag":1558,"props":2215,"children":2216},{"icon":1560},[2217],{"type":413,"tag":422,"props":2218,"children":2219},{},[2220,2222,2227,2229,2235,2237,2243,2245,2250,2252,2257],{"type":419,"value":2221},"If the ",{"type":413,"tag":445,"props":2223,"children":2225},{"className":2224},[],[2226],{"type":419,"value":2087},{"type":419,"value":2228}," folder is in the ",{"type":413,"tag":445,"props":2230,"children":2232},{"className":2231},[],[2233],{"type":419,"value":2234},"gitignore",{"type":419,"value":2236}," of your repository, do not forget to add this line ",{"type":413,"tag":445,"props":2238,"children":2240},{"className":2239},[],[2241],{"type":419,"value":2242},"!.vscode/extensions.json",{"type":419,"value":2244}," to your ",{"type":413,"tag":445,"props":2246,"children":2248},{"className":2247},[],[2249],{"type":419,"value":2234},{"type":419,"value":2251}," file to be able to add your ",{"type":413,"tag":445,"props":2253,"children":2255},{"className":2254},[],[2256],{"type":419,"value":2079},{"type":419,"value":2258}," file in your repository.",{"type":413,"tag":422,"props":2260,"children":2261},{},[2262],{"type":419,"value":2263},"And finally, let's talk a little bit about C#.",{"type":413,"tag":414,"props":2265,"children":2267},{"id":2266},"help-the-c-compiler-helps-you-with-nullable-reference-types",[2268],{"type":419,"value":2269},"Help the C# compiler helps you with nullable reference types.",{"type":413,"tag":422,"props":2271,"children":2272},{},[2273],{"type":419,"value":2274},"I am a big fan of enabling nullable on c# projects because I am convinced that it enforces you to write better code.",{"type":413,"tag":1558,"props":2276,"children":2277},{"icon":1560},[2278],{"type":413,"tag":422,"props":2279,"children":2280},{},[2281],{"type":419,"value":2282},"As you can guess I am very happy to see that nullable will be enabled by default on new projects in .NET 6.  I think that warnings as errors for nullable should be set by default as well but that is another story.",{"type":413,"tag":422,"props":2284,"children":2285},{},[2286],{"type":419,"value":2287},"However, sometimes the compiler is not enough clever or does not have enough context to know that some code is fine and that it should not raise a warning. When something like that happens, we often solve this by using one of these 2 solutions:",{"type":413,"tag":2289,"props":2290,"children":2291},"ul",{},[2292,2306],{"type":413,"tag":536,"props":2293,"children":2294},{},[2295,2297,2304],{"type":419,"value":2296},"Use the ",{"type":413,"tag":428,"props":2298,"children":2301},{"href":2299,"rel":2300},"https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-forgiving",[432],[2302],{"type":419,"value":2303},"null forgiving operator",{"type":419,"value":2305}," that should not be used in most cases",{"type":413,"tag":536,"props":2307,"children":2308},{},[2309],{"type":419,"value":2310},"Use an additional and unnecessary check just to please the compiler",{"type":413,"tag":422,"props":2312,"children":2313},{},[2314,2316,2322],{"type":419,"value":2315},"It's because we often forget that we can add attributes on our code for null-state analysis as it is described in the ",{"type":413,"tag":428,"props":2317,"children":2320},{"href":2318,"rel":2319},"https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/nullable-analysis",[432],[2321],{"type":419,"value":611},{"type":419,"value":2323},". These attributes will provide more information to the compiler which will be able to provide more accurate warnings.",{"type":413,"tag":422,"props":2325,"children":2326},{},[2327,2329,2335],{"type":419,"value":2328},"I recently read a Pull Request where the developer was doing an additional check on the nullability of an out parameter coming from a ",{"type":413,"tag":445,"props":2330,"children":2332},{"className":2331},[],[2333],{"type":419,"value":2334},"TryGet",{"type":419,"value":2336}," method like in the example below.",{"type":413,"tag":439,"props":2338,"children":2340},{"className":1302,"code":2339,"language":326,"meta":401,"style":401},"string name = \".NET 6\";\nvar myStore = new MyAwesomeStore();\nmyStore.Add(\"WelcomeMessage\", \"  Hello \");\n\nif (myStore.TryGet(\"WelcomeMessage\", out var value) && value is not null)\n{\n    var welcomeMessage = value.TrimStart();\n    string message = welcomeMessage + name;\n}\n\npublic class MyAwesomeStore\n{\n    private IDictionary\u003Cstring, string> _store = new Dictionary\u003Cstring, string>();\n\n    public void Add(string key, string value) => _store.Add(key, value);\n    public bool TryGet(string key, out string? value) => _store.TryGetValue(key, out value);\n}\n",[2341],{"type":413,"tag":445,"props":2342,"children":2343},{"__ignoreMap":401},[2344,2381,2412,2469,2478,2569,2576,2611,2647,2655,2663,2682,2690,2766,2774,2860,2956],{"type":413,"tag":449,"props":2345,"children":2346},{"class":451,"line":452},[2347,2352,2357,2362,2367,2372,2376],{"type":413,"tag":449,"props":2348,"children":2349},{"style":1318},[2350],{"type":419,"value":2351},"string",{"type":413,"tag":449,"props":2353,"children":2354},{"style":1342},[2355],{"type":419,"value":2356}," name",{"type":413,"tag":449,"props":2358,"children":2359},{"style":1318},[2360],{"type":419,"value":2361}," =",{"type":413,"tag":449,"props":2363,"children":2364},{"style":1318},[2365],{"type":419,"value":2366}," \"",{"type":413,"tag":449,"props":2368,"children":2369},{"style":1375},[2370],{"type":419,"value":2371},".NET 6",{"type":413,"tag":449,"props":2373,"children":2374},{"style":1318},[2375],{"type":419,"value":1372},{"type":413,"tag":449,"props":2377,"children":2378},{"style":1318},[2379],{"type":419,"value":2380},";\n",{"type":413,"tag":449,"props":2382,"children":2383},{"class":451,"line":569},[2384,2389,2394,2398,2402,2407],{"type":413,"tag":449,"props":2385,"children":2386},{"style":1342},[2387],{"type":419,"value":2388},"var",{"type":413,"tag":449,"props":2390,"children":2391},{"style":1342},[2392],{"type":419,"value":2393}," myStore",{"type":413,"tag":449,"props":2395,"children":2396},{"style":1318},[2397],{"type":419,"value":2361},{"type":413,"tag":449,"props":2399,"children":2400},{"style":1318},[2401],{"type":419,"value":1392},{"type":413,"tag":449,"props":2403,"children":2404},{"style":1342},[2405],{"type":419,"value":2406}," MyAwesomeStore",{"type":413,"tag":449,"props":2408,"children":2409},{"style":1318},[2410],{"type":419,"value":2411},"();\n",{"type":413,"tag":449,"props":2413,"children":2414},{"class":451,"line":593},[2415,2420,2424,2429,2433,2437,2442,2446,2451,2455,2460,2464],{"type":413,"tag":449,"props":2416,"children":2417},{"style":456},[2418],{"type":419,"value":2419},"myStore",{"type":413,"tag":449,"props":2421,"children":2422},{"style":1318},[2423],{"type":419,"value":764},{"type":413,"tag":449,"props":2425,"children":2426},{"style":1331},[2427],{"type":419,"value":2428},"Add",{"type":413,"tag":449,"props":2430,"children":2431},{"style":1318},[2432],{"type":419,"value":1350},{"type":413,"tag":449,"props":2434,"children":2435},{"style":1318},[2436],{"type":419,"value":1372},{"type":413,"tag":449,"props":2438,"children":2439},{"style":1375},[2440],{"type":419,"value":2441},"WelcomeMessage",{"type":413,"tag":449,"props":2443,"children":2444},{"style":1318},[2445],{"type":419,"value":1372},{"type":413,"tag":449,"props":2447,"children":2448},{"style":1318},[2449],{"type":419,"value":2450},",",{"type":413,"tag":449,"props":2452,"children":2453},{"style":1318},[2454],{"type":419,"value":2366},{"type":413,"tag":449,"props":2456,"children":2457},{"style":1375},[2458],{"type":419,"value":2459},"  Hello ",{"type":413,"tag":449,"props":2461,"children":2462},{"style":1318},[2463],{"type":419,"value":1372},{"type":413,"tag":449,"props":2465,"children":2466},{"style":1318},[2467],{"type":419,"value":2468},");\n",{"type":413,"tag":449,"props":2470,"children":2471},{"class":451,"line":2158},[2472],{"type":413,"tag":449,"props":2473,"children":2475},{"emptyLinePlaceholder":2474},true,[2476],{"type":419,"value":2477},"\n",{"type":413,"tag":449,"props":2479,"children":2480},{"class":451,"line":2176},[2481,2487,2492,2496,2500,2504,2508,2512,2516,2520,2524,2529,2534,2539,2544,2549,2554,2559,2564],{"type":413,"tag":449,"props":2482,"children":2484},{"style":2483},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[2485],{"type":419,"value":2486},"if",{"type":413,"tag":449,"props":2488,"children":2489},{"style":1318},[2490],{"type":419,"value":2491}," (",{"type":413,"tag":449,"props":2493,"children":2494},{"style":456},[2495],{"type":419,"value":2419},{"type":413,"tag":449,"props":2497,"children":2498},{"style":1318},[2499],{"type":419,"value":764},{"type":413,"tag":449,"props":2501,"children":2502},{"style":1331},[2503],{"type":419,"value":2334},{"type":413,"tag":449,"props":2505,"children":2506},{"style":1318},[2507],{"type":419,"value":1350},{"type":413,"tag":449,"props":2509,"children":2510},{"style":1318},[2511],{"type":419,"value":1372},{"type":413,"tag":449,"props":2513,"children":2514},{"style":1375},[2515],{"type":419,"value":2441},{"type":413,"tag":449,"props":2517,"children":2518},{"style":1318},[2519],{"type":419,"value":1372},{"type":413,"tag":449,"props":2521,"children":2522},{"style":1318},[2523],{"type":419,"value":2450},{"type":413,"tag":449,"props":2525,"children":2526},{"style":2117},[2527],{"type":419,"value":2528}," out",{"type":413,"tag":449,"props":2530,"children":2531},{"style":1342},[2532],{"type":419,"value":2533}," var",{"type":413,"tag":449,"props":2535,"children":2536},{"style":1342},[2537],{"type":419,"value":2538}," value",{"type":413,"tag":449,"props":2540,"children":2541},{"style":1318},[2542],{"type":419,"value":2543},")",{"type":413,"tag":449,"props":2545,"children":2546},{"style":1318},[2547],{"type":419,"value":2548}," &&",{"type":413,"tag":449,"props":2550,"children":2551},{"style":456},[2552],{"type":419,"value":2553}," value ",{"type":413,"tag":449,"props":2555,"children":2556},{"style":1318},[2557],{"type":419,"value":2558},"is",{"type":413,"tag":449,"props":2560,"children":2561},{"style":1318},[2562],{"type":419,"value":2563}," not",{"type":413,"tag":449,"props":2565,"children":2566},{"style":1318},[2567],{"type":419,"value":2568}," null)\n",{"type":413,"tag":449,"props":2570,"children":2571},{"class":451,"line":2185},[2572],{"type":413,"tag":449,"props":2573,"children":2574},{"style":1318},[2575],{"type":419,"value":2106},{"type":413,"tag":449,"props":2577,"children":2579},{"class":451,"line":2578},7,[2580,2585,2590,2594,2598,2602,2607],{"type":413,"tag":449,"props":2581,"children":2582},{"style":1342},[2583],{"type":419,"value":2584},"    var",{"type":413,"tag":449,"props":2586,"children":2587},{"style":1342},[2588],{"type":419,"value":2589}," welcomeMessage",{"type":413,"tag":449,"props":2591,"children":2592},{"style":1318},[2593],{"type":419,"value":2361},{"type":413,"tag":449,"props":2595,"children":2596},{"style":456},[2597],{"type":419,"value":2538},{"type":413,"tag":449,"props":2599,"children":2600},{"style":1318},[2601],{"type":419,"value":764},{"type":413,"tag":449,"props":2603,"children":2604},{"style":1331},[2605],{"type":419,"value":2606},"TrimStart",{"type":413,"tag":449,"props":2608,"children":2609},{"style":1318},[2610],{"type":419,"value":2411},{"type":413,"tag":449,"props":2612,"children":2614},{"class":451,"line":2613},8,[2615,2620,2625,2629,2634,2639,2643],{"type":413,"tag":449,"props":2616,"children":2617},{"style":1318},[2618],{"type":419,"value":2619},"    string",{"type":413,"tag":449,"props":2621,"children":2622},{"style":1342},[2623],{"type":419,"value":2624}," message",{"type":413,"tag":449,"props":2626,"children":2627},{"style":1318},[2628],{"type":419,"value":2361},{"type":413,"tag":449,"props":2630,"children":2631},{"style":456},[2632],{"type":419,"value":2633}," welcomeMessage ",{"type":413,"tag":449,"props":2635,"children":2636},{"style":1318},[2637],{"type":419,"value":2638},"+",{"type":413,"tag":449,"props":2640,"children":2641},{"style":456},[2642],{"type":419,"value":2356},{"type":413,"tag":449,"props":2644,"children":2645},{"style":1318},[2646],{"type":419,"value":2380},{"type":413,"tag":449,"props":2648,"children":2650},{"class":451,"line":2649},9,[2651],{"type":413,"tag":449,"props":2652,"children":2653},{"style":1318},[2654],{"type":419,"value":2191},{"type":413,"tag":449,"props":2656,"children":2658},{"class":451,"line":2657},10,[2659],{"type":413,"tag":449,"props":2660,"children":2661},{"emptyLinePlaceholder":2474},[2662],{"type":419,"value":2477},{"type":413,"tag":449,"props":2664,"children":2666},{"class":451,"line":2665},11,[2667,2672,2677],{"type":413,"tag":449,"props":2668,"children":2669},{"style":2117},[2670],{"type":419,"value":2671},"public",{"type":413,"tag":449,"props":2673,"children":2674},{"style":1342},[2675],{"type":419,"value":2676}," class",{"type":413,"tag":449,"props":2678,"children":2679},{"style":1342},[2680],{"type":419,"value":2681}," MyAwesomeStore\n",{"type":413,"tag":449,"props":2683,"children":2685},{"class":451,"line":2684},12,[2686],{"type":413,"tag":449,"props":2687,"children":2688},{"style":1318},[2689],{"type":419,"value":2106},{"type":413,"tag":449,"props":2691,"children":2693},{"class":451,"line":2692},13,[2694,2699,2704,2709,2713,2717,2722,2727,2732,2736,2740,2745,2749,2753,2757,2761],{"type":413,"tag":449,"props":2695,"children":2696},{"style":2117},[2697],{"type":419,"value":2698},"    private",{"type":413,"tag":449,"props":2700,"children":2701},{"style":1342},[2702],{"type":419,"value":2703}," IDictionary",{"type":413,"tag":449,"props":2705,"children":2706},{"style":1318},[2707],{"type":419,"value":2708},"\u003C",{"type":413,"tag":449,"props":2710,"children":2711},{"style":1318},[2712],{"type":419,"value":2351},{"type":413,"tag":449,"props":2714,"children":2715},{"style":1318},[2716],{"type":419,"value":2450},{"type":413,"tag":449,"props":2718,"children":2719},{"style":1318},[2720],{"type":419,"value":2721}," string",{"type":413,"tag":449,"props":2723,"children":2724},{"style":1318},[2725],{"type":419,"value":2726},">",{"type":413,"tag":449,"props":2728,"children":2729},{"style":1342},[2730],{"type":419,"value":2731}," _store",{"type":413,"tag":449,"props":2733,"children":2734},{"style":1318},[2735],{"type":419,"value":2361},{"type":413,"tag":449,"props":2737,"children":2738},{"style":1318},[2739],{"type":419,"value":1392},{"type":413,"tag":449,"props":2741,"children":2742},{"style":1342},[2743],{"type":419,"value":2744}," Dictionary",{"type":413,"tag":449,"props":2746,"children":2747},{"style":1318},[2748],{"type":419,"value":2708},{"type":413,"tag":449,"props":2750,"children":2751},{"style":1318},[2752],{"type":419,"value":2351},{"type":413,"tag":449,"props":2754,"children":2755},{"style":1318},[2756],{"type":419,"value":2450},{"type":413,"tag":449,"props":2758,"children":2759},{"style":1318},[2760],{"type":419,"value":2721},{"type":413,"tag":449,"props":2762,"children":2763},{"style":1318},[2764],{"type":419,"value":2765},">();\n",{"type":413,"tag":449,"props":2767,"children":2769},{"class":451,"line":2768},14,[2770],{"type":413,"tag":449,"props":2771,"children":2772},{"emptyLinePlaceholder":2474},[2773],{"type":419,"value":2477},{"type":413,"tag":449,"props":2775,"children":2777},{"class":451,"line":2776},15,[2778,2783,2788,2793,2797,2801,2806,2810,2814,2818,2822,2827,2831,2835,2839,2843,2848,2852,2856],{"type":413,"tag":449,"props":2779,"children":2780},{"style":2117},[2781],{"type":419,"value":2782},"    public",{"type":413,"tag":449,"props":2784,"children":2785},{"style":1318},[2786],{"type":419,"value":2787}," void",{"type":413,"tag":449,"props":2789,"children":2790},{"style":1331},[2791],{"type":419,"value":2792}," Add",{"type":413,"tag":449,"props":2794,"children":2795},{"style":1318},[2796],{"type":419,"value":1350},{"type":413,"tag":449,"props":2798,"children":2799},{"style":1318},[2800],{"type":419,"value":2351},{"type":413,"tag":449,"props":2802,"children":2803},{"style":1342},[2804],{"type":419,"value":2805}," key",{"type":413,"tag":449,"props":2807,"children":2808},{"style":1318},[2809],{"type":419,"value":2450},{"type":413,"tag":449,"props":2811,"children":2812},{"style":1318},[2813],{"type":419,"value":2721},{"type":413,"tag":449,"props":2815,"children":2816},{"style":1342},[2817],{"type":419,"value":2538},{"type":413,"tag":449,"props":2819,"children":2820},{"style":1318},[2821],{"type":419,"value":2543},{"type":413,"tag":449,"props":2823,"children":2824},{"style":1318},[2825],{"type":419,"value":2826}," =>",{"type":413,"tag":449,"props":2828,"children":2829},{"style":456},[2830],{"type":419,"value":2731},{"type":413,"tag":449,"props":2832,"children":2833},{"style":1318},[2834],{"type":419,"value":764},{"type":413,"tag":449,"props":2836,"children":2837},{"style":1331},[2838],{"type":419,"value":2428},{"type":413,"tag":449,"props":2840,"children":2841},{"style":1318},[2842],{"type":419,"value":1350},{"type":413,"tag":449,"props":2844,"children":2845},{"style":456},[2846],{"type":419,"value":2847},"key",{"type":413,"tag":449,"props":2849,"children":2850},{"style":1318},[2851],{"type":419,"value":2450},{"type":413,"tag":449,"props":2853,"children":2854},{"style":456},[2855],{"type":419,"value":2538},{"type":413,"tag":449,"props":2857,"children":2858},{"style":1318},[2859],{"type":419,"value":2468},{"type":413,"tag":449,"props":2861,"children":2863},{"class":451,"line":2862},16,[2864,2868,2873,2878,2882,2886,2890,2894,2898,2902,2907,2911,2915,2919,2923,2927,2932,2936,2940,2944,2948,2952],{"type":413,"tag":449,"props":2865,"children":2866},{"style":2117},[2867],{"type":419,"value":2782},{"type":413,"tag":449,"props":2869,"children":2870},{"style":1318},[2871],{"type":419,"value":2872}," bool",{"type":413,"tag":449,"props":2874,"children":2875},{"style":1331},[2876],{"type":419,"value":2877}," TryGet",{"type":413,"tag":449,"props":2879,"children":2880},{"style":1318},[2881],{"type":419,"value":1350},{"type":413,"tag":449,"props":2883,"children":2884},{"style":1318},[2885],{"type":419,"value":2351},{"type":413,"tag":449,"props":2887,"children":2888},{"style":1342},[2889],{"type":419,"value":2805},{"type":413,"tag":449,"props":2891,"children":2892},{"style":1318},[2893],{"type":419,"value":2450},{"type":413,"tag":449,"props":2895,"children":2896},{"style":2117},[2897],{"type":419,"value":2528},{"type":413,"tag":449,"props":2899,"children":2900},{"style":1318},[2901],{"type":419,"value":2721},{"type":413,"tag":449,"props":2903,"children":2904},{"style":1318},[2905],{"type":419,"value":2906},"?",{"type":413,"tag":449,"props":2908,"children":2909},{"style":1342},[2910],{"type":419,"value":2538},{"type":413,"tag":449,"props":2912,"children":2913},{"style":1318},[2914],{"type":419,"value":2543},{"type":413,"tag":449,"props":2916,"children":2917},{"style":1318},[2918],{"type":419,"value":2826},{"type":413,"tag":449,"props":2920,"children":2921},{"style":456},[2922],{"type":419,"value":2731},{"type":413,"tag":449,"props":2924,"children":2925},{"style":1318},[2926],{"type":419,"value":764},{"type":413,"tag":449,"props":2928,"children":2929},{"style":1331},[2930],{"type":419,"value":2931},"TryGetValue",{"type":413,"tag":449,"props":2933,"children":2934},{"style":1318},[2935],{"type":419,"value":1350},{"type":413,"tag":449,"props":2937,"children":2938},{"style":456},[2939],{"type":419,"value":2847},{"type":413,"tag":449,"props":2941,"children":2942},{"style":1318},[2943],{"type":419,"value":2450},{"type":413,"tag":449,"props":2945,"children":2946},{"style":2117},[2947],{"type":419,"value":2528},{"type":413,"tag":449,"props":2949,"children":2950},{"style":456},[2951],{"type":419,"value":2538},{"type":413,"tag":449,"props":2953,"children":2954},{"style":1318},[2955],{"type":419,"value":2468},{"type":413,"tag":449,"props":2957,"children":2959},{"class":451,"line":2958},17,[2960],{"type":413,"tag":449,"props":2961,"children":2962},{"style":1318},[2963],{"type":419,"value":2191},{"type":413,"tag":422,"props":2965,"children":2966},{},[2967,2969,2974],{"type":419,"value":2968},"But if we annotate correctly the ",{"type":413,"tag":445,"props":2970,"children":2972},{"className":2971},[],[2973],{"type":419,"value":2334},{"type":419,"value":2975}," method we don't need this check:",{"type":413,"tag":439,"props":2977,"children":2979},{"className":1302,"code":2978,"language":326,"meta":401,"style":401},"public bool TryGet(string key, [NotNullWhen(returnValue: true)] out string? value) => _store.TryGetValue(key, out value);\n",[2980],{"type":413,"tag":445,"props":2981,"children":2982},{"__ignoreMap":401},[2983],{"type":413,"tag":449,"props":2984,"children":2985},{"class":451,"line":452},[2986,2990,2994,2998,3002,3006,3010,3014,3019,3024,3028,3033,3037,3043,3048,3052,3056,3060,3064,3068,3072,3076,3080,3084,3088,3092,3096,3100,3104],{"type":413,"tag":449,"props":2987,"children":2988},{"style":2117},[2989],{"type":419,"value":2671},{"type":413,"tag":449,"props":2991,"children":2992},{"style":1318},[2993],{"type":419,"value":2872},{"type":413,"tag":449,"props":2995,"children":2996},{"style":1331},[2997],{"type":419,"value":2877},{"type":413,"tag":449,"props":2999,"children":3000},{"style":1318},[3001],{"type":419,"value":1350},{"type":413,"tag":449,"props":3003,"children":3004},{"style":1318},[3005],{"type":419,"value":2351},{"type":413,"tag":449,"props":3007,"children":3008},{"style":1342},[3009],{"type":419,"value":2805},{"type":413,"tag":449,"props":3011,"children":3012},{"style":1318},[3013],{"type":419,"value":2450},{"type":413,"tag":449,"props":3015,"children":3016},{"style":1318},[3017],{"type":419,"value":3018}," [",{"type":413,"tag":449,"props":3020,"children":3021},{"style":1342},[3022],{"type":419,"value":3023},"NotNullWhen",{"type":413,"tag":449,"props":3025,"children":3026},{"style":1318},[3027],{"type":419,"value":1350},{"type":413,"tag":449,"props":3029,"children":3030},{"style":456},[3031],{"type":419,"value":3032},"returnValue",{"type":413,"tag":449,"props":3034,"children":3035},{"style":1318},[3036],{"type":419,"value":1277},{"type":413,"tag":449,"props":3038,"children":3040},{"style":3039},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[3041],{"type":419,"value":3042}," true",{"type":413,"tag":449,"props":3044,"children":3045},{"style":1318},[3046],{"type":419,"value":3047},")]",{"type":413,"tag":449,"props":3049,"children":3050},{"style":2117},[3051],{"type":419,"value":2528},{"type":413,"tag":449,"props":3053,"children":3054},{"style":1318},[3055],{"type":419,"value":2721},{"type":413,"tag":449,"props":3057,"children":3058},{"style":1318},[3059],{"type":419,"value":2906},{"type":413,"tag":449,"props":3061,"children":3062},{"style":1342},[3063],{"type":419,"value":2538},{"type":413,"tag":449,"props":3065,"children":3066},{"style":1318},[3067],{"type":419,"value":2543},{"type":413,"tag":449,"props":3069,"children":3070},{"style":1318},[3071],{"type":419,"value":2826},{"type":413,"tag":449,"props":3073,"children":3074},{"style":456},[3075],{"type":419,"value":2731},{"type":413,"tag":449,"props":3077,"children":3078},{"style":1318},[3079],{"type":419,"value":764},{"type":413,"tag":449,"props":3081,"children":3082},{"style":1331},[3083],{"type":419,"value":2931},{"type":413,"tag":449,"props":3085,"children":3086},{"style":1318},[3087],{"type":419,"value":1350},{"type":413,"tag":449,"props":3089,"children":3090},{"style":456},[3091],{"type":419,"value":2847},{"type":413,"tag":449,"props":3093,"children":3094},{"style":1318},[3095],{"type":419,"value":2450},{"type":413,"tag":449,"props":3097,"children":3098},{"style":2117},[3099],{"type":419,"value":2528},{"type":413,"tag":449,"props":3101,"children":3102},{"style":456},[3103],{"type":419,"value":2538},{"type":413,"tag":449,"props":3105,"children":3106},{"style":1318},[3107],{"type":419,"value":2468},{"type":413,"tag":439,"props":3109,"children":3111},{"className":1302,"code":3110,"language":326,"meta":401,"style":401},"if (myStore.TryGet(\"WelcomeMessage\", out var value))\n{\n",[3112],{"type":413,"tag":445,"props":3113,"children":3114},{"__ignoreMap":401},[3115,3175],{"type":413,"tag":449,"props":3116,"children":3117},{"class":451,"line":452},[3118,3122,3126,3130,3134,3138,3142,3146,3150,3154,3158,3162,3166,3170],{"type":413,"tag":449,"props":3119,"children":3120},{"style":2483},[3121],{"type":419,"value":2486},{"type":413,"tag":449,"props":3123,"children":3124},{"style":1318},[3125],{"type":419,"value":2491},{"type":413,"tag":449,"props":3127,"children":3128},{"style":456},[3129],{"type":419,"value":2419},{"type":413,"tag":449,"props":3131,"children":3132},{"style":1318},[3133],{"type":419,"value":764},{"type":413,"tag":449,"props":3135,"children":3136},{"style":1331},[3137],{"type":419,"value":2334},{"type":413,"tag":449,"props":3139,"children":3140},{"style":1318},[3141],{"type":419,"value":1350},{"type":413,"tag":449,"props":3143,"children":3144},{"style":1318},[3145],{"type":419,"value":1372},{"type":413,"tag":449,"props":3147,"children":3148},{"style":1375},[3149],{"type":419,"value":2441},{"type":413,"tag":449,"props":3151,"children":3152},{"style":1318},[3153],{"type":419,"value":1372},{"type":413,"tag":449,"props":3155,"children":3156},{"style":1318},[3157],{"type":419,"value":2450},{"type":413,"tag":449,"props":3159,"children":3160},{"style":2117},[3161],{"type":419,"value":2528},{"type":413,"tag":449,"props":3163,"children":3164},{"style":1342},[3165],{"type":419,"value":2533},{"type":413,"tag":449,"props":3167,"children":3168},{"style":1342},[3169],{"type":419,"value":2538},{"type":413,"tag":449,"props":3171,"children":3172},{"style":1318},[3173],{"type":419,"value":3174},"))\n",{"type":413,"tag":449,"props":3176,"children":3177},{"class":451,"line":569},[3178],{"type":413,"tag":449,"props":3179,"children":3180},{"style":1318},[3181],{"type":419,"value":2106},{"type":413,"tag":422,"props":3183,"children":3184},{},[3185],{"type":419,"value":666},{"type":413,"tag":668,"props":3187,"children":3188},{},[3189],{"type":419,"value":672},{"title":401,"searchDepth":569,"depth":569,"links":3191},[3192,3193,3195,3196],{"id":1915,"depth":569,"text":1918},{"id":1957,"depth":569,"text":3194},"vscode-jest, a must-have extension when using Jest",{"id":2051,"depth":569,"text":2054},{"id":2266,"depth":569,"text":2269},"content:1.posts:26.w41-2021-tips-learned-this-week.md","1.posts/26.w41-2021-tips-learned-this-week.md",{"_path":64,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":63,"description":3200,"lead":3201,"date":3202,"image":3203,"badge":3204,"tags":3205,"body":3206,"_type":678,"_id":3562,"_source":680,"_file":3563,"_extension":682},"This week I learned some Azure CLI commands, how to have JSON IntelliSense in vscode and that Azure Storage Explorer was usable again.","IntelliSense in vscode, Azure CLI command to get assigned roles, and Azure Storage Explorer new version.","2021-06-07T00:00:00.000Z",{"src":405},{"label":407},[272,208,225,228],{"type":410,"children":3207,"toc":3557},[3208,3212,3218,3223,3236,3245,3250,3263,3269,3289,3298,3325,3345,3387,3392,3512,3518,3530,3535,3544,3549,3553],{"type":413,"tag":422,"props":3209,"children":3210},{},[3211],{"type":419,"value":3200},{"type":413,"tag":414,"props":3213,"children":3215},{"id":3214},"autocompletion-and-schema-validation-when-editing-a-json-file-in-vscode",[3216],{"type":419,"value":3217},"Autocompletion and schema validation when editing a JSON file in vscode.",{"type":413,"tag":422,"props":3219,"children":3220},{},[3221],{"type":419,"value":3222},"When you are editing a JSON file in vscode, chances are that there is a JSON schema somewhere that describes the shape of the JSON you are modifying. Wouldn't it be great if vscode could provide you suggestions and validate the JSON according to such a schema while you are typing ⌨?",{"type":413,"tag":422,"props":3224,"children":3225},{},[3226,3228,3234],{"type":419,"value":3227},"Well in fact it is possible, you just have to add at the beginning of your file a ",{"type":413,"tag":445,"props":3229,"children":3231},{"className":3230},[],[3232],{"type":419,"value":3233},"$schema",{"type":419,"value":3235}," key (with the URI of the JSON schema as the value) and you will have IntelliSense to edit your JSON in vscode.",{"type":413,"tag":422,"props":3237,"children":3238},{},[3239],{"type":413,"tag":559,"props":3240,"children":3244},{"alt":3241,"className":3242,"src":3243},"Json file in vscode.",[563,564],"/posts/images/w222021tips_vscode_1.png",[],{"type":413,"tag":422,"props":3246,"children":3247},{},[3248],{"type":419,"value":3249},"In the screenshot above, I am editing a JSON file where the linked JSON schema is a Microsoft Teams app manifest schema, and as you can see vscode gives me suggestions based on this schema.",{"type":413,"tag":422,"props":3251,"children":3252},{},[3253,3255,3262],{"type":419,"value":3254},"This is a tip that you probably already know but as far as I am concerned I only discovered it recently and it is really useful. If you want to do more advanced things like mapping some files types to specific JSON schemas you can have a look in ",{"type":413,"tag":428,"props":3256,"children":3259},{"href":3257,"rel":3258},"https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings",[432],[3260],{"type":419,"value":3261},"vscode documentation",{"type":419,"value":764},{"type":413,"tag":414,"props":3264,"children":3266},{"id":3265},"listing-assigned-roles-for-a-user-on-a-subscription-with-azure-cli",[3267],{"type":419,"value":3268},"Listing assigned roles for a user on a subscription with Azure CLI",{"type":413,"tag":422,"props":3270,"children":3271},{},[3272,3274,3287],{"type":419,"value":3273},"I recently had to list all the roles assigned to my user on a subscription. 👮‍♀️\nFor that I used the ",{"type":413,"tag":428,"props":3275,"children":3278},{"href":3276,"rel":3277},"https://docs.microsoft.com/en-us/cli/azure/role/assignment?view=azure-cli-latest#az_role_assignment_list",[432],[3279,3285],{"type":413,"tag":445,"props":3280,"children":3282},{"className":3281},[],[3283],{"type":419,"value":3284},"az role assignment list",{"type":419,"value":3286}," command",{"type":419,"value":3288}," like this:",{"type":413,"tag":422,"props":3290,"children":3291},{},[3292],{"type":413,"tag":559,"props":3293,"children":3297},{"alt":3294,"className":3295,"src":3296},"Terminal showing az role assigment command.",[563,564],"/posts/images/w222021tips_azcli_1.png",[],{"type":413,"tag":422,"props":3299,"children":3300},{},[3301,3303,3309,3311,3317,3318,3324],{"type":419,"value":3302},"I am filtering the command result with the ",{"type":413,"tag":445,"props":3304,"children":3306},{"className":3305},[],[3307],{"type":419,"value":3308},"--query",{"type":419,"value":3310}," argument to only have the information I am interested in which are ",{"type":413,"tag":445,"props":3312,"children":3314},{"className":3313},[],[3315],{"type":419,"value":3316},"roleDefinitionName",{"type":419,"value":1238},{"type":413,"tag":445,"props":3319,"children":3321},{"className":3320},[],[3322],{"type":419,"value":3323},"scope",{"type":419,"value":764},{"type":413,"tag":422,"props":3326,"children":3327},{},[3328,3330,3336,3338,3344],{"type":419,"value":3329},"You can specify a subscription by using the optional parameter ",{"type":413,"tag":445,"props":3331,"children":3333},{"className":3332},[],[3334],{"type":419,"value":3335},"--subscription",{"type":419,"value":3337}," but by default, the subscription selected is the current subscription which you can see by doing an ",{"type":413,"tag":445,"props":3339,"children":3341},{"className":3340},[],[3342],{"type":419,"value":3343},"az account show",{"type":419,"value":764},{"type":413,"tag":422,"props":3346,"children":3347},{},[3348,3350,3356,3358,3364,3366,3372,3374,3385],{"type":419,"value":3349},"The variable ",{"type":413,"tag":445,"props":3351,"children":3353},{"className":3352},[],[3354],{"type":419,"value":3355},"UserId",{"type":419,"value":3357}," which is passed to the option ",{"type":413,"tag":445,"props":3359,"children":3361},{"className":3360},[],[3362],{"type":419,"value":3363},"--assignee",{"type":419,"value":3365}," contains my user id but I could have also passed my user principal name. As I was looking to list my assigned roles on a subscription in a tenant id where I am a guest, my user principal name is a bit strange with an ",{"type":413,"tag":445,"props":3367,"children":3369},{"className":3368},[],[3370],{"type":419,"value":3371},"#EXT#",{"type":419,"value":3373}," in it so I can never remember what it is. And as I don't know by heart my user id either, I use the ",{"type":413,"tag":428,"props":3375,"children":3378},{"href":3376,"rel":3377},"https://docs.microsoft.com/en-us/cli/azure/ad/user?view=azure-cli-latest#az_ad_user_show",[432],[3379],{"type":413,"tag":445,"props":3380,"children":3382},{"className":3381},[],[3383],{"type":419,"value":3384},"az ad signed-in-user show",{"type":419,"value":3386}," command to get my user id.",{"type":413,"tag":422,"props":3388,"children":3389},{},[3390],{"type":419,"value":3391},"So at the end my command to list the assigned roles to my user on the current subscription is the following:",{"type":413,"tag":439,"props":3393,"children":3395},{"className":441,"code":3394,"language":248,"meta":401,"style":401},"az role assignment list --assignee $(az ad signed-in-user show --query \"objectId\") --query \"[*].{role:roleDefinitionName,scope:scope}\" --include-inherited\n",[3396],{"type":413,"tag":445,"props":3397,"children":3398},{"__ignoreMap":401},[3399],{"type":413,"tag":449,"props":3400,"children":3401},{"class":451,"line":452},[3402,3407,3412,3417,3422,3427,3432,3437,3441,3446,3450,3455,3459,3464,3468,3472,3477,3481,3485,3490,3494,3498,3503,3507],{"type":413,"tag":449,"props":3403,"children":3404},{"style":456},[3405],{"type":419,"value":3406},"az role assignment list ",{"type":413,"tag":449,"props":3408,"children":3409},{"style":1318},[3410],{"type":419,"value":3411},"--",{"type":413,"tag":449,"props":3413,"children":3414},{"style":456},[3415],{"type":419,"value":3416},"assignee ",{"type":413,"tag":449,"props":3418,"children":3419},{"style":1318},[3420],{"type":419,"value":3421},"$(",{"type":413,"tag":449,"props":3423,"children":3424},{"style":456},[3425],{"type":419,"value":3426},"az ad signed",{"type":413,"tag":449,"props":3428,"children":3429},{"style":1318},[3430],{"type":419,"value":3431},"-",{"type":413,"tag":449,"props":3433,"children":3434},{"style":456},[3435],{"type":419,"value":3436},"in",{"type":413,"tag":449,"props":3438,"children":3439},{"style":1318},[3440],{"type":419,"value":3431},{"type":413,"tag":449,"props":3442,"children":3443},{"style":456},[3444],{"type":419,"value":3445},"user show ",{"type":413,"tag":449,"props":3447,"children":3448},{"style":1318},[3449],{"type":419,"value":3411},{"type":413,"tag":449,"props":3451,"children":3452},{"style":456},[3453],{"type":419,"value":3454},"query ",{"type":413,"tag":449,"props":3456,"children":3457},{"style":1318},[3458],{"type":419,"value":1372},{"type":413,"tag":449,"props":3460,"children":3461},{"style":1375},[3462],{"type":419,"value":3463},"objectId",{"type":413,"tag":449,"props":3465,"children":3466},{"style":1318},[3467],{"type":419,"value":1372},{"type":413,"tag":449,"props":3469,"children":3470},{"style":1318},[3471],{"type":419,"value":2543},{"type":413,"tag":449,"props":3473,"children":3474},{"style":1318},[3475],{"type":419,"value":3476}," --",{"type":413,"tag":449,"props":3478,"children":3479},{"style":456},[3480],{"type":419,"value":3454},{"type":413,"tag":449,"props":3482,"children":3483},{"style":1318},[3484],{"type":419,"value":1372},{"type":413,"tag":449,"props":3486,"children":3487},{"style":1375},[3488],{"type":419,"value":3489},"[*].{role:roleDefinitionName,scope:scope}",{"type":413,"tag":449,"props":3491,"children":3492},{"style":1318},[3493],{"type":419,"value":1372},{"type":413,"tag":449,"props":3495,"children":3496},{"style":1318},[3497],{"type":419,"value":3476},{"type":413,"tag":449,"props":3499,"children":3500},{"style":456},[3501],{"type":419,"value":3502},"include",{"type":413,"tag":449,"props":3504,"children":3505},{"style":1318},[3506],{"type":419,"value":3431},{"type":413,"tag":449,"props":3508,"children":3509},{"style":456},[3510],{"type":419,"value":3511},"inherited\n",{"type":413,"tag":414,"props":3513,"children":3515},{"id":3514},"azure-storage-explorer-just-got-better",[3516],{"type":419,"value":3517},"Azure Storage Explorer just got better!",{"type":413,"tag":422,"props":3519,"children":3520},{},[3521,3528],{"type":413,"tag":428,"props":3522,"children":3525},{"href":3523,"rel":3524},"https://azure.microsoft.com/en-us/features/storage-explorer/",[432],[3526],{"type":419,"value":3527},"Azure Storage Explorer",{"type":419,"value":3529}," is a tool to manage your Azure cloud storage resources from your desktop. Instead of going to the Azure portal and navigating between all the panes and resources, you can do everything from this tool like viewing the tables and blobs in the storage accounts you have access to.",{"type":413,"tag":422,"props":3531,"children":3532},{},[3533],{"type":419,"value":3534},"Unfortunately, if your account had access to multiple subscriptions on multiple tenants with MFA enabled, using Azure Storage Explorer was a nightmare where you had to log in to every tenant multiple times to access any storage account. If you had the correct permissions you ended up grabbing a secret connection string to access your storage account from Azure Storage Explorer but it was not a good solution (using secrets instead of your Azure AD account to access resources is never a good idea ⛔).",{"type":413,"tag":422,"props":3536,"children":3537},{},[3538],{"type":413,"tag":559,"props":3539,"children":3543},{"alt":3540,"className":3541,"src":3542},"Azure Storage Explorer account management section.",[563,564],"/posts/images/w222021tips_storageexplorer_1.png",[],{"type":413,"tag":422,"props":3545,"children":3546},{},[3547],{"type":419,"value":3548},"As you can see on the screenshot above, in v1.19.x Azure Storage Explorer account management section has been completely refreshed to allow us to control exactly the tenants and the subscriptions that we want to load. This way we only have to enter the credentials we need and Azure Storage Explorer becomes usable again! 🎉",{"type":413,"tag":422,"props":3550,"children":3551},{},[3552],{"type":419,"value":666},{"type":413,"tag":668,"props":3554,"children":3555},{},[3556],{"type":419,"value":672},{"title":401,"searchDepth":569,"depth":569,"links":3558},[3559,3560,3561],{"id":3214,"depth":569,"text":3217},{"id":3265,"depth":569,"text":3268},{"id":3514,"depth":569,"text":3517},"content:1.posts:19.w22-2021-tips-learned-this-week.md","1.posts/19.w22-2021-tips-learned-this-week.md",{"_path":52,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":51,"description":3565,"lead":3566,"date":3567,"image":3568,"badge":3569,"tags":3570,"body":3571,"_type":678,"_id":3741,"_source":680,"_file":3742,"_extension":682},"This week I learned a few things related to vscode and especially about the Azure IoT Hub vscode extension.","Azure tenant in vs code and Azure IoT Hub vs code extension.","2021-04-10T00:00:00.000Z",{"src":405},{"label":407},[272,208,284,228],{"type":410,"children":3572,"toc":3737},[3573,3586,3592,3606,3626,3635,3650,3656,3661,3673,3682,3687,3696,3701,3710,3724,3733],{"type":413,"tag":422,"props":3574,"children":3575},{},[3576,3578,3584],{"type":419,"value":3577},"This week I learned a few things related to vscode and especially about the ",{"type":413,"tag":445,"props":3579,"children":3581},{"className":3580},[],[3582],{"type":419,"value":3583},"Azure IoT Hub",{"type":419,"value":3585}," vscode extension.",{"type":413,"tag":414,"props":3587,"children":3589},{"id":3588},"accessing-azure-resources-in-vscode-from-a-specific-tenant",[3590],{"type":419,"value":3591},"Accessing Azure resources in vscode from a specific tenant.",{"type":413,"tag":422,"props":3593,"children":3594},{},[3595,3597,3604],{"type":419,"value":3596},"There are a lot of vscode extensions (like the ones in ",{"type":413,"tag":428,"props":3598,"children":3601},{"href":3599,"rel":3600},"https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-node-azure-pack",[432],[3602],{"type":419,"value":3603},"this extension pack",{"type":419,"value":3605},") that allow you to access and manipulate your Azure resources from Visual Studio Code.",{"type":413,"tag":422,"props":3607,"children":3608},{},[3609,3611,3624],{"type":419,"value":3610},"This ",{"type":413,"tag":428,"props":3612,"children":3615},{"href":3613,"rel":3614},"https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account",[432],[3616,3618],{"type":419,"value":3617},"specific extension ",{"type":413,"tag":445,"props":3619,"children":3621},{"className":3620},[],[3622],{"type":419,"value":3623},"Azure Account",{"type":419,"value":3625}," makes it easy for you to sign in to your Azure account and select the subscription you want to use. But what if you are working in a consulting company that works for different companies? How do you indicate the tenant of the customer to sign in to? Well, the answer is quite simple, the extension exposes a setting in vscode to specify a specific tenant to use.",{"type":413,"tag":422,"props":3627,"children":3628},{},[3629],{"type":413,"tag":559,"props":3630,"children":3634},{"alt":3631,"className":3632,"src":3633},"Azure tenant settings in vscode.",[563,564],"/posts/images/w142021tips_vscode_1.png",[],{"type":413,"tag":1558,"props":3636,"children":3638},{"icon":3637},"i-fluent-emoji-flat-pushpin",[3639],{"type":413,"tag":422,"props":3640,"children":3641},{},[3642,3644],{"type":419,"value":3643},"If you like to update the settings in JSON mode the key to use is ",{"type":413,"tag":445,"props":3645,"children":3647},{"className":3646},[],[3648],{"type":419,"value":3649},"azure.tenant",{"type":413,"tag":414,"props":3651,"children":3653},{"id":3652},"azure-iot-hub-vs-code-extension-is-awesome",[3654],{"type":419,"value":3655},"Azure IoT Hub vs code extension is awesome.",{"type":413,"tag":422,"props":3657,"children":3658},{},[3659],{"type":419,"value":3660},"I think everything is in the title. I knew about this extension before this week but I did not take the time to really use it. However this week it helped me a lot for my sprint demo where I needed to show new functionalities I implemented on an IoT backend: modify device twin tags in the IoT Hub and send some messages to an IoT device under certain conditions.",{"type":413,"tag":422,"props":3662,"children":3663},{},[3664,3666,3671],{"type":419,"value":3665},"The Azure IoT Hub extension adds an ",{"type":413,"tag":445,"props":3667,"children":3669},{"className":3668},[],[3670],{"type":419,"value":3583},{"type":419,"value":3672}," view in the Explorer where you can see the devices of the IoT Hub you selected and can do some actions on them.",{"type":413,"tag":422,"props":3674,"children":3675},{},[3676],{"type":413,"tag":559,"props":3677,"children":3681},{"alt":3678,"className":3679,"src":3680},"Azure IoT Hub view in vscode.",[563,564],"/posts/images/w142021tips_vscode_2.png",[],{"type":413,"tag":422,"props":3683,"children":3684},{},[3685],{"type":419,"value":3686},"There are also a lot of commands you can use to interact with an IoT Hub and its devices.",{"type":413,"tag":422,"props":3688,"children":3689},{},[3690],{"type":413,"tag":559,"props":3691,"children":3695},{"alt":3692,"className":3693,"src":3694},"Azure IoT Hub commands in vscode command palette.",[563,564],"/posts/images/w142021tips_vscode_3.png",[],{"type":413,"tag":422,"props":3697,"children":3698},{},[3699],{"type":419,"value":3700},"You can do pretty much anything you want from sending C2D / D2C messages to monitoring C2D / D2C messages. I found it quite nice to be able to directly visualize and edit a device twin as a JSON  document in vs code.",{"type":413,"tag":422,"props":3702,"children":3703},{},[3704],{"type":413,"tag":559,"props":3705,"children":3709},{"alt":3706,"className":3707,"src":3708},"Device twin json in vscode.",[563,564],"/posts/images/w142021tips_vscode_4.png",[],{"type":413,"tag":422,"props":3711,"children":3712},{},[3713,3715,3722],{"type":419,"value":3714},"To quickly test something related to IoT Hub, the Azure IoT Hub extension is a very useful tool. An interesting alternative to this tool is the ",{"type":413,"tag":428,"props":3716,"children":3719},{"href":3717,"rel":3718},"https://github.com/Azure/azure-iot-explorer/releases",[432],[3720],{"type":419,"value":3721},"Azure IoT Explorer",{"type":419,"value":3723}," which is more user-friendly thanks to its simple UI but does not have all the features.",{"type":413,"tag":422,"props":3725,"children":3726},{},[3727],{"type":413,"tag":559,"props":3728,"children":3732},{"alt":3729,"className":3730,"src":3731},"Device twin json in Azure Iot Explorer.",[563,564],"/posts/images/w142021tips_iotexplorer_1.png",[],{"type":413,"tag":422,"props":3734,"children":3735},{},[3736],{"type":419,"value":666},{"title":401,"searchDepth":569,"depth":569,"links":3738},[3739,3740],{"id":3588,"depth":569,"text":3591},{"id":3652,"depth":569,"text":3655},"content:1.posts:15.w14-2021-tips-learned-this-week.md","1.posts/15.w14-2021-tips-learned-this-week.md",{"_path":19,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":18,"description":3744,"lead":3745,"date":3746,"image":3747,"tags":3749,"badge":3750,"body":3752,"_type":678,"_id":4012,"_source":680,"_file":4013,"_extension":682},"The other day when I was looking for a way to automate my development environment setup, I came across Gitpod. Not really what I was looking for but I discovered an awesome tool for working on open source projects.","An IDE in the browser","2019-08-12T00:00:00.000Z",{"src":3748},"/images/github-usbkey.jpg",[233,206,208],{"label":3751},"Tooling",{"type":410,"children":3753,"toc":4010},[3754,3768,3773,3802,3807,3818,3841,3870,3885,3890,3905,3910,3915,3924,3942,3960,3965,4005],{"type":413,"tag":422,"props":3755,"children":3756},{},[3757,3759,3766],{"type":419,"value":3758},"The other day when I was looking for a way to automate my development environment setup, I came across ",{"type":413,"tag":428,"props":3760,"children":3763},{"href":3761,"rel":3762},"https://www.gitpod.io/",[432],[3764],{"type":419,"value":3765},"Gitpod",{"type":419,"value":3767},". Not really what I was looking for but I discovered an awesome tool for working on open source projects.",{"type":413,"tag":422,"props":3769,"children":3770},{},[3771],{"type":419,"value":3772},"Gitpod is an online service that aims at providing ready-to-code development environments in the browser for GitHub projects.",{"type":413,"tag":422,"props":3774,"children":3775},{},[3776,3778,3785,3787,3793,3795,3801],{"type":419,"value":3777},"Let's see that with one project I was contributing to a few months ago: the ",{"type":413,"tag":428,"props":3779,"children":3782},{"href":3780,"rel":3781},"https://github.com/voxxrin/voxxrin-companion-ui",[432],[3783],{"type":419,"value":3784},"Voxxrin Companion mobile app",{"type":419,"value":3786},".\nFirst, let's go to the project GitHub's page, and prefix the URL of the page with ",{"type":413,"tag":445,"props":3788,"children":3790},{"className":3789},[],[3791],{"type":419,"value":3792},"gitpod.io/#",{"type":419,"value":3794}," which gives us the following URL: ",{"type":413,"tag":428,"props":3796,"children":3799},{"href":3797,"rel":3798},"http://gitpod.io/#https://github.com/voxxrin/voxxrin-companion-ui",[432],[3800],{"type":419,"value":3797},{"type":419,"value":764},{"type":413,"tag":422,"props":3803,"children":3804},{},[3805],{"type":419,"value":3806},"As I am already logged in to the  Gitpod account I created (free for open source developers with a quota of 100 hours/month) Gitpod will start creating a development environment for me. That means pulling a Docker image with everything I need to code (for specific needs, you can also specify a custom docker image to use) and initializing a workspace for me with the code of the project.",{"type":413,"tag":422,"props":3808,"children":3809},{},[3810,3812],{"type":419,"value":3811},"Less than 30s and here we are :\n",{"type":413,"tag":559,"props":3813,"children":3817},{"alt":3814,"className":3815,"src":3816},"Voxxr.in project opened in gitpod in browser.",[563,564],"/posts/images/gitpod_voxxrin_1.png",[],{"type":413,"tag":422,"props":3819,"children":3820},{},[3821,3823,3830,3832,3839],{"type":419,"value":3822},"I have now a complete development environment running in the cloud with the code of my project already cloned. If the editor looks familiar to you it's because ",{"type":413,"tag":428,"props":3824,"children":3827},{"href":3825,"rel":3826},"https://www.theia-ide.org/",[432],[3828],{"type":419,"value":3829},"Theia",{"type":419,"value":3831}," (the IDE's name) is very similar to ",{"type":413,"tag":428,"props":3833,"children":3836},{"href":3834,"rel":3835},"http://typefox.io/theia-vs-code-in-the-cloud",[432],[3837],{"type":419,"value":3838},"VS Code but in the cloud",{"type":419,"value":3840}," (it reuses many parts from VS Code). This is great because it means I can use an IDE I am already familiar with, and even use vs code extensions (provided you have the .vsix files to install them).",{"type":413,"tag":422,"props":3842,"children":3843},{},[3844,3846,3852,3854,3860,3862,3868],{"type":419,"value":3845},"So let's run my project which is an ionic application. Node is already installed so I just have to type ",{"type":413,"tag":445,"props":3847,"children":3849},{"className":3848},[],[3850],{"type":419,"value":3851},"npm install",{"type":419,"value":3853}," and then ",{"type":413,"tag":445,"props":3855,"children":3857},{"className":3856},[],[3858],{"type":419,"value":3859},"npm run-script serve",{"type":419,"value":3861}," in the terminal opened in the editor exactly as if I was working on my local VS Code. My application is configured to be launched on port ",{"type":413,"tag":445,"props":3863,"children":3865},{"className":3864},[],[3866],{"type":419,"value":3867},"8100",{"type":419,"value":3869}," so Gitpod will suggest I expose this port for me to be able to view my application in my browser.",{"type":413,"tag":422,"props":3871,"children":3872},{},[3873,3879],{"type":413,"tag":559,"props":3874,"children":3878},{"alt":3875,"className":3876,"src":3877},"GitPod suggestion of opening port to run the application.",[563,564],"/posts/images/gitpod_voxxrin_2.png",[],{"type":413,"tag":559,"props":3880,"children":3884},{"alt":3881,"className":3882,"src":3883},"GitPod suggestion of opening live preview of the application.",[563,564],"/posts/images/gitpod_voxxrin_3.png",[],{"type":413,"tag":422,"props":3886,"children":3887},{},[3888],{"type":419,"value":3889},"I can now open in my computer browser the application running in my Gitpod workspace. I can also preview it directly in Gitpod.",{"type":413,"tag":422,"props":3891,"children":3892},{},[3893,3899],{"type":413,"tag":559,"props":3894,"children":3898},{"alt":3895,"className":3896,"src":3897},"Voxxr.in application served in a browser tab.",[563,564],"/posts/images/gitpod_voxxrin_5.png",[],{"type":413,"tag":559,"props":3900,"children":3904},{"alt":3901,"className":3902,"src":3903},"Voxxr.in application served in GitPod tab.",[563,564],"/posts/images/gitpod_voxxrin_4.png",[],{"type":413,"tag":422,"props":3906,"children":3907},{},[3908],{"type":419,"value":3909},"If I have some modifications to do I can push them directly from here to my GitHub repository as my Gitpod account is associated with my GitHub account.",{"type":413,"tag":422,"props":3911,"children":3912},{},[3913],{"type":419,"value":3914},"When I have finished, I can just stop the workspace and that's it.",{"type":413,"tag":422,"props":3916,"children":3917},{},[3918],{"type":413,"tag":559,"props":3919,"children":3923},{"alt":3920,"className":3921,"src":3922},"GitPod menu to stop the workspace.",[563,564],"/posts/images/gitpod_voxxrin_7.png",[],{"type":413,"tag":422,"props":3925,"children":3926},{},[3927,3929,3940],{"type":419,"value":3928},"I created the workspace for my project as-is but lots of things can be configured by having a ",{"type":413,"tag":428,"props":3930,"children":3933},{"href":3931,"rel":3932},"https://www.gitpod.io/docs/41_config_gitpod_file/",[432],[3934],{"type":413,"tag":445,"props":3935,"children":3937},{"className":3936},[],[3938],{"type":419,"value":3939},"gitpod.yml",{"type":419,"value":3941}," file in the repository of your project",{"type":413,"tag":422,"props":3943,"children":3944},{},[3945,3947,3958],{"type":419,"value":3946},"With Gitpod you just need a browser and an internet connection to be able to work on any of your GitHub projects from anywhere. When you work on multiple open source projects the nice thing is that it allows you to easily switch from one to another. I wonder if the Browser-Based Web Companion ",{"type":413,"tag":428,"props":3948,"children":3951},{"href":3949,"rel":3950},"https://devblogs.microsoft.com/visualstudio/intelligent-productivity-and-collaboration-from-anywhere/",[432],[3952],{"type":413,"tag":3953,"props":3954,"children":3955},"strong",{},[3956],{"type":419,"value":3957},"Visual Studio Online",{"type":419,"value":3959}," announced by Microsoft at Build 2019 will offer the same capabilities and how it will differ from Gitpod.",{"type":413,"tag":422,"props":3961,"children":3962},{},[3963],{"type":419,"value":3964},"This was just a quick introduction to Gitpod but there are far more things you can do with it:",{"type":413,"tag":2289,"props":3966,"children":3967},{},[3968,3980,3985,3990,3995,4000],{"type":413,"tag":536,"props":3969,"children":3970},{},[3971,3973,3978],{"type":419,"value":3972},"running scripts on the start-up of your environment  (an ",{"type":413,"tag":445,"props":3974,"children":3976},{"className":3975},[],[3977],{"type":419,"value":3851},{"type":419,"value":3979}," for instance)",{"type":413,"tag":536,"props":3981,"children":3982},{},[3983],{"type":419,"value":3984},"continuously auto-building your repository",{"type":413,"tag":536,"props":3986,"children":3987},{},[3988],{"type":419,"value":3989},"install a database",{"type":413,"tag":536,"props":3991,"children":3992},{},[3993],{"type":419,"value":3994},"use it for private projects (not free, there are multiple pricings available)",{"type":413,"tag":536,"props":3996,"children":3997},{},[3998],{"type":419,"value":3999},"share an environment with other users",{"type":413,"tag":536,"props":4001,"children":4002},{},[4003],{"type":419,"value":4004},"...",{"type":413,"tag":422,"props":4006,"children":4007},{},[4008],{"type":419,"value":4009},"But the best is you try and judge by yourself.",{"title":401,"searchDepth":569,"depth":569,"links":4011},[],"content:1.posts:4.gitpod.md","1.posts/4.gitpod.md",{"_path":10,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":9,"description":4015,"lead":4016,"date":4017,"image":4018,"badge":4020,"tags":4021,"body":4022,"_type":678,"_id":4907,"_source":680,"_file":4908,"_extension":682},"Let's talk about tooling and testing an API!","Why using the vscode extension \"REST Client\" instead of Postman?","2019-03-05T00:00:00.000Z",{"src":4019},"/images/swiss_knifes.jpg",{"label":3751},[206,208,210,213],{"type":410,"children":4023,"toc":4900},[4024,4028,4034,4039,4048,4053,4065,4071,4080,4110,4115,4129,4162,4173,4179,4213,4222,4227,4467,4512,4521,4527,4532,4537,4542,4548,4553,4565,4570,4896],{"type":413,"tag":422,"props":4025,"children":4026},{},[4027],{"type":419,"value":4015},{"type":413,"tag":414,"props":4029,"children":4031},{"id":4030},"gui-tools-and-their-limits",[4032],{"type":419,"value":4033},"GUI Tools and their limits",{"type":413,"tag":422,"props":4035,"children":4036},{},[4037],{"type":419,"value":4038},"Like most developers I guess, I often use GUI tools like Fiddler or Postman to query an API.\nOnce you get used to the HMI of Postman with all its tabs, it's quite easy to create GET / POST / PUT / ... requests, save them in a collection, and visualize the answers. Postman offers a lot of other features, but a very handy one is the possibility to use environment variables in your requests.",{"type":413,"tag":422,"props":4040,"children":4041},{},[4042],{"type":413,"tag":559,"props":4043,"children":4047},{"alt":4044,"className":4045,"src":4046},"Postman UI",[563,564],"/posts/images/restclient_postman_1.png",[],{"type":413,"tag":422,"props":4049,"children":4050},{},[4051],{"type":419,"value":4052},"Seems to be the perfect tool you would say. Well, that's true if you want to quickly test an API on your own, and to be honest I use it a lot for that. But when you are collaborating on a real project with other developers, there might be some things you will miss. For me, it's a way to edit, version, and share requests with other developers.",{"type":413,"tag":422,"props":4054,"children":4055},{},[4056,4058,4064],{"type":419,"value":4057},"Okay, I know that Postman paid plan allows you to share requests with other people of your team. And I am aware of the collection export feature on the free plan, but that's not enough. I don't really like to be too tied to a proprietary software and its GUI to do things. As a developer what I want is to be able to edit my requests in simple text files that I can put in version control. And here's come ",{"type":413,"tag":428,"props":4059,"children":4062},{"href":4060,"rel":4061},"https://marketplace.visualstudio.com/items?itemName=humao.rest-client",[432],[4063],{"type":419,"value":1173},{"type":419,"value":764},{"type":413,"tag":414,"props":4066,"children":4068},{"id":4067},"what-is-rest-client",[4069],{"type":419,"value":4070},"What is REST Client?",{"type":413,"tag":422,"props":4072,"children":4073},{},[4074],{"type":413,"tag":559,"props":4075,"children":4079},{"alt":4076,"className":4077,"src":4078},"REST Client extension in vscode marketplace",[563,564],"/posts/images/restclient_vscode_1.png",[],{"type":413,"tag":422,"props":4081,"children":4082},{},[4083,4085,4092,4094,4100,4102,4109],{"type":419,"value":4084},"The REST Client extension is an open source vs code extension developed by ",{"type":413,"tag":428,"props":4086,"children":4089},{"href":4087,"rel":4088},"https://github.com/Huachao",[432],[4090],{"type":419,"value":4091},"Huachao Mao",{"type":419,"value":4093},". If I quote the README of its ",{"type":413,"tag":428,"props":4095,"children":4097},{"href":1169,"rel":4096},[432],[4098],{"type":419,"value":4099},"GitHub repository",{"type":419,"value":4101},": REST Client allows you to send HTTP request and view the response in Visual Studio Code directly.\nLet's see that with a simple GET request to ",{"type":413,"tag":428,"props":4103,"children":4106},{"href":4104,"rel":4105},"https://swapi.co/",[432],[4107],{"type":419,"value":4108},"The Start Wars API",{"type":419,"value":1277},{"type":413,"tag":422,"props":4111,"children":4112},{},[4113],{"type":419,"value":4114},"05578273",{"type":413,"tag":422,"props":4116,"children":4117},{},[4118,4120,4127],{"type":419,"value":4119},"Nothing new or complicated here, just the request you would have written intuitively. Like this, you can write any kind of request you want simply following the standard RFC 2616. Even if you don't know the standard, it's pretty straightforward and you often find samples with this format on the documentation of the API you are querying, like on the ",{"type":413,"tag":428,"props":4121,"children":4124},{"href":4122,"rel":4123},"https://docs.microsoft.com/en-us/graph/api/user-list-memberof?view=graph-rest-1.0#example",[432],[4125],{"type":419,"value":4126},"Microsoft Graph API documentation",{"type":419,"value":4128}," for instance.",{"type":413,"tag":422,"props":4130,"children":4131},{},[4132,4134,4139,4141,4146,4148,4153,4155,4160],{"type":419,"value":4133},"REST Client works on text files in vscode by selecting ",{"type":413,"tag":4135,"props":4136,"children":4137},"em",{},[4138],{"type":419,"value":213},{"type":419,"value":4140}," as the Language Mode (by default this language mode is associated with files having the ",{"type":413,"tag":4135,"props":4142,"children":4143},{},[4144],{"type":419,"value":4145},".rest",{"type":419,"value":4147}," or ",{"type":413,"tag":4135,"props":4149,"children":4150},{},[4151],{"type":419,"value":4152},".http",{"type":419,"value":4154}," extension). It provides you with some autocompletion and a few snippets to help you write your queries. You can write multiple requests on the same file in vscode just by separating them with ###. Above each request an actionable ",{"type":413,"tag":4135,"props":4156,"children":4157},{},[4158],{"type":419,"value":4159},"Send Request",{"type":419,"value":4161}," link allows you to run the request and see the response in a response panel.",{"type":413,"tag":422,"props":4163,"children":4164},{},[4165],{"type":413,"tag":559,"props":4166,"children":4172},{"alt":4167,"className":4168,"src":4169,"height":4170,"width":4171},"Intellisense in HTTP files in vscode",[563,564],"/posts/images/restclient_swapi_3.png",400,800,[],{"type":413,"tag":414,"props":4174,"children":4176},{"id":4175},"using-variables-in-rest-client",[4177],{"type":419,"value":4178},"Using variables in REST Client",{"type":413,"tag":422,"props":4180,"children":4181},{},[4182,4184,4190,4192,4203,4205,4211],{"type":419,"value":4183},"As you can see below, it is possible to use variables with REST Client. A variable ",{"type":413,"tag":445,"props":4185,"children":4187},{"className":4186},[],[4188],{"type":419,"value":4189},"planetName",{"type":419,"value":4191}," is defined in the file and reused in 2 requests. A variable is also used to name the request ",{"type":413,"tag":4135,"props":4193,"children":4194},{},[4195,4197],{"type":419,"value":4196},"GET ",{"type":413,"tag":428,"props":4198,"children":4201},{"href":4199,"rel":4200},"https://swapi.co/api/people/?search=Luke",[432],[4202],{"type":419,"value":4199},{"type":419,"value":4204}," and makes it possible to use elements from the response (that you can see on the right). Here we are using the ",{"type":413,"tag":445,"props":4206,"children":4208},{"className":4207},[],[4209],{"type":419,"value":4210},"homeworld",{"type":419,"value":4212}," property of the response to retrieve the planet from which Luke was from in the following GET request. With the help of variables you can easily combine and chain requests for the scenario you need to realize.",{"type":413,"tag":422,"props":4214,"children":4215},{},[4216],{"type":413,"tag":559,"props":4217,"children":4221},{"alt":4218,"className":4219,"src":4220},"Execution of an HTTP request in vscode",[563,564],"/posts/images/restclient_swapi_2.png",[],{"type":413,"tag":422,"props":4223,"children":4224},{},[4225],{"type":419,"value":4226},"REST Client allows you to define environments and their associated variables in the user settings file of vscode. For instance, let's say I want to query the Microsoft Graph API (both the V1 version and the beta version of the API), I will add the following JSON to my  settings file:",{"type":413,"tag":439,"props":4228,"children":4230},{"className":2092,"code":4229,"language":2094,"meta":401,"style":401},"\"rest-client.environmentVariables\": {\n    \"$shared\": {\n        \"host\": \"https://graph.microsoft.com/\",\n    },\n    \"graphV1\": {\n        \"version\": \"v1.0\",\n    },\n    \"graphBeta\": {\n        \"version\": \"beta\"\n    },\n}\n",[4231],{"type":413,"tag":445,"props":4232,"children":4233},{"__ignoreMap":401},[4234,4259,4284,4321,4329,4353,4390,4397,4421,4453,4460],{"type":413,"tag":449,"props":4235,"children":4236},{"class":451,"line":452},[4237,4241,4246,4250,4255],{"type":413,"tag":449,"props":4238,"children":4239},{"style":1318},[4240],{"type":419,"value":1372},{"type":413,"tag":449,"props":4242,"children":4243},{"style":1375},[4244],{"type":419,"value":4245},"rest-client.environmentVariables",{"type":413,"tag":449,"props":4247,"children":4248},{"style":1318},[4249],{"type":419,"value":1372},{"type":413,"tag":449,"props":4251,"children":4252},{"style":456},[4253],{"type":419,"value":4254},": ",{"type":413,"tag":449,"props":4256,"children":4257},{"style":1318},[4258],{"type":419,"value":2106},{"type":413,"tag":449,"props":4260,"children":4261},{"class":451,"line":569},[4262,4266,4271,4275,4279],{"type":413,"tag":449,"props":4263,"children":4264},{"style":1318},[4265],{"type":419,"value":2114},{"type":413,"tag":449,"props":4267,"children":4268},{"style":2117},[4269],{"type":419,"value":4270},"$shared",{"type":413,"tag":449,"props":4272,"children":4273},{"style":1318},[4274],{"type":419,"value":1372},{"type":413,"tag":449,"props":4276,"children":4277},{"style":1318},[4278],{"type":419,"value":1277},{"type":413,"tag":449,"props":4280,"children":4281},{"style":1318},[4282],{"type":419,"value":4283}," {\n",{"type":413,"tag":449,"props":4285,"children":4286},{"class":451,"line":593},[4287,4291,4296,4300,4304,4308,4313,4317],{"type":413,"tag":449,"props":4288,"children":4289},{"style":1318},[4290],{"type":419,"value":2141},{"type":413,"tag":449,"props":4292,"children":4293},{"style":1342},[4294],{"type":419,"value":4295},"host",{"type":413,"tag":449,"props":4297,"children":4298},{"style":1318},[4299],{"type":419,"value":1372},{"type":413,"tag":449,"props":4301,"children":4302},{"style":1318},[4303],{"type":419,"value":1277},{"type":413,"tag":449,"props":4305,"children":4306},{"style":1318},[4307],{"type":419,"value":2366},{"type":413,"tag":449,"props":4309,"children":4310},{"style":1375},[4311],{"type":419,"value":4312},"https://graph.microsoft.com/",{"type":413,"tag":449,"props":4314,"children":4315},{"style":1318},[4316],{"type":419,"value":1372},{"type":413,"tag":449,"props":4318,"children":4319},{"style":1318},[4320],{"type":419,"value":2155},{"type":413,"tag":449,"props":4322,"children":4323},{"class":451,"line":2158},[4324],{"type":413,"tag":449,"props":4325,"children":4326},{"style":1318},[4327],{"type":419,"value":4328},"    },\n",{"type":413,"tag":449,"props":4330,"children":4331},{"class":451,"line":2176},[4332,4336,4341,4345,4349],{"type":413,"tag":449,"props":4333,"children":4334},{"style":1318},[4335],{"type":419,"value":2114},{"type":413,"tag":449,"props":4337,"children":4338},{"style":2117},[4339],{"type":419,"value":4340},"graphV1",{"type":413,"tag":449,"props":4342,"children":4343},{"style":1318},[4344],{"type":419,"value":1372},{"type":413,"tag":449,"props":4346,"children":4347},{"style":1318},[4348],{"type":419,"value":1277},{"type":413,"tag":449,"props":4350,"children":4351},{"style":1318},[4352],{"type":419,"value":4283},{"type":413,"tag":449,"props":4354,"children":4355},{"class":451,"line":2185},[4356,4360,4365,4369,4373,4377,4382,4386],{"type":413,"tag":449,"props":4357,"children":4358},{"style":1318},[4359],{"type":419,"value":2141},{"type":413,"tag":449,"props":4361,"children":4362},{"style":1342},[4363],{"type":419,"value":4364},"version",{"type":413,"tag":449,"props":4366,"children":4367},{"style":1318},[4368],{"type":419,"value":1372},{"type":413,"tag":449,"props":4370,"children":4371},{"style":1318},[4372],{"type":419,"value":1277},{"type":413,"tag":449,"props":4374,"children":4375},{"style":1318},[4376],{"type":419,"value":2366},{"type":413,"tag":449,"props":4378,"children":4379},{"style":1375},[4380],{"type":419,"value":4381},"v1.0",{"type":413,"tag":449,"props":4383,"children":4384},{"style":1318},[4385],{"type":419,"value":1372},{"type":413,"tag":449,"props":4387,"children":4388},{"style":1318},[4389],{"type":419,"value":2155},{"type":413,"tag":449,"props":4391,"children":4392},{"class":451,"line":2578},[4393],{"type":413,"tag":449,"props":4394,"children":4395},{"style":1318},[4396],{"type":419,"value":4328},{"type":413,"tag":449,"props":4398,"children":4399},{"class":451,"line":2613},[4400,4404,4409,4413,4417],{"type":413,"tag":449,"props":4401,"children":4402},{"style":1318},[4403],{"type":419,"value":2114},{"type":413,"tag":449,"props":4405,"children":4406},{"style":2117},[4407],{"type":419,"value":4408},"graphBeta",{"type":413,"tag":449,"props":4410,"children":4411},{"style":1318},[4412],{"type":419,"value":1372},{"type":413,"tag":449,"props":4414,"children":4415},{"style":1318},[4416],{"type":419,"value":1277},{"type":413,"tag":449,"props":4418,"children":4419},{"style":1318},[4420],{"type":419,"value":4283},{"type":413,"tag":449,"props":4422,"children":4423},{"class":451,"line":2649},[4424,4428,4432,4436,4440,4444,4449],{"type":413,"tag":449,"props":4425,"children":4426},{"style":1318},[4427],{"type":419,"value":2141},{"type":413,"tag":449,"props":4429,"children":4430},{"style":1342},[4431],{"type":419,"value":4364},{"type":413,"tag":449,"props":4433,"children":4434},{"style":1318},[4435],{"type":419,"value":1372},{"type":413,"tag":449,"props":4437,"children":4438},{"style":1318},[4439],{"type":419,"value":1277},{"type":413,"tag":449,"props":4441,"children":4442},{"style":1318},[4443],{"type":419,"value":2366},{"type":413,"tag":449,"props":4445,"children":4446},{"style":1375},[4447],{"type":419,"value":4448},"beta",{"type":413,"tag":449,"props":4450,"children":4451},{"style":1318},[4452],{"type":419,"value":2173},{"type":413,"tag":449,"props":4454,"children":4455},{"class":451,"line":2657},[4456],{"type":413,"tag":449,"props":4457,"children":4458},{"style":1318},[4459],{"type":419,"value":4328},{"type":413,"tag":449,"props":4461,"children":4462},{"class":451,"line":2665},[4463],{"type":413,"tag":449,"props":4464,"children":4465},{"style":1318},[4466],{"type":419,"value":2191},{"type":413,"tag":422,"props":4468,"children":4469},{},[4470,4472,4476,4477,4481,4483,4487,4489,4493,4495,4499,4501,4505,4506,4510],{"type":419,"value":4471},"I have defined 2 environments ",{"type":413,"tag":4135,"props":4473,"children":4474},{},[4475],{"type":419,"value":4340},{"type":419,"value":1238},{"type":413,"tag":4135,"props":4478,"children":4479},{},[4480],{"type":419,"value":4408},{"type":419,"value":4482}," with a specific value for the ",{"type":413,"tag":4135,"props":4484,"children":4485},{},[4486],{"type":419,"value":4364},{"type":419,"value":4488}," variable. These environments share the ",{"type":413,"tag":4135,"props":4490,"children":4491},{},[4492],{"type":419,"value":4295},{"type":419,"value":4494}," as a common variable which is contained in the shared environment ",{"type":413,"tag":4135,"props":4496,"children":4497},{},[4498],{"type":419,"value":4270},{"type":419,"value":4500},". From my request file, I can now switch between environments and use the variables ",{"type":413,"tag":4135,"props":4502,"children":4503},{},[4504],{"type":419,"value":4364},{"type":419,"value":1238},{"type":413,"tag":4135,"props":4507,"children":4508},{},[4509],{"type":419,"value":4295},{"type":419,"value":4511}," to request the Microsoft Graph API.",{"type":413,"tag":422,"props":4513,"children":4514},{},[4515],{"type":413,"tag":559,"props":4516,"children":4520},{"alt":4517,"className":4518,"src":4519},"Environment selection in vscode.",[563,564],"/posts/images/restclient_msgraph_1.png",[],{"type":413,"tag":414,"props":4522,"children":4524},{"id":4523},"what-i-like-about-rest-client",[4525],{"type":419,"value":4526},"What I like about REST Client?",{"type":413,"tag":422,"props":4528,"children":4529},{},[4530],{"type":419,"value":4531},"REST Client is a nice alternative to Postman as it allows to easily write requests and query APIs from Visual Studio Code. I am already a vscode user so I appreciate staying in the same environment I know and like for testing an API. REST Client may not offer as many functionalities as Postman but for the usage I have, it is quite enough.",{"type":413,"tag":422,"props":4533,"children":4534},{},[4535],{"type":419,"value":4536},"What I like about this tool is that you treat your requests as code: you can commit the files containing your requests, keep track of their modifications and share the requests with your colleagues in your Git project repository.",{"type":413,"tag":422,"props":4538,"children":4539},{},[4540],{"type":419,"value":4541},"I have seen quite a few people using it recently in video tutorials and if you have a look at the number of downloads it seems I am not the only one to find it useful.",{"type":413,"tag":414,"props":4543,"children":4545},{"id":4544},"getting-started",[4546],{"type":419,"value":4547},"Getting started",{"type":413,"tag":422,"props":4549,"children":4550},{},[4551],{"type":419,"value":4552},"There are a lot of other features in REST Client that I didn't talk about (generate code snippet, request history ...) so don't hesitate to give it a try. You can use it on any API you like (there is even basic support for SOAP) the same way you would use Postman or other tools.",{"type":413,"tag":422,"props":4554,"children":4555},{},[4556,4558,4563],{"type":419,"value":4557},"If you quickly want to convert some of your Postman queries, there is a ",{"type":413,"tag":4135,"props":4559,"children":4560},{},[4561],{"type":419,"value":4562},"Code",{"type":419,"value":4564}," button in Postman that allows you to see the HTTP request code that you can just copy and paste in vscode to use it with REST Client.",{"type":413,"tag":422,"props":4566,"children":4567},{},[4568],{"type":419,"value":4569},"Or if you prefer you can get started by testing the Star Wars API, you will find below the requests I used. Enjoy :)",{"type":413,"tag":439,"props":4571,"children":4575},{"className":4572,"code":4573,"filename":4574,"language":212,"meta":401,"style":401},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","#### List of start wars planets\nGET https://swapi.co/api/planets/ HTTP/1.1\n\n### Get Luke Skywalker\n# @name lukeRequest\nGET https://swapi.co/api/people/?search=Luke HTTP/1.1\n\n### Get Luke Skywalker home planet\nGET {{lukeRequest.response.body.results[0].homeworld}} HTTP/1.1\n\n### List available resources\nGET https://swapi.co/api/ HTTP/1.1\n\n### Search planet with a specific name \n@planetName = Naboo\nGET https://swapi.co/api/planets/?search={{planetName}} HTTP/1.1\n\n### Search planet with a specific name in wookie encoding\nGET https://swapi.co/api/planets/?search={{planetName}}&format=wookiee HTTP/1.1\n\n### List starships\nGET https://swapi.co/api/starships HTTP/1.1\n","swapi.http",[4576],{"type":413,"tag":445,"props":4577,"children":4578},{"__ignoreMap":401},[4579,4588,4615,4622,4630,4655,4679,4686,4694,4718,4725,4733,4757,4764,4772,4789,4813,4820,4829,4854,4862,4871],{"type":413,"tag":449,"props":4580,"children":4581},{"class":451,"line":452},[4582],{"type":413,"tag":449,"props":4583,"children":4585},{"style":4584},"--shiki-light:#90A4AE;--shiki-default:#546E7A;--shiki-dark:#676E95;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[4586],{"type":419,"value":4587},"#### List of start wars planets\n",{"type":413,"tag":449,"props":4589,"children":4590},{"class":451,"line":569},[4591,4596,4601,4605,4610],{"type":413,"tag":449,"props":4592,"children":4593},{"style":2483},[4594],{"type":419,"value":4595},"GET",{"type":413,"tag":449,"props":4597,"children":4598},{"style":456},[4599],{"type":419,"value":4600}," https://swapi.co/api/planets/ ",{"type":413,"tag":449,"props":4602,"children":4603},{"style":462},[4604],{"type":419,"value":213},{"type":413,"tag":449,"props":4606,"children":4607},{"style":456},[4608],{"type":419,"value":4609},"/",{"type":413,"tag":449,"props":4611,"children":4612},{"style":462},[4613],{"type":419,"value":4614},"1.1\n",{"type":413,"tag":449,"props":4616,"children":4617},{"class":451,"line":593},[4618],{"type":413,"tag":449,"props":4619,"children":4620},{"emptyLinePlaceholder":2474},[4621],{"type":419,"value":2477},{"type":413,"tag":449,"props":4623,"children":4624},{"class":451,"line":2158},[4625],{"type":413,"tag":449,"props":4626,"children":4627},{"style":4584},[4628],{"type":419,"value":4629},"### Get Luke Skywalker\n",{"type":413,"tag":449,"props":4631,"children":4632},{"class":451,"line":2176},[4633,4638,4643,4649],{"type":413,"tag":449,"props":4634,"children":4635},{"style":4584},[4636],{"type":419,"value":4637},"# ",{"type":413,"tag":449,"props":4639,"children":4640},{"style":2483},[4641],{"type":419,"value":4642},"@",{"type":413,"tag":449,"props":4644,"children":4646},{"style":4645},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[4647],{"type":419,"value":4648},"name",{"type":413,"tag":449,"props":4650,"children":4652},{"style":4651},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[4653],{"type":419,"value":4654}," lukeRequest\n",{"type":413,"tag":449,"props":4656,"children":4657},{"class":451,"line":2185},[4658,4662,4667,4671,4675],{"type":413,"tag":449,"props":4659,"children":4660},{"style":2483},[4661],{"type":419,"value":4595},{"type":413,"tag":449,"props":4663,"children":4664},{"style":456},[4665],{"type":419,"value":4666}," https://swapi.co/api/people/?search=Luke ",{"type":413,"tag":449,"props":4668,"children":4669},{"style":462},[4670],{"type":419,"value":213},{"type":413,"tag":449,"props":4672,"children":4673},{"style":456},[4674],{"type":419,"value":4609},{"type":413,"tag":449,"props":4676,"children":4677},{"style":462},[4678],{"type":419,"value":4614},{"type":413,"tag":449,"props":4680,"children":4681},{"class":451,"line":2578},[4682],{"type":413,"tag":449,"props":4683,"children":4684},{"emptyLinePlaceholder":2474},[4685],{"type":419,"value":2477},{"type":413,"tag":449,"props":4687,"children":4688},{"class":451,"line":2613},[4689],{"type":413,"tag":449,"props":4690,"children":4691},{"style":4584},[4692],{"type":419,"value":4693},"### Get Luke Skywalker home planet\n",{"type":413,"tag":449,"props":4695,"children":4696},{"class":451,"line":2649},[4697,4701,4706,4710,4714],{"type":413,"tag":449,"props":4698,"children":4699},{"style":2483},[4700],{"type":419,"value":4595},{"type":413,"tag":449,"props":4702,"children":4703},{"style":456},[4704],{"type":419,"value":4705}," {{lukeRequest.response.body.results[0].homeworld}} ",{"type":413,"tag":449,"props":4707,"children":4708},{"style":462},[4709],{"type":419,"value":213},{"type":413,"tag":449,"props":4711,"children":4712},{"style":456},[4713],{"type":419,"value":4609},{"type":413,"tag":449,"props":4715,"children":4716},{"style":462},[4717],{"type":419,"value":4614},{"type":413,"tag":449,"props":4719,"children":4720},{"class":451,"line":2657},[4721],{"type":413,"tag":449,"props":4722,"children":4723},{"emptyLinePlaceholder":2474},[4724],{"type":419,"value":2477},{"type":413,"tag":449,"props":4726,"children":4727},{"class":451,"line":2665},[4728],{"type":413,"tag":449,"props":4729,"children":4730},{"style":4584},[4731],{"type":419,"value":4732},"### List available resources\n",{"type":413,"tag":449,"props":4734,"children":4735},{"class":451,"line":2684},[4736,4740,4745,4749,4753],{"type":413,"tag":449,"props":4737,"children":4738},{"style":2483},[4739],{"type":419,"value":4595},{"type":413,"tag":449,"props":4741,"children":4742},{"style":456},[4743],{"type":419,"value":4744}," https://swapi.co/api/ ",{"type":413,"tag":449,"props":4746,"children":4747},{"style":462},[4748],{"type":419,"value":213},{"type":413,"tag":449,"props":4750,"children":4751},{"style":456},[4752],{"type":419,"value":4609},{"type":413,"tag":449,"props":4754,"children":4755},{"style":462},[4756],{"type":419,"value":4614},{"type":413,"tag":449,"props":4758,"children":4759},{"class":451,"line":2692},[4760],{"type":413,"tag":449,"props":4761,"children":4762},{"emptyLinePlaceholder":2474},[4763],{"type":419,"value":2477},{"type":413,"tag":449,"props":4765,"children":4766},{"class":451,"line":2768},[4767],{"type":413,"tag":449,"props":4768,"children":4769},{"style":4584},[4770],{"type":419,"value":4771},"### Search planet with a specific name \n",{"type":413,"tag":449,"props":4773,"children":4774},{"class":451,"line":2776},[4775,4779,4784],{"type":413,"tag":449,"props":4776,"children":4777},{"style":462},[4778],{"type":419,"value":4642},{"type":413,"tag":449,"props":4780,"children":4781},{"style":456},[4782],{"type":419,"value":4783},"planetName = ",{"type":413,"tag":449,"props":4785,"children":4786},{"style":1375},[4787],{"type":419,"value":4788},"Naboo\n",{"type":413,"tag":449,"props":4790,"children":4791},{"class":451,"line":2862},[4792,4796,4801,4805,4809],{"type":413,"tag":449,"props":4793,"children":4794},{"style":2483},[4795],{"type":419,"value":4595},{"type":413,"tag":449,"props":4797,"children":4798},{"style":456},[4799],{"type":419,"value":4800}," https://swapi.co/api/planets/?search={{planetName}} ",{"type":413,"tag":449,"props":4802,"children":4803},{"style":462},[4804],{"type":419,"value":213},{"type":413,"tag":449,"props":4806,"children":4807},{"style":456},[4808],{"type":419,"value":4609},{"type":413,"tag":449,"props":4810,"children":4811},{"style":462},[4812],{"type":419,"value":4614},{"type":413,"tag":449,"props":4814,"children":4815},{"class":451,"line":2958},[4816],{"type":413,"tag":449,"props":4817,"children":4818},{"emptyLinePlaceholder":2474},[4819],{"type":419,"value":2477},{"type":413,"tag":449,"props":4821,"children":4823},{"class":451,"line":4822},18,[4824],{"type":413,"tag":449,"props":4825,"children":4826},{"style":4584},[4827],{"type":419,"value":4828},"### Search planet with a specific name in wookie encoding\n",{"type":413,"tag":449,"props":4830,"children":4832},{"class":451,"line":4831},19,[4833,4837,4842,4846,4850],{"type":413,"tag":449,"props":4834,"children":4835},{"style":2483},[4836],{"type":419,"value":4595},{"type":413,"tag":449,"props":4838,"children":4839},{"style":456},[4840],{"type":419,"value":4841}," https://swapi.co/api/planets/?search={{planetName}}&format=wookiee ",{"type":413,"tag":449,"props":4843,"children":4844},{"style":462},[4845],{"type":419,"value":213},{"type":413,"tag":449,"props":4847,"children":4848},{"style":456},[4849],{"type":419,"value":4609},{"type":413,"tag":449,"props":4851,"children":4852},{"style":462},[4853],{"type":419,"value":4614},{"type":413,"tag":449,"props":4855,"children":4857},{"class":451,"line":4856},20,[4858],{"type":413,"tag":449,"props":4859,"children":4860},{"emptyLinePlaceholder":2474},[4861],{"type":419,"value":2477},{"type":413,"tag":449,"props":4863,"children":4865},{"class":451,"line":4864},21,[4866],{"type":413,"tag":449,"props":4867,"children":4868},{"style":4584},[4869],{"type":419,"value":4870},"### List starships\n",{"type":413,"tag":449,"props":4872,"children":4874},{"class":451,"line":4873},22,[4875,4879,4884,4888,4892],{"type":413,"tag":449,"props":4876,"children":4877},{"style":2483},[4878],{"type":419,"value":4595},{"type":413,"tag":449,"props":4880,"children":4881},{"style":456},[4882],{"type":419,"value":4883}," https://swapi.co/api/starships ",{"type":413,"tag":449,"props":4885,"children":4886},{"style":462},[4887],{"type":419,"value":213},{"type":413,"tag":449,"props":4889,"children":4890},{"style":456},[4891],{"type":419,"value":4609},{"type":413,"tag":449,"props":4893,"children":4894},{"style":462},[4895],{"type":419,"value":4614},{"type":413,"tag":668,"props":4897,"children":4898},{},[4899],{"type":419,"value":672},{"title":401,"searchDepth":569,"depth":569,"links":4901},[4902,4903,4904,4905,4906],{"id":4030,"depth":569,"text":4033},{"id":4067,"depth":569,"text":4070},{"id":4175,"depth":569,"text":4178},{"id":4523,"depth":569,"text":4526},{"id":4544,"depth":569,"text":4547},"content:1.posts:1.testing-your-api-with-rest-client.md","1.posts/1.testing-your-api-with-rest-client.md",1716749600590]