[{"data":1,"prerenderedAt":31815},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-.NET":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,5426,8428,14157,18352,22687,22939,25814,26118,26546,26788,27979],{"_path":187,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":186,"description":402,"lead":403,"date":404,"image":405,"badge":407,"tags":409,"ImageAttribution":410,"body":411,"_type":5421,"_id":5422,"_source":5423,"_file":5424,"_extension":5425},"posts",false,"","In this post, we will discuss how to write a small .NET program that retrieves events from an IT event calendar and submits them to another one using AngleSharp.","Playing with AngleSharp","2024-03-04T00:00:00.000Z",{"src":406},"/images/calendar_1.webp",{"label":408},"Development",[239,390],"Picture of \u003Ca href=\"https://unsplash.com/fr/@towfiqu999999\">Towfiqu barbhuiya on \u003Ca href=\"https://unsplash.com/fr/photos/un-calendrier-avec-des-boutons-poussoirs-rouges-epingles-bwOAixLG0uc\">Unsplash\u003C/a>",{"type":412,"children":413,"toc":5411},"root",[414,421,428,453,467,472,478,509,523,529,543,548,697,733,919,925,930,941,946,1177,1187,1207,1802,1807,1963,1969,1974,1987,2450,2466,2472,2485,2800,2815,2821,2834,5345,5350,5356,5361,5370,5375,5395,5400,5405],{"type":415,"tag":416,"props":417,"children":418},"element","p",{},[419],{"type":420,"value":402},"text",{"type":415,"tag":422,"props":423,"children":425},"h2",{"id":424},"some-context",[426],{"type":420,"value":427},"Some context",{"type":415,"tag":416,"props":429,"children":430},{},[431,433,442,444,451],{"type":420,"value":432},"There are plenty of websites that list IT events in the world. One that is particularly popular is the ",{"type":415,"tag":434,"props":435,"children":439},"a",{"href":436,"rel":437},"https://github.com/scraly/developers-conferences-agenda",[438],"nofollow",[440],{"type":420,"value":441},"developers conferences agenda",{"type":420,"value":443}," Github repository that was created by Aurélie Vache, a well-known French DevRel. This repository is an excellent resource where numerous tech conferences and CFPs (Call for Papers) are listed. Adding a new conference/CFP is very easy for any developer because you just have add it in the readme that contains all the conferences and make a PR. Additionally, there is now a ",{"type":415,"tag":434,"props":445,"children":448},{"href":446,"rel":447},"https://developers.events/",[438],[449],{"type":420,"value":450},"website",{"type":420,"value":452}," available to easily view the list of conferences.",{"type":415,"tag":416,"props":454,"children":455},{},[456,458,465],{"type":420,"value":457},"Another one I like is the ",{"type":415,"tag":434,"props":459,"children":462},{"href":460,"rel":461},"https://techcommunitycalendar.com/",[438],[463],{"type":420,"value":464},"Tech Community Calendar",{"type":420,"value":466}," created by Lee Englestone, a Microsoft MVP. What I find interesting it that it does not just list conferences and call for papers but also other tech events like hackathon or meetups. Events are displayed on small cards with thumbnails of the events websites, and you can filter them by country or type of event. Yet, it is less popular than the developers conferences agenda I mentioned before, so there are fewer events listed. There is a form to suggest new events, and I have been submitted events from time to time. However, most events I submit are developer conferences and CFPs that people have already added in the developer conferences agenda.",{"type":415,"tag":416,"props":468,"children":469},{},[470],{"type":420,"value":471},"So I thought, what if I automate the process of retrieving events from the developer conferences agenda and submitting them to the tech community calendar?",{"type":415,"tag":422,"props":473,"children":475},{"id":474},"its-just-a-poc",[476],{"type":420,"value":477},"It's just a PoC!",{"type":415,"tag":416,"props":479,"children":480},{},[481,483,489,491,498,500,507],{"type":420,"value":482},"At first, I spent too much time thinking about how to schedule and host the program I hadn't even started writing 😁. Of course, time-triggered ",{"type":415,"tag":434,"props":484,"children":487},{"href":485,"rel":486},"https://azure.microsoft.com/fr-fr/products/functions",[438],[488],{"type":420,"value":257},{"type":420,"value":490}," came to my mind, I even considered Durable Functions to break down the process into steps (retrieve events, check for existing events, submitting each event...). Then I thought about ",{"type":415,"tag":434,"props":492,"children":495},{"href":493,"rel":494},"https://learn.microsoft.com/en-us/azure/container-apps/jobs",[438],[496],{"type":420,"value":497},"Jobs in Azure Container Apps",{"type":420,"value":499},", or Dapr with Azure Container Apps and even ",{"type":415,"tag":434,"props":501,"children":504},{"href":502,"rel":503},"https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-overview/",[438],[505],{"type":420,"value":506},"Dapr Workflows",{"type":420,"value":508},". Eventually, I realized it did not matter much since it was just a proof of concept. I decided to postpone the choice for later (if ever it goes beyond the poc) and just start coding.",{"type":415,"tag":416,"props":510,"children":511},{},[512,514,521],{"type":420,"value":513},"I often like writing .NET tools or small programs using the Worker Service template because it's straightforward and includes useful features like dependency injection and configuration. However, this time I decided to keep things simple: just a .NET console application and all the code in Program.cs file. With ",{"type":415,"tag":434,"props":515,"children":518},{"href":516,"rel":517},"https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements",[438],[519],{"type":420,"value":520},"top level statement",{"type":420,"value":522},", it feels similar to writing a Bash or PowerShell script, making it quite convenient for experimenting. Of course, this approach isn't what I would use for a real project.",{"type":415,"tag":422,"props":524,"children":526},{"id":525},"retrieve-developer-conferences",[527],{"type":420,"value":528},"Retrieve Developer Conferences",{"type":415,"tag":416,"props":530,"children":531},{},[532,534,541],{"type":420,"value":533},"In addition to the readme file, the developers conferences agenda exposes all the data publicly in JSON ",{"type":415,"tag":434,"props":535,"children":538},{"href":536,"rel":537},"https://developers.events/all-events.json",[438],[539],{"type":420,"value":540},"here",{"type":420,"value":542},".",{"type":415,"tag":416,"props":544,"children":545},{},[546],{"type":420,"value":547},"Developer conferences can be easily represented with a record (I only kept the properties I needed):",{"type":415,"tag":549,"props":550,"children":553},"pre",{"className":551,"code":552,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","public record DeveloperEvent(\n    string Name,\n    long[] Date,\n    string Hyperlink,\n    string Location,\n    string City,\n    string Country\n);\n",[554],{"type":415,"tag":555,"props":556,"children":557},"code",{"__ignoreMap":401},[558,587,606,624,641,658,675,688],{"type":415,"tag":559,"props":560,"children":563},"span",{"class":561,"line":562},"line",1,[564,570,576,581],{"type":415,"tag":559,"props":565,"children":567},{"style":566},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[568],{"type":420,"value":569},"public",{"type":415,"tag":559,"props":571,"children":573},{"style":572},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[574],{"type":420,"value":575}," record",{"type":415,"tag":559,"props":577,"children":578},{"style":572},[579],{"type":420,"value":580}," DeveloperEvent",{"type":415,"tag":559,"props":582,"children":584},{"style":583},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[585],{"type":420,"value":586},"(\n",{"type":415,"tag":559,"props":588,"children":590},{"class":561,"line":589},2,[591,596,601],{"type":415,"tag":559,"props":592,"children":593},{"style":583},[594],{"type":420,"value":595},"    string",{"type":415,"tag":559,"props":597,"children":598},{"style":572},[599],{"type":420,"value":600}," Name",{"type":415,"tag":559,"props":602,"children":603},{"style":583},[604],{"type":420,"value":605},",\n",{"type":415,"tag":559,"props":607,"children":609},{"class":561,"line":608},3,[610,615,620],{"type":415,"tag":559,"props":611,"children":612},{"style":583},[613],{"type":420,"value":614},"    long[]",{"type":415,"tag":559,"props":616,"children":617},{"style":572},[618],{"type":420,"value":619}," Date",{"type":415,"tag":559,"props":621,"children":622},{"style":583},[623],{"type":420,"value":605},{"type":415,"tag":559,"props":625,"children":627},{"class":561,"line":626},4,[628,632,637],{"type":415,"tag":559,"props":629,"children":630},{"style":583},[631],{"type":420,"value":595},{"type":415,"tag":559,"props":633,"children":634},{"style":572},[635],{"type":420,"value":636}," Hyperlink",{"type":415,"tag":559,"props":638,"children":639},{"style":583},[640],{"type":420,"value":605},{"type":415,"tag":559,"props":642,"children":644},{"class":561,"line":643},5,[645,649,654],{"type":415,"tag":559,"props":646,"children":647},{"style":583},[648],{"type":420,"value":595},{"type":415,"tag":559,"props":650,"children":651},{"style":572},[652],{"type":420,"value":653}," Location",{"type":415,"tag":559,"props":655,"children":656},{"style":583},[657],{"type":420,"value":605},{"type":415,"tag":559,"props":659,"children":661},{"class":561,"line":660},6,[662,666,671],{"type":415,"tag":559,"props":663,"children":664},{"style":583},[665],{"type":420,"value":595},{"type":415,"tag":559,"props":667,"children":668},{"style":572},[669],{"type":420,"value":670}," City",{"type":415,"tag":559,"props":672,"children":673},{"style":583},[674],{"type":420,"value":605},{"type":415,"tag":559,"props":676,"children":678},{"class":561,"line":677},7,[679,683],{"type":415,"tag":559,"props":680,"children":681},{"style":583},[682],{"type":420,"value":595},{"type":415,"tag":559,"props":684,"children":685},{"style":572},[686],{"type":420,"value":687}," Country\n",{"type":415,"tag":559,"props":689,"children":691},{"class":561,"line":690},8,[692],{"type":415,"tag":559,"props":693,"children":694},{"style":583},[695],{"type":420,"value":696},");\n",{"type":415,"tag":416,"props":698,"children":699},{},[700,702,708,710,716,718,724,726,732],{"type":420,"value":701},"We can use an ",{"type":415,"tag":555,"props":703,"children":705},{"className":704},[],[706],{"type":420,"value":707},"HttpClient",{"type":420,"value":709}," to retrieve the events. The namespace ",{"type":415,"tag":555,"props":711,"children":713},{"className":712},[],[714],{"type":420,"value":715},"System.Net.Http.Json",{"type":420,"value":717}," contains an interesting method to make the ",{"type":415,"tag":555,"props":719,"children":721},{"className":720},[],[722],{"type":420,"value":723},"GET",{"type":420,"value":725}," HTTP call and deserialize the data using ",{"type":415,"tag":555,"props":727,"children":729},{"className":728},[],[730],{"type":420,"value":731},"System.Text.Json",{"type":420,"value":542},{"type":415,"tag":549,"props":734,"children":736},{"className":551,"code":735,"language":326,"meta":401,"style":401},"using var httpClient = new HttpClient()\n{\n    BaseAddress = new Uri(\"https://developers.events/\")\n};\n\nvar events = await httpClient.GetFromJsonAsync\u003CDeveloperEvent[]>(\"all-events.json\");\n",[737],{"type":415,"tag":555,"props":738,"children":739},{"__ignoreMap":401},[740,779,787,834,842,851],{"type":415,"tag":559,"props":741,"children":742},{"class":561,"line":562},[743,749,754,759,764,769,774],{"type":415,"tag":559,"props":744,"children":746},{"style":745},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[747],{"type":420,"value":748},"using",{"type":415,"tag":559,"props":750,"children":751},{"style":572},[752],{"type":420,"value":753}," var",{"type":415,"tag":559,"props":755,"children":756},{"style":572},[757],{"type":420,"value":758}," httpClient",{"type":415,"tag":559,"props":760,"children":761},{"style":583},[762],{"type":420,"value":763}," =",{"type":415,"tag":559,"props":765,"children":766},{"style":583},[767],{"type":420,"value":768}," new",{"type":415,"tag":559,"props":770,"children":771},{"style":572},[772],{"type":420,"value":773}," HttpClient",{"type":415,"tag":559,"props":775,"children":776},{"style":583},[777],{"type":420,"value":778},"()\n",{"type":415,"tag":559,"props":780,"children":781},{"class":561,"line":589},[782],{"type":415,"tag":559,"props":783,"children":784},{"style":583},[785],{"type":420,"value":786},"{\n",{"type":415,"tag":559,"props":788,"children":789},{"class":561,"line":608},[790,796,801,805,810,815,820,825,829],{"type":415,"tag":559,"props":791,"children":793},{"style":792},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[794],{"type":420,"value":795},"    BaseAddress ",{"type":415,"tag":559,"props":797,"children":798},{"style":583},[799],{"type":420,"value":800},"=",{"type":415,"tag":559,"props":802,"children":803},{"style":583},[804],{"type":420,"value":768},{"type":415,"tag":559,"props":806,"children":807},{"style":572},[808],{"type":420,"value":809}," Uri",{"type":415,"tag":559,"props":811,"children":812},{"style":583},[813],{"type":420,"value":814},"(",{"type":415,"tag":559,"props":816,"children":817},{"style":583},[818],{"type":420,"value":819},"\"",{"type":415,"tag":559,"props":821,"children":823},{"style":822},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[824],{"type":420,"value":446},{"type":415,"tag":559,"props":826,"children":827},{"style":583},[828],{"type":420,"value":819},{"type":415,"tag":559,"props":830,"children":831},{"style":583},[832],{"type":420,"value":833},")\n",{"type":415,"tag":559,"props":835,"children":836},{"class":561,"line":626},[837],{"type":415,"tag":559,"props":838,"children":839},{"style":583},[840],{"type":420,"value":841},"};\n",{"type":415,"tag":559,"props":843,"children":844},{"class":561,"line":643},[845],{"type":415,"tag":559,"props":846,"children":848},{"emptyLinePlaceholder":847},true,[849],{"type":420,"value":850},"\n",{"type":415,"tag":559,"props":852,"children":853},{"class":561,"line":660},[854,859,864,868,873,877,881,887,892,897,902,906,911,915],{"type":415,"tag":559,"props":855,"children":856},{"style":572},[857],{"type":420,"value":858},"var",{"type":415,"tag":559,"props":860,"children":861},{"style":572},[862],{"type":420,"value":863}," events",{"type":415,"tag":559,"props":865,"children":866},{"style":583},[867],{"type":420,"value":763},{"type":415,"tag":559,"props":869,"children":870},{"style":583},[871],{"type":420,"value":872}," await",{"type":415,"tag":559,"props":874,"children":875},{"style":792},[876],{"type":420,"value":758},{"type":415,"tag":559,"props":878,"children":879},{"style":583},[880],{"type":420,"value":542},{"type":415,"tag":559,"props":882,"children":884},{"style":883},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[885],{"type":420,"value":886},"GetFromJsonAsync",{"type":415,"tag":559,"props":888,"children":889},{"style":583},[890],{"type":420,"value":891},"\u003C",{"type":415,"tag":559,"props":893,"children":894},{"style":572},[895],{"type":420,"value":896},"DeveloperEvent",{"type":415,"tag":559,"props":898,"children":899},{"style":583},[900],{"type":420,"value":901},"[]>(",{"type":415,"tag":559,"props":903,"children":904},{"style":583},[905],{"type":420,"value":819},{"type":415,"tag":559,"props":907,"children":908},{"style":822},[909],{"type":420,"value":910},"all-events.json",{"type":415,"tag":559,"props":912,"children":913},{"style":583},[914],{"type":420,"value":819},{"type":415,"tag":559,"props":916,"children":917},{"style":583},[918],{"type":420,"value":696},{"type":415,"tag":422,"props":920,"children":922},{"id":921},"convert-events-to-the-proper-format",[923],{"type":420,"value":924},"Convert Events To The Proper Format",{"type":415,"tag":416,"props":926,"children":927},{},[928],{"type":420,"value":929},"The form to submit events in the Tech Community Calendar look likes that:",{"type":415,"tag":416,"props":931,"children":932},{},[933],{"type":415,"tag":934,"props":935,"children":940},"img",{"alt":936,"className":937,"src":939},"Form to submit events to tech community calendar",[938],"rounded-lg","/posts/images/iteventcalendar_tcc.webp",[],{"type":415,"tag":416,"props":942,"children":943},{},[944],{"type":420,"value":945},"The Tech Community Calendar events can be represented with the following record :",{"type":415,"tag":549,"props":947,"children":949},{"className":551,"code":948,"language":326,"meta":401,"style":401},"public record TechCommunityCalendarEvent(\n    string Name,\n    string Url,\n    DateTimeOffset StartDate,\n    DateTimeOffset EndDate,\n    EventType EventType,\n    EventFormat EventFormat,\n    string Country,\n    string City\n)\n{\n    public string? TwitterHandle { get; set; }\n}; \n",[950],{"type":415,"tag":555,"props":951,"children":952},{"__ignoreMap":401},[953,973,988,1004,1021,1037,1054,1071,1087,1100,1108,1116,1169],{"type":415,"tag":559,"props":954,"children":955},{"class":561,"line":562},[956,960,964,969],{"type":415,"tag":559,"props":957,"children":958},{"style":566},[959],{"type":420,"value":569},{"type":415,"tag":559,"props":961,"children":962},{"style":572},[963],{"type":420,"value":575},{"type":415,"tag":559,"props":965,"children":966},{"style":572},[967],{"type":420,"value":968}," TechCommunityCalendarEvent",{"type":415,"tag":559,"props":970,"children":971},{"style":583},[972],{"type":420,"value":586},{"type":415,"tag":559,"props":974,"children":975},{"class":561,"line":589},[976,980,984],{"type":415,"tag":559,"props":977,"children":978},{"style":583},[979],{"type":420,"value":595},{"type":415,"tag":559,"props":981,"children":982},{"style":572},[983],{"type":420,"value":600},{"type":415,"tag":559,"props":985,"children":986},{"style":583},[987],{"type":420,"value":605},{"type":415,"tag":559,"props":989,"children":990},{"class":561,"line":608},[991,995,1000],{"type":415,"tag":559,"props":992,"children":993},{"style":583},[994],{"type":420,"value":595},{"type":415,"tag":559,"props":996,"children":997},{"style":572},[998],{"type":420,"value":999}," Url",{"type":415,"tag":559,"props":1001,"children":1002},{"style":583},[1003],{"type":420,"value":605},{"type":415,"tag":559,"props":1005,"children":1006},{"class":561,"line":626},[1007,1012,1017],{"type":415,"tag":559,"props":1008,"children":1009},{"style":572},[1010],{"type":420,"value":1011},"    DateTimeOffset",{"type":415,"tag":559,"props":1013,"children":1014},{"style":572},[1015],{"type":420,"value":1016}," StartDate",{"type":415,"tag":559,"props":1018,"children":1019},{"style":583},[1020],{"type":420,"value":605},{"type":415,"tag":559,"props":1022,"children":1023},{"class":561,"line":643},[1024,1028,1033],{"type":415,"tag":559,"props":1025,"children":1026},{"style":572},[1027],{"type":420,"value":1011},{"type":415,"tag":559,"props":1029,"children":1030},{"style":572},[1031],{"type":420,"value":1032}," EndDate",{"type":415,"tag":559,"props":1034,"children":1035},{"style":583},[1036],{"type":420,"value":605},{"type":415,"tag":559,"props":1038,"children":1039},{"class":561,"line":660},[1040,1045,1050],{"type":415,"tag":559,"props":1041,"children":1042},{"style":572},[1043],{"type":420,"value":1044},"    EventType",{"type":415,"tag":559,"props":1046,"children":1047},{"style":572},[1048],{"type":420,"value":1049}," EventType",{"type":415,"tag":559,"props":1051,"children":1052},{"style":583},[1053],{"type":420,"value":605},{"type":415,"tag":559,"props":1055,"children":1056},{"class":561,"line":677},[1057,1062,1067],{"type":415,"tag":559,"props":1058,"children":1059},{"style":572},[1060],{"type":420,"value":1061},"    EventFormat",{"type":415,"tag":559,"props":1063,"children":1064},{"style":572},[1065],{"type":420,"value":1066}," EventFormat",{"type":415,"tag":559,"props":1068,"children":1069},{"style":583},[1070],{"type":420,"value":605},{"type":415,"tag":559,"props":1072,"children":1073},{"class":561,"line":690},[1074,1078,1083],{"type":415,"tag":559,"props":1075,"children":1076},{"style":583},[1077],{"type":420,"value":595},{"type":415,"tag":559,"props":1079,"children":1080},{"style":572},[1081],{"type":420,"value":1082}," Country",{"type":415,"tag":559,"props":1084,"children":1085},{"style":583},[1086],{"type":420,"value":605},{"type":415,"tag":559,"props":1088,"children":1090},{"class":561,"line":1089},9,[1091,1095],{"type":415,"tag":559,"props":1092,"children":1093},{"style":583},[1094],{"type":420,"value":595},{"type":415,"tag":559,"props":1096,"children":1097},{"style":572},[1098],{"type":420,"value":1099}," City\n",{"type":415,"tag":559,"props":1101,"children":1103},{"class":561,"line":1102},10,[1104],{"type":415,"tag":559,"props":1105,"children":1106},{"style":583},[1107],{"type":420,"value":833},{"type":415,"tag":559,"props":1109,"children":1111},{"class":561,"line":1110},11,[1112],{"type":415,"tag":559,"props":1113,"children":1114},{"style":583},[1115],{"type":420,"value":786},{"type":415,"tag":559,"props":1117,"children":1119},{"class":561,"line":1118},12,[1120,1125,1130,1135,1140,1145,1150,1155,1160,1164],{"type":415,"tag":559,"props":1121,"children":1122},{"style":566},[1123],{"type":420,"value":1124},"    public",{"type":415,"tag":559,"props":1126,"children":1127},{"style":583},[1128],{"type":420,"value":1129}," string",{"type":415,"tag":559,"props":1131,"children":1132},{"style":583},[1133],{"type":420,"value":1134},"?",{"type":415,"tag":559,"props":1136,"children":1137},{"style":572},[1138],{"type":420,"value":1139}," TwitterHandle",{"type":415,"tag":559,"props":1141,"children":1142},{"style":583},[1143],{"type":420,"value":1144}," {",{"type":415,"tag":559,"props":1146,"children":1147},{"style":572},[1148],{"type":420,"value":1149}," get",{"type":415,"tag":559,"props":1151,"children":1152},{"style":583},[1153],{"type":420,"value":1154},";",{"type":415,"tag":559,"props":1156,"children":1157},{"style":572},[1158],{"type":420,"value":1159}," set",{"type":415,"tag":559,"props":1161,"children":1162},{"style":583},[1163],{"type":420,"value":1154},{"type":415,"tag":559,"props":1165,"children":1166},{"style":583},[1167],{"type":420,"value":1168}," }\n",{"type":415,"tag":559,"props":1170,"children":1172},{"class":561,"line":1171},13,[1173],{"type":415,"tag":559,"props":1174,"children":1175},{"style":583},[1176],{"type":420,"value":841},{"type":415,"tag":1178,"props":1179,"children":1181},"callout",{"icon":1180},"i-heroicons-chat-bubble-left-20-solid",[1182],{"type":415,"tag":416,"props":1183,"children":1184},{},[1185],{"type":420,"value":1186},"Positional parameters in a record are init-only. As I want to set the Twitter URL after the event has been created, I use a read-write property for it.",{"type":415,"tag":416,"props":1188,"children":1189},{},[1190,1192,1197,1199,1205],{"type":420,"value":1191},"We can write a method to convert a ",{"type":415,"tag":555,"props":1193,"children":1195},{"className":1194},[],[1196],{"type":420,"value":896},{"type":420,"value":1198}," to a ",{"type":415,"tag":555,"props":1200,"children":1202},{"className":1201},[],[1203],{"type":420,"value":1204},"TechCommunityCalendarEvent",{"type":420,"value":1206},":",{"type":415,"tag":549,"props":1208,"children":1210},{"className":551,"code":1209,"language":326,"meta":401,"style":401},"TechCommunityCalendarEvent ConvertToTechEvent(DeveloperEvent developerEvent)\n{\n    var startingDate = DateTimeOffset.FromUnixTimeMilliseconds(developerEvent.Date.First());\n    var endingDate = DateTimeOffset.FromUnixTimeMilliseconds(developerEvent.Date.Last());\n    var eventNameContainsYear = int.TryParse(developerEvent.Name.Split(\" \").LastOrDefault(), out var year) \n                                && year == startingDate.Year;\n    return new TechCommunityCalendarEvent(\n        eventNameContainsYear ? developerEvent.Name : $\"{developerEvent.Name} {startingDate.Year}\",\n        developerEvent.Hyperlink,\n        startingDate,\n        endingDate,\n        EventType.Conference,\n        developerEvent.Country is \"Online\" ? EventFormat.Virtual : EventFormat.In_Person,\n        developerEvent.Country,\n        developerEvent.City\n    );\n}\n",[1211],{"type":415,"tag":555,"props":1212,"children":1213},{"__ignoreMap":401},[1214,1243,1250,1313,1370,1474,1510,1530,1607,1628,1640,1652,1673,1746,1767,1784,1793],{"type":415,"tag":559,"props":1215,"children":1216},{"class":561,"line":562},[1217,1221,1226,1230,1234,1239],{"type":415,"tag":559,"props":1218,"children":1219},{"style":572},[1220],{"type":420,"value":1204},{"type":415,"tag":559,"props":1222,"children":1223},{"style":883},[1224],{"type":420,"value":1225}," ConvertToTechEvent",{"type":415,"tag":559,"props":1227,"children":1228},{"style":583},[1229],{"type":420,"value":814},{"type":415,"tag":559,"props":1231,"children":1232},{"style":572},[1233],{"type":420,"value":896},{"type":415,"tag":559,"props":1235,"children":1236},{"style":572},[1237],{"type":420,"value":1238}," developerEvent",{"type":415,"tag":559,"props":1240,"children":1241},{"style":583},[1242],{"type":420,"value":833},{"type":415,"tag":559,"props":1244,"children":1245},{"class":561,"line":589},[1246],{"type":415,"tag":559,"props":1247,"children":1248},{"style":583},[1249],{"type":420,"value":786},{"type":415,"tag":559,"props":1251,"children":1252},{"class":561,"line":608},[1253,1258,1263,1267,1272,1276,1281,1285,1290,1294,1299,1303,1308],{"type":415,"tag":559,"props":1254,"children":1255},{"style":572},[1256],{"type":420,"value":1257},"    var",{"type":415,"tag":559,"props":1259,"children":1260},{"style":572},[1261],{"type":420,"value":1262}," startingDate",{"type":415,"tag":559,"props":1264,"children":1265},{"style":583},[1266],{"type":420,"value":763},{"type":415,"tag":559,"props":1268,"children":1269},{"style":792},[1270],{"type":420,"value":1271}," DateTimeOffset",{"type":415,"tag":559,"props":1273,"children":1274},{"style":583},[1275],{"type":420,"value":542},{"type":415,"tag":559,"props":1277,"children":1278},{"style":883},[1279],{"type":420,"value":1280},"FromUnixTimeMilliseconds",{"type":415,"tag":559,"props":1282,"children":1283},{"style":583},[1284],{"type":420,"value":814},{"type":415,"tag":559,"props":1286,"children":1287},{"style":792},[1288],{"type":420,"value":1289},"developerEvent",{"type":415,"tag":559,"props":1291,"children":1292},{"style":583},[1293],{"type":420,"value":542},{"type":415,"tag":559,"props":1295,"children":1296},{"style":792},[1297],{"type":420,"value":1298},"Date",{"type":415,"tag":559,"props":1300,"children":1301},{"style":583},[1302],{"type":420,"value":542},{"type":415,"tag":559,"props":1304,"children":1305},{"style":883},[1306],{"type":420,"value":1307},"First",{"type":415,"tag":559,"props":1309,"children":1310},{"style":583},[1311],{"type":420,"value":1312},"());\n",{"type":415,"tag":559,"props":1314,"children":1315},{"class":561,"line":626},[1316,1320,1325,1329,1333,1337,1341,1345,1349,1353,1357,1361,1366],{"type":415,"tag":559,"props":1317,"children":1318},{"style":572},[1319],{"type":420,"value":1257},{"type":415,"tag":559,"props":1321,"children":1322},{"style":572},[1323],{"type":420,"value":1324}," endingDate",{"type":415,"tag":559,"props":1326,"children":1327},{"style":583},[1328],{"type":420,"value":763},{"type":415,"tag":559,"props":1330,"children":1331},{"style":792},[1332],{"type":420,"value":1271},{"type":415,"tag":559,"props":1334,"children":1335},{"style":583},[1336],{"type":420,"value":542},{"type":415,"tag":559,"props":1338,"children":1339},{"style":883},[1340],{"type":420,"value":1280},{"type":415,"tag":559,"props":1342,"children":1343},{"style":583},[1344],{"type":420,"value":814},{"type":415,"tag":559,"props":1346,"children":1347},{"style":792},[1348],{"type":420,"value":1289},{"type":415,"tag":559,"props":1350,"children":1351},{"style":583},[1352],{"type":420,"value":542},{"type":415,"tag":559,"props":1354,"children":1355},{"style":792},[1356],{"type":420,"value":1298},{"type":415,"tag":559,"props":1358,"children":1359},{"style":583},[1360],{"type":420,"value":542},{"type":415,"tag":559,"props":1362,"children":1363},{"style":883},[1364],{"type":420,"value":1365},"Last",{"type":415,"tag":559,"props":1367,"children":1368},{"style":583},[1369],{"type":420,"value":1312},{"type":415,"tag":559,"props":1371,"children":1372},{"class":561,"line":643},[1373,1377,1382,1386,1391,1396,1400,1404,1408,1413,1417,1422,1426,1430,1435,1440,1445,1450,1455,1459,1464,1469],{"type":415,"tag":559,"props":1374,"children":1375},{"style":572},[1376],{"type":420,"value":1257},{"type":415,"tag":559,"props":1378,"children":1379},{"style":572},[1380],{"type":420,"value":1381}," eventNameContainsYear",{"type":415,"tag":559,"props":1383,"children":1384},{"style":583},[1385],{"type":420,"value":763},{"type":415,"tag":559,"props":1387,"children":1388},{"style":583},[1389],{"type":420,"value":1390}," int.",{"type":415,"tag":559,"props":1392,"children":1393},{"style":883},[1394],{"type":420,"value":1395},"TryParse",{"type":415,"tag":559,"props":1397,"children":1398},{"style":583},[1399],{"type":420,"value":814},{"type":415,"tag":559,"props":1401,"children":1402},{"style":792},[1403],{"type":420,"value":1289},{"type":415,"tag":559,"props":1405,"children":1406},{"style":583},[1407],{"type":420,"value":542},{"type":415,"tag":559,"props":1409,"children":1410},{"style":792},[1411],{"type":420,"value":1412},"Name",{"type":415,"tag":559,"props":1414,"children":1415},{"style":583},[1416],{"type":420,"value":542},{"type":415,"tag":559,"props":1418,"children":1419},{"style":883},[1420],{"type":420,"value":1421},"Split",{"type":415,"tag":559,"props":1423,"children":1424},{"style":583},[1425],{"type":420,"value":814},{"type":415,"tag":559,"props":1427,"children":1428},{"style":583},[1429],{"type":420,"value":819},{"type":415,"tag":559,"props":1431,"children":1432},{"style":583},[1433],{"type":420,"value":1434}," \"",{"type":415,"tag":559,"props":1436,"children":1437},{"style":583},[1438],{"type":420,"value":1439},").",{"type":415,"tag":559,"props":1441,"children":1442},{"style":883},[1443],{"type":420,"value":1444},"LastOrDefault",{"type":415,"tag":559,"props":1446,"children":1447},{"style":583},[1448],{"type":420,"value":1449},"(),",{"type":415,"tag":559,"props":1451,"children":1452},{"style":566},[1453],{"type":420,"value":1454}," out",{"type":415,"tag":559,"props":1456,"children":1457},{"style":572},[1458],{"type":420,"value":753},{"type":415,"tag":559,"props":1460,"children":1461},{"style":572},[1462],{"type":420,"value":1463}," year",{"type":415,"tag":559,"props":1465,"children":1466},{"style":583},[1467],{"type":420,"value":1468},")",{"type":415,"tag":559,"props":1470,"children":1471},{"style":792},[1472],{"type":420,"value":1473}," \n",{"type":415,"tag":559,"props":1475,"children":1476},{"class":561,"line":660},[1477,1482,1487,1492,1496,1500,1505],{"type":415,"tag":559,"props":1478,"children":1479},{"style":583},[1480],{"type":420,"value":1481},"                                &&",{"type":415,"tag":559,"props":1483,"children":1484},{"style":792},[1485],{"type":420,"value":1486}," year ",{"type":415,"tag":559,"props":1488,"children":1489},{"style":583},[1490],{"type":420,"value":1491},"==",{"type":415,"tag":559,"props":1493,"children":1494},{"style":792},[1495],{"type":420,"value":1262},{"type":415,"tag":559,"props":1497,"children":1498},{"style":583},[1499],{"type":420,"value":542},{"type":415,"tag":559,"props":1501,"children":1502},{"style":792},[1503],{"type":420,"value":1504},"Year",{"type":415,"tag":559,"props":1506,"children":1507},{"style":583},[1508],{"type":420,"value":1509},";\n",{"type":415,"tag":559,"props":1511,"children":1512},{"class":561,"line":677},[1513,1518,1522,1526],{"type":415,"tag":559,"props":1514,"children":1515},{"style":745},[1516],{"type":420,"value":1517},"    return",{"type":415,"tag":559,"props":1519,"children":1520},{"style":583},[1521],{"type":420,"value":768},{"type":415,"tag":559,"props":1523,"children":1524},{"style":572},[1525],{"type":420,"value":968},{"type":415,"tag":559,"props":1527,"children":1528},{"style":583},[1529],{"type":420,"value":586},{"type":415,"tag":559,"props":1531,"children":1532},{"class":561,"line":690},[1533,1538,1542,1546,1550,1555,1559,1564,1568,1572,1576,1581,1585,1590,1594,1598,1603],{"type":415,"tag":559,"props":1534,"children":1535},{"style":792},[1536],{"type":420,"value":1537},"        eventNameContainsYear ",{"type":415,"tag":559,"props":1539,"children":1540},{"style":583},[1541],{"type":420,"value":1134},{"type":415,"tag":559,"props":1543,"children":1544},{"style":792},[1545],{"type":420,"value":1238},{"type":415,"tag":559,"props":1547,"children":1548},{"style":583},[1549],{"type":420,"value":542},{"type":415,"tag":559,"props":1551,"children":1552},{"style":792},[1553],{"type":420,"value":1554},"Name ",{"type":415,"tag":559,"props":1556,"children":1557},{"style":583},[1558],{"type":420,"value":1206},{"type":415,"tag":559,"props":1560,"children":1561},{"style":583},[1562],{"type":420,"value":1563}," $\"{",{"type":415,"tag":559,"props":1565,"children":1566},{"style":792},[1567],{"type":420,"value":1289},{"type":415,"tag":559,"props":1569,"children":1570},{"style":583},[1571],{"type":420,"value":542},{"type":415,"tag":559,"props":1573,"children":1574},{"style":792},[1575],{"type":420,"value":1412},{"type":415,"tag":559,"props":1577,"children":1578},{"style":583},[1579],{"type":420,"value":1580},"}",{"type":415,"tag":559,"props":1582,"children":1583},{"style":583},[1584],{"type":420,"value":1144},{"type":415,"tag":559,"props":1586,"children":1587},{"style":792},[1588],{"type":420,"value":1589},"startingDate",{"type":415,"tag":559,"props":1591,"children":1592},{"style":583},[1593],{"type":420,"value":542},{"type":415,"tag":559,"props":1595,"children":1596},{"style":792},[1597],{"type":420,"value":1504},{"type":415,"tag":559,"props":1599,"children":1600},{"style":583},[1601],{"type":420,"value":1602},"}\"",{"type":415,"tag":559,"props":1604,"children":1605},{"style":583},[1606],{"type":420,"value":605},{"type":415,"tag":559,"props":1608,"children":1609},{"class":561,"line":1089},[1610,1615,1619,1624],{"type":415,"tag":559,"props":1611,"children":1612},{"style":792},[1613],{"type":420,"value":1614},"        developerEvent",{"type":415,"tag":559,"props":1616,"children":1617},{"style":583},[1618],{"type":420,"value":542},{"type":415,"tag":559,"props":1620,"children":1621},{"style":792},[1622],{"type":420,"value":1623},"Hyperlink",{"type":415,"tag":559,"props":1625,"children":1626},{"style":583},[1627],{"type":420,"value":605},{"type":415,"tag":559,"props":1629,"children":1630},{"class":561,"line":1102},[1631,1636],{"type":415,"tag":559,"props":1632,"children":1633},{"style":792},[1634],{"type":420,"value":1635},"        startingDate",{"type":415,"tag":559,"props":1637,"children":1638},{"style":583},[1639],{"type":420,"value":605},{"type":415,"tag":559,"props":1641,"children":1642},{"class":561,"line":1110},[1643,1648],{"type":415,"tag":559,"props":1644,"children":1645},{"style":792},[1646],{"type":420,"value":1647},"        endingDate",{"type":415,"tag":559,"props":1649,"children":1650},{"style":583},[1651],{"type":420,"value":605},{"type":415,"tag":559,"props":1653,"children":1654},{"class":561,"line":1118},[1655,1660,1664,1669],{"type":415,"tag":559,"props":1656,"children":1657},{"style":792},[1658],{"type":420,"value":1659},"        EventType",{"type":415,"tag":559,"props":1661,"children":1662},{"style":583},[1663],{"type":420,"value":542},{"type":415,"tag":559,"props":1665,"children":1666},{"style":792},[1667],{"type":420,"value":1668},"Conference",{"type":415,"tag":559,"props":1670,"children":1671},{"style":583},[1672],{"type":420,"value":605},{"type":415,"tag":559,"props":1674,"children":1675},{"class":561,"line":1171},[1676,1680,1684,1689,1694,1698,1703,1707,1712,1716,1720,1725,1729,1733,1737,1742],{"type":415,"tag":559,"props":1677,"children":1678},{"style":792},[1679],{"type":420,"value":1614},{"type":415,"tag":559,"props":1681,"children":1682},{"style":583},[1683],{"type":420,"value":542},{"type":415,"tag":559,"props":1685,"children":1686},{"style":792},[1687],{"type":420,"value":1688},"Country ",{"type":415,"tag":559,"props":1690,"children":1691},{"style":583},[1692],{"type":420,"value":1693},"is",{"type":415,"tag":559,"props":1695,"children":1696},{"style":583},[1697],{"type":420,"value":1434},{"type":415,"tag":559,"props":1699,"children":1700},{"style":822},[1701],{"type":420,"value":1702},"Online",{"type":415,"tag":559,"props":1704,"children":1705},{"style":583},[1706],{"type":420,"value":819},{"type":415,"tag":559,"props":1708,"children":1709},{"style":583},[1710],{"type":420,"value":1711}," ?",{"type":415,"tag":559,"props":1713,"children":1714},{"style":792},[1715],{"type":420,"value":1066},{"type":415,"tag":559,"props":1717,"children":1718},{"style":583},[1719],{"type":420,"value":542},{"type":415,"tag":559,"props":1721,"children":1722},{"style":792},[1723],{"type":420,"value":1724},"Virtual ",{"type":415,"tag":559,"props":1726,"children":1727},{"style":583},[1728],{"type":420,"value":1206},{"type":415,"tag":559,"props":1730,"children":1731},{"style":792},[1732],{"type":420,"value":1066},{"type":415,"tag":559,"props":1734,"children":1735},{"style":583},[1736],{"type":420,"value":542},{"type":415,"tag":559,"props":1738,"children":1739},{"style":792},[1740],{"type":420,"value":1741},"In_Person",{"type":415,"tag":559,"props":1743,"children":1744},{"style":583},[1745],{"type":420,"value":605},{"type":415,"tag":559,"props":1747,"children":1749},{"class":561,"line":1748},14,[1750,1754,1758,1763],{"type":415,"tag":559,"props":1751,"children":1752},{"style":792},[1753],{"type":420,"value":1614},{"type":415,"tag":559,"props":1755,"children":1756},{"style":583},[1757],{"type":420,"value":542},{"type":415,"tag":559,"props":1759,"children":1760},{"style":792},[1761],{"type":420,"value":1762},"Country",{"type":415,"tag":559,"props":1764,"children":1765},{"style":583},[1766],{"type":420,"value":605},{"type":415,"tag":559,"props":1768,"children":1770},{"class":561,"line":1769},15,[1771,1775,1779],{"type":415,"tag":559,"props":1772,"children":1773},{"style":792},[1774],{"type":420,"value":1614},{"type":415,"tag":559,"props":1776,"children":1777},{"style":583},[1778],{"type":420,"value":542},{"type":415,"tag":559,"props":1780,"children":1781},{"style":792},[1782],{"type":420,"value":1783},"City\n",{"type":415,"tag":559,"props":1785,"children":1787},{"class":561,"line":1786},16,[1788],{"type":415,"tag":559,"props":1789,"children":1790},{"style":583},[1791],{"type":420,"value":1792},"    );\n",{"type":415,"tag":559,"props":1794,"children":1796},{"class":561,"line":1795},17,[1797],{"type":415,"tag":559,"props":1798,"children":1799},{"style":583},[1800],{"type":420,"value":1801},"}\n",{"type":415,"tag":416,"props":1803,"children":1804},{},[1805],{"type":420,"value":1806},"It allows us to convert all retrieved events after filtering on their date to only keep upcoming events.",{"type":415,"tag":549,"props":1808,"children":1810},{"className":551,"code":1809,"language":326,"meta":401,"style":401},"var upcomingEvents =  events\n    .Where(e => e.Date.FirstOrDefault() > DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())\n    .Select(ConvertToTechEvent)\n    .ToList();\n",[1811],{"type":415,"tag":555,"props":1812,"children":1813},{"__ignoreMap":401},[1814,1835,1921,1946],{"type":415,"tag":559,"props":1815,"children":1816},{"class":561,"line":562},[1817,1821,1826,1830],{"type":415,"tag":559,"props":1818,"children":1819},{"style":572},[1820],{"type":420,"value":858},{"type":415,"tag":559,"props":1822,"children":1823},{"style":572},[1824],{"type":420,"value":1825}," upcomingEvents",{"type":415,"tag":559,"props":1827,"children":1828},{"style":583},[1829],{"type":420,"value":763},{"type":415,"tag":559,"props":1831,"children":1832},{"style":792},[1833],{"type":420,"value":1834},"  events\n",{"type":415,"tag":559,"props":1836,"children":1837},{"class":561,"line":589},[1838,1843,1848,1852,1857,1862,1867,1871,1875,1879,1884,1889,1894,1898,1902,1907,1911,1916],{"type":415,"tag":559,"props":1839,"children":1840},{"style":583},[1841],{"type":420,"value":1842},"    .",{"type":415,"tag":559,"props":1844,"children":1845},{"style":883},[1846],{"type":420,"value":1847},"Where",{"type":415,"tag":559,"props":1849,"children":1850},{"style":583},[1851],{"type":420,"value":814},{"type":415,"tag":559,"props":1853,"children":1854},{"style":572},[1855],{"type":420,"value":1856},"e",{"type":415,"tag":559,"props":1858,"children":1859},{"style":583},[1860],{"type":420,"value":1861}," =>",{"type":415,"tag":559,"props":1863,"children":1864},{"style":792},[1865],{"type":420,"value":1866}," e",{"type":415,"tag":559,"props":1868,"children":1869},{"style":583},[1870],{"type":420,"value":542},{"type":415,"tag":559,"props":1872,"children":1873},{"style":792},[1874],{"type":420,"value":1298},{"type":415,"tag":559,"props":1876,"children":1877},{"style":583},[1878],{"type":420,"value":542},{"type":415,"tag":559,"props":1880,"children":1881},{"style":883},[1882],{"type":420,"value":1883},"FirstOrDefault",{"type":415,"tag":559,"props":1885,"children":1886},{"style":583},[1887],{"type":420,"value":1888},"()",{"type":415,"tag":559,"props":1890,"children":1891},{"style":583},[1892],{"type":420,"value":1893}," >",{"type":415,"tag":559,"props":1895,"children":1896},{"style":792},[1897],{"type":420,"value":1271},{"type":415,"tag":559,"props":1899,"children":1900},{"style":583},[1901],{"type":420,"value":542},{"type":415,"tag":559,"props":1903,"children":1904},{"style":792},[1905],{"type":420,"value":1906},"UtcNow",{"type":415,"tag":559,"props":1908,"children":1909},{"style":583},[1910],{"type":420,"value":542},{"type":415,"tag":559,"props":1912,"children":1913},{"style":883},[1914],{"type":420,"value":1915},"ToUnixTimeMilliseconds",{"type":415,"tag":559,"props":1917,"children":1918},{"style":583},[1919],{"type":420,"value":1920},"())\n",{"type":415,"tag":559,"props":1922,"children":1923},{"class":561,"line":608},[1924,1928,1933,1937,1942],{"type":415,"tag":559,"props":1925,"children":1926},{"style":583},[1927],{"type":420,"value":1842},{"type":415,"tag":559,"props":1929,"children":1930},{"style":883},[1931],{"type":420,"value":1932},"Select",{"type":415,"tag":559,"props":1934,"children":1935},{"style":583},[1936],{"type":420,"value":814},{"type":415,"tag":559,"props":1938,"children":1939},{"style":792},[1940],{"type":420,"value":1941},"ConvertToTechEvent",{"type":415,"tag":559,"props":1943,"children":1944},{"style":583},[1945],{"type":420,"value":833},{"type":415,"tag":559,"props":1947,"children":1948},{"class":561,"line":626},[1949,1953,1958],{"type":415,"tag":559,"props":1950,"children":1951},{"style":583},[1952],{"type":420,"value":1842},{"type":415,"tag":559,"props":1954,"children":1955},{"style":883},[1956],{"type":420,"value":1957},"ToList",{"type":415,"tag":559,"props":1959,"children":1960},{"style":583},[1961],{"type":420,"value":1962},"();\n",{"type":415,"tag":422,"props":1964,"children":1966},{"id":1965},"retrieve-an-event-twitter-profile-link",[1967],{"type":420,"value":1968},"Retrieve An Event Twitter Profile Link",{"type":415,"tag":416,"props":1970,"children":1971},{},[1972],{"type":420,"value":1973},"In the submission form, there's an optional field for entering the Twitter Profile Link of an event. That's not something the events from the developers conferences agenda have but that's interesting data that could be useful to supply. All events have an associated website and most of them contain a link to their Twitter Profile on it.",{"type":415,"tag":416,"props":1975,"children":1976},{},[1977,1979,1985],{"type":420,"value":1978},"This is where a library like ",{"type":415,"tag":434,"props":1980,"children":1983},{"href":1981,"rel":1982},"https://github.com/AngleSharp/AngleSharp",[438],[1984],{"type":420,"value":390},{"type":420,"value":1986},", which can parse HTML according to W3C specifications, becomes useful. Although I have not used this library before, creating a method to find the Twitter URL on an event's webpage is straightforward.",{"type":415,"tag":549,"props":1988,"children":1990},{"className":551,"code":1989,"language":326,"meta":401,"style":401},"async Task\u003Cstring?> RetrieveEventTwitterProfileLink(string eventUrl)\n{\n    var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader());\n    var queryDocument = await context.OpenAsync(eventUrl);\n\n    var twitterSelector = \"a[href*='twitter.com'], a[href*='https://x.com']\";\n    var twitterSocialLink = queryDocument.QuerySelector(twitterSelector)\n        ?.GetAttribute(\"href\");\n\n    return Uri.TryCreate(twitterSocialLink, UriKind.Absolute, out var twitterProfileUri) ?\n        // Normalize X/Twitter profile URL by removing query parameters and fragments\n        $\"{twitterProfileUri.Scheme}://{twitterProfileUri.Host}{twitterProfileUri.AbsolutePath}\" : null;\n}\n",[1991],{"type":415,"tag":555,"props":1992,"children":1993},{"__ignoreMap":401},[1994,2043,2050,2110,2156,2163,2196,2238,2272,2279,2353,2362,2443],{"type":415,"tag":559,"props":1995,"children":1996},{"class":561,"line":562},[1997,2002,2007,2011,2016,2021,2026,2030,2034,2039],{"type":415,"tag":559,"props":1998,"children":1999},{"style":566},[2000],{"type":420,"value":2001},"async",{"type":415,"tag":559,"props":2003,"children":2004},{"style":572},[2005],{"type":420,"value":2006}," Task",{"type":415,"tag":559,"props":2008,"children":2009},{"style":583},[2010],{"type":420,"value":891},{"type":415,"tag":559,"props":2012,"children":2013},{"style":583},[2014],{"type":420,"value":2015},"string",{"type":415,"tag":559,"props":2017,"children":2018},{"style":583},[2019],{"type":420,"value":2020},"?>",{"type":415,"tag":559,"props":2022,"children":2023},{"style":883},[2024],{"type":420,"value":2025}," RetrieveEventTwitterProfileLink",{"type":415,"tag":559,"props":2027,"children":2028},{"style":583},[2029],{"type":420,"value":814},{"type":415,"tag":559,"props":2031,"children":2032},{"style":583},[2033],{"type":420,"value":2015},{"type":415,"tag":559,"props":2035,"children":2036},{"style":572},[2037],{"type":420,"value":2038}," eventUrl",{"type":415,"tag":559,"props":2040,"children":2041},{"style":583},[2042],{"type":420,"value":833},{"type":415,"tag":559,"props":2044,"children":2045},{"class":561,"line":589},[2046],{"type":415,"tag":559,"props":2047,"children":2048},{"style":583},[2049],{"type":420,"value":786},{"type":415,"tag":559,"props":2051,"children":2052},{"class":561,"line":608},[2053,2057,2062,2066,2071,2075,2080,2084,2088,2092,2097,2101,2106],{"type":415,"tag":559,"props":2054,"children":2055},{"style":572},[2056],{"type":420,"value":1257},{"type":415,"tag":559,"props":2058,"children":2059},{"style":572},[2060],{"type":420,"value":2061}," context",{"type":415,"tag":559,"props":2063,"children":2064},{"style":583},[2065],{"type":420,"value":763},{"type":415,"tag":559,"props":2067,"children":2068},{"style":792},[2069],{"type":420,"value":2070}," BrowsingContext",{"type":415,"tag":559,"props":2072,"children":2073},{"style":583},[2074],{"type":420,"value":542},{"type":415,"tag":559,"props":2076,"children":2077},{"style":883},[2078],{"type":420,"value":2079},"New",{"type":415,"tag":559,"props":2081,"children":2082},{"style":583},[2083],{"type":420,"value":814},{"type":415,"tag":559,"props":2085,"children":2086},{"style":792},[2087],{"type":420,"value":263},{"type":415,"tag":559,"props":2089,"children":2090},{"style":583},[2091],{"type":420,"value":542},{"type":415,"tag":559,"props":2093,"children":2094},{"style":792},[2095],{"type":420,"value":2096},"Default",{"type":415,"tag":559,"props":2098,"children":2099},{"style":583},[2100],{"type":420,"value":542},{"type":415,"tag":559,"props":2102,"children":2103},{"style":883},[2104],{"type":420,"value":2105},"WithDefaultLoader",{"type":415,"tag":559,"props":2107,"children":2108},{"style":583},[2109],{"type":420,"value":1312},{"type":415,"tag":559,"props":2111,"children":2112},{"class":561,"line":626},[2113,2117,2122,2126,2130,2134,2138,2143,2147,2152],{"type":415,"tag":559,"props":2114,"children":2115},{"style":572},[2116],{"type":420,"value":1257},{"type":415,"tag":559,"props":2118,"children":2119},{"style":572},[2120],{"type":420,"value":2121}," queryDocument",{"type":415,"tag":559,"props":2123,"children":2124},{"style":583},[2125],{"type":420,"value":763},{"type":415,"tag":559,"props":2127,"children":2128},{"style":583},[2129],{"type":420,"value":872},{"type":415,"tag":559,"props":2131,"children":2132},{"style":792},[2133],{"type":420,"value":2061},{"type":415,"tag":559,"props":2135,"children":2136},{"style":583},[2137],{"type":420,"value":542},{"type":415,"tag":559,"props":2139,"children":2140},{"style":883},[2141],{"type":420,"value":2142},"OpenAsync",{"type":415,"tag":559,"props":2144,"children":2145},{"style":583},[2146],{"type":420,"value":814},{"type":415,"tag":559,"props":2148,"children":2149},{"style":792},[2150],{"type":420,"value":2151},"eventUrl",{"type":415,"tag":559,"props":2153,"children":2154},{"style":583},[2155],{"type":420,"value":696},{"type":415,"tag":559,"props":2157,"children":2158},{"class":561,"line":643},[2159],{"type":415,"tag":559,"props":2160,"children":2161},{"emptyLinePlaceholder":847},[2162],{"type":420,"value":850},{"type":415,"tag":559,"props":2164,"children":2165},{"class":561,"line":660},[2166,2170,2175,2179,2183,2188,2192],{"type":415,"tag":559,"props":2167,"children":2168},{"style":572},[2169],{"type":420,"value":1257},{"type":415,"tag":559,"props":2171,"children":2172},{"style":572},[2173],{"type":420,"value":2174}," twitterSelector",{"type":415,"tag":559,"props":2176,"children":2177},{"style":583},[2178],{"type":420,"value":763},{"type":415,"tag":559,"props":2180,"children":2181},{"style":583},[2182],{"type":420,"value":1434},{"type":415,"tag":559,"props":2184,"children":2185},{"style":822},[2186],{"type":420,"value":2187},"a[href*='twitter.com'], a[href*='https://x.com']",{"type":415,"tag":559,"props":2189,"children":2190},{"style":583},[2191],{"type":420,"value":819},{"type":415,"tag":559,"props":2193,"children":2194},{"style":583},[2195],{"type":420,"value":1509},{"type":415,"tag":559,"props":2197,"children":2198},{"class":561,"line":677},[2199,2203,2208,2212,2216,2220,2225,2229,2234],{"type":415,"tag":559,"props":2200,"children":2201},{"style":572},[2202],{"type":420,"value":1257},{"type":415,"tag":559,"props":2204,"children":2205},{"style":572},[2206],{"type":420,"value":2207}," twitterSocialLink",{"type":415,"tag":559,"props":2209,"children":2210},{"style":583},[2211],{"type":420,"value":763},{"type":415,"tag":559,"props":2213,"children":2214},{"style":792},[2215],{"type":420,"value":2121},{"type":415,"tag":559,"props":2217,"children":2218},{"style":583},[2219],{"type":420,"value":542},{"type":415,"tag":559,"props":2221,"children":2222},{"style":883},[2223],{"type":420,"value":2224},"QuerySelector",{"type":415,"tag":559,"props":2226,"children":2227},{"style":583},[2228],{"type":420,"value":814},{"type":415,"tag":559,"props":2230,"children":2231},{"style":792},[2232],{"type":420,"value":2233},"twitterSelector",{"type":415,"tag":559,"props":2235,"children":2236},{"style":583},[2237],{"type":420,"value":833},{"type":415,"tag":559,"props":2239,"children":2240},{"class":561,"line":690},[2241,2246,2251,2255,2259,2264,2268],{"type":415,"tag":559,"props":2242,"children":2243},{"style":583},[2244],{"type":420,"value":2245},"        ?.",{"type":415,"tag":559,"props":2247,"children":2248},{"style":883},[2249],{"type":420,"value":2250},"GetAttribute",{"type":415,"tag":559,"props":2252,"children":2253},{"style":583},[2254],{"type":420,"value":814},{"type":415,"tag":559,"props":2256,"children":2257},{"style":583},[2258],{"type":420,"value":819},{"type":415,"tag":559,"props":2260,"children":2261},{"style":822},[2262],{"type":420,"value":2263},"href",{"type":415,"tag":559,"props":2265,"children":2266},{"style":583},[2267],{"type":420,"value":819},{"type":415,"tag":559,"props":2269,"children":2270},{"style":583},[2271],{"type":420,"value":696},{"type":415,"tag":559,"props":2273,"children":2274},{"class":561,"line":1089},[2275],{"type":415,"tag":559,"props":2276,"children":2277},{"emptyLinePlaceholder":847},[2278],{"type":420,"value":850},{"type":415,"tag":559,"props":2280,"children":2281},{"class":561,"line":1102},[2282,2286,2290,2294,2299,2303,2308,2313,2318,2322,2327,2331,2335,2339,2344,2348],{"type":415,"tag":559,"props":2283,"children":2284},{"style":745},[2285],{"type":420,"value":1517},{"type":415,"tag":559,"props":2287,"children":2288},{"style":792},[2289],{"type":420,"value":809},{"type":415,"tag":559,"props":2291,"children":2292},{"style":583},[2293],{"type":420,"value":542},{"type":415,"tag":559,"props":2295,"children":2296},{"style":883},[2297],{"type":420,"value":2298},"TryCreate",{"type":415,"tag":559,"props":2300,"children":2301},{"style":583},[2302],{"type":420,"value":814},{"type":415,"tag":559,"props":2304,"children":2305},{"style":792},[2306],{"type":420,"value":2307},"twitterSocialLink",{"type":415,"tag":559,"props":2309,"children":2310},{"style":583},[2311],{"type":420,"value":2312},",",{"type":415,"tag":559,"props":2314,"children":2315},{"style":792},[2316],{"type":420,"value":2317}," UriKind",{"type":415,"tag":559,"props":2319,"children":2320},{"style":583},[2321],{"type":420,"value":542},{"type":415,"tag":559,"props":2323,"children":2324},{"style":792},[2325],{"type":420,"value":2326},"Absolute",{"type":415,"tag":559,"props":2328,"children":2329},{"style":583},[2330],{"type":420,"value":2312},{"type":415,"tag":559,"props":2332,"children":2333},{"style":566},[2334],{"type":420,"value":1454},{"type":415,"tag":559,"props":2336,"children":2337},{"style":572},[2338],{"type":420,"value":753},{"type":415,"tag":559,"props":2340,"children":2341},{"style":572},[2342],{"type":420,"value":2343}," twitterProfileUri",{"type":415,"tag":559,"props":2345,"children":2346},{"style":583},[2347],{"type":420,"value":1468},{"type":415,"tag":559,"props":2349,"children":2350},{"style":583},[2351],{"type":420,"value":2352}," ?\n",{"type":415,"tag":559,"props":2354,"children":2355},{"class":561,"line":1110},[2356],{"type":415,"tag":559,"props":2357,"children":2359},{"style":2358},"--shiki-light:#90A4AE;--shiki-default:#546E7A;--shiki-dark:#676E95;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[2360],{"type":420,"value":2361},"        // Normalize X/Twitter profile URL by removing query parameters and fragments\n",{"type":415,"tag":559,"props":2363,"children":2364},{"class":561,"line":1118},[2365,2370,2375,2379,2384,2388,2393,2398,2402,2406,2411,2416,2420,2424,2429,2433,2438],{"type":415,"tag":559,"props":2366,"children":2367},{"style":583},[2368],{"type":420,"value":2369},"        $\"{",{"type":415,"tag":559,"props":2371,"children":2372},{"style":792},[2373],{"type":420,"value":2374},"twitterProfileUri",{"type":415,"tag":559,"props":2376,"children":2377},{"style":583},[2378],{"type":420,"value":542},{"type":415,"tag":559,"props":2380,"children":2381},{"style":792},[2382],{"type":420,"value":2383},"Scheme",{"type":415,"tag":559,"props":2385,"children":2386},{"style":583},[2387],{"type":420,"value":1580},{"type":415,"tag":559,"props":2389,"children":2390},{"style":822},[2391],{"type":420,"value":2392},"://",{"type":415,"tag":559,"props":2394,"children":2395},{"style":583},[2396],{"type":420,"value":2397},"{",{"type":415,"tag":559,"props":2399,"children":2400},{"style":792},[2401],{"type":420,"value":2374},{"type":415,"tag":559,"props":2403,"children":2404},{"style":583},[2405],{"type":420,"value":542},{"type":415,"tag":559,"props":2407,"children":2408},{"style":792},[2409],{"type":420,"value":2410},"Host",{"type":415,"tag":559,"props":2412,"children":2413},{"style":583},[2414],{"type":420,"value":2415},"}{",{"type":415,"tag":559,"props":2417,"children":2418},{"style":792},[2419],{"type":420,"value":2374},{"type":415,"tag":559,"props":2421,"children":2422},{"style":583},[2423],{"type":420,"value":542},{"type":415,"tag":559,"props":2425,"children":2426},{"style":792},[2427],{"type":420,"value":2428},"AbsolutePath",{"type":415,"tag":559,"props":2430,"children":2431},{"style":583},[2432],{"type":420,"value":1602},{"type":415,"tag":559,"props":2434,"children":2435},{"style":583},[2436],{"type":420,"value":2437}," :",{"type":415,"tag":559,"props":2439,"children":2440},{"style":583},[2441],{"type":420,"value":2442}," null;\n",{"type":415,"tag":559,"props":2444,"children":2445},{"class":561,"line":1171},[2446],{"type":415,"tag":559,"props":2447,"children":2448},{"style":583},[2449],{"type":420,"value":1801},{"type":415,"tag":1178,"props":2451,"children":2452},{"icon":1180},[2453],{"type":415,"tag":416,"props":2454,"children":2455},{},[2456,2458,2464],{"type":420,"value":2457},"As the DOM API exposed follows the W3C specifications, it is very convenient. If you can retrieve something with ",{"type":415,"tag":555,"props":2459,"children":2461},{"className":2460},[],[2462],{"type":420,"value":2463},"document.querySelector",{"type":420,"value":2465}," in your browser console, you will be able to retrieve it using the same selector in your AngleSharp code.",{"type":415,"tag":422,"props":2467,"children":2469},{"id":2468},"submit-an-event",[2470],{"type":420,"value":2471},"Submit An Event",{"type":415,"tag":416,"props":2473,"children":2474},{},[2475,2477,2483],{"type":420,"value":2476},"Submitting forms is also possible using AngleSharp. We first have to retrieve the form element in the HTML document using the query sector ",{"type":415,"tag":555,"props":2478,"children":2480},{"className":2479},[],[2481],{"type":420,"value":2482},"form[action=\"/addevent/\"]",{"type":420,"value":2484},". Then we can directly submit the event.",{"type":415,"tag":549,"props":2486,"children":2488},{"className":551,"code":2487,"language":326,"meta":401,"style":401},"async Task SubmitEventToTechCommunityCalendar(TechCommunityCalendarEvent techCommunityCalendarEvent)\n{\n    var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader());\n    var queryDocument = await context.OpenAsync(\"https://techcommunitycalendar.com/addevent/\");\n    var form = queryDocument.QuerySelector\u003CIHtmlFormElement>(\"\"\"form[action=\"/addevent/\"]\"\"\");\n    if (form is not null)\n    {\n        var response = await form.SubmitAsync(techCommunityCalendarEvent);\n    }\n}\n",[2489],{"type":415,"tag":555,"props":2490,"children":2491},{"__ignoreMap":401},[2492,2525,2532,2587,2639,2698,2730,2738,2785,2793],{"type":415,"tag":559,"props":2493,"children":2494},{"class":561,"line":562},[2495,2499,2503,2508,2512,2516,2521],{"type":415,"tag":559,"props":2496,"children":2497},{"style":566},[2498],{"type":420,"value":2001},{"type":415,"tag":559,"props":2500,"children":2501},{"style":572},[2502],{"type":420,"value":2006},{"type":415,"tag":559,"props":2504,"children":2505},{"style":883},[2506],{"type":420,"value":2507}," SubmitEventToTechCommunityCalendar",{"type":415,"tag":559,"props":2509,"children":2510},{"style":583},[2511],{"type":420,"value":814},{"type":415,"tag":559,"props":2513,"children":2514},{"style":572},[2515],{"type":420,"value":1204},{"type":415,"tag":559,"props":2517,"children":2518},{"style":572},[2519],{"type":420,"value":2520}," techCommunityCalendarEvent",{"type":415,"tag":559,"props":2522,"children":2523},{"style":583},[2524],{"type":420,"value":833},{"type":415,"tag":559,"props":2526,"children":2527},{"class":561,"line":589},[2528],{"type":415,"tag":559,"props":2529,"children":2530},{"style":583},[2531],{"type":420,"value":786},{"type":415,"tag":559,"props":2533,"children":2534},{"class":561,"line":608},[2535,2539,2543,2547,2551,2555,2559,2563,2567,2571,2575,2579,2583],{"type":415,"tag":559,"props":2536,"children":2537},{"style":572},[2538],{"type":420,"value":1257},{"type":415,"tag":559,"props":2540,"children":2541},{"style":572},[2542],{"type":420,"value":2061},{"type":415,"tag":559,"props":2544,"children":2545},{"style":583},[2546],{"type":420,"value":763},{"type":415,"tag":559,"props":2548,"children":2549},{"style":792},[2550],{"type":420,"value":2070},{"type":415,"tag":559,"props":2552,"children":2553},{"style":583},[2554],{"type":420,"value":542},{"type":415,"tag":559,"props":2556,"children":2557},{"style":883},[2558],{"type":420,"value":2079},{"type":415,"tag":559,"props":2560,"children":2561},{"style":583},[2562],{"type":420,"value":814},{"type":415,"tag":559,"props":2564,"children":2565},{"style":792},[2566],{"type":420,"value":263},{"type":415,"tag":559,"props":2568,"children":2569},{"style":583},[2570],{"type":420,"value":542},{"type":415,"tag":559,"props":2572,"children":2573},{"style":792},[2574],{"type":420,"value":2096},{"type":415,"tag":559,"props":2576,"children":2577},{"style":583},[2578],{"type":420,"value":542},{"type":415,"tag":559,"props":2580,"children":2581},{"style":883},[2582],{"type":420,"value":2105},{"type":415,"tag":559,"props":2584,"children":2585},{"style":583},[2586],{"type":420,"value":1312},{"type":415,"tag":559,"props":2588,"children":2589},{"class":561,"line":626},[2590,2594,2598,2602,2606,2610,2614,2618,2622,2626,2631,2635],{"type":415,"tag":559,"props":2591,"children":2592},{"style":572},[2593],{"type":420,"value":1257},{"type":415,"tag":559,"props":2595,"children":2596},{"style":572},[2597],{"type":420,"value":2121},{"type":415,"tag":559,"props":2599,"children":2600},{"style":583},[2601],{"type":420,"value":763},{"type":415,"tag":559,"props":2603,"children":2604},{"style":583},[2605],{"type":420,"value":872},{"type":415,"tag":559,"props":2607,"children":2608},{"style":792},[2609],{"type":420,"value":2061},{"type":415,"tag":559,"props":2611,"children":2612},{"style":583},[2613],{"type":420,"value":542},{"type":415,"tag":559,"props":2615,"children":2616},{"style":883},[2617],{"type":420,"value":2142},{"type":415,"tag":559,"props":2619,"children":2620},{"style":583},[2621],{"type":420,"value":814},{"type":415,"tag":559,"props":2623,"children":2624},{"style":583},[2625],{"type":420,"value":819},{"type":415,"tag":559,"props":2627,"children":2628},{"style":822},[2629],{"type":420,"value":2630},"https://techcommunitycalendar.com/addevent/",{"type":415,"tag":559,"props":2632,"children":2633},{"style":583},[2634],{"type":420,"value":819},{"type":415,"tag":559,"props":2636,"children":2637},{"style":583},[2638],{"type":420,"value":696},{"type":415,"tag":559,"props":2640,"children":2641},{"class":561,"line":643},[2642,2646,2651,2655,2659,2663,2667,2671,2676,2681,2686,2690,2694],{"type":415,"tag":559,"props":2643,"children":2644},{"style":572},[2645],{"type":420,"value":1257},{"type":415,"tag":559,"props":2647,"children":2648},{"style":572},[2649],{"type":420,"value":2650}," form",{"type":415,"tag":559,"props":2652,"children":2653},{"style":583},[2654],{"type":420,"value":763},{"type":415,"tag":559,"props":2656,"children":2657},{"style":792},[2658],{"type":420,"value":2121},{"type":415,"tag":559,"props":2660,"children":2661},{"style":583},[2662],{"type":420,"value":542},{"type":415,"tag":559,"props":2664,"children":2665},{"style":883},[2666],{"type":420,"value":2224},{"type":415,"tag":559,"props":2668,"children":2669},{"style":583},[2670],{"type":420,"value":891},{"type":415,"tag":559,"props":2672,"children":2673},{"style":572},[2674],{"type":420,"value":2675},"IHtmlFormElement",{"type":415,"tag":559,"props":2677,"children":2678},{"style":583},[2679],{"type":420,"value":2680},">(",{"type":415,"tag":559,"props":2682,"children":2683},{"style":583},[2684],{"type":420,"value":2685},"\"\"\"",{"type":415,"tag":559,"props":2687,"children":2688},{"style":822},[2689],{"type":420,"value":2482},{"type":415,"tag":559,"props":2691,"children":2692},{"style":583},[2693],{"type":420,"value":2685},{"type":415,"tag":559,"props":2695,"children":2696},{"style":583},[2697],{"type":420,"value":696},{"type":415,"tag":559,"props":2699,"children":2700},{"class":561,"line":660},[2701,2706,2711,2716,2720,2725],{"type":415,"tag":559,"props":2702,"children":2703},{"style":745},[2704],{"type":420,"value":2705},"    if",{"type":415,"tag":559,"props":2707,"children":2708},{"style":583},[2709],{"type":420,"value":2710}," (",{"type":415,"tag":559,"props":2712,"children":2713},{"style":792},[2714],{"type":420,"value":2715},"form ",{"type":415,"tag":559,"props":2717,"children":2718},{"style":583},[2719],{"type":420,"value":1693},{"type":415,"tag":559,"props":2721,"children":2722},{"style":583},[2723],{"type":420,"value":2724}," not",{"type":415,"tag":559,"props":2726,"children":2727},{"style":583},[2728],{"type":420,"value":2729}," null)\n",{"type":415,"tag":559,"props":2731,"children":2732},{"class":561,"line":677},[2733],{"type":415,"tag":559,"props":2734,"children":2735},{"style":583},[2736],{"type":420,"value":2737},"    {\n",{"type":415,"tag":559,"props":2739,"children":2740},{"class":561,"line":690},[2741,2746,2751,2755,2759,2763,2767,2772,2776,2781],{"type":415,"tag":559,"props":2742,"children":2743},{"style":572},[2744],{"type":420,"value":2745},"        var",{"type":415,"tag":559,"props":2747,"children":2748},{"style":572},[2749],{"type":420,"value":2750}," response",{"type":415,"tag":559,"props":2752,"children":2753},{"style":583},[2754],{"type":420,"value":763},{"type":415,"tag":559,"props":2756,"children":2757},{"style":583},[2758],{"type":420,"value":872},{"type":415,"tag":559,"props":2760,"children":2761},{"style":792},[2762],{"type":420,"value":2650},{"type":415,"tag":559,"props":2764,"children":2765},{"style":583},[2766],{"type":420,"value":542},{"type":415,"tag":559,"props":2768,"children":2769},{"style":883},[2770],{"type":420,"value":2771},"SubmitAsync",{"type":415,"tag":559,"props":2773,"children":2774},{"style":583},[2775],{"type":420,"value":814},{"type":415,"tag":559,"props":2777,"children":2778},{"style":792},[2779],{"type":420,"value":2780},"techCommunityCalendarEvent",{"type":415,"tag":559,"props":2782,"children":2783},{"style":583},[2784],{"type":420,"value":696},{"type":415,"tag":559,"props":2786,"children":2787},{"class":561,"line":1089},[2788],{"type":415,"tag":559,"props":2789,"children":2790},{"style":583},[2791],{"type":420,"value":2792},"    }\n",{"type":415,"tag":559,"props":2794,"children":2795},{"class":561,"line":1102},[2796],{"type":415,"tag":559,"props":2797,"children":2798},{"style":583},[2799],{"type":420,"value":1801},{"type":415,"tag":1178,"props":2801,"children":2802},{"icon":1180},[2803],{"type":415,"tag":416,"props":2804,"children":2805},{},[2806,2808,2813],{"type":420,"value":2807},"I intentionally named the properties in the ",{"type":415,"tag":555,"props":2809,"children":2811},{"className":2810},[],[2812],{"type":420,"value":1204},{"type":420,"value":2814}," record with the same names as the fields in the form. This way, I can directly submit the event without any transformation. Otherwise, I would have to convert the event to an anonymous object with the correct names.",{"type":415,"tag":422,"props":2816,"children":2818},{"id":2817},"the-full-program",[2819],{"type":420,"value":2820},"The Full Program",{"type":415,"tag":416,"props":2822,"children":2823},{},[2824,2826,2832],{"type":420,"value":2825},"Here is the content of the complete ",{"type":415,"tag":555,"props":2827,"children":2829},{"className":2828},[],[2830],{"type":420,"value":2831},"Program.cs",{"type":420,"value":2833}," file.",{"type":415,"tag":549,"props":2835,"children":2837},{"className":551,"code":2836,"filename":2831,"language":326,"meta":401,"style":401},"using System.Net.Http.Json;\nusing AngleSharp;\nusing AngleSharp.Dom;\nusing AngleSharp.Html.Dom;\n\nusing var httpClient = new HttpClient()\n{\n    BaseAddress = new Uri(\"https://developers.events/\")\n};\n\nvar events = await httpClient.GetFromJsonAsync\u003CDeveloperEvent[]>(\"all-events.json\");\nvar upcomingEvents =  events\n    .Where(e => e.Date.FirstOrDefault() > DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())\n    .Select(ConvertToTechEvent)\n    .ToList();\n\nforeach (var upcomingEvent in upcomingEvents)\n{\n    upcomingEvent.TwitterHandle = await RetrieveEventTwitterProfileLink(upcomingEvent.Url);\n    await SubmitEventToTechCommunityCalendar(upcomingEvent);\n}\n\nasync Task\u003Cstring?> RetrieveEventTwitterProfileLink(string eventUrl)\n{\n    var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader());\n    var queryDocument = await context.OpenAsync(eventUrl);\n\n    var twitterSelector = \"a[href*='twitter.com'], a[href*='https://x.com']\";\n    var twitterSocialLink = queryDocument.QuerySelector(twitterSelector)\n        ?.GetAttribute(\"href\");\n\n    return Uri.TryCreate(twitterSocialLink, UriKind.Absolute, out var twitterProfileUri) ?\n        // Normalize X/Twitter profile URL by removing query parameters and fragments\n        $\"{twitterProfileUri.Scheme}://{twitterProfileUri.Host}{twitterProfileUri.AbsolutePath}\" : null;\n}\n\nasync Task SubmitEventToTechCommunityCalendar(TechCommunityCalendarEvent techCommunityCalendarEvent)\n{\n    var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader());\n    var queryDocument = await context.OpenAsync(\"https://techcommunitycalendar.com/addevent/\");\n    var form = queryDocument.QuerySelector\u003CIHtmlFormElement>(\"\"\"form[action=\"/addevent/\"]\"\"\");\n    if (form is not null)\n    {\n        var response = await form.SubmitAsync(techCommunityCalendarEvent);\n    }\n}\n\nTechCommunityCalendarEvent ConvertToTechEvent(DeveloperEvent developerEvent)\n{\n    var startingDate = DateTimeOffset.FromUnixTimeMilliseconds(developerEvent.Date.First());\n    var endingDate = DateTimeOffset.FromUnixTimeMilliseconds(developerEvent.Date.Last());\n    var eventNameContainsYear = int.TryParse(developerEvent.Name.Split(\" \").LastOrDefault(), out var year) \n                                && year == startingDate.Year;\n    return new TechCommunityCalendarEvent(\n        eventNameContainsYear ? developerEvent.Name : $\"{developerEvent.Name} {startingDate.Year}\",\n        developerEvent.Hyperlink,\n        startingDate,\n        endingDate,\n        EventType.Conference,\n        developerEvent.Country is \"Online\" ? EventFormat.Virtual : EventFormat.In_Person,\n        developerEvent.Country,\n        developerEvent.City\n    );\n}\n\npublic record DeveloperEvent(\n    string Name,\n    long[] Date,\n    string Hyperlink,\n    string Location,\n    string City,\n    string Country\n);\n\npublic record TechCommunityCalendarEvent(\n    string Name,\n    string Url,\n    DateTimeOffset StartDate,\n    DateTimeOffset EndDate,\n    EventType EventType,\n    EventFormat EventFormat,\n    string Country,\n    string City\n)\n{\n    public string? TwitterHandle { get; set; }\n};\n\npublic enum EventFormat\n{\n    Unknown = 1,\n    Virtual = 2,\n    In_Person = 3,\n    Hybrid = 4\n}\n\npublic enum EventType\n{\n    Any = 0,\n    Unknown = 1,\n    Conference = 2,\n    Meetup = 3,\n    Hackathon = 4,\n    Call_For_Papers = 5,\n    Website = 6,\n}\n",[2838],{"type":415,"tag":555,"props":2839,"children":2840},{"__ignoreMap":401},[2841,2885,2901,2925,2957,2964,2995,3002,3041,3048,3055,3114,3133,3208,3231,3246,3253,3287,3295,3347,3372,3380,3388,3432,3440,3496,3540,3548,3580,3620,3652,3660,3728,3736,3808,3816,3824,3856,3864,3920,3972,4028,4056,4064,4108,4116,4124,4132,4160,4168,4224,4280,4372,4404,4424,4496,4516,4528,4540,4560,4628,4648,4664,4672,4680,4688,4708,4724,4740,4756,4772,4788,4800,4808,4816,4836,4852,4868,4884,4900,4916,4932,4948,4960,4968,4976,5020,5028,5036,5054,5062,5084,5106,5128,5146,5154,5162,5179,5187,5209,5229,5250,5271,5293,5315,5337],{"type":415,"tag":559,"props":2842,"children":2843},{"class":561,"line":562},[2844,2849,2854,2858,2863,2867,2872,2876,2881],{"type":415,"tag":559,"props":2845,"children":2847},{"style":2846},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[2848],{"type":420,"value":748},{"type":415,"tag":559,"props":2850,"children":2851},{"style":792},[2852],{"type":420,"value":2853}," System",{"type":415,"tag":559,"props":2855,"children":2856},{"style":583},[2857],{"type":420,"value":542},{"type":415,"tag":559,"props":2859,"children":2860},{"style":792},[2861],{"type":420,"value":2862},"Net",{"type":415,"tag":559,"props":2864,"children":2865},{"style":583},[2866],{"type":420,"value":542},{"type":415,"tag":559,"props":2868,"children":2869},{"style":792},[2870],{"type":420,"value":2871},"Http",{"type":415,"tag":559,"props":2873,"children":2874},{"style":583},[2875],{"type":420,"value":542},{"type":415,"tag":559,"props":2877,"children":2878},{"style":792},[2879],{"type":420,"value":2880},"Json",{"type":415,"tag":559,"props":2882,"children":2883},{"style":583},[2884],{"type":420,"value":1509},{"type":415,"tag":559,"props":2886,"children":2887},{"class":561,"line":589},[2888,2892,2897],{"type":415,"tag":559,"props":2889,"children":2890},{"style":2846},[2891],{"type":420,"value":748},{"type":415,"tag":559,"props":2893,"children":2894},{"style":792},[2895],{"type":420,"value":2896}," AngleSharp",{"type":415,"tag":559,"props":2898,"children":2899},{"style":583},[2900],{"type":420,"value":1509},{"type":415,"tag":559,"props":2902,"children":2903},{"class":561,"line":608},[2904,2908,2912,2916,2921],{"type":415,"tag":559,"props":2905,"children":2906},{"style":2846},[2907],{"type":420,"value":748},{"type":415,"tag":559,"props":2909,"children":2910},{"style":792},[2911],{"type":420,"value":2896},{"type":415,"tag":559,"props":2913,"children":2914},{"style":583},[2915],{"type":420,"value":542},{"type":415,"tag":559,"props":2917,"children":2918},{"style":792},[2919],{"type":420,"value":2920},"Dom",{"type":415,"tag":559,"props":2922,"children":2923},{"style":583},[2924],{"type":420,"value":1509},{"type":415,"tag":559,"props":2926,"children":2927},{"class":561,"line":626},[2928,2932,2936,2940,2945,2949,2953],{"type":415,"tag":559,"props":2929,"children":2930},{"style":2846},[2931],{"type":420,"value":748},{"type":415,"tag":559,"props":2933,"children":2934},{"style":792},[2935],{"type":420,"value":2896},{"type":415,"tag":559,"props":2937,"children":2938},{"style":583},[2939],{"type":420,"value":542},{"type":415,"tag":559,"props":2941,"children":2942},{"style":792},[2943],{"type":420,"value":2944},"Html",{"type":415,"tag":559,"props":2946,"children":2947},{"style":583},[2948],{"type":420,"value":542},{"type":415,"tag":559,"props":2950,"children":2951},{"style":792},[2952],{"type":420,"value":2920},{"type":415,"tag":559,"props":2954,"children":2955},{"style":583},[2956],{"type":420,"value":1509},{"type":415,"tag":559,"props":2958,"children":2959},{"class":561,"line":643},[2960],{"type":415,"tag":559,"props":2961,"children":2962},{"emptyLinePlaceholder":847},[2963],{"type":420,"value":850},{"type":415,"tag":559,"props":2965,"children":2966},{"class":561,"line":660},[2967,2971,2975,2979,2983,2987,2991],{"type":415,"tag":559,"props":2968,"children":2969},{"style":745},[2970],{"type":420,"value":748},{"type":415,"tag":559,"props":2972,"children":2973},{"style":572},[2974],{"type":420,"value":753},{"type":415,"tag":559,"props":2976,"children":2977},{"style":572},[2978],{"type":420,"value":758},{"type":415,"tag":559,"props":2980,"children":2981},{"style":583},[2982],{"type":420,"value":763},{"type":415,"tag":559,"props":2984,"children":2985},{"style":583},[2986],{"type":420,"value":768},{"type":415,"tag":559,"props":2988,"children":2989},{"style":572},[2990],{"type":420,"value":773},{"type":415,"tag":559,"props":2992,"children":2993},{"style":583},[2994],{"type":420,"value":778},{"type":415,"tag":559,"props":2996,"children":2997},{"class":561,"line":677},[2998],{"type":415,"tag":559,"props":2999,"children":3000},{"style":583},[3001],{"type":420,"value":786},{"type":415,"tag":559,"props":3003,"children":3004},{"class":561,"line":690},[3005,3009,3013,3017,3021,3025,3029,3033,3037],{"type":415,"tag":559,"props":3006,"children":3007},{"style":792},[3008],{"type":420,"value":795},{"type":415,"tag":559,"props":3010,"children":3011},{"style":583},[3012],{"type":420,"value":800},{"type":415,"tag":559,"props":3014,"children":3015},{"style":583},[3016],{"type":420,"value":768},{"type":415,"tag":559,"props":3018,"children":3019},{"style":572},[3020],{"type":420,"value":809},{"type":415,"tag":559,"props":3022,"children":3023},{"style":583},[3024],{"type":420,"value":814},{"type":415,"tag":559,"props":3026,"children":3027},{"style":583},[3028],{"type":420,"value":819},{"type":415,"tag":559,"props":3030,"children":3031},{"style":822},[3032],{"type":420,"value":446},{"type":415,"tag":559,"props":3034,"children":3035},{"style":583},[3036],{"type":420,"value":819},{"type":415,"tag":559,"props":3038,"children":3039},{"style":583},[3040],{"type":420,"value":833},{"type":415,"tag":559,"props":3042,"children":3043},{"class":561,"line":1089},[3044],{"type":415,"tag":559,"props":3045,"children":3046},{"style":583},[3047],{"type":420,"value":841},{"type":415,"tag":559,"props":3049,"children":3050},{"class":561,"line":1102},[3051],{"type":415,"tag":559,"props":3052,"children":3053},{"emptyLinePlaceholder":847},[3054],{"type":420,"value":850},{"type":415,"tag":559,"props":3056,"children":3057},{"class":561,"line":1110},[3058,3062,3066,3070,3074,3078,3082,3086,3090,3094,3098,3102,3106,3110],{"type":415,"tag":559,"props":3059,"children":3060},{"style":572},[3061],{"type":420,"value":858},{"type":415,"tag":559,"props":3063,"children":3064},{"style":572},[3065],{"type":420,"value":863},{"type":415,"tag":559,"props":3067,"children":3068},{"style":583},[3069],{"type":420,"value":763},{"type":415,"tag":559,"props":3071,"children":3072},{"style":583},[3073],{"type":420,"value":872},{"type":415,"tag":559,"props":3075,"children":3076},{"style":792},[3077],{"type":420,"value":758},{"type":415,"tag":559,"props":3079,"children":3080},{"style":583},[3081],{"type":420,"value":542},{"type":415,"tag":559,"props":3083,"children":3084},{"style":883},[3085],{"type":420,"value":886},{"type":415,"tag":559,"props":3087,"children":3088},{"style":583},[3089],{"type":420,"value":891},{"type":415,"tag":559,"props":3091,"children":3092},{"style":572},[3093],{"type":420,"value":896},{"type":415,"tag":559,"props":3095,"children":3096},{"style":583},[3097],{"type":420,"value":901},{"type":415,"tag":559,"props":3099,"children":3100},{"style":583},[3101],{"type":420,"value":819},{"type":415,"tag":559,"props":3103,"children":3104},{"style":822},[3105],{"type":420,"value":910},{"type":415,"tag":559,"props":3107,"children":3108},{"style":583},[3109],{"type":420,"value":819},{"type":415,"tag":559,"props":3111,"children":3112},{"style":583},[3113],{"type":420,"value":696},{"type":415,"tag":559,"props":3115,"children":3116},{"class":561,"line":1118},[3117,3121,3125,3129],{"type":415,"tag":559,"props":3118,"children":3119},{"style":572},[3120],{"type":420,"value":858},{"type":415,"tag":559,"props":3122,"children":3123},{"style":572},[3124],{"type":420,"value":1825},{"type":415,"tag":559,"props":3126,"children":3127},{"style":583},[3128],{"type":420,"value":763},{"type":415,"tag":559,"props":3130,"children":3131},{"style":792},[3132],{"type":420,"value":1834},{"type":415,"tag":559,"props":3134,"children":3135},{"class":561,"line":1171},[3136,3140,3144,3148,3152,3156,3160,3164,3168,3172,3176,3180,3184,3188,3192,3196,3200,3204],{"type":415,"tag":559,"props":3137,"children":3138},{"style":583},[3139],{"type":420,"value":1842},{"type":415,"tag":559,"props":3141,"children":3142},{"style":883},[3143],{"type":420,"value":1847},{"type":415,"tag":559,"props":3145,"children":3146},{"style":583},[3147],{"type":420,"value":814},{"type":415,"tag":559,"props":3149,"children":3150},{"style":572},[3151],{"type":420,"value":1856},{"type":415,"tag":559,"props":3153,"children":3154},{"style":583},[3155],{"type":420,"value":1861},{"type":415,"tag":559,"props":3157,"children":3158},{"style":792},[3159],{"type":420,"value":1866},{"type":415,"tag":559,"props":3161,"children":3162},{"style":583},[3163],{"type":420,"value":542},{"type":415,"tag":559,"props":3165,"children":3166},{"style":792},[3167],{"type":420,"value":1298},{"type":415,"tag":559,"props":3169,"children":3170},{"style":583},[3171],{"type":420,"value":542},{"type":415,"tag":559,"props":3173,"children":3174},{"style":883},[3175],{"type":420,"value":1883},{"type":415,"tag":559,"props":3177,"children":3178},{"style":583},[3179],{"type":420,"value":1888},{"type":415,"tag":559,"props":3181,"children":3182},{"style":583},[3183],{"type":420,"value":1893},{"type":415,"tag":559,"props":3185,"children":3186},{"style":792},[3187],{"type":420,"value":1271},{"type":415,"tag":559,"props":3189,"children":3190},{"style":583},[3191],{"type":420,"value":542},{"type":415,"tag":559,"props":3193,"children":3194},{"style":792},[3195],{"type":420,"value":1906},{"type":415,"tag":559,"props":3197,"children":3198},{"style":583},[3199],{"type":420,"value":542},{"type":415,"tag":559,"props":3201,"children":3202},{"style":883},[3203],{"type":420,"value":1915},{"type":415,"tag":559,"props":3205,"children":3206},{"style":583},[3207],{"type":420,"value":1920},{"type":415,"tag":559,"props":3209,"children":3210},{"class":561,"line":1748},[3211,3215,3219,3223,3227],{"type":415,"tag":559,"props":3212,"children":3213},{"style":583},[3214],{"type":420,"value":1842},{"type":415,"tag":559,"props":3216,"children":3217},{"style":883},[3218],{"type":420,"value":1932},{"type":415,"tag":559,"props":3220,"children":3221},{"style":583},[3222],{"type":420,"value":814},{"type":415,"tag":559,"props":3224,"children":3225},{"style":792},[3226],{"type":420,"value":1941},{"type":415,"tag":559,"props":3228,"children":3229},{"style":583},[3230],{"type":420,"value":833},{"type":415,"tag":559,"props":3232,"children":3233},{"class":561,"line":1769},[3234,3238,3242],{"type":415,"tag":559,"props":3235,"children":3236},{"style":583},[3237],{"type":420,"value":1842},{"type":415,"tag":559,"props":3239,"children":3240},{"style":883},[3241],{"type":420,"value":1957},{"type":415,"tag":559,"props":3243,"children":3244},{"style":583},[3245],{"type":420,"value":1962},{"type":415,"tag":559,"props":3247,"children":3248},{"class":561,"line":1786},[3249],{"type":415,"tag":559,"props":3250,"children":3251},{"emptyLinePlaceholder":847},[3252],{"type":420,"value":850},{"type":415,"tag":559,"props":3254,"children":3255},{"class":561,"line":1795},[3256,3261,3265,3269,3274,3279,3283],{"type":415,"tag":559,"props":3257,"children":3258},{"style":745},[3259],{"type":420,"value":3260},"foreach",{"type":415,"tag":559,"props":3262,"children":3263},{"style":583},[3264],{"type":420,"value":2710},{"type":415,"tag":559,"props":3266,"children":3267},{"style":572},[3268],{"type":420,"value":858},{"type":415,"tag":559,"props":3270,"children":3271},{"style":572},[3272],{"type":420,"value":3273}," upcomingEvent",{"type":415,"tag":559,"props":3275,"children":3276},{"style":745},[3277],{"type":420,"value":3278}," in",{"type":415,"tag":559,"props":3280,"children":3281},{"style":792},[3282],{"type":420,"value":1825},{"type":415,"tag":559,"props":3284,"children":3285},{"style":583},[3286],{"type":420,"value":833},{"type":415,"tag":559,"props":3288,"children":3290},{"class":561,"line":3289},18,[3291],{"type":415,"tag":559,"props":3292,"children":3293},{"style":583},[3294],{"type":420,"value":786},{"type":415,"tag":559,"props":3296,"children":3298},{"class":561,"line":3297},19,[3299,3304,3308,3313,3317,3321,3325,3329,3334,3338,3343],{"type":415,"tag":559,"props":3300,"children":3301},{"style":792},[3302],{"type":420,"value":3303},"    upcomingEvent",{"type":415,"tag":559,"props":3305,"children":3306},{"style":583},[3307],{"type":420,"value":542},{"type":415,"tag":559,"props":3309,"children":3310},{"style":792},[3311],{"type":420,"value":3312},"TwitterHandle ",{"type":415,"tag":559,"props":3314,"children":3315},{"style":583},[3316],{"type":420,"value":800},{"type":415,"tag":559,"props":3318,"children":3319},{"style":583},[3320],{"type":420,"value":872},{"type":415,"tag":559,"props":3322,"children":3323},{"style":883},[3324],{"type":420,"value":2025},{"type":415,"tag":559,"props":3326,"children":3327},{"style":583},[3328],{"type":420,"value":814},{"type":415,"tag":559,"props":3330,"children":3331},{"style":792},[3332],{"type":420,"value":3333},"upcomingEvent",{"type":415,"tag":559,"props":3335,"children":3336},{"style":583},[3337],{"type":420,"value":542},{"type":415,"tag":559,"props":3339,"children":3340},{"style":792},[3341],{"type":420,"value":3342},"Url",{"type":415,"tag":559,"props":3344,"children":3345},{"style":583},[3346],{"type":420,"value":696},{"type":415,"tag":559,"props":3348,"children":3350},{"class":561,"line":3349},20,[3351,3356,3360,3364,3368],{"type":415,"tag":559,"props":3352,"children":3353},{"style":583},[3354],{"type":420,"value":3355},"    await",{"type":415,"tag":559,"props":3357,"children":3358},{"style":883},[3359],{"type":420,"value":2507},{"type":415,"tag":559,"props":3361,"children":3362},{"style":583},[3363],{"type":420,"value":814},{"type":415,"tag":559,"props":3365,"children":3366},{"style":792},[3367],{"type":420,"value":3333},{"type":415,"tag":559,"props":3369,"children":3370},{"style":583},[3371],{"type":420,"value":696},{"type":415,"tag":559,"props":3373,"children":3375},{"class":561,"line":3374},21,[3376],{"type":415,"tag":559,"props":3377,"children":3378},{"style":583},[3379],{"type":420,"value":1801},{"type":415,"tag":559,"props":3381,"children":3383},{"class":561,"line":3382},22,[3384],{"type":415,"tag":559,"props":3385,"children":3386},{"emptyLinePlaceholder":847},[3387],{"type":420,"value":850},{"type":415,"tag":559,"props":3389,"children":3391},{"class":561,"line":3390},23,[3392,3396,3400,3404,3408,3412,3416,3420,3424,3428],{"type":415,"tag":559,"props":3393,"children":3394},{"style":566},[3395],{"type":420,"value":2001},{"type":415,"tag":559,"props":3397,"children":3398},{"style":572},[3399],{"type":420,"value":2006},{"type":415,"tag":559,"props":3401,"children":3402},{"style":583},[3403],{"type":420,"value":891},{"type":415,"tag":559,"props":3405,"children":3406},{"style":583},[3407],{"type":420,"value":2015},{"type":415,"tag":559,"props":3409,"children":3410},{"style":583},[3411],{"type":420,"value":2020},{"type":415,"tag":559,"props":3413,"children":3414},{"style":883},[3415],{"type":420,"value":2025},{"type":415,"tag":559,"props":3417,"children":3418},{"style":583},[3419],{"type":420,"value":814},{"type":415,"tag":559,"props":3421,"children":3422},{"style":583},[3423],{"type":420,"value":2015},{"type":415,"tag":559,"props":3425,"children":3426},{"style":572},[3427],{"type":420,"value":2038},{"type":415,"tag":559,"props":3429,"children":3430},{"style":583},[3431],{"type":420,"value":833},{"type":415,"tag":559,"props":3433,"children":3435},{"class":561,"line":3434},24,[3436],{"type":415,"tag":559,"props":3437,"children":3438},{"style":583},[3439],{"type":420,"value":786},{"type":415,"tag":559,"props":3441,"children":3443},{"class":561,"line":3442},25,[3444,3448,3452,3456,3460,3464,3468,3472,3476,3480,3484,3488,3492],{"type":415,"tag":559,"props":3445,"children":3446},{"style":572},[3447],{"type":420,"value":1257},{"type":415,"tag":559,"props":3449,"children":3450},{"style":572},[3451],{"type":420,"value":2061},{"type":415,"tag":559,"props":3453,"children":3454},{"style":583},[3455],{"type":420,"value":763},{"type":415,"tag":559,"props":3457,"children":3458},{"style":792},[3459],{"type":420,"value":2070},{"type":415,"tag":559,"props":3461,"children":3462},{"style":583},[3463],{"type":420,"value":542},{"type":415,"tag":559,"props":3465,"children":3466},{"style":883},[3467],{"type":420,"value":2079},{"type":415,"tag":559,"props":3469,"children":3470},{"style":583},[3471],{"type":420,"value":814},{"type":415,"tag":559,"props":3473,"children":3474},{"style":792},[3475],{"type":420,"value":263},{"type":415,"tag":559,"props":3477,"children":3478},{"style":583},[3479],{"type":420,"value":542},{"type":415,"tag":559,"props":3481,"children":3482},{"style":792},[3483],{"type":420,"value":2096},{"type":415,"tag":559,"props":3485,"children":3486},{"style":583},[3487],{"type":420,"value":542},{"type":415,"tag":559,"props":3489,"children":3490},{"style":883},[3491],{"type":420,"value":2105},{"type":415,"tag":559,"props":3493,"children":3494},{"style":583},[3495],{"type":420,"value":1312},{"type":415,"tag":559,"props":3497,"children":3499},{"class":561,"line":3498},26,[3500,3504,3508,3512,3516,3520,3524,3528,3532,3536],{"type":415,"tag":559,"props":3501,"children":3502},{"style":572},[3503],{"type":420,"value":1257},{"type":415,"tag":559,"props":3505,"children":3506},{"style":572},[3507],{"type":420,"value":2121},{"type":415,"tag":559,"props":3509,"children":3510},{"style":583},[3511],{"type":420,"value":763},{"type":415,"tag":559,"props":3513,"children":3514},{"style":583},[3515],{"type":420,"value":872},{"type":415,"tag":559,"props":3517,"children":3518},{"style":792},[3519],{"type":420,"value":2061},{"type":415,"tag":559,"props":3521,"children":3522},{"style":583},[3523],{"type":420,"value":542},{"type":415,"tag":559,"props":3525,"children":3526},{"style":883},[3527],{"type":420,"value":2142},{"type":415,"tag":559,"props":3529,"children":3530},{"style":583},[3531],{"type":420,"value":814},{"type":415,"tag":559,"props":3533,"children":3534},{"style":792},[3535],{"type":420,"value":2151},{"type":415,"tag":559,"props":3537,"children":3538},{"style":583},[3539],{"type":420,"value":696},{"type":415,"tag":559,"props":3541,"children":3543},{"class":561,"line":3542},27,[3544],{"type":415,"tag":559,"props":3545,"children":3546},{"emptyLinePlaceholder":847},[3547],{"type":420,"value":850},{"type":415,"tag":559,"props":3549,"children":3551},{"class":561,"line":3550},28,[3552,3556,3560,3564,3568,3572,3576],{"type":415,"tag":559,"props":3553,"children":3554},{"style":572},[3555],{"type":420,"value":1257},{"type":415,"tag":559,"props":3557,"children":3558},{"style":572},[3559],{"type":420,"value":2174},{"type":415,"tag":559,"props":3561,"children":3562},{"style":583},[3563],{"type":420,"value":763},{"type":415,"tag":559,"props":3565,"children":3566},{"style":583},[3567],{"type":420,"value":1434},{"type":415,"tag":559,"props":3569,"children":3570},{"style":822},[3571],{"type":420,"value":2187},{"type":415,"tag":559,"props":3573,"children":3574},{"style":583},[3575],{"type":420,"value":819},{"type":415,"tag":559,"props":3577,"children":3578},{"style":583},[3579],{"type":420,"value":1509},{"type":415,"tag":559,"props":3581,"children":3583},{"class":561,"line":3582},29,[3584,3588,3592,3596,3600,3604,3608,3612,3616],{"type":415,"tag":559,"props":3585,"children":3586},{"style":572},[3587],{"type":420,"value":1257},{"type":415,"tag":559,"props":3589,"children":3590},{"style":572},[3591],{"type":420,"value":2207},{"type":415,"tag":559,"props":3593,"children":3594},{"style":583},[3595],{"type":420,"value":763},{"type":415,"tag":559,"props":3597,"children":3598},{"style":792},[3599],{"type":420,"value":2121},{"type":415,"tag":559,"props":3601,"children":3602},{"style":583},[3603],{"type":420,"value":542},{"type":415,"tag":559,"props":3605,"children":3606},{"style":883},[3607],{"type":420,"value":2224},{"type":415,"tag":559,"props":3609,"children":3610},{"style":583},[3611],{"type":420,"value":814},{"type":415,"tag":559,"props":3613,"children":3614},{"style":792},[3615],{"type":420,"value":2233},{"type":415,"tag":559,"props":3617,"children":3618},{"style":583},[3619],{"type":420,"value":833},{"type":415,"tag":559,"props":3621,"children":3623},{"class":561,"line":3622},30,[3624,3628,3632,3636,3640,3644,3648],{"type":415,"tag":559,"props":3625,"children":3626},{"style":583},[3627],{"type":420,"value":2245},{"type":415,"tag":559,"props":3629,"children":3630},{"style":883},[3631],{"type":420,"value":2250},{"type":415,"tag":559,"props":3633,"children":3634},{"style":583},[3635],{"type":420,"value":814},{"type":415,"tag":559,"props":3637,"children":3638},{"style":583},[3639],{"type":420,"value":819},{"type":415,"tag":559,"props":3641,"children":3642},{"style":822},[3643],{"type":420,"value":2263},{"type":415,"tag":559,"props":3645,"children":3646},{"style":583},[3647],{"type":420,"value":819},{"type":415,"tag":559,"props":3649,"children":3650},{"style":583},[3651],{"type":420,"value":696},{"type":415,"tag":559,"props":3653,"children":3655},{"class":561,"line":3654},31,[3656],{"type":415,"tag":559,"props":3657,"children":3658},{"emptyLinePlaceholder":847},[3659],{"type":420,"value":850},{"type":415,"tag":559,"props":3661,"children":3663},{"class":561,"line":3662},32,[3664,3668,3672,3676,3680,3684,3688,3692,3696,3700,3704,3708,3712,3716,3720,3724],{"type":415,"tag":559,"props":3665,"children":3666},{"style":745},[3667],{"type":420,"value":1517},{"type":415,"tag":559,"props":3669,"children":3670},{"style":792},[3671],{"type":420,"value":809},{"type":415,"tag":559,"props":3673,"children":3674},{"style":583},[3675],{"type":420,"value":542},{"type":415,"tag":559,"props":3677,"children":3678},{"style":883},[3679],{"type":420,"value":2298},{"type":415,"tag":559,"props":3681,"children":3682},{"style":583},[3683],{"type":420,"value":814},{"type":415,"tag":559,"props":3685,"children":3686},{"style":792},[3687],{"type":420,"value":2307},{"type":415,"tag":559,"props":3689,"children":3690},{"style":583},[3691],{"type":420,"value":2312},{"type":415,"tag":559,"props":3693,"children":3694},{"style":792},[3695],{"type":420,"value":2317},{"type":415,"tag":559,"props":3697,"children":3698},{"style":583},[3699],{"type":420,"value":542},{"type":415,"tag":559,"props":3701,"children":3702},{"style":792},[3703],{"type":420,"value":2326},{"type":415,"tag":559,"props":3705,"children":3706},{"style":583},[3707],{"type":420,"value":2312},{"type":415,"tag":559,"props":3709,"children":3710},{"style":566},[3711],{"type":420,"value":1454},{"type":415,"tag":559,"props":3713,"children":3714},{"style":572},[3715],{"type":420,"value":753},{"type":415,"tag":559,"props":3717,"children":3718},{"style":572},[3719],{"type":420,"value":2343},{"type":415,"tag":559,"props":3721,"children":3722},{"style":583},[3723],{"type":420,"value":1468},{"type":415,"tag":559,"props":3725,"children":3726},{"style":583},[3727],{"type":420,"value":2352},{"type":415,"tag":559,"props":3729,"children":3731},{"class":561,"line":3730},33,[3732],{"type":415,"tag":559,"props":3733,"children":3734},{"style":2358},[3735],{"type":420,"value":2361},{"type":415,"tag":559,"props":3737,"children":3739},{"class":561,"line":3738},34,[3740,3744,3748,3752,3756,3760,3764,3768,3772,3776,3780,3784,3788,3792,3796,3800,3804],{"type":415,"tag":559,"props":3741,"children":3742},{"style":583},[3743],{"type":420,"value":2369},{"type":415,"tag":559,"props":3745,"children":3746},{"style":792},[3747],{"type":420,"value":2374},{"type":415,"tag":559,"props":3749,"children":3750},{"style":583},[3751],{"type":420,"value":542},{"type":415,"tag":559,"props":3753,"children":3754},{"style":792},[3755],{"type":420,"value":2383},{"type":415,"tag":559,"props":3757,"children":3758},{"style":583},[3759],{"type":420,"value":1580},{"type":415,"tag":559,"props":3761,"children":3762},{"style":822},[3763],{"type":420,"value":2392},{"type":415,"tag":559,"props":3765,"children":3766},{"style":583},[3767],{"type":420,"value":2397},{"type":415,"tag":559,"props":3769,"children":3770},{"style":792},[3771],{"type":420,"value":2374},{"type":415,"tag":559,"props":3773,"children":3774},{"style":583},[3775],{"type":420,"value":542},{"type":415,"tag":559,"props":3777,"children":3778},{"style":792},[3779],{"type":420,"value":2410},{"type":415,"tag":559,"props":3781,"children":3782},{"style":583},[3783],{"type":420,"value":2415},{"type":415,"tag":559,"props":3785,"children":3786},{"style":792},[3787],{"type":420,"value":2374},{"type":415,"tag":559,"props":3789,"children":3790},{"style":583},[3791],{"type":420,"value":542},{"type":415,"tag":559,"props":3793,"children":3794},{"style":792},[3795],{"type":420,"value":2428},{"type":415,"tag":559,"props":3797,"children":3798},{"style":583},[3799],{"type":420,"value":1602},{"type":415,"tag":559,"props":3801,"children":3802},{"style":583},[3803],{"type":420,"value":2437},{"type":415,"tag":559,"props":3805,"children":3806},{"style":583},[3807],{"type":420,"value":2442},{"type":415,"tag":559,"props":3809,"children":3811},{"class":561,"line":3810},35,[3812],{"type":415,"tag":559,"props":3813,"children":3814},{"style":583},[3815],{"type":420,"value":1801},{"type":415,"tag":559,"props":3817,"children":3819},{"class":561,"line":3818},36,[3820],{"type":415,"tag":559,"props":3821,"children":3822},{"emptyLinePlaceholder":847},[3823],{"type":420,"value":850},{"type":415,"tag":559,"props":3825,"children":3827},{"class":561,"line":3826},37,[3828,3832,3836,3840,3844,3848,3852],{"type":415,"tag":559,"props":3829,"children":3830},{"style":566},[3831],{"type":420,"value":2001},{"type":415,"tag":559,"props":3833,"children":3834},{"style":572},[3835],{"type":420,"value":2006},{"type":415,"tag":559,"props":3837,"children":3838},{"style":883},[3839],{"type":420,"value":2507},{"type":415,"tag":559,"props":3841,"children":3842},{"style":583},[3843],{"type":420,"value":814},{"type":415,"tag":559,"props":3845,"children":3846},{"style":572},[3847],{"type":420,"value":1204},{"type":415,"tag":559,"props":3849,"children":3850},{"style":572},[3851],{"type":420,"value":2520},{"type":415,"tag":559,"props":3853,"children":3854},{"style":583},[3855],{"type":420,"value":833},{"type":415,"tag":559,"props":3857,"children":3859},{"class":561,"line":3858},38,[3860],{"type":415,"tag":559,"props":3861,"children":3862},{"style":583},[3863],{"type":420,"value":786},{"type":415,"tag":559,"props":3865,"children":3867},{"class":561,"line":3866},39,[3868,3872,3876,3880,3884,3888,3892,3896,3900,3904,3908,3912,3916],{"type":415,"tag":559,"props":3869,"children":3870},{"style":572},[3871],{"type":420,"value":1257},{"type":415,"tag":559,"props":3873,"children":3874},{"style":572},[3875],{"type":420,"value":2061},{"type":415,"tag":559,"props":3877,"children":3878},{"style":583},[3879],{"type":420,"value":763},{"type":415,"tag":559,"props":3881,"children":3882},{"style":792},[3883],{"type":420,"value":2070},{"type":415,"tag":559,"props":3885,"children":3886},{"style":583},[3887],{"type":420,"value":542},{"type":415,"tag":559,"props":3889,"children":3890},{"style":883},[3891],{"type":420,"value":2079},{"type":415,"tag":559,"props":3893,"children":3894},{"style":583},[3895],{"type":420,"value":814},{"type":415,"tag":559,"props":3897,"children":3898},{"style":792},[3899],{"type":420,"value":263},{"type":415,"tag":559,"props":3901,"children":3902},{"style":583},[3903],{"type":420,"value":542},{"type":415,"tag":559,"props":3905,"children":3906},{"style":792},[3907],{"type":420,"value":2096},{"type":415,"tag":559,"props":3909,"children":3910},{"style":583},[3911],{"type":420,"value":542},{"type":415,"tag":559,"props":3913,"children":3914},{"style":883},[3915],{"type":420,"value":2105},{"type":415,"tag":559,"props":3917,"children":3918},{"style":583},[3919],{"type":420,"value":1312},{"type":415,"tag":559,"props":3921,"children":3923},{"class":561,"line":3922},40,[3924,3928,3932,3936,3940,3944,3948,3952,3956,3960,3964,3968],{"type":415,"tag":559,"props":3925,"children":3926},{"style":572},[3927],{"type":420,"value":1257},{"type":415,"tag":559,"props":3929,"children":3930},{"style":572},[3931],{"type":420,"value":2121},{"type":415,"tag":559,"props":3933,"children":3934},{"style":583},[3935],{"type":420,"value":763},{"type":415,"tag":559,"props":3937,"children":3938},{"style":583},[3939],{"type":420,"value":872},{"type":415,"tag":559,"props":3941,"children":3942},{"style":792},[3943],{"type":420,"value":2061},{"type":415,"tag":559,"props":3945,"children":3946},{"style":583},[3947],{"type":420,"value":542},{"type":415,"tag":559,"props":3949,"children":3950},{"style":883},[3951],{"type":420,"value":2142},{"type":415,"tag":559,"props":3953,"children":3954},{"style":583},[3955],{"type":420,"value":814},{"type":415,"tag":559,"props":3957,"children":3958},{"style":583},[3959],{"type":420,"value":819},{"type":415,"tag":559,"props":3961,"children":3962},{"style":822},[3963],{"type":420,"value":2630},{"type":415,"tag":559,"props":3965,"children":3966},{"style":583},[3967],{"type":420,"value":819},{"type":415,"tag":559,"props":3969,"children":3970},{"style":583},[3971],{"type":420,"value":696},{"type":415,"tag":559,"props":3973,"children":3975},{"class":561,"line":3974},41,[3976,3980,3984,3988,3992,3996,4000,4004,4008,4012,4016,4020,4024],{"type":415,"tag":559,"props":3977,"children":3978},{"style":572},[3979],{"type":420,"value":1257},{"type":415,"tag":559,"props":3981,"children":3982},{"style":572},[3983],{"type":420,"value":2650},{"type":415,"tag":559,"props":3985,"children":3986},{"style":583},[3987],{"type":420,"value":763},{"type":415,"tag":559,"props":3989,"children":3990},{"style":792},[3991],{"type":420,"value":2121},{"type":415,"tag":559,"props":3993,"children":3994},{"style":583},[3995],{"type":420,"value":542},{"type":415,"tag":559,"props":3997,"children":3998},{"style":883},[3999],{"type":420,"value":2224},{"type":415,"tag":559,"props":4001,"children":4002},{"style":583},[4003],{"type":420,"value":891},{"type":415,"tag":559,"props":4005,"children":4006},{"style":572},[4007],{"type":420,"value":2675},{"type":415,"tag":559,"props":4009,"children":4010},{"style":583},[4011],{"type":420,"value":2680},{"type":415,"tag":559,"props":4013,"children":4014},{"style":583},[4015],{"type":420,"value":2685},{"type":415,"tag":559,"props":4017,"children":4018},{"style":822},[4019],{"type":420,"value":2482},{"type":415,"tag":559,"props":4021,"children":4022},{"style":583},[4023],{"type":420,"value":2685},{"type":415,"tag":559,"props":4025,"children":4026},{"style":583},[4027],{"type":420,"value":696},{"type":415,"tag":559,"props":4029,"children":4031},{"class":561,"line":4030},42,[4032,4036,4040,4044,4048,4052],{"type":415,"tag":559,"props":4033,"children":4034},{"style":745},[4035],{"type":420,"value":2705},{"type":415,"tag":559,"props":4037,"children":4038},{"style":583},[4039],{"type":420,"value":2710},{"type":415,"tag":559,"props":4041,"children":4042},{"style":792},[4043],{"type":420,"value":2715},{"type":415,"tag":559,"props":4045,"children":4046},{"style":583},[4047],{"type":420,"value":1693},{"type":415,"tag":559,"props":4049,"children":4050},{"style":583},[4051],{"type":420,"value":2724},{"type":415,"tag":559,"props":4053,"children":4054},{"style":583},[4055],{"type":420,"value":2729},{"type":415,"tag":559,"props":4057,"children":4059},{"class":561,"line":4058},43,[4060],{"type":415,"tag":559,"props":4061,"children":4062},{"style":583},[4063],{"type":420,"value":2737},{"type":415,"tag":559,"props":4065,"children":4067},{"class":561,"line":4066},44,[4068,4072,4076,4080,4084,4088,4092,4096,4100,4104],{"type":415,"tag":559,"props":4069,"children":4070},{"style":572},[4071],{"type":420,"value":2745},{"type":415,"tag":559,"props":4073,"children":4074},{"style":572},[4075],{"type":420,"value":2750},{"type":415,"tag":559,"props":4077,"children":4078},{"style":583},[4079],{"type":420,"value":763},{"type":415,"tag":559,"props":4081,"children":4082},{"style":583},[4083],{"type":420,"value":872},{"type":415,"tag":559,"props":4085,"children":4086},{"style":792},[4087],{"type":420,"value":2650},{"type":415,"tag":559,"props":4089,"children":4090},{"style":583},[4091],{"type":420,"value":542},{"type":415,"tag":559,"props":4093,"children":4094},{"style":883},[4095],{"type":420,"value":2771},{"type":415,"tag":559,"props":4097,"children":4098},{"style":583},[4099],{"type":420,"value":814},{"type":415,"tag":559,"props":4101,"children":4102},{"style":792},[4103],{"type":420,"value":2780},{"type":415,"tag":559,"props":4105,"children":4106},{"style":583},[4107],{"type":420,"value":696},{"type":415,"tag":559,"props":4109,"children":4111},{"class":561,"line":4110},45,[4112],{"type":415,"tag":559,"props":4113,"children":4114},{"style":583},[4115],{"type":420,"value":2792},{"type":415,"tag":559,"props":4117,"children":4119},{"class":561,"line":4118},46,[4120],{"type":415,"tag":559,"props":4121,"children":4122},{"style":583},[4123],{"type":420,"value":1801},{"type":415,"tag":559,"props":4125,"children":4127},{"class":561,"line":4126},47,[4128],{"type":415,"tag":559,"props":4129,"children":4130},{"emptyLinePlaceholder":847},[4131],{"type":420,"value":850},{"type":415,"tag":559,"props":4133,"children":4135},{"class":561,"line":4134},48,[4136,4140,4144,4148,4152,4156],{"type":415,"tag":559,"props":4137,"children":4138},{"style":572},[4139],{"type":420,"value":1204},{"type":415,"tag":559,"props":4141,"children":4142},{"style":883},[4143],{"type":420,"value":1225},{"type":415,"tag":559,"props":4145,"children":4146},{"style":583},[4147],{"type":420,"value":814},{"type":415,"tag":559,"props":4149,"children":4150},{"style":572},[4151],{"type":420,"value":896},{"type":415,"tag":559,"props":4153,"children":4154},{"style":572},[4155],{"type":420,"value":1238},{"type":415,"tag":559,"props":4157,"children":4158},{"style":583},[4159],{"type":420,"value":833},{"type":415,"tag":559,"props":4161,"children":4163},{"class":561,"line":4162},49,[4164],{"type":415,"tag":559,"props":4165,"children":4166},{"style":583},[4167],{"type":420,"value":786},{"type":415,"tag":559,"props":4169,"children":4171},{"class":561,"line":4170},50,[4172,4176,4180,4184,4188,4192,4196,4200,4204,4208,4212,4216,4220],{"type":415,"tag":559,"props":4173,"children":4174},{"style":572},[4175],{"type":420,"value":1257},{"type":415,"tag":559,"props":4177,"children":4178},{"style":572},[4179],{"type":420,"value":1262},{"type":415,"tag":559,"props":4181,"children":4182},{"style":583},[4183],{"type":420,"value":763},{"type":415,"tag":559,"props":4185,"children":4186},{"style":792},[4187],{"type":420,"value":1271},{"type":415,"tag":559,"props":4189,"children":4190},{"style":583},[4191],{"type":420,"value":542},{"type":415,"tag":559,"props":4193,"children":4194},{"style":883},[4195],{"type":420,"value":1280},{"type":415,"tag":559,"props":4197,"children":4198},{"style":583},[4199],{"type":420,"value":814},{"type":415,"tag":559,"props":4201,"children":4202},{"style":792},[4203],{"type":420,"value":1289},{"type":415,"tag":559,"props":4205,"children":4206},{"style":583},[4207],{"type":420,"value":542},{"type":415,"tag":559,"props":4209,"children":4210},{"style":792},[4211],{"type":420,"value":1298},{"type":415,"tag":559,"props":4213,"children":4214},{"style":583},[4215],{"type":420,"value":542},{"type":415,"tag":559,"props":4217,"children":4218},{"style":883},[4219],{"type":420,"value":1307},{"type":415,"tag":559,"props":4221,"children":4222},{"style":583},[4223],{"type":420,"value":1312},{"type":415,"tag":559,"props":4225,"children":4227},{"class":561,"line":4226},51,[4228,4232,4236,4240,4244,4248,4252,4256,4260,4264,4268,4272,4276],{"type":415,"tag":559,"props":4229,"children":4230},{"style":572},[4231],{"type":420,"value":1257},{"type":415,"tag":559,"props":4233,"children":4234},{"style":572},[4235],{"type":420,"value":1324},{"type":415,"tag":559,"props":4237,"children":4238},{"style":583},[4239],{"type":420,"value":763},{"type":415,"tag":559,"props":4241,"children":4242},{"style":792},[4243],{"type":420,"value":1271},{"type":415,"tag":559,"props":4245,"children":4246},{"style":583},[4247],{"type":420,"value":542},{"type":415,"tag":559,"props":4249,"children":4250},{"style":883},[4251],{"type":420,"value":1280},{"type":415,"tag":559,"props":4253,"children":4254},{"style":583},[4255],{"type":420,"value":814},{"type":415,"tag":559,"props":4257,"children":4258},{"style":792},[4259],{"type":420,"value":1289},{"type":415,"tag":559,"props":4261,"children":4262},{"style":583},[4263],{"type":420,"value":542},{"type":415,"tag":559,"props":4265,"children":4266},{"style":792},[4267],{"type":420,"value":1298},{"type":415,"tag":559,"props":4269,"children":4270},{"style":583},[4271],{"type":420,"value":542},{"type":415,"tag":559,"props":4273,"children":4274},{"style":883},[4275],{"type":420,"value":1365},{"type":415,"tag":559,"props":4277,"children":4278},{"style":583},[4279],{"type":420,"value":1312},{"type":415,"tag":559,"props":4281,"children":4283},{"class":561,"line":4282},52,[4284,4288,4292,4296,4300,4304,4308,4312,4316,4320,4324,4328,4332,4336,4340,4344,4348,4352,4356,4360,4364,4368],{"type":415,"tag":559,"props":4285,"children":4286},{"style":572},[4287],{"type":420,"value":1257},{"type":415,"tag":559,"props":4289,"children":4290},{"style":572},[4291],{"type":420,"value":1381},{"type":415,"tag":559,"props":4293,"children":4294},{"style":583},[4295],{"type":420,"value":763},{"type":415,"tag":559,"props":4297,"children":4298},{"style":583},[4299],{"type":420,"value":1390},{"type":415,"tag":559,"props":4301,"children":4302},{"style":883},[4303],{"type":420,"value":1395},{"type":415,"tag":559,"props":4305,"children":4306},{"style":583},[4307],{"type":420,"value":814},{"type":415,"tag":559,"props":4309,"children":4310},{"style":792},[4311],{"type":420,"value":1289},{"type":415,"tag":559,"props":4313,"children":4314},{"style":583},[4315],{"type":420,"value":542},{"type":415,"tag":559,"props":4317,"children":4318},{"style":792},[4319],{"type":420,"value":1412},{"type":415,"tag":559,"props":4321,"children":4322},{"style":583},[4323],{"type":420,"value":542},{"type":415,"tag":559,"props":4325,"children":4326},{"style":883},[4327],{"type":420,"value":1421},{"type":415,"tag":559,"props":4329,"children":4330},{"style":583},[4331],{"type":420,"value":814},{"type":415,"tag":559,"props":4333,"children":4334},{"style":583},[4335],{"type":420,"value":819},{"type":415,"tag":559,"props":4337,"children":4338},{"style":583},[4339],{"type":420,"value":1434},{"type":415,"tag":559,"props":4341,"children":4342},{"style":583},[4343],{"type":420,"value":1439},{"type":415,"tag":559,"props":4345,"children":4346},{"style":883},[4347],{"type":420,"value":1444},{"type":415,"tag":559,"props":4349,"children":4350},{"style":583},[4351],{"type":420,"value":1449},{"type":415,"tag":559,"props":4353,"children":4354},{"style":566},[4355],{"type":420,"value":1454},{"type":415,"tag":559,"props":4357,"children":4358},{"style":572},[4359],{"type":420,"value":753},{"type":415,"tag":559,"props":4361,"children":4362},{"style":572},[4363],{"type":420,"value":1463},{"type":415,"tag":559,"props":4365,"children":4366},{"style":583},[4367],{"type":420,"value":1468},{"type":415,"tag":559,"props":4369,"children":4370},{"style":792},[4371],{"type":420,"value":1473},{"type":415,"tag":559,"props":4373,"children":4375},{"class":561,"line":4374},53,[4376,4380,4384,4388,4392,4396,4400],{"type":415,"tag":559,"props":4377,"children":4378},{"style":583},[4379],{"type":420,"value":1481},{"type":415,"tag":559,"props":4381,"children":4382},{"style":792},[4383],{"type":420,"value":1486},{"type":415,"tag":559,"props":4385,"children":4386},{"style":583},[4387],{"type":420,"value":1491},{"type":415,"tag":559,"props":4389,"children":4390},{"style":792},[4391],{"type":420,"value":1262},{"type":415,"tag":559,"props":4393,"children":4394},{"style":583},[4395],{"type":420,"value":542},{"type":415,"tag":559,"props":4397,"children":4398},{"style":792},[4399],{"type":420,"value":1504},{"type":415,"tag":559,"props":4401,"children":4402},{"style":583},[4403],{"type":420,"value":1509},{"type":415,"tag":559,"props":4405,"children":4407},{"class":561,"line":4406},54,[4408,4412,4416,4420],{"type":415,"tag":559,"props":4409,"children":4410},{"style":745},[4411],{"type":420,"value":1517},{"type":415,"tag":559,"props":4413,"children":4414},{"style":583},[4415],{"type":420,"value":768},{"type":415,"tag":559,"props":4417,"children":4418},{"style":572},[4419],{"type":420,"value":968},{"type":415,"tag":559,"props":4421,"children":4422},{"style":583},[4423],{"type":420,"value":586},{"type":415,"tag":559,"props":4425,"children":4427},{"class":561,"line":4426},55,[4428,4432,4436,4440,4444,4448,4452,4456,4460,4464,4468,4472,4476,4480,4484,4488,4492],{"type":415,"tag":559,"props":4429,"children":4430},{"style":792},[4431],{"type":420,"value":1537},{"type":415,"tag":559,"props":4433,"children":4434},{"style":583},[4435],{"type":420,"value":1134},{"type":415,"tag":559,"props":4437,"children":4438},{"style":792},[4439],{"type":420,"value":1238},{"type":415,"tag":559,"props":4441,"children":4442},{"style":583},[4443],{"type":420,"value":542},{"type":415,"tag":559,"props":4445,"children":4446},{"style":792},[4447],{"type":420,"value":1554},{"type":415,"tag":559,"props":4449,"children":4450},{"style":583},[4451],{"type":420,"value":1206},{"type":415,"tag":559,"props":4453,"children":4454},{"style":583},[4455],{"type":420,"value":1563},{"type":415,"tag":559,"props":4457,"children":4458},{"style":792},[4459],{"type":420,"value":1289},{"type":415,"tag":559,"props":4461,"children":4462},{"style":583},[4463],{"type":420,"value":542},{"type":415,"tag":559,"props":4465,"children":4466},{"style":792},[4467],{"type":420,"value":1412},{"type":415,"tag":559,"props":4469,"children":4470},{"style":583},[4471],{"type":420,"value":1580},{"type":415,"tag":559,"props":4473,"children":4474},{"style":583},[4475],{"type":420,"value":1144},{"type":415,"tag":559,"props":4477,"children":4478},{"style":792},[4479],{"type":420,"value":1589},{"type":415,"tag":559,"props":4481,"children":4482},{"style":583},[4483],{"type":420,"value":542},{"type":415,"tag":559,"props":4485,"children":4486},{"style":792},[4487],{"type":420,"value":1504},{"type":415,"tag":559,"props":4489,"children":4490},{"style":583},[4491],{"type":420,"value":1602},{"type":415,"tag":559,"props":4493,"children":4494},{"style":583},[4495],{"type":420,"value":605},{"type":415,"tag":559,"props":4497,"children":4499},{"class":561,"line":4498},56,[4500,4504,4508,4512],{"type":415,"tag":559,"props":4501,"children":4502},{"style":792},[4503],{"type":420,"value":1614},{"type":415,"tag":559,"props":4505,"children":4506},{"style":583},[4507],{"type":420,"value":542},{"type":415,"tag":559,"props":4509,"children":4510},{"style":792},[4511],{"type":420,"value":1623},{"type":415,"tag":559,"props":4513,"children":4514},{"style":583},[4515],{"type":420,"value":605},{"type":415,"tag":559,"props":4517,"children":4519},{"class":561,"line":4518},57,[4520,4524],{"type":415,"tag":559,"props":4521,"children":4522},{"style":792},[4523],{"type":420,"value":1635},{"type":415,"tag":559,"props":4525,"children":4526},{"style":583},[4527],{"type":420,"value":605},{"type":415,"tag":559,"props":4529,"children":4531},{"class":561,"line":4530},58,[4532,4536],{"type":415,"tag":559,"props":4533,"children":4534},{"style":792},[4535],{"type":420,"value":1647},{"type":415,"tag":559,"props":4537,"children":4538},{"style":583},[4539],{"type":420,"value":605},{"type":415,"tag":559,"props":4541,"children":4543},{"class":561,"line":4542},59,[4544,4548,4552,4556],{"type":415,"tag":559,"props":4545,"children":4546},{"style":792},[4547],{"type":420,"value":1659},{"type":415,"tag":559,"props":4549,"children":4550},{"style":583},[4551],{"type":420,"value":542},{"type":415,"tag":559,"props":4553,"children":4554},{"style":792},[4555],{"type":420,"value":1668},{"type":415,"tag":559,"props":4557,"children":4558},{"style":583},[4559],{"type":420,"value":605},{"type":415,"tag":559,"props":4561,"children":4563},{"class":561,"line":4562},60,[4564,4568,4572,4576,4580,4584,4588,4592,4596,4600,4604,4608,4612,4616,4620,4624],{"type":415,"tag":559,"props":4565,"children":4566},{"style":792},[4567],{"type":420,"value":1614},{"type":415,"tag":559,"props":4569,"children":4570},{"style":583},[4571],{"type":420,"value":542},{"type":415,"tag":559,"props":4573,"children":4574},{"style":792},[4575],{"type":420,"value":1688},{"type":415,"tag":559,"props":4577,"children":4578},{"style":583},[4579],{"type":420,"value":1693},{"type":415,"tag":559,"props":4581,"children":4582},{"style":583},[4583],{"type":420,"value":1434},{"type":415,"tag":559,"props":4585,"children":4586},{"style":822},[4587],{"type":420,"value":1702},{"type":415,"tag":559,"props":4589,"children":4590},{"style":583},[4591],{"type":420,"value":819},{"type":415,"tag":559,"props":4593,"children":4594},{"style":583},[4595],{"type":420,"value":1711},{"type":415,"tag":559,"props":4597,"children":4598},{"style":792},[4599],{"type":420,"value":1066},{"type":415,"tag":559,"props":4601,"children":4602},{"style":583},[4603],{"type":420,"value":542},{"type":415,"tag":559,"props":4605,"children":4606},{"style":792},[4607],{"type":420,"value":1724},{"type":415,"tag":559,"props":4609,"children":4610},{"style":583},[4611],{"type":420,"value":1206},{"type":415,"tag":559,"props":4613,"children":4614},{"style":792},[4615],{"type":420,"value":1066},{"type":415,"tag":559,"props":4617,"children":4618},{"style":583},[4619],{"type":420,"value":542},{"type":415,"tag":559,"props":4621,"children":4622},{"style":792},[4623],{"type":420,"value":1741},{"type":415,"tag":559,"props":4625,"children":4626},{"style":583},[4627],{"type":420,"value":605},{"type":415,"tag":559,"props":4629,"children":4631},{"class":561,"line":4630},61,[4632,4636,4640,4644],{"type":415,"tag":559,"props":4633,"children":4634},{"style":792},[4635],{"type":420,"value":1614},{"type":415,"tag":559,"props":4637,"children":4638},{"style":583},[4639],{"type":420,"value":542},{"type":415,"tag":559,"props":4641,"children":4642},{"style":792},[4643],{"type":420,"value":1762},{"type":415,"tag":559,"props":4645,"children":4646},{"style":583},[4647],{"type":420,"value":605},{"type":415,"tag":559,"props":4649,"children":4651},{"class":561,"line":4650},62,[4652,4656,4660],{"type":415,"tag":559,"props":4653,"children":4654},{"style":792},[4655],{"type":420,"value":1614},{"type":415,"tag":559,"props":4657,"children":4658},{"style":583},[4659],{"type":420,"value":542},{"type":415,"tag":559,"props":4661,"children":4662},{"style":792},[4663],{"type":420,"value":1783},{"type":415,"tag":559,"props":4665,"children":4667},{"class":561,"line":4666},63,[4668],{"type":415,"tag":559,"props":4669,"children":4670},{"style":583},[4671],{"type":420,"value":1792},{"type":415,"tag":559,"props":4673,"children":4675},{"class":561,"line":4674},64,[4676],{"type":415,"tag":559,"props":4677,"children":4678},{"style":583},[4679],{"type":420,"value":1801},{"type":415,"tag":559,"props":4681,"children":4683},{"class":561,"line":4682},65,[4684],{"type":415,"tag":559,"props":4685,"children":4686},{"emptyLinePlaceholder":847},[4687],{"type":420,"value":850},{"type":415,"tag":559,"props":4689,"children":4691},{"class":561,"line":4690},66,[4692,4696,4700,4704],{"type":415,"tag":559,"props":4693,"children":4694},{"style":566},[4695],{"type":420,"value":569},{"type":415,"tag":559,"props":4697,"children":4698},{"style":572},[4699],{"type":420,"value":575},{"type":415,"tag":559,"props":4701,"children":4702},{"style":572},[4703],{"type":420,"value":580},{"type":415,"tag":559,"props":4705,"children":4706},{"style":583},[4707],{"type":420,"value":586},{"type":415,"tag":559,"props":4709,"children":4711},{"class":561,"line":4710},67,[4712,4716,4720],{"type":415,"tag":559,"props":4713,"children":4714},{"style":583},[4715],{"type":420,"value":595},{"type":415,"tag":559,"props":4717,"children":4718},{"style":572},[4719],{"type":420,"value":600},{"type":415,"tag":559,"props":4721,"children":4722},{"style":583},[4723],{"type":420,"value":605},{"type":415,"tag":559,"props":4725,"children":4727},{"class":561,"line":4726},68,[4728,4732,4736],{"type":415,"tag":559,"props":4729,"children":4730},{"style":583},[4731],{"type":420,"value":614},{"type":415,"tag":559,"props":4733,"children":4734},{"style":572},[4735],{"type":420,"value":619},{"type":415,"tag":559,"props":4737,"children":4738},{"style":583},[4739],{"type":420,"value":605},{"type":415,"tag":559,"props":4741,"children":4743},{"class":561,"line":4742},69,[4744,4748,4752],{"type":415,"tag":559,"props":4745,"children":4746},{"style":583},[4747],{"type":420,"value":595},{"type":415,"tag":559,"props":4749,"children":4750},{"style":572},[4751],{"type":420,"value":636},{"type":415,"tag":559,"props":4753,"children":4754},{"style":583},[4755],{"type":420,"value":605},{"type":415,"tag":559,"props":4757,"children":4759},{"class":561,"line":4758},70,[4760,4764,4768],{"type":415,"tag":559,"props":4761,"children":4762},{"style":583},[4763],{"type":420,"value":595},{"type":415,"tag":559,"props":4765,"children":4766},{"style":572},[4767],{"type":420,"value":653},{"type":415,"tag":559,"props":4769,"children":4770},{"style":583},[4771],{"type":420,"value":605},{"type":415,"tag":559,"props":4773,"children":4775},{"class":561,"line":4774},71,[4776,4780,4784],{"type":415,"tag":559,"props":4777,"children":4778},{"style":583},[4779],{"type":420,"value":595},{"type":415,"tag":559,"props":4781,"children":4782},{"style":572},[4783],{"type":420,"value":670},{"type":415,"tag":559,"props":4785,"children":4786},{"style":583},[4787],{"type":420,"value":605},{"type":415,"tag":559,"props":4789,"children":4791},{"class":561,"line":4790},72,[4792,4796],{"type":415,"tag":559,"props":4793,"children":4794},{"style":583},[4795],{"type":420,"value":595},{"type":415,"tag":559,"props":4797,"children":4798},{"style":572},[4799],{"type":420,"value":687},{"type":415,"tag":559,"props":4801,"children":4803},{"class":561,"line":4802},73,[4804],{"type":415,"tag":559,"props":4805,"children":4806},{"style":583},[4807],{"type":420,"value":696},{"type":415,"tag":559,"props":4809,"children":4811},{"class":561,"line":4810},74,[4812],{"type":415,"tag":559,"props":4813,"children":4814},{"emptyLinePlaceholder":847},[4815],{"type":420,"value":850},{"type":415,"tag":559,"props":4817,"children":4819},{"class":561,"line":4818},75,[4820,4824,4828,4832],{"type":415,"tag":559,"props":4821,"children":4822},{"style":566},[4823],{"type":420,"value":569},{"type":415,"tag":559,"props":4825,"children":4826},{"style":572},[4827],{"type":420,"value":575},{"type":415,"tag":559,"props":4829,"children":4830},{"style":572},[4831],{"type":420,"value":968},{"type":415,"tag":559,"props":4833,"children":4834},{"style":583},[4835],{"type":420,"value":586},{"type":415,"tag":559,"props":4837,"children":4839},{"class":561,"line":4838},76,[4840,4844,4848],{"type":415,"tag":559,"props":4841,"children":4842},{"style":583},[4843],{"type":420,"value":595},{"type":415,"tag":559,"props":4845,"children":4846},{"style":572},[4847],{"type":420,"value":600},{"type":415,"tag":559,"props":4849,"children":4850},{"style":583},[4851],{"type":420,"value":605},{"type":415,"tag":559,"props":4853,"children":4855},{"class":561,"line":4854},77,[4856,4860,4864],{"type":415,"tag":559,"props":4857,"children":4858},{"style":583},[4859],{"type":420,"value":595},{"type":415,"tag":559,"props":4861,"children":4862},{"style":572},[4863],{"type":420,"value":999},{"type":415,"tag":559,"props":4865,"children":4866},{"style":583},[4867],{"type":420,"value":605},{"type":415,"tag":559,"props":4869,"children":4871},{"class":561,"line":4870},78,[4872,4876,4880],{"type":415,"tag":559,"props":4873,"children":4874},{"style":572},[4875],{"type":420,"value":1011},{"type":415,"tag":559,"props":4877,"children":4878},{"style":572},[4879],{"type":420,"value":1016},{"type":415,"tag":559,"props":4881,"children":4882},{"style":583},[4883],{"type":420,"value":605},{"type":415,"tag":559,"props":4885,"children":4887},{"class":561,"line":4886},79,[4888,4892,4896],{"type":415,"tag":559,"props":4889,"children":4890},{"style":572},[4891],{"type":420,"value":1011},{"type":415,"tag":559,"props":4893,"children":4894},{"style":572},[4895],{"type":420,"value":1032},{"type":415,"tag":559,"props":4897,"children":4898},{"style":583},[4899],{"type":420,"value":605},{"type":415,"tag":559,"props":4901,"children":4903},{"class":561,"line":4902},80,[4904,4908,4912],{"type":415,"tag":559,"props":4905,"children":4906},{"style":572},[4907],{"type":420,"value":1044},{"type":415,"tag":559,"props":4909,"children":4910},{"style":572},[4911],{"type":420,"value":1049},{"type":415,"tag":559,"props":4913,"children":4914},{"style":583},[4915],{"type":420,"value":605},{"type":415,"tag":559,"props":4917,"children":4919},{"class":561,"line":4918},81,[4920,4924,4928],{"type":415,"tag":559,"props":4921,"children":4922},{"style":572},[4923],{"type":420,"value":1061},{"type":415,"tag":559,"props":4925,"children":4926},{"style":572},[4927],{"type":420,"value":1066},{"type":415,"tag":559,"props":4929,"children":4930},{"style":583},[4931],{"type":420,"value":605},{"type":415,"tag":559,"props":4933,"children":4935},{"class":561,"line":4934},82,[4936,4940,4944],{"type":415,"tag":559,"props":4937,"children":4938},{"style":583},[4939],{"type":420,"value":595},{"type":415,"tag":559,"props":4941,"children":4942},{"style":572},[4943],{"type":420,"value":1082},{"type":415,"tag":559,"props":4945,"children":4946},{"style":583},[4947],{"type":420,"value":605},{"type":415,"tag":559,"props":4949,"children":4951},{"class":561,"line":4950},83,[4952,4956],{"type":415,"tag":559,"props":4953,"children":4954},{"style":583},[4955],{"type":420,"value":595},{"type":415,"tag":559,"props":4957,"children":4958},{"style":572},[4959],{"type":420,"value":1099},{"type":415,"tag":559,"props":4961,"children":4963},{"class":561,"line":4962},84,[4964],{"type":415,"tag":559,"props":4965,"children":4966},{"style":583},[4967],{"type":420,"value":833},{"type":415,"tag":559,"props":4969,"children":4971},{"class":561,"line":4970},85,[4972],{"type":415,"tag":559,"props":4973,"children":4974},{"style":583},[4975],{"type":420,"value":786},{"type":415,"tag":559,"props":4977,"children":4979},{"class":561,"line":4978},86,[4980,4984,4988,4992,4996,5000,5004,5008,5012,5016],{"type":415,"tag":559,"props":4981,"children":4982},{"style":566},[4983],{"type":420,"value":1124},{"type":415,"tag":559,"props":4985,"children":4986},{"style":583},[4987],{"type":420,"value":1129},{"type":415,"tag":559,"props":4989,"children":4990},{"style":583},[4991],{"type":420,"value":1134},{"type":415,"tag":559,"props":4993,"children":4994},{"style":572},[4995],{"type":420,"value":1139},{"type":415,"tag":559,"props":4997,"children":4998},{"style":583},[4999],{"type":420,"value":1144},{"type":415,"tag":559,"props":5001,"children":5002},{"style":572},[5003],{"type":420,"value":1149},{"type":415,"tag":559,"props":5005,"children":5006},{"style":583},[5007],{"type":420,"value":1154},{"type":415,"tag":559,"props":5009,"children":5010},{"style":572},[5011],{"type":420,"value":1159},{"type":415,"tag":559,"props":5013,"children":5014},{"style":583},[5015],{"type":420,"value":1154},{"type":415,"tag":559,"props":5017,"children":5018},{"style":583},[5019],{"type":420,"value":1168},{"type":415,"tag":559,"props":5021,"children":5023},{"class":561,"line":5022},87,[5024],{"type":415,"tag":559,"props":5025,"children":5026},{"style":583},[5027],{"type":420,"value":841},{"type":415,"tag":559,"props":5029,"children":5031},{"class":561,"line":5030},88,[5032],{"type":415,"tag":559,"props":5033,"children":5034},{"emptyLinePlaceholder":847},[5035],{"type":420,"value":850},{"type":415,"tag":559,"props":5037,"children":5039},{"class":561,"line":5038},89,[5040,5044,5049],{"type":415,"tag":559,"props":5041,"children":5042},{"style":566},[5043],{"type":420,"value":569},{"type":415,"tag":559,"props":5045,"children":5046},{"style":572},[5047],{"type":420,"value":5048}," enum",{"type":415,"tag":559,"props":5050,"children":5051},{"style":572},[5052],{"type":420,"value":5053}," EventFormat\n",{"type":415,"tag":559,"props":5055,"children":5057},{"class":561,"line":5056},90,[5058],{"type":415,"tag":559,"props":5059,"children":5060},{"style":583},[5061],{"type":420,"value":786},{"type":415,"tag":559,"props":5063,"children":5065},{"class":561,"line":5064},91,[5066,5071,5075,5080],{"type":415,"tag":559,"props":5067,"children":5068},{"style":572},[5069],{"type":420,"value":5070},"    Unknown",{"type":415,"tag":559,"props":5072,"children":5073},{"style":583},[5074],{"type":420,"value":763},{"type":415,"tag":559,"props":5076,"children":5077},{"style":2846},[5078],{"type":420,"value":5079}," 1",{"type":415,"tag":559,"props":5081,"children":5082},{"style":583},[5083],{"type":420,"value":605},{"type":415,"tag":559,"props":5085,"children":5087},{"class":561,"line":5086},92,[5088,5093,5097,5102],{"type":415,"tag":559,"props":5089,"children":5090},{"style":572},[5091],{"type":420,"value":5092},"    Virtual",{"type":415,"tag":559,"props":5094,"children":5095},{"style":583},[5096],{"type":420,"value":763},{"type":415,"tag":559,"props":5098,"children":5099},{"style":2846},[5100],{"type":420,"value":5101}," 2",{"type":415,"tag":559,"props":5103,"children":5104},{"style":583},[5105],{"type":420,"value":605},{"type":415,"tag":559,"props":5107,"children":5109},{"class":561,"line":5108},93,[5110,5115,5119,5124],{"type":415,"tag":559,"props":5111,"children":5112},{"style":572},[5113],{"type":420,"value":5114},"    In_Person",{"type":415,"tag":559,"props":5116,"children":5117},{"style":583},[5118],{"type":420,"value":763},{"type":415,"tag":559,"props":5120,"children":5121},{"style":2846},[5122],{"type":420,"value":5123}," 3",{"type":415,"tag":559,"props":5125,"children":5126},{"style":583},[5127],{"type":420,"value":605},{"type":415,"tag":559,"props":5129,"children":5131},{"class":561,"line":5130},94,[5132,5137,5141],{"type":415,"tag":559,"props":5133,"children":5134},{"style":572},[5135],{"type":420,"value":5136},"    Hybrid",{"type":415,"tag":559,"props":5138,"children":5139},{"style":583},[5140],{"type":420,"value":763},{"type":415,"tag":559,"props":5142,"children":5143},{"style":2846},[5144],{"type":420,"value":5145}," 4\n",{"type":415,"tag":559,"props":5147,"children":5149},{"class":561,"line":5148},95,[5150],{"type":415,"tag":559,"props":5151,"children":5152},{"style":583},[5153],{"type":420,"value":1801},{"type":415,"tag":559,"props":5155,"children":5157},{"class":561,"line":5156},96,[5158],{"type":415,"tag":559,"props":5159,"children":5160},{"emptyLinePlaceholder":847},[5161],{"type":420,"value":850},{"type":415,"tag":559,"props":5163,"children":5165},{"class":561,"line":5164},97,[5166,5170,5174],{"type":415,"tag":559,"props":5167,"children":5168},{"style":566},[5169],{"type":420,"value":569},{"type":415,"tag":559,"props":5171,"children":5172},{"style":572},[5173],{"type":420,"value":5048},{"type":415,"tag":559,"props":5175,"children":5176},{"style":572},[5177],{"type":420,"value":5178}," EventType\n",{"type":415,"tag":559,"props":5180,"children":5182},{"class":561,"line":5181},98,[5183],{"type":415,"tag":559,"props":5184,"children":5185},{"style":583},[5186],{"type":420,"value":786},{"type":415,"tag":559,"props":5188,"children":5190},{"class":561,"line":5189},99,[5191,5196,5200,5205],{"type":415,"tag":559,"props":5192,"children":5193},{"style":572},[5194],{"type":420,"value":5195},"    Any",{"type":415,"tag":559,"props":5197,"children":5198},{"style":583},[5199],{"type":420,"value":763},{"type":415,"tag":559,"props":5201,"children":5202},{"style":2846},[5203],{"type":420,"value":5204}," 0",{"type":415,"tag":559,"props":5206,"children":5207},{"style":583},[5208],{"type":420,"value":605},{"type":415,"tag":559,"props":5210,"children":5212},{"class":561,"line":5211},100,[5213,5217,5221,5225],{"type":415,"tag":559,"props":5214,"children":5215},{"style":572},[5216],{"type":420,"value":5070},{"type":415,"tag":559,"props":5218,"children":5219},{"style":583},[5220],{"type":420,"value":763},{"type":415,"tag":559,"props":5222,"children":5223},{"style":2846},[5224],{"type":420,"value":5079},{"type":415,"tag":559,"props":5226,"children":5227},{"style":583},[5228],{"type":420,"value":605},{"type":415,"tag":559,"props":5230,"children":5232},{"class":561,"line":5231},101,[5233,5238,5242,5246],{"type":415,"tag":559,"props":5234,"children":5235},{"style":572},[5236],{"type":420,"value":5237},"    Conference",{"type":415,"tag":559,"props":5239,"children":5240},{"style":583},[5241],{"type":420,"value":763},{"type":415,"tag":559,"props":5243,"children":5244},{"style":2846},[5245],{"type":420,"value":5101},{"type":415,"tag":559,"props":5247,"children":5248},{"style":583},[5249],{"type":420,"value":605},{"type":415,"tag":559,"props":5251,"children":5253},{"class":561,"line":5252},102,[5254,5259,5263,5267],{"type":415,"tag":559,"props":5255,"children":5256},{"style":572},[5257],{"type":420,"value":5258},"    Meetup",{"type":415,"tag":559,"props":5260,"children":5261},{"style":583},[5262],{"type":420,"value":763},{"type":415,"tag":559,"props":5264,"children":5265},{"style":2846},[5266],{"type":420,"value":5123},{"type":415,"tag":559,"props":5268,"children":5269},{"style":583},[5270],{"type":420,"value":605},{"type":415,"tag":559,"props":5272,"children":5274},{"class":561,"line":5273},103,[5275,5280,5284,5289],{"type":415,"tag":559,"props":5276,"children":5277},{"style":572},[5278],{"type":420,"value":5279},"    Hackathon",{"type":415,"tag":559,"props":5281,"children":5282},{"style":583},[5283],{"type":420,"value":763},{"type":415,"tag":559,"props":5285,"children":5286},{"style":2846},[5287],{"type":420,"value":5288}," 4",{"type":415,"tag":559,"props":5290,"children":5291},{"style":583},[5292],{"type":420,"value":605},{"type":415,"tag":559,"props":5294,"children":5296},{"class":561,"line":5295},104,[5297,5302,5306,5311],{"type":415,"tag":559,"props":5298,"children":5299},{"style":572},[5300],{"type":420,"value":5301},"    Call_For_Papers",{"type":415,"tag":559,"props":5303,"children":5304},{"style":583},[5305],{"type":420,"value":763},{"type":415,"tag":559,"props":5307,"children":5308},{"style":2846},[5309],{"type":420,"value":5310}," 5",{"type":415,"tag":559,"props":5312,"children":5313},{"style":583},[5314],{"type":420,"value":605},{"type":415,"tag":559,"props":5316,"children":5318},{"class":561,"line":5317},105,[5319,5324,5328,5333],{"type":415,"tag":559,"props":5320,"children":5321},{"style":572},[5322],{"type":420,"value":5323},"    Website",{"type":415,"tag":559,"props":5325,"children":5326},{"style":583},[5327],{"type":420,"value":763},{"type":415,"tag":559,"props":5329,"children":5330},{"style":2846},[5331],{"type":420,"value":5332}," 6",{"type":415,"tag":559,"props":5334,"children":5335},{"style":583},[5336],{"type":420,"value":605},{"type":415,"tag":559,"props":5338,"children":5340},{"class":561,"line":5339},106,[5341],{"type":415,"tag":559,"props":5342,"children":5343},{"style":583},[5344],{"type":420,"value":1801},{"type":415,"tag":416,"props":5346,"children":5347},{},[5348],{"type":420,"value":5349},"Keep it mind that it's a quick experiment to automate the submission of developer conferences to the Tech Community Calendar, not production-ready code.",{"type":415,"tag":422,"props":5351,"children":5353},{"id":5352},"final-thoughts",[5354],{"type":420,"value":5355},"Final Thoughts",{"type":415,"tag":416,"props":5357,"children":5358},{},[5359],{"type":420,"value":5360},"I think this PoC is a good starting point to create a scheduled process that automatically submit the events from the developers conferences agenda to the tech community calendar.",{"type":415,"tag":1178,"props":5362,"children":5364},{"icon":5363},"i-heroicons-light-bulb",[5365],{"type":415,"tag":416,"props":5366,"children":5367},{},[5368],{"type":420,"value":5369},"Of course it would be great to do the opposite as well (automatically import events from the tech community calendar to the developers conferences agenda) but it seems complicated as events in the tech community calendar are stored in a database I don't have access to and it would involved parsing and writing in the README file of the developers conferences agenda repository.",{"type":415,"tag":416,"props":5371,"children":5372},{},[5373],{"type":420,"value":5374},"Some ideas for improvement:",{"type":415,"tag":5376,"props":5377,"children":5378},"ul",{},[5379,5385,5390],{"type":415,"tag":5380,"props":5381,"children":5382},"li",{},[5383],{"type":420,"value":5384},"store somewhere the events already submitted to only process new events on each run",{"type":415,"tag":5380,"props":5386,"children":5387},{},[5388],{"type":420,"value":5389},"parallelize the processing of events as retrieving the twitter URL of submitting an event can take some time",{"type":415,"tag":5380,"props":5391,"children":5392},{},[5393],{"type":420,"value":5394},"reorganize the code",{"type":415,"tag":416,"props":5396,"children":5397},{},[5398],{"type":420,"value":5399},"It was the first time I used AngleSharp, and I was happy with the result. It's a nice library that I would use again for similar needs.",{"type":415,"tag":416,"props":5401,"children":5402},{},[5403],{"type":420,"value":5404},"A big thank you to the contributors of these IT event calendars. As someone who tries to attend tech events and speak at developer conferences, I find them incredibly useful. A special shoutout to Aurélie Vache and her developer conferences agenda for making this data openly available (JSON files with CFPs and conferences publicly accessible).",{"type":415,"tag":5406,"props":5407,"children":5408},"style",{},[5409],{"type":420,"value":5410},"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":589,"depth":589,"links":5412},[5413,5414,5415,5416,5417,5418,5419,5420],{"id":424,"depth":589,"text":427},{"id":474,"depth":589,"text":477},{"id":525,"depth":589,"text":528},{"id":921,"depth":589,"text":924},{"id":1965,"depth":589,"text":1968},{"id":2468,"depth":589,"text":2471},{"id":2817,"depth":589,"text":2820},{"id":5352,"depth":589,"text":5355},"markdown","content:1.posts:60.it-event-calendars.md","content","1.posts/60.it-event-calendars.md","md",{"_path":184,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":183,"description":5427,"lead":5428,"date":5429,"image":5430,"badge":5432,"tags":5433,"ImageAttribution":5434,"body":5435,"_type":5421,"_id":8426,"_source":5423,"_file":8427,"_extension":5425},"I love how the Azure SDKs have evolved over the years. In the past, there was no consistency between the various Azure SDKs. However, that's not longer the case (at least for most Azure libraries), as they now adhere to the same principles and follow a set of well-defined guidelines.","Register your Azure clients the proper way","2024-02-19T00:00:00.000Z",{"src":5431},"/images/apple-di.webp",{"label":408},[228,302,239],"Picture of \u003Ca href=\"https://unsplash.com/fr/@sarabakhshi\">Sara Bakhshi\u003C/a> on \u003Ca href=\"https://unsplash.com/fr/photos/pomme-fruit-avec-des-seringues-en-plastique-MfnX4XtGnvU\">Unsplash\u003C/a>",{"type":412,"children":5436,"toc":8418},[5437,5450,5467,5472,5490,5495,5501,5515,5520,5533,5895,5915,6331,6369,6375,6389,6669,6674,6699,6705,6717,6986,6999,7424,7435,7449,7455,7468,7473,7715,7720,7890,7896,7918,7962,8375,8387,8393,8409,8414],{"type":415,"tag":416,"props":5438,"children":5439},{},[5440,5442,5449],{"type":420,"value":5441},"I love how the Azure SDKs have evolved over the years. In the past, there was no consistency between the various Azure SDKs. However, that's not longer the case (at least for most Azure libraries), as they now adhere to the same principles and follow a set of well-defined ",{"type":415,"tag":434,"props":5443,"children":5446},{"href":5444,"rel":5445},"https://azure.github.io/azure-sdk/general_introduction.html",[438],[5447],{"type":420,"value":5448},"guidelines",{"type":420,"value":542},{"type":415,"tag":1178,"props":5451,"children":5452},{"icon":5363},[5453],{"type":415,"tag":416,"props":5454,"children":5455},{},[5456,5458,5465],{"type":420,"value":5457},"You can learn more about these guidelines and how the Azure .NET SDKs work in this ",{"type":415,"tag":434,"props":5459,"children":5462},{"href":5460,"rel":5461},"https://youtu.be/v36NXLU3TLY?si=L8e1ic898kDCisJ7",[438],[5463],{"type":420,"value":5464},"video",{"type":420,"value":5466}," from 2021 which is I think still relevant today.",{"type":415,"tag":416,"props":5468,"children":5469},{},[5470],{"type":420,"value":5471},"Having consistency between libraries, it's easier to handle things like authentication and dependency injection consistently when you are using multiple Azure SDKs in your project.",{"type":415,"tag":416,"props":5473,"children":5474},{},[5475,5477,5488],{"type":420,"value":5476},"One aspect often overlooked by people using Azure SDKs is the use of ",{"type":415,"tag":434,"props":5478,"children":5481},{"href":5479,"rel":5480},"https://www.nuget.org/packages/Microsoft.Extensions.Azure",[438],[5482],{"type":415,"tag":555,"props":5483,"children":5485},{"className":5484},[],[5486],{"type":420,"value":5487},"Microsoft.Extensions.Azure",{"type":420,"value":5489},". This package facilitates registering and configuring the service clients for interacting with Azure APIs.",{"type":415,"tag":416,"props":5491,"children":5492},{},[5493],{"type":420,"value":5494},"Let's see why using this package could be beneficial for your project.",{"type":415,"tag":422,"props":5496,"children":5498},{"id":5497},"avoid-making-mistakes-when-registering-service-clients",[5499],{"type":420,"value":5500},"Avoid making mistakes when registering service clients",{"type":415,"tag":416,"props":5502,"children":5503},{},[5504,5506,5513],{"type":420,"value":5505},"It's mentioned in the ",{"type":415,"tag":434,"props":5507,"children":5510},{"href":5508,"rel":5509},"https://learn.microsoft.com/en-us/dotnet/azure/sdk/dependency-injection?view=azure-dotnet&tabs=web-app-builder",[438],[5511],{"type":420,"value":5512},"documentation",{"type":420,"value":5514}," to use this package for dependency injection with the Azure SDK for .NET. Still, many people don't read the documentation and manually register the Azure service clients.",{"type":415,"tag":416,"props":5516,"children":5517},{},[5518],{"type":420,"value":5519},"It's not a problem in itself if you know what you are doing. Otherwise,",{"type":415,"tag":5376,"props":5521,"children":5522},{},[5523,5528],{"type":415,"tag":5380,"props":5524,"children":5525},{},[5526],{"type":420,"value":5527},"you might choose the wrong lifetime for the Azure service clients, they must be singleton",{"type":415,"tag":5380,"props":5529,"children":5530},{},[5531],{"type":420,"value":5532},"you may forget to register a dependency that is needed for your use of the SDK",{"type":415,"tag":549,"props":5534,"children":5536},{"className":551,"code":5535,"language":326,"meta":401,"style":401},"using Azure.Identity;\nusing DIWithAzureSDK;\nusing Microsoft.Extensions.Azure;\n\nvar builder = Host.CreateApplicationBuilder(args);\nbuilder.Services.AddHostedService\u003CWorker>();\nbuilder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"));\n    clientBuilder.UseCredential(new DefaultAzureCredential());\n});\n\nvar host = builder.Build();\nhost.Run();\n",[5537],{"type":415,"tag":555,"props":5538,"children":5539},{"__ignoreMap":401},[5540,5565,5581,5614,5621,5664,5704,5742,5749,5797,5826,5834,5841,5874],{"type":415,"tag":559,"props":5541,"children":5542},{"class":561,"line":562},[5543,5547,5552,5556,5561],{"type":415,"tag":559,"props":5544,"children":5545},{"style":2846},[5546],{"type":420,"value":748},{"type":415,"tag":559,"props":5548,"children":5549},{"style":792},[5550],{"type":420,"value":5551}," Azure",{"type":415,"tag":559,"props":5553,"children":5554},{"style":583},[5555],{"type":420,"value":542},{"type":415,"tag":559,"props":5557,"children":5558},{"style":792},[5559],{"type":420,"value":5560},"Identity",{"type":415,"tag":559,"props":5562,"children":5563},{"style":583},[5564],{"type":420,"value":1509},{"type":415,"tag":559,"props":5566,"children":5567},{"class":561,"line":589},[5568,5572,5577],{"type":415,"tag":559,"props":5569,"children":5570},{"style":2846},[5571],{"type":420,"value":748},{"type":415,"tag":559,"props":5573,"children":5574},{"style":792},[5575],{"type":420,"value":5576}," DIWithAzureSDK",{"type":415,"tag":559,"props":5578,"children":5579},{"style":583},[5580],{"type":420,"value":1509},{"type":415,"tag":559,"props":5582,"children":5583},{"class":561,"line":608},[5584,5588,5593,5597,5602,5606,5610],{"type":415,"tag":559,"props":5585,"children":5586},{"style":2846},[5587],{"type":420,"value":748},{"type":415,"tag":559,"props":5589,"children":5590},{"style":792},[5591],{"type":420,"value":5592}," Microsoft",{"type":415,"tag":559,"props":5594,"children":5595},{"style":583},[5596],{"type":420,"value":542},{"type":415,"tag":559,"props":5598,"children":5599},{"style":792},[5600],{"type":420,"value":5601},"Extensions",{"type":415,"tag":559,"props":5603,"children":5604},{"style":583},[5605],{"type":420,"value":542},{"type":415,"tag":559,"props":5607,"children":5608},{"style":792},[5609],{"type":420,"value":228},{"type":415,"tag":559,"props":5611,"children":5612},{"style":583},[5613],{"type":420,"value":1509},{"type":415,"tag":559,"props":5615,"children":5616},{"class":561,"line":626},[5617],{"type":415,"tag":559,"props":5618,"children":5619},{"emptyLinePlaceholder":847},[5620],{"type":420,"value":850},{"type":415,"tag":559,"props":5622,"children":5623},{"class":561,"line":643},[5624,5628,5633,5637,5642,5646,5651,5655,5660],{"type":415,"tag":559,"props":5625,"children":5626},{"style":572},[5627],{"type":420,"value":858},{"type":415,"tag":559,"props":5629,"children":5630},{"style":572},[5631],{"type":420,"value":5632}," builder",{"type":415,"tag":559,"props":5634,"children":5635},{"style":583},[5636],{"type":420,"value":763},{"type":415,"tag":559,"props":5638,"children":5639},{"style":792},[5640],{"type":420,"value":5641}," Host",{"type":415,"tag":559,"props":5643,"children":5644},{"style":583},[5645],{"type":420,"value":542},{"type":415,"tag":559,"props":5647,"children":5648},{"style":883},[5649],{"type":420,"value":5650},"CreateApplicationBuilder",{"type":415,"tag":559,"props":5652,"children":5653},{"style":583},[5654],{"type":420,"value":814},{"type":415,"tag":559,"props":5656,"children":5657},{"style":792},[5658],{"type":420,"value":5659},"args",{"type":415,"tag":559,"props":5661,"children":5662},{"style":583},[5663],{"type":420,"value":696},{"type":415,"tag":559,"props":5665,"children":5666},{"class":561,"line":660},[5667,5672,5676,5681,5685,5690,5694,5699],{"type":415,"tag":559,"props":5668,"children":5669},{"style":792},[5670],{"type":420,"value":5671},"builder",{"type":415,"tag":559,"props":5673,"children":5674},{"style":583},[5675],{"type":420,"value":542},{"type":415,"tag":559,"props":5677,"children":5678},{"style":792},[5679],{"type":420,"value":5680},"Services",{"type":415,"tag":559,"props":5682,"children":5683},{"style":583},[5684],{"type":420,"value":542},{"type":415,"tag":559,"props":5686,"children":5687},{"style":883},[5688],{"type":420,"value":5689},"AddHostedService",{"type":415,"tag":559,"props":5691,"children":5692},{"style":583},[5693],{"type":420,"value":891},{"type":415,"tag":559,"props":5695,"children":5696},{"style":572},[5697],{"type":420,"value":5698},"Worker",{"type":415,"tag":559,"props":5700,"children":5701},{"style":583},[5702],{"type":420,"value":5703},">();\n",{"type":415,"tag":559,"props":5705,"children":5706},{"class":561,"line":677},[5707,5711,5715,5719,5723,5728,5732,5737],{"type":415,"tag":559,"props":5708,"children":5709},{"style":792},[5710],{"type":420,"value":5671},{"type":415,"tag":559,"props":5712,"children":5713},{"style":583},[5714],{"type":420,"value":542},{"type":415,"tag":559,"props":5716,"children":5717},{"style":792},[5718],{"type":420,"value":5680},{"type":415,"tag":559,"props":5720,"children":5721},{"style":583},[5722],{"type":420,"value":542},{"type":415,"tag":559,"props":5724,"children":5725},{"style":883},[5726],{"type":420,"value":5727},"AddAzureClients",{"type":415,"tag":559,"props":5729,"children":5730},{"style":583},[5731],{"type":420,"value":814},{"type":415,"tag":559,"props":5733,"children":5734},{"style":572},[5735],{"type":420,"value":5736},"clientBuilder",{"type":415,"tag":559,"props":5738,"children":5739},{"style":583},[5740],{"type":420,"value":5741}," =>\n",{"type":415,"tag":559,"props":5743,"children":5744},{"class":561,"line":690},[5745],{"type":415,"tag":559,"props":5746,"children":5747},{"style":583},[5748],{"type":420,"value":786},{"type":415,"tag":559,"props":5750,"children":5751},{"class":561,"line":1089},[5752,5757,5761,5766,5771,5775,5779,5783,5788,5792],{"type":415,"tag":559,"props":5753,"children":5754},{"style":792},[5755],{"type":420,"value":5756},"    clientBuilder",{"type":415,"tag":559,"props":5758,"children":5759},{"style":583},[5760],{"type":420,"value":542},{"type":415,"tag":559,"props":5762,"children":5763},{"style":883},[5764],{"type":420,"value":5765},"AddBlobServiceClient",{"type":415,"tag":559,"props":5767,"children":5768},{"style":583},[5769],{"type":420,"value":5770},"(new",{"type":415,"tag":559,"props":5772,"children":5773},{"style":572},[5774],{"type":420,"value":809},{"type":415,"tag":559,"props":5776,"children":5777},{"style":583},[5778],{"type":420,"value":814},{"type":415,"tag":559,"props":5780,"children":5781},{"style":583},[5782],{"type":420,"value":819},{"type":415,"tag":559,"props":5784,"children":5785},{"style":822},[5786],{"type":420,"value":5787},"https://stdiwithazuresdk.blob.core.windows.net/",{"type":415,"tag":559,"props":5789,"children":5790},{"style":583},[5791],{"type":420,"value":819},{"type":415,"tag":559,"props":5793,"children":5794},{"style":583},[5795],{"type":420,"value":5796},"));\n",{"type":415,"tag":559,"props":5798,"children":5799},{"class":561,"line":1102},[5800,5804,5808,5813,5817,5822],{"type":415,"tag":559,"props":5801,"children":5802},{"style":792},[5803],{"type":420,"value":5756},{"type":415,"tag":559,"props":5805,"children":5806},{"style":583},[5807],{"type":420,"value":542},{"type":415,"tag":559,"props":5809,"children":5810},{"style":883},[5811],{"type":420,"value":5812},"UseCredential",{"type":415,"tag":559,"props":5814,"children":5815},{"style":583},[5816],{"type":420,"value":5770},{"type":415,"tag":559,"props":5818,"children":5819},{"style":572},[5820],{"type":420,"value":5821}," DefaultAzureCredential",{"type":415,"tag":559,"props":5823,"children":5824},{"style":583},[5825],{"type":420,"value":1312},{"type":415,"tag":559,"props":5827,"children":5828},{"class":561,"line":1110},[5829],{"type":415,"tag":559,"props":5830,"children":5831},{"style":583},[5832],{"type":420,"value":5833},"});\n",{"type":415,"tag":559,"props":5835,"children":5836},{"class":561,"line":1118},[5837],{"type":415,"tag":559,"props":5838,"children":5839},{"emptyLinePlaceholder":847},[5840],{"type":420,"value":850},{"type":415,"tag":559,"props":5842,"children":5843},{"class":561,"line":1171},[5844,5848,5853,5857,5861,5865,5870],{"type":415,"tag":559,"props":5845,"children":5846},{"style":572},[5847],{"type":420,"value":858},{"type":415,"tag":559,"props":5849,"children":5850},{"style":572},[5851],{"type":420,"value":5852}," host",{"type":415,"tag":559,"props":5854,"children":5855},{"style":583},[5856],{"type":420,"value":763},{"type":415,"tag":559,"props":5858,"children":5859},{"style":792},[5860],{"type":420,"value":5632},{"type":415,"tag":559,"props":5862,"children":5863},{"style":583},[5864],{"type":420,"value":542},{"type":415,"tag":559,"props":5866,"children":5867},{"style":883},[5868],{"type":420,"value":5869},"Build",{"type":415,"tag":559,"props":5871,"children":5872},{"style":583},[5873],{"type":420,"value":1962},{"type":415,"tag":559,"props":5875,"children":5876},{"class":561,"line":1748},[5877,5882,5886,5891],{"type":415,"tag":559,"props":5878,"children":5879},{"style":792},[5880],{"type":420,"value":5881},"host",{"type":415,"tag":559,"props":5883,"children":5884},{"style":583},[5885],{"type":420,"value":542},{"type":415,"tag":559,"props":5887,"children":5888},{"style":883},[5889],{"type":420,"value":5890},"Run",{"type":415,"tag":559,"props":5892,"children":5893},{"style":583},[5894],{"type":420,"value":1962},{"type":415,"tag":416,"props":5896,"children":5897},{},[5898,5900,5905,5907,5913],{"type":420,"value":5899},"In this sample, the ",{"type":415,"tag":555,"props":5901,"children":5903},{"className":5902},[],[5904],{"type":420,"value":5765},{"type":420,"value":5906}," handles the registration of all dependencies for us so that the ",{"type":415,"tag":555,"props":5908,"children":5910},{"className":5909},[],[5911],{"type":420,"value":5912},"BlobServiceClient",{"type":420,"value":5914}," can then be injected directly where needed.",{"type":415,"tag":549,"props":5916,"children":5918},{"className":551,"code":5917,"language":326,"meta":401,"style":401},"public class Worker : BackgroundService\n{\n    private readonly ILogger\u003CWorker> _logger;\n    private readonly BlobServiceClient _blobServiceClient;\n\n    public Worker(ILogger\u003CWorker> logger, BlobServiceClient blobServiceClient)\n    {\n        _logger = logger;\n        _blobServiceClient = blobServiceClient;\n    }\n\n    protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n    {\n        await foreach (var blobContainer in _blobServiceClient.GetBlobContainersAsync(cancellationToken: stoppingToken))\n        {\n            _logger.LogInformation(blobContainer.Name);\n        }\n    }\n}\n",[5919],{"type":415,"tag":555,"props":5920,"children":5921},{"__ignoreMap":401},[5922,5948,5955,5995,6020,6027,6081,6088,6108,6128,6135,6142,6187,6194,6259,6267,6309,6317,6324],{"type":415,"tag":559,"props":5923,"children":5924},{"class":561,"line":562},[5925,5929,5934,5939,5943],{"type":415,"tag":559,"props":5926,"children":5927},{"style":566},[5928],{"type":420,"value":569},{"type":415,"tag":559,"props":5930,"children":5931},{"style":572},[5932],{"type":420,"value":5933}," class",{"type":415,"tag":559,"props":5935,"children":5936},{"style":572},[5937],{"type":420,"value":5938}," Worker",{"type":415,"tag":559,"props":5940,"children":5941},{"style":583},[5942],{"type":420,"value":2437},{"type":415,"tag":559,"props":5944,"children":5945},{"style":572},[5946],{"type":420,"value":5947}," BackgroundService\n",{"type":415,"tag":559,"props":5949,"children":5950},{"class":561,"line":589},[5951],{"type":415,"tag":559,"props":5952,"children":5953},{"style":583},[5954],{"type":420,"value":786},{"type":415,"tag":559,"props":5956,"children":5957},{"class":561,"line":608},[5958,5963,5968,5973,5977,5981,5986,5991],{"type":415,"tag":559,"props":5959,"children":5960},{"style":566},[5961],{"type":420,"value":5962},"    private",{"type":415,"tag":559,"props":5964,"children":5965},{"style":566},[5966],{"type":420,"value":5967}," readonly",{"type":415,"tag":559,"props":5969,"children":5970},{"style":572},[5971],{"type":420,"value":5972}," ILogger",{"type":415,"tag":559,"props":5974,"children":5975},{"style":583},[5976],{"type":420,"value":891},{"type":415,"tag":559,"props":5978,"children":5979},{"style":572},[5980],{"type":420,"value":5698},{"type":415,"tag":559,"props":5982,"children":5983},{"style":583},[5984],{"type":420,"value":5985},">",{"type":415,"tag":559,"props":5987,"children":5988},{"style":572},[5989],{"type":420,"value":5990}," _logger",{"type":415,"tag":559,"props":5992,"children":5993},{"style":583},[5994],{"type":420,"value":1509},{"type":415,"tag":559,"props":5996,"children":5997},{"class":561,"line":626},[5998,6002,6006,6011,6016],{"type":415,"tag":559,"props":5999,"children":6000},{"style":566},[6001],{"type":420,"value":5962},{"type":415,"tag":559,"props":6003,"children":6004},{"style":566},[6005],{"type":420,"value":5967},{"type":415,"tag":559,"props":6007,"children":6008},{"style":572},[6009],{"type":420,"value":6010}," BlobServiceClient",{"type":415,"tag":559,"props":6012,"children":6013},{"style":572},[6014],{"type":420,"value":6015}," _blobServiceClient",{"type":415,"tag":559,"props":6017,"children":6018},{"style":583},[6019],{"type":420,"value":1509},{"type":415,"tag":559,"props":6021,"children":6022},{"class":561,"line":643},[6023],{"type":415,"tag":559,"props":6024,"children":6025},{"emptyLinePlaceholder":847},[6026],{"type":420,"value":850},{"type":415,"tag":559,"props":6028,"children":6029},{"class":561,"line":660},[6030,6034,6038,6042,6047,6051,6055,6059,6064,6068,6072,6077],{"type":415,"tag":559,"props":6031,"children":6032},{"style":566},[6033],{"type":420,"value":1124},{"type":415,"tag":559,"props":6035,"children":6036},{"style":883},[6037],{"type":420,"value":5938},{"type":415,"tag":559,"props":6039,"children":6040},{"style":583},[6041],{"type":420,"value":814},{"type":415,"tag":559,"props":6043,"children":6044},{"style":572},[6045],{"type":420,"value":6046},"ILogger",{"type":415,"tag":559,"props":6048,"children":6049},{"style":583},[6050],{"type":420,"value":891},{"type":415,"tag":559,"props":6052,"children":6053},{"style":572},[6054],{"type":420,"value":5698},{"type":415,"tag":559,"props":6056,"children":6057},{"style":583},[6058],{"type":420,"value":5985},{"type":415,"tag":559,"props":6060,"children":6061},{"style":572},[6062],{"type":420,"value":6063}," logger",{"type":415,"tag":559,"props":6065,"children":6066},{"style":583},[6067],{"type":420,"value":2312},{"type":415,"tag":559,"props":6069,"children":6070},{"style":572},[6071],{"type":420,"value":6010},{"type":415,"tag":559,"props":6073,"children":6074},{"style":572},[6075],{"type":420,"value":6076}," blobServiceClient",{"type":415,"tag":559,"props":6078,"children":6079},{"style":583},[6080],{"type":420,"value":833},{"type":415,"tag":559,"props":6082,"children":6083},{"class":561,"line":677},[6084],{"type":415,"tag":559,"props":6085,"children":6086},{"style":583},[6087],{"type":420,"value":2737},{"type":415,"tag":559,"props":6089,"children":6090},{"class":561,"line":690},[6091,6096,6100,6104],{"type":415,"tag":559,"props":6092,"children":6093},{"style":792},[6094],{"type":420,"value":6095},"        _logger ",{"type":415,"tag":559,"props":6097,"children":6098},{"style":583},[6099],{"type":420,"value":800},{"type":415,"tag":559,"props":6101,"children":6102},{"style":792},[6103],{"type":420,"value":6063},{"type":415,"tag":559,"props":6105,"children":6106},{"style":583},[6107],{"type":420,"value":1509},{"type":415,"tag":559,"props":6109,"children":6110},{"class":561,"line":1089},[6111,6116,6120,6124],{"type":415,"tag":559,"props":6112,"children":6113},{"style":792},[6114],{"type":420,"value":6115},"        _blobServiceClient ",{"type":415,"tag":559,"props":6117,"children":6118},{"style":583},[6119],{"type":420,"value":800},{"type":415,"tag":559,"props":6121,"children":6122},{"style":792},[6123],{"type":420,"value":6076},{"type":415,"tag":559,"props":6125,"children":6126},{"style":583},[6127],{"type":420,"value":1509},{"type":415,"tag":559,"props":6129,"children":6130},{"class":561,"line":1102},[6131],{"type":415,"tag":559,"props":6132,"children":6133},{"style":583},[6134],{"type":420,"value":2792},{"type":415,"tag":559,"props":6136,"children":6137},{"class":561,"line":1110},[6138],{"type":415,"tag":559,"props":6139,"children":6140},{"emptyLinePlaceholder":847},[6141],{"type":420,"value":850},{"type":415,"tag":559,"props":6143,"children":6144},{"class":561,"line":1118},[6145,6150,6155,6160,6164,6169,6173,6178,6183],{"type":415,"tag":559,"props":6146,"children":6147},{"style":566},[6148],{"type":420,"value":6149},"    protected",{"type":415,"tag":559,"props":6151,"children":6152},{"style":566},[6153],{"type":420,"value":6154}," override",{"type":415,"tag":559,"props":6156,"children":6157},{"style":566},[6158],{"type":420,"value":6159}," async",{"type":415,"tag":559,"props":6161,"children":6162},{"style":572},[6163],{"type":420,"value":2006},{"type":415,"tag":559,"props":6165,"children":6166},{"style":883},[6167],{"type":420,"value":6168}," ExecuteAsync",{"type":415,"tag":559,"props":6170,"children":6171},{"style":583},[6172],{"type":420,"value":814},{"type":415,"tag":559,"props":6174,"children":6175},{"style":572},[6176],{"type":420,"value":6177},"CancellationToken",{"type":415,"tag":559,"props":6179,"children":6180},{"style":572},[6181],{"type":420,"value":6182}," stoppingToken",{"type":415,"tag":559,"props":6184,"children":6185},{"style":583},[6186],{"type":420,"value":833},{"type":415,"tag":559,"props":6188,"children":6189},{"class":561,"line":1171},[6190],{"type":415,"tag":559,"props":6191,"children":6192},{"style":583},[6193],{"type":420,"value":2737},{"type":415,"tag":559,"props":6195,"children":6196},{"class":561,"line":1748},[6197,6202,6207,6211,6215,6220,6224,6228,6232,6237,6241,6246,6250,6254],{"type":415,"tag":559,"props":6198,"children":6199},{"style":583},[6200],{"type":420,"value":6201},"        await",{"type":415,"tag":559,"props":6203,"children":6204},{"style":745},[6205],{"type":420,"value":6206}," foreach",{"type":415,"tag":559,"props":6208,"children":6209},{"style":583},[6210],{"type":420,"value":2710},{"type":415,"tag":559,"props":6212,"children":6213},{"style":572},[6214],{"type":420,"value":858},{"type":415,"tag":559,"props":6216,"children":6217},{"style":572},[6218],{"type":420,"value":6219}," blobContainer",{"type":415,"tag":559,"props":6221,"children":6222},{"style":745},[6223],{"type":420,"value":3278},{"type":415,"tag":559,"props":6225,"children":6226},{"style":792},[6227],{"type":420,"value":6015},{"type":415,"tag":559,"props":6229,"children":6230},{"style":583},[6231],{"type":420,"value":542},{"type":415,"tag":559,"props":6233,"children":6234},{"style":883},[6235],{"type":420,"value":6236},"GetBlobContainersAsync",{"type":415,"tag":559,"props":6238,"children":6239},{"style":583},[6240],{"type":420,"value":814},{"type":415,"tag":559,"props":6242,"children":6243},{"style":572},[6244],{"type":420,"value":6245},"cancellationToken",{"type":415,"tag":559,"props":6247,"children":6248},{"style":583},[6249],{"type":420,"value":1206},{"type":415,"tag":559,"props":6251,"children":6252},{"style":792},[6253],{"type":420,"value":6182},{"type":415,"tag":559,"props":6255,"children":6256},{"style":583},[6257],{"type":420,"value":6258},"))\n",{"type":415,"tag":559,"props":6260,"children":6261},{"class":561,"line":1769},[6262],{"type":415,"tag":559,"props":6263,"children":6264},{"style":583},[6265],{"type":420,"value":6266},"        {\n",{"type":415,"tag":559,"props":6268,"children":6269},{"class":561,"line":1786},[6270,6275,6279,6284,6288,6293,6297,6301,6305],{"type":415,"tag":559,"props":6271,"children":6272},{"style":792},[6273],{"type":420,"value":6274},"            _logger",{"type":415,"tag":559,"props":6276,"children":6277},{"style":583},[6278],{"type":420,"value":542},{"type":415,"tag":559,"props":6280,"children":6281},{"style":883},[6282],{"type":420,"value":6283},"LogInformation",{"type":415,"tag":559,"props":6285,"children":6286},{"style":583},[6287],{"type":420,"value":814},{"type":415,"tag":559,"props":6289,"children":6290},{"style":792},[6291],{"type":420,"value":6292},"blobContainer",{"type":415,"tag":559,"props":6294,"children":6295},{"style":583},[6296],{"type":420,"value":542},{"type":415,"tag":559,"props":6298,"children":6299},{"style":792},[6300],{"type":420,"value":1412},{"type":415,"tag":559,"props":6302,"children":6303},{"style":583},[6304],{"type":420,"value":1468},{"type":415,"tag":559,"props":6306,"children":6307},{"style":792},[6308],{"type":420,"value":1509},{"type":415,"tag":559,"props":6310,"children":6311},{"class":561,"line":1795},[6312],{"type":415,"tag":559,"props":6313,"children":6314},{"style":583},[6315],{"type":420,"value":6316},"        }\n",{"type":415,"tag":559,"props":6318,"children":6319},{"class":561,"line":3289},[6320],{"type":415,"tag":559,"props":6321,"children":6322},{"style":583},[6323],{"type":420,"value":2792},{"type":415,"tag":559,"props":6325,"children":6326},{"class":561,"line":3297},[6327],{"type":415,"tag":559,"props":6328,"children":6329},{"style":583},[6330],{"type":420,"value":1801},{"type":415,"tag":1178,"props":6332,"children":6333},{"icon":1180},[6334],{"type":415,"tag":416,"props":6335,"children":6336},{},[6337,6339,6344,6346,6352,6354,6360,6362,6367],{"type":420,"value":6338},"You may find it convenient to configure the dependency injection for all Azure service clients in a central place with the ",{"type":415,"tag":555,"props":6340,"children":6342},{"className":6341},[],[6343],{"type":420,"value":5727},{"type":420,"value":6345}," method. When applications become larger with different ",{"type":415,"tag":555,"props":6347,"children":6349},{"className":6348},[],[6350],{"type":420,"value":6351},"csproj,",{"type":420,"value":6353}," I often prefer to separate service registration by business domain/module so having everything in a central place does not always suit my needs. That's not a problem, as the internal methods of the library make use of the ",{"type":415,"tag":555,"props":6355,"children":6357},{"className":6356},[],[6358],{"type":420,"value":6359},"TryAddd",{"type":420,"value":6361}," methods for registering services, I can call ",{"type":415,"tag":555,"props":6363,"children":6365},{"className":6364},[],[6366],{"type":420,"value":5727},{"type":420,"value":6368}," in multiple places with only the services I want to register.",{"type":415,"tag":422,"props":6370,"children":6372},{"id":6371},"easily-manage-the-authentication-to-azure-services",[6373],{"type":420,"value":6374},"Easily manage the authentication to Azure services",{"type":415,"tag":416,"props":6376,"children":6377},{},[6378,6380,6387],{"type":420,"value":6379},"All the SDKs use the ",{"type":415,"tag":434,"props":6381,"children":6384},{"href":6382,"rel":6383},"https://www.nuget.org/packages/Azure.Identity",[438],[6385],{"type":420,"value":6386},"Azure.Identity",{"type":420,"value":6388}," package to authenticate to Azure. There are different authentication methods available and you can easily specify which one to use with each client. Additionally, you can define a default authentication method for all clients, as demonstrated in the previous example.",{"type":415,"tag":549,"props":6390,"children":6392},{"className":551,"code":6391,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddServiceBusClient(\"https://sb-diwithazuresdk.servicebus.windows.net/\")\n        .WithCredential(new ManagedIdentityCredential());\n    \n    clientBuilder.AddTableServiceClient(new Uri(\"https://stdiwithazuresdk.table.core.windows.net\"))\n        .WithCredential(new EnvironmentCredential());\n\n    clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"));\n    \n    clientBuilder.UseCredential(new DefaultAzureCredential());\n});\n",[6393],{"type":415,"tag":555,"props":6394,"children":6395},{"__ignoreMap":401},[6396,6431,6438,6475,6501,6509,6554,6578,6585,6628,6635,6662],{"type":415,"tag":559,"props":6397,"children":6398},{"class":561,"line":562},[6399,6403,6407,6411,6415,6419,6423,6427],{"type":415,"tag":559,"props":6400,"children":6401},{"style":792},[6402],{"type":420,"value":5671},{"type":415,"tag":559,"props":6404,"children":6405},{"style":583},[6406],{"type":420,"value":542},{"type":415,"tag":559,"props":6408,"children":6409},{"style":792},[6410],{"type":420,"value":5680},{"type":415,"tag":559,"props":6412,"children":6413},{"style":583},[6414],{"type":420,"value":542},{"type":415,"tag":559,"props":6416,"children":6417},{"style":883},[6418],{"type":420,"value":5727},{"type":415,"tag":559,"props":6420,"children":6421},{"style":583},[6422],{"type":420,"value":814},{"type":415,"tag":559,"props":6424,"children":6425},{"style":572},[6426],{"type":420,"value":5736},{"type":415,"tag":559,"props":6428,"children":6429},{"style":583},[6430],{"type":420,"value":5741},{"type":415,"tag":559,"props":6432,"children":6433},{"class":561,"line":589},[6434],{"type":415,"tag":559,"props":6435,"children":6436},{"style":583},[6437],{"type":420,"value":786},{"type":415,"tag":559,"props":6439,"children":6440},{"class":561,"line":608},[6441,6445,6449,6454,6458,6462,6467,6471],{"type":415,"tag":559,"props":6442,"children":6443},{"style":792},[6444],{"type":420,"value":5756},{"type":415,"tag":559,"props":6446,"children":6447},{"style":583},[6448],{"type":420,"value":542},{"type":415,"tag":559,"props":6450,"children":6451},{"style":883},[6452],{"type":420,"value":6453},"AddServiceBusClient",{"type":415,"tag":559,"props":6455,"children":6456},{"style":583},[6457],{"type":420,"value":814},{"type":415,"tag":559,"props":6459,"children":6460},{"style":583},[6461],{"type":420,"value":819},{"type":415,"tag":559,"props":6463,"children":6464},{"style":822},[6465],{"type":420,"value":6466},"https://sb-diwithazuresdk.servicebus.windows.net/",{"type":415,"tag":559,"props":6468,"children":6469},{"style":583},[6470],{"type":420,"value":819},{"type":415,"tag":559,"props":6472,"children":6473},{"style":583},[6474],{"type":420,"value":833},{"type":415,"tag":559,"props":6476,"children":6477},{"class":561,"line":626},[6478,6483,6488,6492,6497],{"type":415,"tag":559,"props":6479,"children":6480},{"style":583},[6481],{"type":420,"value":6482},"        .",{"type":415,"tag":559,"props":6484,"children":6485},{"style":883},[6486],{"type":420,"value":6487},"WithCredential",{"type":415,"tag":559,"props":6489,"children":6490},{"style":583},[6491],{"type":420,"value":5770},{"type":415,"tag":559,"props":6493,"children":6494},{"style":572},[6495],{"type":420,"value":6496}," ManagedIdentityCredential",{"type":415,"tag":559,"props":6498,"children":6499},{"style":583},[6500],{"type":420,"value":1312},{"type":415,"tag":559,"props":6502,"children":6503},{"class":561,"line":643},[6504],{"type":415,"tag":559,"props":6505,"children":6506},{"style":792},[6507],{"type":420,"value":6508},"    \n",{"type":415,"tag":559,"props":6510,"children":6511},{"class":561,"line":660},[6512,6516,6520,6525,6529,6533,6537,6541,6546,6550],{"type":415,"tag":559,"props":6513,"children":6514},{"style":792},[6515],{"type":420,"value":5756},{"type":415,"tag":559,"props":6517,"children":6518},{"style":583},[6519],{"type":420,"value":542},{"type":415,"tag":559,"props":6521,"children":6522},{"style":883},[6523],{"type":420,"value":6524},"AddTableServiceClient",{"type":415,"tag":559,"props":6526,"children":6527},{"style":583},[6528],{"type":420,"value":5770},{"type":415,"tag":559,"props":6530,"children":6531},{"style":572},[6532],{"type":420,"value":809},{"type":415,"tag":559,"props":6534,"children":6535},{"style":583},[6536],{"type":420,"value":814},{"type":415,"tag":559,"props":6538,"children":6539},{"style":583},[6540],{"type":420,"value":819},{"type":415,"tag":559,"props":6542,"children":6543},{"style":822},[6544],{"type":420,"value":6545},"https://stdiwithazuresdk.table.core.windows.net",{"type":415,"tag":559,"props":6547,"children":6548},{"style":583},[6549],{"type":420,"value":819},{"type":415,"tag":559,"props":6551,"children":6552},{"style":583},[6553],{"type":420,"value":6258},{"type":415,"tag":559,"props":6555,"children":6556},{"class":561,"line":677},[6557,6561,6565,6569,6574],{"type":415,"tag":559,"props":6558,"children":6559},{"style":583},[6560],{"type":420,"value":6482},{"type":415,"tag":559,"props":6562,"children":6563},{"style":883},[6564],{"type":420,"value":6487},{"type":415,"tag":559,"props":6566,"children":6567},{"style":583},[6568],{"type":420,"value":5770},{"type":415,"tag":559,"props":6570,"children":6571},{"style":572},[6572],{"type":420,"value":6573}," EnvironmentCredential",{"type":415,"tag":559,"props":6575,"children":6576},{"style":583},[6577],{"type":420,"value":1312},{"type":415,"tag":559,"props":6579,"children":6580},{"class":561,"line":690},[6581],{"type":415,"tag":559,"props":6582,"children":6583},{"emptyLinePlaceholder":847},[6584],{"type":420,"value":850},{"type":415,"tag":559,"props":6586,"children":6587},{"class":561,"line":1089},[6588,6592,6596,6600,6604,6608,6612,6616,6620,6624],{"type":415,"tag":559,"props":6589,"children":6590},{"style":792},[6591],{"type":420,"value":5756},{"type":415,"tag":559,"props":6593,"children":6594},{"style":583},[6595],{"type":420,"value":542},{"type":415,"tag":559,"props":6597,"children":6598},{"style":883},[6599],{"type":420,"value":5765},{"type":415,"tag":559,"props":6601,"children":6602},{"style":583},[6603],{"type":420,"value":5770},{"type":415,"tag":559,"props":6605,"children":6606},{"style":572},[6607],{"type":420,"value":809},{"type":415,"tag":559,"props":6609,"children":6610},{"style":583},[6611],{"type":420,"value":814},{"type":415,"tag":559,"props":6613,"children":6614},{"style":583},[6615],{"type":420,"value":819},{"type":415,"tag":559,"props":6617,"children":6618},{"style":822},[6619],{"type":420,"value":5787},{"type":415,"tag":559,"props":6621,"children":6622},{"style":583},[6623],{"type":420,"value":819},{"type":415,"tag":559,"props":6625,"children":6626},{"style":583},[6627],{"type":420,"value":5796},{"type":415,"tag":559,"props":6629,"children":6630},{"class":561,"line":1102},[6631],{"type":415,"tag":559,"props":6632,"children":6633},{"style":792},[6634],{"type":420,"value":6508},{"type":415,"tag":559,"props":6636,"children":6637},{"class":561,"line":1110},[6638,6642,6646,6650,6654,6658],{"type":415,"tag":559,"props":6639,"children":6640},{"style":792},[6641],{"type":420,"value":5756},{"type":415,"tag":559,"props":6643,"children":6644},{"style":583},[6645],{"type":420,"value":542},{"type":415,"tag":559,"props":6647,"children":6648},{"style":883},[6649],{"type":420,"value":5812},{"type":415,"tag":559,"props":6651,"children":6652},{"style":583},[6653],{"type":420,"value":5770},{"type":415,"tag":559,"props":6655,"children":6656},{"style":572},[6657],{"type":420,"value":5821},{"type":415,"tag":559,"props":6659,"children":6660},{"style":583},[6661],{"type":420,"value":1312},{"type":415,"tag":559,"props":6663,"children":6664},{"class":561,"line":1118},[6665],{"type":415,"tag":559,"props":6666,"children":6667},{"style":583},[6668],{"type":420,"value":5833},{"type":415,"tag":416,"props":6670,"children":6671},{},[6672],{"type":420,"value":6673},"In the example above, we configured:",{"type":415,"tag":5376,"props":6675,"children":6676},{},[6677,6682,6687],{"type":415,"tag":5380,"props":6678,"children":6679},{},[6680],{"type":420,"value":6681},"the service bus client to use the managed identity of the application to obtain a valid token for the service bus",{"type":415,"tag":5380,"props":6683,"children":6684},{},[6685],{"type":420,"value":6686},"the table client to use environment variables to obtain a valid token for the storage table",{"type":415,"tag":5380,"props":6688,"children":6689},{},[6690,6692,6697],{"type":420,"value":6691},"the blob client without any credentials so that it will use the one that we configured by default (with the ",{"type":415,"tag":555,"props":6693,"children":6695},{"className":6694},[],[6696],{"type":420,"value":5812},{"type":420,"value":6698}," method)",{"type":415,"tag":422,"props":6700,"children":6702},{"id":6701},"effortlessly-configure-the-azure-clients-options",[6703],{"type":420,"value":6704},"Effortlessly configure the Azure clients' options",{"type":415,"tag":416,"props":6706,"children":6707},{},[6708,6710,6715],{"type":420,"value":6709},"All Azure clients have options that can be effortlessly configured when registering them in the ",{"type":415,"tag":555,"props":6711,"children":6713},{"className":6712},[],[6714],{"type":420,"value":5727},{"type":420,"value":6716}," method.",{"type":415,"tag":549,"props":6718,"children":6720},{"className":551,"code":6719,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"))\n        .WithCredential(new DefaultAzureCredential())\n        .ConfigureOptions(options =>\n        {\n            options.TrimBlobNameSlashes = true;\n            options.Retry.MaxRetries = 10;\n            options.Diagnostics.IsLoggingEnabled = false;\n        });\n});\n",[6721],{"type":415,"tag":555,"props":6722,"children":6723},{"__ignoreMap":401},[6724,6759,6766,6809,6832,6857,6864,6895,6933,6971,6979],{"type":415,"tag":559,"props":6725,"children":6726},{"class":561,"line":562},[6727,6731,6735,6739,6743,6747,6751,6755],{"type":415,"tag":559,"props":6728,"children":6729},{"style":792},[6730],{"type":420,"value":5671},{"type":415,"tag":559,"props":6732,"children":6733},{"style":583},[6734],{"type":420,"value":542},{"type":415,"tag":559,"props":6736,"children":6737},{"style":792},[6738],{"type":420,"value":5680},{"type":415,"tag":559,"props":6740,"children":6741},{"style":583},[6742],{"type":420,"value":542},{"type":415,"tag":559,"props":6744,"children":6745},{"style":883},[6746],{"type":420,"value":5727},{"type":415,"tag":559,"props":6748,"children":6749},{"style":583},[6750],{"type":420,"value":814},{"type":415,"tag":559,"props":6752,"children":6753},{"style":572},[6754],{"type":420,"value":5736},{"type":415,"tag":559,"props":6756,"children":6757},{"style":583},[6758],{"type":420,"value":5741},{"type":415,"tag":559,"props":6760,"children":6761},{"class":561,"line":589},[6762],{"type":415,"tag":559,"props":6763,"children":6764},{"style":583},[6765],{"type":420,"value":786},{"type":415,"tag":559,"props":6767,"children":6768},{"class":561,"line":608},[6769,6773,6777,6781,6785,6789,6793,6797,6801,6805],{"type":415,"tag":559,"props":6770,"children":6771},{"style":792},[6772],{"type":420,"value":5756},{"type":415,"tag":559,"props":6774,"children":6775},{"style":583},[6776],{"type":420,"value":542},{"type":415,"tag":559,"props":6778,"children":6779},{"style":883},[6780],{"type":420,"value":5765},{"type":415,"tag":559,"props":6782,"children":6783},{"style":583},[6784],{"type":420,"value":5770},{"type":415,"tag":559,"props":6786,"children":6787},{"style":572},[6788],{"type":420,"value":809},{"type":415,"tag":559,"props":6790,"children":6791},{"style":583},[6792],{"type":420,"value":814},{"type":415,"tag":559,"props":6794,"children":6795},{"style":583},[6796],{"type":420,"value":819},{"type":415,"tag":559,"props":6798,"children":6799},{"style":822},[6800],{"type":420,"value":5787},{"type":415,"tag":559,"props":6802,"children":6803},{"style":583},[6804],{"type":420,"value":819},{"type":415,"tag":559,"props":6806,"children":6807},{"style":583},[6808],{"type":420,"value":6258},{"type":415,"tag":559,"props":6810,"children":6811},{"class":561,"line":626},[6812,6816,6820,6824,6828],{"type":415,"tag":559,"props":6813,"children":6814},{"style":583},[6815],{"type":420,"value":6482},{"type":415,"tag":559,"props":6817,"children":6818},{"style":883},[6819],{"type":420,"value":6487},{"type":415,"tag":559,"props":6821,"children":6822},{"style":583},[6823],{"type":420,"value":5770},{"type":415,"tag":559,"props":6825,"children":6826},{"style":572},[6827],{"type":420,"value":5821},{"type":415,"tag":559,"props":6829,"children":6830},{"style":583},[6831],{"type":420,"value":1920},{"type":415,"tag":559,"props":6833,"children":6834},{"class":561,"line":643},[6835,6839,6844,6848,6853],{"type":415,"tag":559,"props":6836,"children":6837},{"style":583},[6838],{"type":420,"value":6482},{"type":415,"tag":559,"props":6840,"children":6841},{"style":883},[6842],{"type":420,"value":6843},"ConfigureOptions",{"type":415,"tag":559,"props":6845,"children":6846},{"style":583},[6847],{"type":420,"value":814},{"type":415,"tag":559,"props":6849,"children":6850},{"style":572},[6851],{"type":420,"value":6852},"options",{"type":415,"tag":559,"props":6854,"children":6855},{"style":583},[6856],{"type":420,"value":5741},{"type":415,"tag":559,"props":6858,"children":6859},{"class":561,"line":660},[6860],{"type":415,"tag":559,"props":6861,"children":6862},{"style":583},[6863],{"type":420,"value":6266},{"type":415,"tag":559,"props":6865,"children":6866},{"class":561,"line":677},[6867,6872,6876,6881,6885,6891],{"type":415,"tag":559,"props":6868,"children":6869},{"style":792},[6870],{"type":420,"value":6871},"            options",{"type":415,"tag":559,"props":6873,"children":6874},{"style":583},[6875],{"type":420,"value":542},{"type":415,"tag":559,"props":6877,"children":6878},{"style":792},[6879],{"type":420,"value":6880},"TrimBlobNameSlashes ",{"type":415,"tag":559,"props":6882,"children":6883},{"style":583},[6884],{"type":420,"value":800},{"type":415,"tag":559,"props":6886,"children":6888},{"style":6887},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[6889],{"type":420,"value":6890}," true",{"type":415,"tag":559,"props":6892,"children":6893},{"style":583},[6894],{"type":420,"value":1509},{"type":415,"tag":559,"props":6896,"children":6897},{"class":561,"line":690},[6898,6902,6906,6911,6915,6920,6924,6929],{"type":415,"tag":559,"props":6899,"children":6900},{"style":792},[6901],{"type":420,"value":6871},{"type":415,"tag":559,"props":6903,"children":6904},{"style":583},[6905],{"type":420,"value":542},{"type":415,"tag":559,"props":6907,"children":6908},{"style":792},[6909],{"type":420,"value":6910},"Retry",{"type":415,"tag":559,"props":6912,"children":6913},{"style":583},[6914],{"type":420,"value":542},{"type":415,"tag":559,"props":6916,"children":6917},{"style":792},[6918],{"type":420,"value":6919},"MaxRetries ",{"type":415,"tag":559,"props":6921,"children":6922},{"style":583},[6923],{"type":420,"value":800},{"type":415,"tag":559,"props":6925,"children":6926},{"style":2846},[6927],{"type":420,"value":6928}," 10",{"type":415,"tag":559,"props":6930,"children":6931},{"style":583},[6932],{"type":420,"value":1509},{"type":415,"tag":559,"props":6934,"children":6935},{"class":561,"line":1089},[6936,6940,6944,6949,6953,6958,6962,6967],{"type":415,"tag":559,"props":6937,"children":6938},{"style":792},[6939],{"type":420,"value":6871},{"type":415,"tag":559,"props":6941,"children":6942},{"style":583},[6943],{"type":420,"value":542},{"type":415,"tag":559,"props":6945,"children":6946},{"style":792},[6947],{"type":420,"value":6948},"Diagnostics",{"type":415,"tag":559,"props":6950,"children":6951},{"style":583},[6952],{"type":420,"value":542},{"type":415,"tag":559,"props":6954,"children":6955},{"style":792},[6956],{"type":420,"value":6957},"IsLoggingEnabled ",{"type":415,"tag":559,"props":6959,"children":6960},{"style":583},[6961],{"type":420,"value":800},{"type":415,"tag":559,"props":6963,"children":6964},{"style":6887},[6965],{"type":420,"value":6966}," false",{"type":415,"tag":559,"props":6968,"children":6969},{"style":583},[6970],{"type":420,"value":1509},{"type":415,"tag":559,"props":6972,"children":6973},{"class":561,"line":1102},[6974],{"type":415,"tag":559,"props":6975,"children":6976},{"style":583},[6977],{"type":420,"value":6978},"        });\n",{"type":415,"tag":559,"props":6980,"children":6981},{"class":561,"line":1110},[6982],{"type":415,"tag":559,"props":6983,"children":6984},{"style":583},[6985],{"type":420,"value":5833},{"type":415,"tag":416,"props":6987,"children":6988},{},[6989,6991,6997],{"type":420,"value":6990},"Some options are specific to the client (like the ",{"type":415,"tag":555,"props":6992,"children":6994},{"className":6993},[],[6995],{"type":420,"value":6996},"TrimBlobNameSlashes",{"type":420,"value":6998}," here for Blob client). Others can be configured globally and overridden on a client if necessary.",{"type":415,"tag":549,"props":7000,"children":7002},{"className":551,"code":7001,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n   clientBuilder.AddBlobServiceClient(new Uri(\"https://stdiwithazuresdk.blob.core.windows.net/\"))\n        .WithCredential(new DefaultAzureCredential())\n        .ConfigureOptions(options =>\n        {\n            options.TrimBlobNameSlashes = true;\n            options.Retry.MaxRetries = 10;\n            options.Diagnostics.IsLoggingEnabled = false;\n        });\n    \n    clientBuilder.ConfigureDefaults(options =>\n    {\n        options.Retry.MaxRetries = 5;\n        options.Retry.Mode = RetryMode.Exponential;\n        options.Diagnostics.IsDistributedTracingEnabled = true;\n    });\n});\n",[7003],{"type":415,"tag":555,"props":7004,"children":7005},{"__ignoreMap":401},[7006,7041,7048,7092,7115,7138,7145,7172,7207,7242,7249,7256,7284,7291,7327,7373,7409,7417],{"type":415,"tag":559,"props":7007,"children":7008},{"class":561,"line":562},[7009,7013,7017,7021,7025,7029,7033,7037],{"type":415,"tag":559,"props":7010,"children":7011},{"style":792},[7012],{"type":420,"value":5671},{"type":415,"tag":559,"props":7014,"children":7015},{"style":583},[7016],{"type":420,"value":542},{"type":415,"tag":559,"props":7018,"children":7019},{"style":792},[7020],{"type":420,"value":5680},{"type":415,"tag":559,"props":7022,"children":7023},{"style":583},[7024],{"type":420,"value":542},{"type":415,"tag":559,"props":7026,"children":7027},{"style":883},[7028],{"type":420,"value":5727},{"type":415,"tag":559,"props":7030,"children":7031},{"style":583},[7032],{"type":420,"value":814},{"type":415,"tag":559,"props":7034,"children":7035},{"style":572},[7036],{"type":420,"value":5736},{"type":415,"tag":559,"props":7038,"children":7039},{"style":583},[7040],{"type":420,"value":5741},{"type":415,"tag":559,"props":7042,"children":7043},{"class":561,"line":589},[7044],{"type":415,"tag":559,"props":7045,"children":7046},{"style":583},[7047],{"type":420,"value":786},{"type":415,"tag":559,"props":7049,"children":7050},{"class":561,"line":608},[7051,7056,7060,7064,7068,7072,7076,7080,7084,7088],{"type":415,"tag":559,"props":7052,"children":7053},{"style":792},[7054],{"type":420,"value":7055},"   clientBuilder",{"type":415,"tag":559,"props":7057,"children":7058},{"style":583},[7059],{"type":420,"value":542},{"type":415,"tag":559,"props":7061,"children":7062},{"style":883},[7063],{"type":420,"value":5765},{"type":415,"tag":559,"props":7065,"children":7066},{"style":583},[7067],{"type":420,"value":5770},{"type":415,"tag":559,"props":7069,"children":7070},{"style":572},[7071],{"type":420,"value":809},{"type":415,"tag":559,"props":7073,"children":7074},{"style":583},[7075],{"type":420,"value":814},{"type":415,"tag":559,"props":7077,"children":7078},{"style":583},[7079],{"type":420,"value":819},{"type":415,"tag":559,"props":7081,"children":7082},{"style":822},[7083],{"type":420,"value":5787},{"type":415,"tag":559,"props":7085,"children":7086},{"style":583},[7087],{"type":420,"value":819},{"type":415,"tag":559,"props":7089,"children":7090},{"style":583},[7091],{"type":420,"value":6258},{"type":415,"tag":559,"props":7093,"children":7094},{"class":561,"line":626},[7095,7099,7103,7107,7111],{"type":415,"tag":559,"props":7096,"children":7097},{"style":583},[7098],{"type":420,"value":6482},{"type":415,"tag":559,"props":7100,"children":7101},{"style":883},[7102],{"type":420,"value":6487},{"type":415,"tag":559,"props":7104,"children":7105},{"style":583},[7106],{"type":420,"value":5770},{"type":415,"tag":559,"props":7108,"children":7109},{"style":572},[7110],{"type":420,"value":5821},{"type":415,"tag":559,"props":7112,"children":7113},{"style":583},[7114],{"type":420,"value":1920},{"type":415,"tag":559,"props":7116,"children":7117},{"class":561,"line":643},[7118,7122,7126,7130,7134],{"type":415,"tag":559,"props":7119,"children":7120},{"style":583},[7121],{"type":420,"value":6482},{"type":415,"tag":559,"props":7123,"children":7124},{"style":883},[7125],{"type":420,"value":6843},{"type":415,"tag":559,"props":7127,"children":7128},{"style":583},[7129],{"type":420,"value":814},{"type":415,"tag":559,"props":7131,"children":7132},{"style":572},[7133],{"type":420,"value":6852},{"type":415,"tag":559,"props":7135,"children":7136},{"style":583},[7137],{"type":420,"value":5741},{"type":415,"tag":559,"props":7139,"children":7140},{"class":561,"line":660},[7141],{"type":415,"tag":559,"props":7142,"children":7143},{"style":583},[7144],{"type":420,"value":6266},{"type":415,"tag":559,"props":7146,"children":7147},{"class":561,"line":677},[7148,7152,7156,7160,7164,7168],{"type":415,"tag":559,"props":7149,"children":7150},{"style":792},[7151],{"type":420,"value":6871},{"type":415,"tag":559,"props":7153,"children":7154},{"style":583},[7155],{"type":420,"value":542},{"type":415,"tag":559,"props":7157,"children":7158},{"style":792},[7159],{"type":420,"value":6880},{"type":415,"tag":559,"props":7161,"children":7162},{"style":583},[7163],{"type":420,"value":800},{"type":415,"tag":559,"props":7165,"children":7166},{"style":6887},[7167],{"type":420,"value":6890},{"type":415,"tag":559,"props":7169,"children":7170},{"style":583},[7171],{"type":420,"value":1509},{"type":415,"tag":559,"props":7173,"children":7174},{"class":561,"line":690},[7175,7179,7183,7187,7191,7195,7199,7203],{"type":415,"tag":559,"props":7176,"children":7177},{"style":792},[7178],{"type":420,"value":6871},{"type":415,"tag":559,"props":7180,"children":7181},{"style":583},[7182],{"type":420,"value":542},{"type":415,"tag":559,"props":7184,"children":7185},{"style":792},[7186],{"type":420,"value":6910},{"type":415,"tag":559,"props":7188,"children":7189},{"style":583},[7190],{"type":420,"value":542},{"type":415,"tag":559,"props":7192,"children":7193},{"style":792},[7194],{"type":420,"value":6919},{"type":415,"tag":559,"props":7196,"children":7197},{"style":583},[7198],{"type":420,"value":800},{"type":415,"tag":559,"props":7200,"children":7201},{"style":2846},[7202],{"type":420,"value":6928},{"type":415,"tag":559,"props":7204,"children":7205},{"style":583},[7206],{"type":420,"value":1509},{"type":415,"tag":559,"props":7208,"children":7209},{"class":561,"line":1089},[7210,7214,7218,7222,7226,7230,7234,7238],{"type":415,"tag":559,"props":7211,"children":7212},{"style":792},[7213],{"type":420,"value":6871},{"type":415,"tag":559,"props":7215,"children":7216},{"style":583},[7217],{"type":420,"value":542},{"type":415,"tag":559,"props":7219,"children":7220},{"style":792},[7221],{"type":420,"value":6948},{"type":415,"tag":559,"props":7223,"children":7224},{"style":583},[7225],{"type":420,"value":542},{"type":415,"tag":559,"props":7227,"children":7228},{"style":792},[7229],{"type":420,"value":6957},{"type":415,"tag":559,"props":7231,"children":7232},{"style":583},[7233],{"type":420,"value":800},{"type":415,"tag":559,"props":7235,"children":7236},{"style":6887},[7237],{"type":420,"value":6966},{"type":415,"tag":559,"props":7239,"children":7240},{"style":583},[7241],{"type":420,"value":1509},{"type":415,"tag":559,"props":7243,"children":7244},{"class":561,"line":1102},[7245],{"type":415,"tag":559,"props":7246,"children":7247},{"style":583},[7248],{"type":420,"value":6978},{"type":415,"tag":559,"props":7250,"children":7251},{"class":561,"line":1110},[7252],{"type":415,"tag":559,"props":7253,"children":7254},{"style":792},[7255],{"type":420,"value":6508},{"type":415,"tag":559,"props":7257,"children":7258},{"class":561,"line":1118},[7259,7263,7267,7272,7276,7280],{"type":415,"tag":559,"props":7260,"children":7261},{"style":792},[7262],{"type":420,"value":5756},{"type":415,"tag":559,"props":7264,"children":7265},{"style":583},[7266],{"type":420,"value":542},{"type":415,"tag":559,"props":7268,"children":7269},{"style":883},[7270],{"type":420,"value":7271},"ConfigureDefaults",{"type":415,"tag":559,"props":7273,"children":7274},{"style":583},[7275],{"type":420,"value":814},{"type":415,"tag":559,"props":7277,"children":7278},{"style":572},[7279],{"type":420,"value":6852},{"type":415,"tag":559,"props":7281,"children":7282},{"style":583},[7283],{"type":420,"value":5741},{"type":415,"tag":559,"props":7285,"children":7286},{"class":561,"line":1171},[7287],{"type":415,"tag":559,"props":7288,"children":7289},{"style":583},[7290],{"type":420,"value":2737},{"type":415,"tag":559,"props":7292,"children":7293},{"class":561,"line":1748},[7294,7299,7303,7307,7311,7315,7319,7323],{"type":415,"tag":559,"props":7295,"children":7296},{"style":792},[7297],{"type":420,"value":7298},"        options",{"type":415,"tag":559,"props":7300,"children":7301},{"style":583},[7302],{"type":420,"value":542},{"type":415,"tag":559,"props":7304,"children":7305},{"style":792},[7306],{"type":420,"value":6910},{"type":415,"tag":559,"props":7308,"children":7309},{"style":583},[7310],{"type":420,"value":542},{"type":415,"tag":559,"props":7312,"children":7313},{"style":792},[7314],{"type":420,"value":6919},{"type":415,"tag":559,"props":7316,"children":7317},{"style":583},[7318],{"type":420,"value":800},{"type":415,"tag":559,"props":7320,"children":7321},{"style":2846},[7322],{"type":420,"value":5310},{"type":415,"tag":559,"props":7324,"children":7325},{"style":583},[7326],{"type":420,"value":1509},{"type":415,"tag":559,"props":7328,"children":7329},{"class":561,"line":1769},[7330,7334,7338,7342,7346,7351,7355,7360,7364,7369],{"type":415,"tag":559,"props":7331,"children":7332},{"style":792},[7333],{"type":420,"value":7298},{"type":415,"tag":559,"props":7335,"children":7336},{"style":583},[7337],{"type":420,"value":542},{"type":415,"tag":559,"props":7339,"children":7340},{"style":792},[7341],{"type":420,"value":6910},{"type":415,"tag":559,"props":7343,"children":7344},{"style":583},[7345],{"type":420,"value":542},{"type":415,"tag":559,"props":7347,"children":7348},{"style":792},[7349],{"type":420,"value":7350},"Mode ",{"type":415,"tag":559,"props":7352,"children":7353},{"style":583},[7354],{"type":420,"value":800},{"type":415,"tag":559,"props":7356,"children":7357},{"style":792},[7358],{"type":420,"value":7359}," RetryMode",{"type":415,"tag":559,"props":7361,"children":7362},{"style":583},[7363],{"type":420,"value":542},{"type":415,"tag":559,"props":7365,"children":7366},{"style":792},[7367],{"type":420,"value":7368},"Exponential",{"type":415,"tag":559,"props":7370,"children":7371},{"style":583},[7372],{"type":420,"value":1509},{"type":415,"tag":559,"props":7374,"children":7375},{"class":561,"line":1786},[7376,7380,7384,7388,7392,7397,7401,7405],{"type":415,"tag":559,"props":7377,"children":7378},{"style":792},[7379],{"type":420,"value":7298},{"type":415,"tag":559,"props":7381,"children":7382},{"style":583},[7383],{"type":420,"value":542},{"type":415,"tag":559,"props":7385,"children":7386},{"style":792},[7387],{"type":420,"value":6948},{"type":415,"tag":559,"props":7389,"children":7390},{"style":583},[7391],{"type":420,"value":542},{"type":415,"tag":559,"props":7393,"children":7394},{"style":792},[7395],{"type":420,"value":7396},"IsDistributedTracingEnabled ",{"type":415,"tag":559,"props":7398,"children":7399},{"style":583},[7400],{"type":420,"value":800},{"type":415,"tag":559,"props":7402,"children":7403},{"style":6887},[7404],{"type":420,"value":6890},{"type":415,"tag":559,"props":7406,"children":7407},{"style":583},[7408],{"type":420,"value":1509},{"type":415,"tag":559,"props":7410,"children":7411},{"class":561,"line":1795},[7412],{"type":415,"tag":559,"props":7413,"children":7414},{"style":583},[7415],{"type":420,"value":7416},"    });\n",{"type":415,"tag":559,"props":7418,"children":7419},{"class":561,"line":3289},[7420],{"type":415,"tag":559,"props":7421,"children":7422},{"style":583},[7423],{"type":420,"value":5833},{"type":415,"tag":416,"props":7425,"children":7426},{},[7427,7429,7434],{"type":420,"value":7428},"That's the purpose of the ",{"type":415,"tag":555,"props":7430,"children":7432},{"className":7431},[],[7433],{"type":420,"value":7271},{"type":420,"value":6716},{"type":415,"tag":1178,"props":7436,"children":7437},{"icon":5363},[7438],{"type":415,"tag":416,"props":7439,"children":7440},{},[7441,7443],{"type":420,"value":7442},"Please note that all this configuration (as well as the Uris of each client) can be loaded from the configuration like this ",{"type":415,"tag":555,"props":7444,"children":7446},{"className":7445},[],[7447],{"type":420,"value":7448},"clientBuilder.AddTableServiceClient(builder.Configuration.GetSection(\"Inventory:Tables\"));",{"type":415,"tag":422,"props":7450,"children":7452},{"id":7451},"use-named-clients-for-different-azure-resources",[7453],{"type":420,"value":7454},"Use named clients for different Azure resources",{"type":415,"tag":416,"props":7456,"children":7457},{},[7458,7460,7466],{"type":420,"value":7459},"Usually, you only need one client of each SDK in your application. Let's say you have multiple Azure Storage tables that are used in your application, you will only need to have one ",{"type":415,"tag":555,"props":7461,"children":7463},{"className":7462},[],[7464],{"type":420,"value":7465},"TableServiceClient",{"type":420,"value":7467},". However, if you are interacting with tables in two different storage accounts, you will need multiple table clients.",{"type":415,"tag":416,"props":7469,"children":7470},{},[7471],{"type":420,"value":7472},"To do that you can register your clients with a specific name:",{"type":415,"tag":549,"props":7474,"children":7476},{"className":551,"code":7475,"language":326,"meta":401,"style":401},"builder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddTableServiceClient(builder.Configuration.GetSection(\"Shop:Inventory\"))\n        .WithName(\"Shop\");\n    clientBuilder.AddTableServiceClient(builder.Configuration.GetSection(\"Warehouse:Inventory\"))\n        .WithName(\"Warehouse\");\n}\n",[7477],{"type":415,"tag":555,"props":7478,"children":7479},{"__ignoreMap":401},[7480,7515,7522,7583,7616,7676,7708],{"type":415,"tag":559,"props":7481,"children":7482},{"class":561,"line":562},[7483,7487,7491,7495,7499,7503,7507,7511],{"type":415,"tag":559,"props":7484,"children":7485},{"style":792},[7486],{"type":420,"value":5671},{"type":415,"tag":559,"props":7488,"children":7489},{"style":583},[7490],{"type":420,"value":542},{"type":415,"tag":559,"props":7492,"children":7493},{"style":792},[7494],{"type":420,"value":5680},{"type":415,"tag":559,"props":7496,"children":7497},{"style":583},[7498],{"type":420,"value":542},{"type":415,"tag":559,"props":7500,"children":7501},{"style":883},[7502],{"type":420,"value":5727},{"type":415,"tag":559,"props":7504,"children":7505},{"style":583},[7506],{"type":420,"value":814},{"type":415,"tag":559,"props":7508,"children":7509},{"style":572},[7510],{"type":420,"value":5736},{"type":415,"tag":559,"props":7512,"children":7513},{"style":583},[7514],{"type":420,"value":5741},{"type":415,"tag":559,"props":7516,"children":7517},{"class":561,"line":589},[7518],{"type":415,"tag":559,"props":7519,"children":7520},{"style":583},[7521],{"type":420,"value":786},{"type":415,"tag":559,"props":7523,"children":7524},{"class":561,"line":608},[7525,7529,7533,7537,7541,7545,7549,7553,7557,7562,7566,7570,7575,7579],{"type":415,"tag":559,"props":7526,"children":7527},{"style":792},[7528],{"type":420,"value":5756},{"type":415,"tag":559,"props":7530,"children":7531},{"style":583},[7532],{"type":420,"value":542},{"type":415,"tag":559,"props":7534,"children":7535},{"style":883},[7536],{"type":420,"value":6524},{"type":415,"tag":559,"props":7538,"children":7539},{"style":583},[7540],{"type":420,"value":814},{"type":415,"tag":559,"props":7542,"children":7543},{"style":792},[7544],{"type":420,"value":5671},{"type":415,"tag":559,"props":7546,"children":7547},{"style":583},[7548],{"type":420,"value":542},{"type":415,"tag":559,"props":7550,"children":7551},{"style":792},[7552],{"type":420,"value":263},{"type":415,"tag":559,"props":7554,"children":7555},{"style":583},[7556],{"type":420,"value":542},{"type":415,"tag":559,"props":7558,"children":7559},{"style":883},[7560],{"type":420,"value":7561},"GetSection",{"type":415,"tag":559,"props":7563,"children":7564},{"style":583},[7565],{"type":420,"value":814},{"type":415,"tag":559,"props":7567,"children":7568},{"style":583},[7569],{"type":420,"value":819},{"type":415,"tag":559,"props":7571,"children":7572},{"style":822},[7573],{"type":420,"value":7574},"Shop:Inventory",{"type":415,"tag":559,"props":7576,"children":7577},{"style":583},[7578],{"type":420,"value":819},{"type":415,"tag":559,"props":7580,"children":7581},{"style":583},[7582],{"type":420,"value":6258},{"type":415,"tag":559,"props":7584,"children":7585},{"class":561,"line":626},[7586,7590,7595,7599,7603,7608,7612],{"type":415,"tag":559,"props":7587,"children":7588},{"style":583},[7589],{"type":420,"value":6482},{"type":415,"tag":559,"props":7591,"children":7592},{"style":883},[7593],{"type":420,"value":7594},"WithName",{"type":415,"tag":559,"props":7596,"children":7597},{"style":583},[7598],{"type":420,"value":814},{"type":415,"tag":559,"props":7600,"children":7601},{"style":583},[7602],{"type":420,"value":819},{"type":415,"tag":559,"props":7604,"children":7605},{"style":822},[7606],{"type":420,"value":7607},"Shop",{"type":415,"tag":559,"props":7609,"children":7610},{"style":583},[7611],{"type":420,"value":819},{"type":415,"tag":559,"props":7613,"children":7614},{"style":583},[7615],{"type":420,"value":696},{"type":415,"tag":559,"props":7617,"children":7618},{"class":561,"line":643},[7619,7623,7627,7631,7635,7639,7643,7647,7651,7655,7659,7663,7668,7672],{"type":415,"tag":559,"props":7620,"children":7621},{"style":792},[7622],{"type":420,"value":5756},{"type":415,"tag":559,"props":7624,"children":7625},{"style":583},[7626],{"type":420,"value":542},{"type":415,"tag":559,"props":7628,"children":7629},{"style":883},[7630],{"type":420,"value":6524},{"type":415,"tag":559,"props":7632,"children":7633},{"style":583},[7634],{"type":420,"value":814},{"type":415,"tag":559,"props":7636,"children":7637},{"style":792},[7638],{"type":420,"value":5671},{"type":415,"tag":559,"props":7640,"children":7641},{"style":583},[7642],{"type":420,"value":542},{"type":415,"tag":559,"props":7644,"children":7645},{"style":792},[7646],{"type":420,"value":263},{"type":415,"tag":559,"props":7648,"children":7649},{"style":583},[7650],{"type":420,"value":542},{"type":415,"tag":559,"props":7652,"children":7653},{"style":883},[7654],{"type":420,"value":7561},{"type":415,"tag":559,"props":7656,"children":7657},{"style":583},[7658],{"type":420,"value":814},{"type":415,"tag":559,"props":7660,"children":7661},{"style":583},[7662],{"type":420,"value":819},{"type":415,"tag":559,"props":7664,"children":7665},{"style":822},[7666],{"type":420,"value":7667},"Warehouse:Inventory",{"type":415,"tag":559,"props":7669,"children":7670},{"style":583},[7671],{"type":420,"value":819},{"type":415,"tag":559,"props":7673,"children":7674},{"style":583},[7675],{"type":420,"value":6258},{"type":415,"tag":559,"props":7677,"children":7678},{"class":561,"line":660},[7679,7683,7687,7691,7695,7700,7704],{"type":415,"tag":559,"props":7680,"children":7681},{"style":583},[7682],{"type":420,"value":6482},{"type":415,"tag":559,"props":7684,"children":7685},{"style":883},[7686],{"type":420,"value":7594},{"type":415,"tag":559,"props":7688,"children":7689},{"style":583},[7690],{"type":420,"value":814},{"type":415,"tag":559,"props":7692,"children":7693},{"style":583},[7694],{"type":420,"value":819},{"type":415,"tag":559,"props":7696,"children":7697},{"style":822},[7698],{"type":420,"value":7699},"Warehouse",{"type":415,"tag":559,"props":7701,"children":7702},{"style":583},[7703],{"type":420,"value":819},{"type":415,"tag":559,"props":7705,"children":7706},{"style":583},[7707],{"type":420,"value":696},{"type":415,"tag":559,"props":7709,"children":7710},{"class":561,"line":677},[7711],{"type":415,"tag":559,"props":7712,"children":7713},{"style":583},[7714],{"type":420,"value":1801},{"type":415,"tag":416,"props":7716,"children":7717},{},[7718],{"type":420,"value":7719},"This way, you will be able to retrieve the specific client you need in your code:",{"type":415,"tag":549,"props":7721,"children":7723},{"className":551,"code":7722,"language":326,"meta":401,"style":401},"public class WarehouseDeliveryService\n{\n    private readonly TableServiceClient _tableServiceClient;\n\n    public WarehouseDeliveryService(IAzureClientFactory\u003CTableServiceClient> azureClientFactory)\n    {\n        _tableServiceClient = azureClientFactory.CreateClient(\"Warehouse\");\n    }\n}\n",[7724],{"type":415,"tag":555,"props":7725,"children":7726},{"__ignoreMap":401},[7727,7743,7750,7775,7782,7824,7831,7876,7883],{"type":415,"tag":559,"props":7728,"children":7729},{"class":561,"line":562},[7730,7734,7738],{"type":415,"tag":559,"props":7731,"children":7732},{"style":566},[7733],{"type":420,"value":569},{"type":415,"tag":559,"props":7735,"children":7736},{"style":572},[7737],{"type":420,"value":5933},{"type":415,"tag":559,"props":7739,"children":7740},{"style":572},[7741],{"type":420,"value":7742}," WarehouseDeliveryService\n",{"type":415,"tag":559,"props":7744,"children":7745},{"class":561,"line":589},[7746],{"type":415,"tag":559,"props":7747,"children":7748},{"style":583},[7749],{"type":420,"value":786},{"type":415,"tag":559,"props":7751,"children":7752},{"class":561,"line":608},[7753,7757,7761,7766,7771],{"type":415,"tag":559,"props":7754,"children":7755},{"style":566},[7756],{"type":420,"value":5962},{"type":415,"tag":559,"props":7758,"children":7759},{"style":566},[7760],{"type":420,"value":5967},{"type":415,"tag":559,"props":7762,"children":7763},{"style":572},[7764],{"type":420,"value":7765}," TableServiceClient",{"type":415,"tag":559,"props":7767,"children":7768},{"style":572},[7769],{"type":420,"value":7770}," _tableServiceClient",{"type":415,"tag":559,"props":7772,"children":7773},{"style":583},[7774],{"type":420,"value":1509},{"type":415,"tag":559,"props":7776,"children":7777},{"class":561,"line":626},[7778],{"type":415,"tag":559,"props":7779,"children":7780},{"emptyLinePlaceholder":847},[7781],{"type":420,"value":850},{"type":415,"tag":559,"props":7783,"children":7784},{"class":561,"line":643},[7785,7789,7794,7798,7803,7807,7811,7815,7820],{"type":415,"tag":559,"props":7786,"children":7787},{"style":566},[7788],{"type":420,"value":1124},{"type":415,"tag":559,"props":7790,"children":7791},{"style":883},[7792],{"type":420,"value":7793}," WarehouseDeliveryService",{"type":415,"tag":559,"props":7795,"children":7796},{"style":583},[7797],{"type":420,"value":814},{"type":415,"tag":559,"props":7799,"children":7800},{"style":572},[7801],{"type":420,"value":7802},"IAzureClientFactory",{"type":415,"tag":559,"props":7804,"children":7805},{"style":583},[7806],{"type":420,"value":891},{"type":415,"tag":559,"props":7808,"children":7809},{"style":572},[7810],{"type":420,"value":7465},{"type":415,"tag":559,"props":7812,"children":7813},{"style":583},[7814],{"type":420,"value":5985},{"type":415,"tag":559,"props":7816,"children":7817},{"style":572},[7818],{"type":420,"value":7819}," azureClientFactory",{"type":415,"tag":559,"props":7821,"children":7822},{"style":583},[7823],{"type":420,"value":833},{"type":415,"tag":559,"props":7825,"children":7826},{"class":561,"line":660},[7827],{"type":415,"tag":559,"props":7828,"children":7829},{"style":583},[7830],{"type":420,"value":2737},{"type":415,"tag":559,"props":7832,"children":7833},{"class":561,"line":677},[7834,7839,7843,7847,7851,7856,7860,7864,7868,7872],{"type":415,"tag":559,"props":7835,"children":7836},{"style":792},[7837],{"type":420,"value":7838},"        _tableServiceClient ",{"type":415,"tag":559,"props":7840,"children":7841},{"style":583},[7842],{"type":420,"value":800},{"type":415,"tag":559,"props":7844,"children":7845},{"style":792},[7846],{"type":420,"value":7819},{"type":415,"tag":559,"props":7848,"children":7849},{"style":583},[7850],{"type":420,"value":542},{"type":415,"tag":559,"props":7852,"children":7853},{"style":883},[7854],{"type":420,"value":7855},"CreateClient",{"type":415,"tag":559,"props":7857,"children":7858},{"style":583},[7859],{"type":420,"value":814},{"type":415,"tag":559,"props":7861,"children":7862},{"style":583},[7863],{"type":420,"value":819},{"type":415,"tag":559,"props":7865,"children":7866},{"style":822},[7867],{"type":420,"value":7699},{"type":415,"tag":559,"props":7869,"children":7870},{"style":583},[7871],{"type":420,"value":819},{"type":415,"tag":559,"props":7873,"children":7874},{"style":583},[7875],{"type":420,"value":696},{"type":415,"tag":559,"props":7877,"children":7878},{"class":561,"line":690},[7879],{"type":415,"tag":559,"props":7880,"children":7881},{"style":583},[7882],{"type":420,"value":2792},{"type":415,"tag":559,"props":7884,"children":7885},{"class":561,"line":1089},[7886],{"type":415,"tag":559,"props":7887,"children":7888},{"style":583},[7889],{"type":420,"value":1801},{"type":415,"tag":422,"props":7891,"children":7893},{"id":7892},"register-a-custom-client-factory",[7894],{"type":420,"value":7895},"Register a custom client factory",{"type":415,"tag":416,"props":7897,"children":7898},{},[7899,7901,7908,7910,7916],{"type":420,"value":7900},"If you have ",{"type":415,"tag":434,"props":7902,"children":7905},{"href":7903,"rel":7904},"https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/extensions/Microsoft.Extensions.Azure/README.md#registering-a-custom-client-factory",[438],[7906],{"type":420,"value":7907},"specific needs",{"type":420,"value":7909},", the ",{"type":415,"tag":555,"props":7911,"children":7913},{"className":7912},[],[7914],{"type":420,"value":7915},"AddClient",{"type":420,"value":7917}," method can help you register your Azure client while letting you control how you instantiate the client.",{"type":415,"tag":416,"props":7919,"children":7920},{},[7921,7923,7929,7931,7937,7939,7944,7946,7953,7955,7960],{"type":420,"value":7922},"For instance, the Azure Cosmos Db .NET SDK is not built on the same foundation (",{"type":415,"tag":555,"props":7924,"children":7926},{"className":7925},[],[7927],{"type":420,"value":7928},"Azure.Core",{"type":420,"value":7930},") as the other SDKs. So at the time of writing, there is no ",{"type":415,"tag":555,"props":7932,"children":7934},{"className":7933},[],[7935],{"type":420,"value":7936},"AddCosmosServiceClient",{"type":420,"value":7938}," you can use in the ",{"type":415,"tag":555,"props":7940,"children":7942},{"className":7941},[],[7943],{"type":420,"value":5727},{"type":420,"value":7945}," (there is an ",{"type":415,"tag":434,"props":7947,"children":7950},{"href":7948,"rel":7949},"https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4002",[438],[7951],{"type":420,"value":7952},"issue",{"type":420,"value":7954}," about that though). However, you can use the ",{"type":415,"tag":555,"props":7956,"children":7958},{"className":7957},[],[7959],{"type":420,"value":7915},{"type":420,"value":7961}," I've just mentioned.",{"type":415,"tag":549,"props":7963,"children":7965},{"className":551,"code":7964,"language":326,"meta":401,"style":401},"builder.Services.AddOptions\u003CCosmosDbConfiguration>().BindConfiguration(\"Warehouse:CosmosDb\");\nbuilder.Services.AddAzureClients(clientBuilder =>\n{\n    clientBuilder.AddClient\u003CCosmosClient, CosmosClientOptions>((_, _, serviceProvider) =>\n    {\n        var cosmosConfiguration = serviceProvider.GetRequiredService\u003CIOptions\u003CCosmosDbConfiguration>>().Value;\n        return new CosmosClientBuilder(cosmosConfiguration.Endpoint, cosmosConfiguration.AuthKey)\n            .WithSerializerOptions(new () { PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase })\n            .Build();\n    }).WithName(\"Warehouse\");\n}\n",[7966],{"type":415,"tag":555,"props":7967,"children":7968},{"__ignoreMap":401},[7969,8033,8068,8075,8144,8151,8211,8267,8321,8336,8368],{"type":415,"tag":559,"props":7970,"children":7971},{"class":561,"line":562},[7972,7976,7980,7984,7988,7993,7997,8002,8007,8012,8016,8020,8025,8029],{"type":415,"tag":559,"props":7973,"children":7974},{"style":792},[7975],{"type":420,"value":5671},{"type":415,"tag":559,"props":7977,"children":7978},{"style":583},[7979],{"type":420,"value":542},{"type":415,"tag":559,"props":7981,"children":7982},{"style":792},[7983],{"type":420,"value":5680},{"type":415,"tag":559,"props":7985,"children":7986},{"style":583},[7987],{"type":420,"value":542},{"type":415,"tag":559,"props":7989,"children":7990},{"style":883},[7991],{"type":420,"value":7992},"AddOptions",{"type":415,"tag":559,"props":7994,"children":7995},{"style":583},[7996],{"type":420,"value":891},{"type":415,"tag":559,"props":7998,"children":7999},{"style":572},[8000],{"type":420,"value":8001},"CosmosDbConfiguration",{"type":415,"tag":559,"props":8003,"children":8004},{"style":583},[8005],{"type":420,"value":8006},">().",{"type":415,"tag":559,"props":8008,"children":8009},{"style":883},[8010],{"type":420,"value":8011},"BindConfiguration",{"type":415,"tag":559,"props":8013,"children":8014},{"style":583},[8015],{"type":420,"value":814},{"type":415,"tag":559,"props":8017,"children":8018},{"style":583},[8019],{"type":420,"value":819},{"type":415,"tag":559,"props":8021,"children":8022},{"style":822},[8023],{"type":420,"value":8024},"Warehouse:CosmosDb",{"type":415,"tag":559,"props":8026,"children":8027},{"style":583},[8028],{"type":420,"value":819},{"type":415,"tag":559,"props":8030,"children":8031},{"style":583},[8032],{"type":420,"value":696},{"type":415,"tag":559,"props":8034,"children":8035},{"class":561,"line":589},[8036,8040,8044,8048,8052,8056,8060,8064],{"type":415,"tag":559,"props":8037,"children":8038},{"style":792},[8039],{"type":420,"value":5671},{"type":415,"tag":559,"props":8041,"children":8042},{"style":583},[8043],{"type":420,"value":542},{"type":415,"tag":559,"props":8045,"children":8046},{"style":792},[8047],{"type":420,"value":5680},{"type":415,"tag":559,"props":8049,"children":8050},{"style":583},[8051],{"type":420,"value":542},{"type":415,"tag":559,"props":8053,"children":8054},{"style":883},[8055],{"type":420,"value":5727},{"type":415,"tag":559,"props":8057,"children":8058},{"style":583},[8059],{"type":420,"value":814},{"type":415,"tag":559,"props":8061,"children":8062},{"style":572},[8063],{"type":420,"value":5736},{"type":415,"tag":559,"props":8065,"children":8066},{"style":583},[8067],{"type":420,"value":5741},{"type":415,"tag":559,"props":8069,"children":8070},{"class":561,"line":608},[8071],{"type":415,"tag":559,"props":8072,"children":8073},{"style":583},[8074],{"type":420,"value":786},{"type":415,"tag":559,"props":8076,"children":8077},{"class":561,"line":626},[8078,8082,8086,8090,8094,8099,8103,8108,8113,8118,8122,8127,8131,8136,8140],{"type":415,"tag":559,"props":8079,"children":8080},{"style":792},[8081],{"type":420,"value":5756},{"type":415,"tag":559,"props":8083,"children":8084},{"style":583},[8085],{"type":420,"value":542},{"type":415,"tag":559,"props":8087,"children":8088},{"style":883},[8089],{"type":420,"value":7915},{"type":415,"tag":559,"props":8091,"children":8092},{"style":583},[8093],{"type":420,"value":891},{"type":415,"tag":559,"props":8095,"children":8096},{"style":572},[8097],{"type":420,"value":8098},"CosmosClient",{"type":415,"tag":559,"props":8100,"children":8101},{"style":583},[8102],{"type":420,"value":2312},{"type":415,"tag":559,"props":8104,"children":8105},{"style":572},[8106],{"type":420,"value":8107}," CosmosClientOptions",{"type":415,"tag":559,"props":8109,"children":8110},{"style":583},[8111],{"type":420,"value":8112},">((",{"type":415,"tag":559,"props":8114,"children":8115},{"style":572},[8116],{"type":420,"value":8117},"_",{"type":415,"tag":559,"props":8119,"children":8120},{"style":583},[8121],{"type":420,"value":2312},{"type":415,"tag":559,"props":8123,"children":8124},{"style":572},[8125],{"type":420,"value":8126}," _",{"type":415,"tag":559,"props":8128,"children":8129},{"style":583},[8130],{"type":420,"value":2312},{"type":415,"tag":559,"props":8132,"children":8133},{"style":572},[8134],{"type":420,"value":8135}," serviceProvider",{"type":415,"tag":559,"props":8137,"children":8138},{"style":583},[8139],{"type":420,"value":1468},{"type":415,"tag":559,"props":8141,"children":8142},{"style":583},[8143],{"type":420,"value":5741},{"type":415,"tag":559,"props":8145,"children":8146},{"class":561,"line":643},[8147],{"type":415,"tag":559,"props":8148,"children":8149},{"style":583},[8150],{"type":420,"value":2737},{"type":415,"tag":559,"props":8152,"children":8153},{"class":561,"line":660},[8154,8158,8163,8167,8171,8175,8180,8184,8189,8193,8197,8202,8207],{"type":415,"tag":559,"props":8155,"children":8156},{"style":572},[8157],{"type":420,"value":2745},{"type":415,"tag":559,"props":8159,"children":8160},{"style":572},[8161],{"type":420,"value":8162}," cosmosConfiguration",{"type":415,"tag":559,"props":8164,"children":8165},{"style":583},[8166],{"type":420,"value":763},{"type":415,"tag":559,"props":8168,"children":8169},{"style":792},[8170],{"type":420,"value":8135},{"type":415,"tag":559,"props":8172,"children":8173},{"style":583},[8174],{"type":420,"value":542},{"type":415,"tag":559,"props":8176,"children":8177},{"style":883},[8178],{"type":420,"value":8179},"GetRequiredService",{"type":415,"tag":559,"props":8181,"children":8182},{"style":583},[8183],{"type":420,"value":891},{"type":415,"tag":559,"props":8185,"children":8186},{"style":572},[8187],{"type":420,"value":8188},"IOptions",{"type":415,"tag":559,"props":8190,"children":8191},{"style":583},[8192],{"type":420,"value":891},{"type":415,"tag":559,"props":8194,"children":8195},{"style":572},[8196],{"type":420,"value":8001},{"type":415,"tag":559,"props":8198,"children":8199},{"style":583},[8200],{"type":420,"value":8201},">>().",{"type":415,"tag":559,"props":8203,"children":8204},{"style":792},[8205],{"type":420,"value":8206},"Value",{"type":415,"tag":559,"props":8208,"children":8209},{"style":583},[8210],{"type":420,"value":1509},{"type":415,"tag":559,"props":8212,"children":8213},{"class":561,"line":677},[8214,8219,8223,8228,8232,8237,8241,8246,8250,8254,8258,8263],{"type":415,"tag":559,"props":8215,"children":8216},{"style":745},[8217],{"type":420,"value":8218},"        return",{"type":415,"tag":559,"props":8220,"children":8221},{"style":583},[8222],{"type":420,"value":768},{"type":415,"tag":559,"props":8224,"children":8225},{"style":572},[8226],{"type":420,"value":8227}," CosmosClientBuilder",{"type":415,"tag":559,"props":8229,"children":8230},{"style":583},[8231],{"type":420,"value":814},{"type":415,"tag":559,"props":8233,"children":8234},{"style":792},[8235],{"type":420,"value":8236},"cosmosConfiguration",{"type":415,"tag":559,"props":8238,"children":8239},{"style":583},[8240],{"type":420,"value":542},{"type":415,"tag":559,"props":8242,"children":8243},{"style":792},[8244],{"type":420,"value":8245},"Endpoint",{"type":415,"tag":559,"props":8247,"children":8248},{"style":583},[8249],{"type":420,"value":2312},{"type":415,"tag":559,"props":8251,"children":8252},{"style":792},[8253],{"type":420,"value":8162},{"type":415,"tag":559,"props":8255,"children":8256},{"style":583},[8257],{"type":420,"value":542},{"type":415,"tag":559,"props":8259,"children":8260},{"style":792},[8261],{"type":420,"value":8262},"AuthKey",{"type":415,"tag":559,"props":8264,"children":8265},{"style":583},[8266],{"type":420,"value":833},{"type":415,"tag":559,"props":8268,"children":8269},{"class":561,"line":690},[8270,8275,8280,8284,8289,8293,8298,8302,8307,8311,8316],{"type":415,"tag":559,"props":8271,"children":8272},{"style":583},[8273],{"type":420,"value":8274},"            .",{"type":415,"tag":559,"props":8276,"children":8277},{"style":883},[8278],{"type":420,"value":8279},"WithSerializerOptions",{"type":415,"tag":559,"props":8281,"children":8282},{"style":583},[8283],{"type":420,"value":5770},{"type":415,"tag":559,"props":8285,"children":8286},{"style":583},[8287],{"type":420,"value":8288}," ()",{"type":415,"tag":559,"props":8290,"children":8291},{"style":583},[8292],{"type":420,"value":1144},{"type":415,"tag":559,"props":8294,"children":8295},{"style":792},[8296],{"type":420,"value":8297}," PropertyNamingPolicy ",{"type":415,"tag":559,"props":8299,"children":8300},{"style":583},[8301],{"type":420,"value":800},{"type":415,"tag":559,"props":8303,"children":8304},{"style":792},[8305],{"type":420,"value":8306}," CosmosPropertyNamingPolicy",{"type":415,"tag":559,"props":8308,"children":8309},{"style":583},[8310],{"type":420,"value":542},{"type":415,"tag":559,"props":8312,"children":8313},{"style":792},[8314],{"type":420,"value":8315},"CamelCase ",{"type":415,"tag":559,"props":8317,"children":8318},{"style":583},[8319],{"type":420,"value":8320},"})\n",{"type":415,"tag":559,"props":8322,"children":8323},{"class":561,"line":1089},[8324,8328,8332],{"type":415,"tag":559,"props":8325,"children":8326},{"style":583},[8327],{"type":420,"value":8274},{"type":415,"tag":559,"props":8329,"children":8330},{"style":883},[8331],{"type":420,"value":5869},{"type":415,"tag":559,"props":8333,"children":8334},{"style":583},[8335],{"type":420,"value":1962},{"type":415,"tag":559,"props":8337,"children":8338},{"class":561,"line":1102},[8339,8344,8348,8352,8356,8360,8364],{"type":415,"tag":559,"props":8340,"children":8341},{"style":583},[8342],{"type":420,"value":8343},"    }).",{"type":415,"tag":559,"props":8345,"children":8346},{"style":883},[8347],{"type":420,"value":7594},{"type":415,"tag":559,"props":8349,"children":8350},{"style":583},[8351],{"type":420,"value":814},{"type":415,"tag":559,"props":8353,"children":8354},{"style":583},[8355],{"type":420,"value":819},{"type":415,"tag":559,"props":8357,"children":8358},{"style":822},[8359],{"type":420,"value":7699},{"type":415,"tag":559,"props":8361,"children":8362},{"style":583},[8363],{"type":420,"value":819},{"type":415,"tag":559,"props":8365,"children":8366},{"style":583},[8367],{"type":420,"value":696},{"type":415,"tag":559,"props":8369,"children":8370},{"class":561,"line":1110},[8371],{"type":415,"tag":559,"props":8372,"children":8373},{"style":583},[8374],{"type":420,"value":1801},{"type":415,"tag":416,"props":8376,"children":8377},{},[8378,8380,8385],{"type":420,"value":8379},"You can note that using the ",{"type":415,"tag":555,"props":8381,"children":8383},{"className":8382},[],[8384],{"type":420,"value":7915},{"type":420,"value":8386}," method allows us to take profit from the named clients' feature.",{"type":415,"tag":422,"props":8388,"children":8390},{"id":8389},"wrapping-up",[8391],{"type":420,"value":8392},"Wrapping up",{"type":415,"tag":416,"props":8394,"children":8395},{},[8396,8398,8407],{"type":420,"value":8397},"As you have seen, the use of the ",{"type":415,"tag":434,"props":8399,"children":8401},{"href":5479,"rel":8400},[438],[8402],{"type":415,"tag":555,"props":8403,"children":8405},{"className":8404},[],[8406],{"type":420,"value":5487},{"type":420,"value":8408}," package simplifies the registration and configuration of Azure clients. While providing you with a consistent way of handling the dependency injection for Azure SDKs, it also allows you to easily customize the authentication and other options available.",{"type":415,"tag":416,"props":8410,"children":8411},{},[8412],{"type":420,"value":8413},"I hope you learned something. Don't hesitate to share your tips or what you like about the Azure SDKs in the comments.",{"type":415,"tag":5406,"props":8415,"children":8416},{},[8417],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":8419},[8420,8421,8422,8423,8424,8425],{"id":5497,"depth":589,"text":5500},{"id":6371,"depth":589,"text":6374},{"id":6701,"depth":589,"text":6704},{"id":7451,"depth":589,"text":7454},{"id":7892,"depth":589,"text":7895},{"id":8389,"depth":589,"text":8392},"content:1.posts:59.azure-sdk-di.md","1.posts/59.azure-sdk-di.md",{"_path":175,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":174,"description":8429,"lead":8430,"date":8431,"image":8432,"badge":8434,"tags":8435,"body":8436,"_type":5421,"_id":14155,"_source":5423,"_file":14156,"_extension":5425},"In this article, we will explore the latest C# 12 and .NET 8 features by applying them to the basic dotnet Web API template.","Enhanced weather forecast API","2023-12-19T00:00:00.000Z",{"src":8433},"/images/weather_flag.webp",{"label":408},[326,239,236,213,384],{"type":412,"children":8437,"toc":14150},[8438,8442,8448,8461,8492,8497,8507,8512,8546,8559,8568,8581,8644,8665,8682,8701,8710,8716,8721,8726,8768,8777,8790,9147,9175,9333,9345,9374,10508,10513,10668,10689,11208,11218,11433,11447,11651,11656,11918,11923,11934,12255,12263,12276,12506,12534,12539,12668,12673,12807,12820,13146,13158,13181,13485,13504,13908,13914,13919,13921,14083,14111,14132,14146],{"type":415,"tag":416,"props":8439,"children":8440},{},[8441],{"type":420,"value":8429},{"type":415,"tag":422,"props":8443,"children":8445},{"id":8444},"getting-started-with-the-aspnet-core-web-api-template",[8446],{"type":420,"value":8447},"Getting started with the ASP.NET Core Web API template",{"type":415,"tag":416,"props":8449,"children":8450},{},[8451,8453,8460],{"type":420,"value":8452},"First, let's install the latest ",{"type":415,"tag":434,"props":8454,"children":8457},{"href":8455,"rel":8456},"https://dotnet.microsoft.com/en-us/download/dotnet/8.0",[438],[8458],{"type":420,"value":8459},".NET 8 SDK",{"type":420,"value":1206},{"type":415,"tag":549,"props":8462,"children":8465},{"className":8463,"code":8464,"language":248,"meta":401,"style":401},"language-powershell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","winget install --id Microsoft.DotNet.SDK.8\n",[8466],{"type":415,"tag":555,"props":8467,"children":8468},{"__ignoreMap":401},[8469],{"type":415,"tag":559,"props":8470,"children":8471},{"class":561,"line":562},[8472,8477,8482,8487],{"type":415,"tag":559,"props":8473,"children":8474},{"style":792},[8475],{"type":420,"value":8476},"winget install ",{"type":415,"tag":559,"props":8478,"children":8479},{"style":583},[8480],{"type":420,"value":8481},"--",{"type":415,"tag":559,"props":8483,"children":8484},{"style":792},[8485],{"type":420,"value":8486},"id Microsoft.DotNet.SDK.",{"type":415,"tag":559,"props":8488,"children":8489},{"style":2846},[8490],{"type":420,"value":8491},"8\n",{"type":415,"tag":416,"props":8493,"children":8494},{},[8495],{"type":420,"value":8496},"We can list the available templates:",{"type":415,"tag":416,"props":8498,"children":8499},{},[8500],{"type":415,"tag":934,"props":8501,"children":8506},{"alt":8502,"className":8503,"src":8505},"List of the available dotnet templates",[938,8504],"mx-auto","/posts/images/dontnet8_templates.webp",[],{"type":415,"tag":416,"props":8508,"children":8509},{},[8510],{"type":420,"value":8511},"Let's go for the basic ASP.NET Core Web API template but with the controllers:",{"type":415,"tag":549,"props":8513,"children":8515},{"className":8463,"code":8514,"language":248,"meta":401,"style":401},"dotnet new webapi --use-controllers -n WeatherApi\n",[8516],{"type":415,"tag":555,"props":8517,"children":8518},{"__ignoreMap":401},[8519],{"type":415,"tag":559,"props":8520,"children":8521},{"class":561,"line":562},[8522,8527,8531,8536,8541],{"type":415,"tag":559,"props":8523,"children":8524},{"style":792},[8525],{"type":420,"value":8526},"dotnet new webapi ",{"type":415,"tag":559,"props":8528,"children":8529},{"style":583},[8530],{"type":420,"value":8481},{"type":415,"tag":559,"props":8532,"children":8533},{"style":883},[8534],{"type":420,"value":8535},"use-controllers",{"type":415,"tag":559,"props":8537,"children":8538},{"style":583},[8539],{"type":420,"value":8540}," -",{"type":415,"tag":559,"props":8542,"children":8543},{"style":792},[8544],{"type":420,"value":8545},"n WeatherApi\n",{"type":415,"tag":1178,"props":8547,"children":8548},{"icon":5363},[8549],{"type":415,"tag":416,"props":8550,"children":8551},{},[8552,8557],{"type":415,"tag":559,"props":8553,"children":8554},{},[8555],{"type":420,"value":8556},"Minimal APIs",{"type":420,"value":8558}," are great too but having controllers is more suited to what I want to show in this article.",{"type":415,"tag":416,"props":8560,"children":8561},{},[8562],{"type":415,"tag":934,"props":8563,"children":8567},{"alt":8564,"className":8565,"src":8566},"Screenshot of the generated project in Rider",[938,8504],"/posts/images/dontnet8_webapi_template.webp",[],{"type":415,"tag":416,"props":8569,"children":8570},{},[8571,8573,8579],{"type":420,"value":8572},"We can run the API and test the ",{"type":415,"tag":555,"props":8574,"children":8576},{"className":8575},[],[8577],{"type":420,"value":8578},"GET /weatherforecast",{"type":420,"value":8580}," endpoint using the generated request file:",{"type":415,"tag":549,"props":8582,"children":8585},{"className":8583,"code":8584,"language":212,"meta":401,"style":401},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","@WeatherApi_HostAddress = http://localhost:5103\n\nGET {{WeatherApi_HostAddress}}/weatherforecast/\nAccept: application/json\n",[8586],{"type":415,"tag":555,"props":8587,"children":8588},{"__ignoreMap":401},[8589,8607,8614,8626],{"type":415,"tag":559,"props":8590,"children":8591},{"class":561,"line":562},[8592,8597,8602],{"type":415,"tag":559,"props":8593,"children":8594},{"style":2846},[8595],{"type":420,"value":8596},"@",{"type":415,"tag":559,"props":8598,"children":8599},{"style":792},[8600],{"type":420,"value":8601},"WeatherApi_HostAddress = ",{"type":415,"tag":559,"props":8603,"children":8604},{"style":822},[8605],{"type":420,"value":8606},"http://localhost:5103\n",{"type":415,"tag":559,"props":8608,"children":8609},{"class":561,"line":589},[8610],{"type":415,"tag":559,"props":8611,"children":8612},{"emptyLinePlaceholder":847},[8613],{"type":420,"value":850},{"type":415,"tag":559,"props":8615,"children":8616},{"class":561,"line":608},[8617,8621],{"type":415,"tag":559,"props":8618,"children":8619},{"style":745},[8620],{"type":420,"value":723},{"type":415,"tag":559,"props":8622,"children":8623},{"style":792},[8624],{"type":420,"value":8625}," {{WeatherApi_HostAddress}}/weatherforecast/\n",{"type":415,"tag":559,"props":8627,"children":8628},{"class":561,"line":626},[8629,8635,8639],{"type":415,"tag":559,"props":8630,"children":8632},{"style":8631},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[8633],{"type":420,"value":8634},"Accept",{"type":415,"tag":559,"props":8636,"children":8637},{"style":2846},[8638],{"type":420,"value":1206},{"type":415,"tag":559,"props":8640,"children":8641},{"style":822},[8642],{"type":420,"value":8643}," application/json\n",{"type":415,"tag":416,"props":8645,"children":8646},{},[8647,8649,8655,8657,8664],{"type":420,"value":8648},"This is included in the dotnet ",{"type":415,"tag":555,"props":8650,"children":8652},{"className":8651},[],[8653],{"type":420,"value":8654},"webapi",{"type":420,"value":8656}," template and is supported by Visual Studio, Rider, and vscode (using the ",{"type":415,"tag":434,"props":8658,"children":8661},{"href":8659,"rel":8660},"https://marketplace.visualstudio.com/items?itemName=humao.rest-client",[438],[8662],{"type":420,"value":8663},"REST Client extension",{"type":420,"value":1468},{"type":415,"tag":1178,"props":8666,"children":8667},{"icon":5363},[8668],{"type":415,"tag":416,"props":8669,"children":8670},{},[8671,8673,8680],{"type":420,"value":8672},"Read my article about ",{"type":415,"tag":434,"props":8674,"children":8677},{"href":8675,"rel":8676},"https://www.techwatching.dev/posts/http-clients",[438],[8678],{"type":420,"value":8679},"choosing an API Client",{"type":420,"value":8681}," and why I prefer versioned HTTP files rather than GUI tools like Postman.",{"type":415,"tag":416,"props":8683,"children":8684},{},[8685,8687,8700],{"type":420,"value":8686},"If we put a breakpoint in the controller we can see one small ASP.NET 8 improvement concerning the debugging experience: ",{"type":415,"tag":434,"props":8688,"children":8691},{"href":8689,"rel":8690},"https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0#improved-debugging-experience",[438],[8692,8694],{"type":420,"value":8693},"better debug summaries are displayed for types like ",{"type":415,"tag":555,"props":8695,"children":8697},{"className":8696},[],[8698],{"type":420,"value":8699},"HttpContext",{"type":420,"value":542},{"type":415,"tag":416,"props":8702,"children":8703},{},[8704],{"type":415,"tag":934,"props":8705,"children":8709},{"alt":8706,"className":8707,"src":8708},"Debugging display of the HTTPContext class",[938,8504],"/posts/images/dontnet8_httpcontext.webp",[],{"type":415,"tag":422,"props":8711,"children":8713},{"id":8712},"enhancing-the-weather-forecast-api",[8714],{"type":420,"value":8715},"Enhancing the Weather Forecast API",{"type":415,"tag":416,"props":8717,"children":8718},{},[8719],{"type":420,"value":8720},"Currently, the template randomly generates weather forecasts in the controller. It would be nice to retrieve real weather data from a weather API.",{"type":415,"tag":416,"props":8722,"children":8723},{},[8724],{"type":420,"value":8725},"To do that we can:",{"type":415,"tag":5376,"props":8727,"children":8728},{},[8729,8742,8755],{"type":415,"tag":5380,"props":8730,"children":8731},{},[8732,8734,8740],{"type":420,"value":8733},"introduce an ",{"type":415,"tag":555,"props":8735,"children":8737},{"className":8736},[],[8738],{"type":420,"value":8739},"IWeatherService",{"type":420,"value":8741}," interface that contains a method to retrieve weather forecasts",{"type":415,"tag":5380,"props":8743,"children":8744},{},[8745,8747,8753],{"type":420,"value":8746},"extract the current logic that generates the random weather forecasts in a ",{"type":415,"tag":555,"props":8748,"children":8750},{"className":8749},[],[8751],{"type":420,"value":8752},"RandomWeatherService.cs",{"type":420,"value":8754}," that implements this interface",{"type":415,"tag":5380,"props":8756,"children":8757},{},[8758,8760,8766],{"type":420,"value":8759},"creates a new implementation ",{"type":415,"tag":555,"props":8761,"children":8763},{"className":8762},[],[8764],{"type":420,"value":8765},"OpenWeatherService",{"type":420,"value":8767}," of this interface that retrieves the weather data from the Open Weather Map API",{"type":415,"tag":416,"props":8769,"children":8770},{},[8771],{"type":415,"tag":934,"props":8772,"children":8776},{"alt":8773,"className":8774,"src":8775},"A diagram of the ASP.NETCore Weather API",[938,8504],"/posts/images/dontnet8_webapi_diagram.webp",[],{"type":415,"tag":416,"props":8778,"children":8779},{},[8780,8782,8788],{"type":420,"value":8781},"The ",{"type":415,"tag":555,"props":8783,"children":8785},{"className":8784},[],[8786],{"type":420,"value":8787},"WeatherForecastController",{"type":420,"value":8789}," becomes:",{"type":415,"tag":549,"props":8791,"children":8793},{"className":551,"code":8792,"language":326,"meta":401,"style":401},"[ApiController]\n[Route(\"[controller]\")]\npublic class WeatherForecastController : ControllerBase\n{\n    private readonly IWeatherService _weatherService;\n\n    public WeatherForecastController(IWeatherService weatherService)\n    {\n        _weatherService = weatherService;\n    }\n\n    [HttpGet(Name = \"GetWeatherForecast\")]\n    [ProducesResponseType(typeof(WeatherForecast), StatusCodes.Status200OK)]\n    public Task\u003CWeatherForecast[]> Get()\n    {\n        return _weatherService.GetWeatherForecasts();\n    }\n}\n",[8794],{"type":415,"tag":555,"props":8795,"children":8796},{"__ignoreMap":401},[8797,8815,8849,8874,8881,8906,8913,8941,8948,8968,8975,8982,9024,9069,9102,9109,9133,9140],{"type":415,"tag":559,"props":8798,"children":8799},{"class":561,"line":562},[8800,8805,8810],{"type":415,"tag":559,"props":8801,"children":8802},{"style":583},[8803],{"type":420,"value":8804},"[",{"type":415,"tag":559,"props":8806,"children":8807},{"style":572},[8808],{"type":420,"value":8809},"ApiController",{"type":415,"tag":559,"props":8811,"children":8812},{"style":583},[8813],{"type":420,"value":8814},"]\n",{"type":415,"tag":559,"props":8816,"children":8817},{"class":561,"line":589},[8818,8822,8827,8831,8835,8840,8844],{"type":415,"tag":559,"props":8819,"children":8820},{"style":583},[8821],{"type":420,"value":8804},{"type":415,"tag":559,"props":8823,"children":8824},{"style":572},[8825],{"type":420,"value":8826},"Route",{"type":415,"tag":559,"props":8828,"children":8829},{"style":583},[8830],{"type":420,"value":814},{"type":415,"tag":559,"props":8832,"children":8833},{"style":583},[8834],{"type":420,"value":819},{"type":415,"tag":559,"props":8836,"children":8837},{"style":822},[8838],{"type":420,"value":8839},"[controller]",{"type":415,"tag":559,"props":8841,"children":8842},{"style":583},[8843],{"type":420,"value":819},{"type":415,"tag":559,"props":8845,"children":8846},{"style":583},[8847],{"type":420,"value":8848},")]\n",{"type":415,"tag":559,"props":8850,"children":8851},{"class":561,"line":608},[8852,8856,8860,8865,8869],{"type":415,"tag":559,"props":8853,"children":8854},{"style":566},[8855],{"type":420,"value":569},{"type":415,"tag":559,"props":8857,"children":8858},{"style":572},[8859],{"type":420,"value":5933},{"type":415,"tag":559,"props":8861,"children":8862},{"style":572},[8863],{"type":420,"value":8864}," WeatherForecastController",{"type":415,"tag":559,"props":8866,"children":8867},{"style":583},[8868],{"type":420,"value":2437},{"type":415,"tag":559,"props":8870,"children":8871},{"style":572},[8872],{"type":420,"value":8873}," ControllerBase\n",{"type":415,"tag":559,"props":8875,"children":8876},{"class":561,"line":626},[8877],{"type":415,"tag":559,"props":8878,"children":8879},{"style":583},[8880],{"type":420,"value":786},{"type":415,"tag":559,"props":8882,"children":8883},{"class":561,"line":643},[8884,8888,8892,8897,8902],{"type":415,"tag":559,"props":8885,"children":8886},{"style":566},[8887],{"type":420,"value":5962},{"type":415,"tag":559,"props":8889,"children":8890},{"style":566},[8891],{"type":420,"value":5967},{"type":415,"tag":559,"props":8893,"children":8894},{"style":572},[8895],{"type":420,"value":8896}," IWeatherService",{"type":415,"tag":559,"props":8898,"children":8899},{"style":572},[8900],{"type":420,"value":8901}," _weatherService",{"type":415,"tag":559,"props":8903,"children":8904},{"style":583},[8905],{"type":420,"value":1509},{"type":415,"tag":559,"props":8907,"children":8908},{"class":561,"line":660},[8909],{"type":415,"tag":559,"props":8910,"children":8911},{"emptyLinePlaceholder":847},[8912],{"type":420,"value":850},{"type":415,"tag":559,"props":8914,"children":8915},{"class":561,"line":677},[8916,8920,8924,8928,8932,8937],{"type":415,"tag":559,"props":8917,"children":8918},{"style":566},[8919],{"type":420,"value":1124},{"type":415,"tag":559,"props":8921,"children":8922},{"style":883},[8923],{"type":420,"value":8864},{"type":415,"tag":559,"props":8925,"children":8926},{"style":583},[8927],{"type":420,"value":814},{"type":415,"tag":559,"props":8929,"children":8930},{"style":572},[8931],{"type":420,"value":8739},{"type":415,"tag":559,"props":8933,"children":8934},{"style":572},[8935],{"type":420,"value":8936}," weatherService",{"type":415,"tag":559,"props":8938,"children":8939},{"style":583},[8940],{"type":420,"value":833},{"type":415,"tag":559,"props":8942,"children":8943},{"class":561,"line":690},[8944],{"type":415,"tag":559,"props":8945,"children":8946},{"style":583},[8947],{"type":420,"value":2737},{"type":415,"tag":559,"props":8949,"children":8950},{"class":561,"line":1089},[8951,8956,8960,8964],{"type":415,"tag":559,"props":8952,"children":8953},{"style":792},[8954],{"type":420,"value":8955},"        _weatherService ",{"type":415,"tag":559,"props":8957,"children":8958},{"style":583},[8959],{"type":420,"value":800},{"type":415,"tag":559,"props":8961,"children":8962},{"style":792},[8963],{"type":420,"value":8936},{"type":415,"tag":559,"props":8965,"children":8966},{"style":583},[8967],{"type":420,"value":1509},{"type":415,"tag":559,"props":8969,"children":8970},{"class":561,"line":1102},[8971],{"type":415,"tag":559,"props":8972,"children":8973},{"style":583},[8974],{"type":420,"value":2792},{"type":415,"tag":559,"props":8976,"children":8977},{"class":561,"line":1110},[8978],{"type":415,"tag":559,"props":8979,"children":8980},{"emptyLinePlaceholder":847},[8981],{"type":420,"value":850},{"type":415,"tag":559,"props":8983,"children":8984},{"class":561,"line":1118},[8985,8990,8995,8999,9003,9007,9011,9016,9020],{"type":415,"tag":559,"props":8986,"children":8987},{"style":583},[8988],{"type":420,"value":8989},"    [",{"type":415,"tag":559,"props":8991,"children":8992},{"style":572},[8993],{"type":420,"value":8994},"HttpGet",{"type":415,"tag":559,"props":8996,"children":8997},{"style":583},[8998],{"type":420,"value":814},{"type":415,"tag":559,"props":9000,"children":9001},{"style":572},[9002],{"type":420,"value":1412},{"type":415,"tag":559,"props":9004,"children":9005},{"style":583},[9006],{"type":420,"value":763},{"type":415,"tag":559,"props":9008,"children":9009},{"style":583},[9010],{"type":420,"value":1434},{"type":415,"tag":559,"props":9012,"children":9013},{"style":822},[9014],{"type":420,"value":9015},"GetWeatherForecast",{"type":415,"tag":559,"props":9017,"children":9018},{"style":583},[9019],{"type":420,"value":819},{"type":415,"tag":559,"props":9021,"children":9022},{"style":583},[9023],{"type":420,"value":8848},{"type":415,"tag":559,"props":9025,"children":9026},{"class":561,"line":1171},[9027,9031,9036,9041,9046,9051,9056,9060,9065],{"type":415,"tag":559,"props":9028,"children":9029},{"style":583},[9030],{"type":420,"value":8989},{"type":415,"tag":559,"props":9032,"children":9033},{"style":572},[9034],{"type":420,"value":9035},"ProducesResponseType",{"type":415,"tag":559,"props":9037,"children":9038},{"style":583},[9039],{"type":420,"value":9040},"(typeof(",{"type":415,"tag":559,"props":9042,"children":9043},{"style":572},[9044],{"type":420,"value":9045},"WeatherForecast",{"type":415,"tag":559,"props":9047,"children":9048},{"style":583},[9049],{"type":420,"value":9050},"),",{"type":415,"tag":559,"props":9052,"children":9053},{"style":792},[9054],{"type":420,"value":9055}," StatusCodes",{"type":415,"tag":559,"props":9057,"children":9058},{"style":583},[9059],{"type":420,"value":542},{"type":415,"tag":559,"props":9061,"children":9062},{"style":792},[9063],{"type":420,"value":9064},"Status200OK",{"type":415,"tag":559,"props":9066,"children":9067},{"style":583},[9068],{"type":420,"value":8848},{"type":415,"tag":559,"props":9070,"children":9071},{"class":561,"line":1748},[9072,9076,9080,9084,9088,9093,9098],{"type":415,"tag":559,"props":9073,"children":9074},{"style":566},[9075],{"type":420,"value":1124},{"type":415,"tag":559,"props":9077,"children":9078},{"style":572},[9079],{"type":420,"value":2006},{"type":415,"tag":559,"props":9081,"children":9082},{"style":583},[9083],{"type":420,"value":891},{"type":415,"tag":559,"props":9085,"children":9086},{"style":572},[9087],{"type":420,"value":9045},{"type":415,"tag":559,"props":9089,"children":9090},{"style":583},[9091],{"type":420,"value":9092},"[]>",{"type":415,"tag":559,"props":9094,"children":9095},{"style":883},[9096],{"type":420,"value":9097}," Get",{"type":415,"tag":559,"props":9099,"children":9100},{"style":583},[9101],{"type":420,"value":778},{"type":415,"tag":559,"props":9103,"children":9104},{"class":561,"line":1769},[9105],{"type":415,"tag":559,"props":9106,"children":9107},{"style":583},[9108],{"type":420,"value":2737},{"type":415,"tag":559,"props":9110,"children":9111},{"class":561,"line":1786},[9112,9116,9120,9124,9129],{"type":415,"tag":559,"props":9113,"children":9114},{"style":745},[9115],{"type":420,"value":8218},{"type":415,"tag":559,"props":9117,"children":9118},{"style":792},[9119],{"type":420,"value":8901},{"type":415,"tag":559,"props":9121,"children":9122},{"style":583},[9123],{"type":420,"value":542},{"type":415,"tag":559,"props":9125,"children":9126},{"style":883},[9127],{"type":420,"value":9128},"GetWeatherForecasts",{"type":415,"tag":559,"props":9130,"children":9131},{"style":583},[9132],{"type":420,"value":1962},{"type":415,"tag":559,"props":9134,"children":9135},{"class":561,"line":1795},[9136],{"type":415,"tag":559,"props":9137,"children":9138},{"style":583},[9139],{"type":420,"value":2792},{"type":415,"tag":559,"props":9141,"children":9142},{"class":561,"line":3289},[9143],{"type":415,"tag":559,"props":9144,"children":9145},{"style":583},[9146],{"type":420,"value":1801},{"type":415,"tag":416,"props":9148,"children":9149},{},[9150,9152,9158,9160,9167,9169],{"type":420,"value":9151},"We can get rid of the ",{"type":415,"tag":555,"props":9153,"children":9155},{"className":9154},[],[9156],{"type":420,"value":9157},"typeof",{"type":420,"value":9159}," because there are now ",{"type":415,"tag":434,"props":9161,"children":9164},{"href":9162,"rel":9163},"https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0#support-for-generic-attributes",[438],[9165],{"type":420,"value":9166},"generic attributes for some common ASP.NET Core attributes",{"type":420,"value":9168}," like ",{"type":415,"tag":555,"props":9170,"children":9172},{"className":9171},[],[9173],{"type":420,"value":9174},"ProducesResponseType.",{"type":415,"tag":549,"props":9176,"children":9178},{"className":551,"code":9177,"language":326,"meta":401,"style":401},"    [HttpGet(Name = \"GetWeatherForecast\")]\n    [ProducesResponseType\u003CWeatherForecast>(StatusCodes.Status200OK)]\n    public Task\u003CWeatherForecast[]> Get()\n    {\n        return _weatherService.GetWeatherForecasts();\n    }\n",[9179],{"type":415,"tag":555,"props":9180,"children":9181},{"__ignoreMap":401},[9182,9221,9265,9296,9303,9326],{"type":415,"tag":559,"props":9183,"children":9184},{"class":561,"line":562},[9185,9189,9193,9197,9201,9205,9209,9213,9217],{"type":415,"tag":559,"props":9186,"children":9187},{"style":583},[9188],{"type":420,"value":8989},{"type":415,"tag":559,"props":9190,"children":9191},{"style":572},[9192],{"type":420,"value":8994},{"type":415,"tag":559,"props":9194,"children":9195},{"style":583},[9196],{"type":420,"value":814},{"type":415,"tag":559,"props":9198,"children":9199},{"style":572},[9200],{"type":420,"value":1412},{"type":415,"tag":559,"props":9202,"children":9203},{"style":583},[9204],{"type":420,"value":763},{"type":415,"tag":559,"props":9206,"children":9207},{"style":583},[9208],{"type":420,"value":1434},{"type":415,"tag":559,"props":9210,"children":9211},{"style":822},[9212],{"type":420,"value":9015},{"type":415,"tag":559,"props":9214,"children":9215},{"style":583},[9216],{"type":420,"value":819},{"type":415,"tag":559,"props":9218,"children":9219},{"style":583},[9220],{"type":420,"value":8848},{"type":415,"tag":559,"props":9222,"children":9223},{"class":561,"line":589},[9224,9228,9232,9236,9240,9244,9248,9253,9257,9261],{"type":415,"tag":559,"props":9225,"children":9226},{"style":583},[9227],{"type":420,"value":8989},{"type":415,"tag":559,"props":9229,"children":9230},{"style":572},[9231],{"type":420,"value":9035},{"type":415,"tag":559,"props":9233,"children":9234},{"style":792},[9235],{"type":420,"value":891},{"type":415,"tag":559,"props":9237,"children":9238},{"style":572},[9239],{"type":420,"value":9045},{"type":415,"tag":559,"props":9241,"children":9242},{"style":792},[9243],{"type":420,"value":5985},{"type":415,"tag":559,"props":9245,"children":9246},{"style":583},[9247],{"type":420,"value":814},{"type":415,"tag":559,"props":9249,"children":9250},{"style":792},[9251],{"type":420,"value":9252},"StatusCodes",{"type":415,"tag":559,"props":9254,"children":9255},{"style":583},[9256],{"type":420,"value":542},{"type":415,"tag":559,"props":9258,"children":9259},{"style":792},[9260],{"type":420,"value":9064},{"type":415,"tag":559,"props":9262,"children":9263},{"style":583},[9264],{"type":420,"value":8848},{"type":415,"tag":559,"props":9266,"children":9267},{"class":561,"line":608},[9268,9272,9276,9280,9284,9288,9292],{"type":415,"tag":559,"props":9269,"children":9270},{"style":566},[9271],{"type":420,"value":1124},{"type":415,"tag":559,"props":9273,"children":9274},{"style":572},[9275],{"type":420,"value":2006},{"type":415,"tag":559,"props":9277,"children":9278},{"style":583},[9279],{"type":420,"value":891},{"type":415,"tag":559,"props":9281,"children":9282},{"style":572},[9283],{"type":420,"value":9045},{"type":415,"tag":559,"props":9285,"children":9286},{"style":583},[9287],{"type":420,"value":9092},{"type":415,"tag":559,"props":9289,"children":9290},{"style":883},[9291],{"type":420,"value":9097},{"type":415,"tag":559,"props":9293,"children":9294},{"style":583},[9295],{"type":420,"value":778},{"type":415,"tag":559,"props":9297,"children":9298},{"class":561,"line":626},[9299],{"type":415,"tag":559,"props":9300,"children":9301},{"style":583},[9302],{"type":420,"value":2737},{"type":415,"tag":559,"props":9304,"children":9305},{"class":561,"line":643},[9306,9310,9314,9318,9322],{"type":415,"tag":559,"props":9307,"children":9308},{"style":745},[9309],{"type":420,"value":8218},{"type":415,"tag":559,"props":9311,"children":9312},{"style":792},[9313],{"type":420,"value":8901},{"type":415,"tag":559,"props":9315,"children":9316},{"style":583},[9317],{"type":420,"value":542},{"type":415,"tag":559,"props":9319,"children":9320},{"style":883},[9321],{"type":420,"value":9128},{"type":415,"tag":559,"props":9323,"children":9324},{"style":583},[9325],{"type":420,"value":1962},{"type":415,"tag":559,"props":9327,"children":9328},{"class":561,"line":660},[9329],{"type":415,"tag":559,"props":9330,"children":9331},{"style":583},[9332],{"type":420,"value":2792},{"type":415,"tag":416,"props":9334,"children":9335},{},[9336,9338,9343],{"type":420,"value":9337},"There are now 2 implementations of the ",{"type":415,"tag":555,"props":9339,"children":9341},{"className":9340},[],[9342],{"type":420,"value":8739},{"type":420,"value":9344}," interface:",{"type":415,"tag":5376,"props":9346,"children":9347},{},[9348,9359],{"type":415,"tag":5380,"props":9349,"children":9350},{},[9351,9357],{"type":415,"tag":555,"props":9352,"children":9354},{"className":9353},[],[9355],{"type":420,"value":9356},"RandomWeatherService",{"type":420,"value":9358}," that contains the code that previously was in the controller",{"type":415,"tag":5380,"props":9360,"children":9361},{},[9362,9367,9369],{"type":415,"tag":555,"props":9363,"children":9365},{"className":9364},[],[9366],{"type":420,"value":8765},{"type":420,"value":9368}," that makes a call to the Open Weather Map API to retrieve the weather forecasts and then maps the obtained data to a list of ",{"type":415,"tag":555,"props":9370,"children":9372},{"className":9371},[],[9373],{"type":420,"value":9045},{"type":415,"tag":549,"props":9375,"children":9377},{"className":551,"code":9376,"language":326,"meta":401,"style":401},"public class OpenWeatherService : IWeatherService\n{\n    private readonly IOpenWeatherMapApi _openWeatherMapApi;\n    private static readonly (double Latitude, double Longitude) BordeauxCoordinates = (44.837789, -0.57918);\n\n    public OpenWeatherService(IOpenWeatherMapApi openWeatherMapApi)\n    {\n        _openWeatherMapApi = openWeatherMapApi;\n    }\n\n    public async Task\u003CWeatherForecast[]> GetWeatherForecasts()\n    {\n        var weatherApiResponse = await _openWeatherMapApi.GetWeatherForecast(BordeauxCoordinates.Latitude, BordeauxCoordinates.Longitude);\n        \n        var computeWeatherSummary = (double temperature) =>\n            temperature switch\n            {\n                \u003C 0 => \"Freezing\",\n                >= 0 and \u003C 5 => \"Bracing\",\n                >= 5 and \u003C 12 => \"Chilly\",\n                >= 12 and \u003C 18 => \"Cool\",\n                >= 18 and \u003C 24 => \"Mild\",\n                >= 24 and \u003C 30 => \"Warm\",\n                >= 30 and \u003C 35 => \"Balmy\",\n                >= 35 and \u003C 40 => \"Hot\",\n                >= 40 and \u003C 45 => \"Sweltering\",\n                >= 45 => \"Scorching\",\n                _ => \"Warm\"\n            };\n        return weatherApiResponse.List\n            .Select(x =>\n                new WeatherForecast\n                {\n                    Date = DateOnly.FromDateTime(DateTimeOffset.FromUnixTimeSeconds(x.Dt).Date),\n                    TemperatureC = Convert.ToInt32(x.Main.Temp),\n                    Summary = computeWeatherSummary(x.Main.Temp)\n                })\n            .ToArray();\n    }\n}\n",[9378],{"type":415,"tag":555,"props":9379,"children":9380},{"__ignoreMap":401},[9381,9406,9413,9438,9517,9524,9553,9560,9580,9587,9594,9630,9637,9708,9716,9749,9762,9770,9803,9850,9895,9940,9985,10030,10075,10120,10165,10197,10223,10231,10251,10275,10288,10296,10370,10426,10470,10478,10494,10501],{"type":415,"tag":559,"props":9382,"children":9383},{"class":561,"line":562},[9384,9388,9392,9397,9401],{"type":415,"tag":559,"props":9385,"children":9386},{"style":566},[9387],{"type":420,"value":569},{"type":415,"tag":559,"props":9389,"children":9390},{"style":572},[9391],{"type":420,"value":5933},{"type":415,"tag":559,"props":9393,"children":9394},{"style":572},[9395],{"type":420,"value":9396}," OpenWeatherService",{"type":415,"tag":559,"props":9398,"children":9399},{"style":583},[9400],{"type":420,"value":2437},{"type":415,"tag":559,"props":9402,"children":9403},{"style":572},[9404],{"type":420,"value":9405}," IWeatherService\n",{"type":415,"tag":559,"props":9407,"children":9408},{"class":561,"line":589},[9409],{"type":415,"tag":559,"props":9410,"children":9411},{"style":583},[9412],{"type":420,"value":786},{"type":415,"tag":559,"props":9414,"children":9415},{"class":561,"line":608},[9416,9420,9424,9429,9434],{"type":415,"tag":559,"props":9417,"children":9418},{"style":566},[9419],{"type":420,"value":5962},{"type":415,"tag":559,"props":9421,"children":9422},{"style":566},[9423],{"type":420,"value":5967},{"type":415,"tag":559,"props":9425,"children":9426},{"style":572},[9427],{"type":420,"value":9428}," IOpenWeatherMapApi",{"type":415,"tag":559,"props":9430,"children":9431},{"style":572},[9432],{"type":420,"value":9433}," _openWeatherMapApi",{"type":415,"tag":559,"props":9435,"children":9436},{"style":583},[9437],{"type":420,"value":1509},{"type":415,"tag":559,"props":9439,"children":9440},{"class":561,"line":626},[9441,9445,9450,9454,9459,9464,9468,9473,9478,9482,9487,9491,9495,9500,9504,9508,9513],{"type":415,"tag":559,"props":9442,"children":9443},{"style":566},[9444],{"type":420,"value":5962},{"type":415,"tag":559,"props":9446,"children":9447},{"style":566},[9448],{"type":420,"value":9449}," static",{"type":415,"tag":559,"props":9451,"children":9452},{"style":566},[9453],{"type":420,"value":5967},{"type":415,"tag":559,"props":9455,"children":9456},{"style":583},[9457],{"type":420,"value":9458}," (double",{"type":415,"tag":559,"props":9460,"children":9461},{"style":572},[9462],{"type":420,"value":9463}," Latitude",{"type":415,"tag":559,"props":9465,"children":9466},{"style":583},[9467],{"type":420,"value":2312},{"type":415,"tag":559,"props":9469,"children":9470},{"style":583},[9471],{"type":420,"value":9472}," double",{"type":415,"tag":559,"props":9474,"children":9475},{"style":572},[9476],{"type":420,"value":9477}," Longitude",{"type":415,"tag":559,"props":9479,"children":9480},{"style":583},[9481],{"type":420,"value":1468},{"type":415,"tag":559,"props":9483,"children":9484},{"style":572},[9485],{"type":420,"value":9486}," BordeauxCoordinates",{"type":415,"tag":559,"props":9488,"children":9489},{"style":583},[9490],{"type":420,"value":763},{"type":415,"tag":559,"props":9492,"children":9493},{"style":583},[9494],{"type":420,"value":2710},{"type":415,"tag":559,"props":9496,"children":9497},{"style":2846},[9498],{"type":420,"value":9499},"44.837789",{"type":415,"tag":559,"props":9501,"children":9502},{"style":583},[9503],{"type":420,"value":2312},{"type":415,"tag":559,"props":9505,"children":9506},{"style":583},[9507],{"type":420,"value":8540},{"type":415,"tag":559,"props":9509,"children":9510},{"style":2846},[9511],{"type":420,"value":9512},"0.57918",{"type":415,"tag":559,"props":9514,"children":9515},{"style":583},[9516],{"type":420,"value":696},{"type":415,"tag":559,"props":9518,"children":9519},{"class":561,"line":643},[9520],{"type":415,"tag":559,"props":9521,"children":9522},{"emptyLinePlaceholder":847},[9523],{"type":420,"value":850},{"type":415,"tag":559,"props":9525,"children":9526},{"class":561,"line":660},[9527,9531,9535,9539,9544,9549],{"type":415,"tag":559,"props":9528,"children":9529},{"style":566},[9530],{"type":420,"value":1124},{"type":415,"tag":559,"props":9532,"children":9533},{"style":883},[9534],{"type":420,"value":9396},{"type":415,"tag":559,"props":9536,"children":9537},{"style":583},[9538],{"type":420,"value":814},{"type":415,"tag":559,"props":9540,"children":9541},{"style":572},[9542],{"type":420,"value":9543},"IOpenWeatherMapApi",{"type":415,"tag":559,"props":9545,"children":9546},{"style":572},[9547],{"type":420,"value":9548}," openWeatherMapApi",{"type":415,"tag":559,"props":9550,"children":9551},{"style":583},[9552],{"type":420,"value":833},{"type":415,"tag":559,"props":9554,"children":9555},{"class":561,"line":677},[9556],{"type":415,"tag":559,"props":9557,"children":9558},{"style":583},[9559],{"type":420,"value":2737},{"type":415,"tag":559,"props":9561,"children":9562},{"class":561,"line":690},[9563,9568,9572,9576],{"type":415,"tag":559,"props":9564,"children":9565},{"style":792},[9566],{"type":420,"value":9567},"        _openWeatherMapApi ",{"type":415,"tag":559,"props":9569,"children":9570},{"style":583},[9571],{"type":420,"value":800},{"type":415,"tag":559,"props":9573,"children":9574},{"style":792},[9575],{"type":420,"value":9548},{"type":415,"tag":559,"props":9577,"children":9578},{"style":583},[9579],{"type":420,"value":1509},{"type":415,"tag":559,"props":9581,"children":9582},{"class":561,"line":1089},[9583],{"type":415,"tag":559,"props":9584,"children":9585},{"style":583},[9586],{"type":420,"value":2792},{"type":415,"tag":559,"props":9588,"children":9589},{"class":561,"line":1102},[9590],{"type":415,"tag":559,"props":9591,"children":9592},{"emptyLinePlaceholder":847},[9593],{"type":420,"value":850},{"type":415,"tag":559,"props":9595,"children":9596},{"class":561,"line":1110},[9597,9601,9605,9609,9613,9617,9621,9626],{"type":415,"tag":559,"props":9598,"children":9599},{"style":566},[9600],{"type":420,"value":1124},{"type":415,"tag":559,"props":9602,"children":9603},{"style":566},[9604],{"type":420,"value":6159},{"type":415,"tag":559,"props":9606,"children":9607},{"style":572},[9608],{"type":420,"value":2006},{"type":415,"tag":559,"props":9610,"children":9611},{"style":583},[9612],{"type":420,"value":891},{"type":415,"tag":559,"props":9614,"children":9615},{"style":572},[9616],{"type":420,"value":9045},{"type":415,"tag":559,"props":9618,"children":9619},{"style":583},[9620],{"type":420,"value":9092},{"type":415,"tag":559,"props":9622,"children":9623},{"style":883},[9624],{"type":420,"value":9625}," GetWeatherForecasts",{"type":415,"tag":559,"props":9627,"children":9628},{"style":583},[9629],{"type":420,"value":778},{"type":415,"tag":559,"props":9631,"children":9632},{"class":561,"line":1118},[9633],{"type":415,"tag":559,"props":9634,"children":9635},{"style":583},[9636],{"type":420,"value":2737},{"type":415,"tag":559,"props":9638,"children":9639},{"class":561,"line":1171},[9640,9644,9649,9653,9657,9661,9665,9669,9673,9678,9682,9687,9691,9695,9699,9704],{"type":415,"tag":559,"props":9641,"children":9642},{"style":572},[9643],{"type":420,"value":2745},{"type":415,"tag":559,"props":9645,"children":9646},{"style":572},[9647],{"type":420,"value":9648}," weatherApiResponse",{"type":415,"tag":559,"props":9650,"children":9651},{"style":583},[9652],{"type":420,"value":763},{"type":415,"tag":559,"props":9654,"children":9655},{"style":583},[9656],{"type":420,"value":872},{"type":415,"tag":559,"props":9658,"children":9659},{"style":792},[9660],{"type":420,"value":9433},{"type":415,"tag":559,"props":9662,"children":9663},{"style":583},[9664],{"type":420,"value":542},{"type":415,"tag":559,"props":9666,"children":9667},{"style":883},[9668],{"type":420,"value":9015},{"type":415,"tag":559,"props":9670,"children":9671},{"style":583},[9672],{"type":420,"value":814},{"type":415,"tag":559,"props":9674,"children":9675},{"style":792},[9676],{"type":420,"value":9677},"BordeauxCoordinates",{"type":415,"tag":559,"props":9679,"children":9680},{"style":583},[9681],{"type":420,"value":542},{"type":415,"tag":559,"props":9683,"children":9684},{"style":792},[9685],{"type":420,"value":9686},"Latitude",{"type":415,"tag":559,"props":9688,"children":9689},{"style":583},[9690],{"type":420,"value":2312},{"type":415,"tag":559,"props":9692,"children":9693},{"style":792},[9694],{"type":420,"value":9486},{"type":415,"tag":559,"props":9696,"children":9697},{"style":583},[9698],{"type":420,"value":542},{"type":415,"tag":559,"props":9700,"children":9701},{"style":792},[9702],{"type":420,"value":9703},"Longitude",{"type":415,"tag":559,"props":9705,"children":9706},{"style":583},[9707],{"type":420,"value":696},{"type":415,"tag":559,"props":9709,"children":9710},{"class":561,"line":1748},[9711],{"type":415,"tag":559,"props":9712,"children":9713},{"style":792},[9714],{"type":420,"value":9715},"        \n",{"type":415,"tag":559,"props":9717,"children":9718},{"class":561,"line":1769},[9719,9723,9728,9732,9736,9741,9745],{"type":415,"tag":559,"props":9720,"children":9721},{"style":572},[9722],{"type":420,"value":2745},{"type":415,"tag":559,"props":9724,"children":9725},{"style":572},[9726],{"type":420,"value":9727}," computeWeatherSummary",{"type":415,"tag":559,"props":9729,"children":9730},{"style":583},[9731],{"type":420,"value":763},{"type":415,"tag":559,"props":9733,"children":9734},{"style":583},[9735],{"type":420,"value":9458},{"type":415,"tag":559,"props":9737,"children":9738},{"style":572},[9739],{"type":420,"value":9740}," temperature",{"type":415,"tag":559,"props":9742,"children":9743},{"style":583},[9744],{"type":420,"value":1468},{"type":415,"tag":559,"props":9746,"children":9747},{"style":583},[9748],{"type":420,"value":5741},{"type":415,"tag":559,"props":9750,"children":9751},{"class":561,"line":1786},[9752,9757],{"type":415,"tag":559,"props":9753,"children":9754},{"style":792},[9755],{"type":420,"value":9756},"            temperature ",{"type":415,"tag":559,"props":9758,"children":9759},{"style":745},[9760],{"type":420,"value":9761},"switch\n",{"type":415,"tag":559,"props":9763,"children":9764},{"class":561,"line":1795},[9765],{"type":415,"tag":559,"props":9766,"children":9767},{"style":583},[9768],{"type":420,"value":9769},"            {\n",{"type":415,"tag":559,"props":9771,"children":9772},{"class":561,"line":3289},[9773,9778,9782,9786,9790,9795,9799],{"type":415,"tag":559,"props":9774,"children":9775},{"style":583},[9776],{"type":420,"value":9777},"                \u003C",{"type":415,"tag":559,"props":9779,"children":9780},{"style":2846},[9781],{"type":420,"value":5204},{"type":415,"tag":559,"props":9783,"children":9784},{"style":583},[9785],{"type":420,"value":1861},{"type":415,"tag":559,"props":9787,"children":9788},{"style":583},[9789],{"type":420,"value":1434},{"type":415,"tag":559,"props":9791,"children":9792},{"style":822},[9793],{"type":420,"value":9794},"Freezing",{"type":415,"tag":559,"props":9796,"children":9797},{"style":583},[9798],{"type":420,"value":819},{"type":415,"tag":559,"props":9800,"children":9801},{"style":583},[9802],{"type":420,"value":605},{"type":415,"tag":559,"props":9804,"children":9805},{"class":561,"line":3297},[9806,9811,9815,9820,9825,9829,9833,9837,9842,9846],{"type":415,"tag":559,"props":9807,"children":9808},{"style":583},[9809],{"type":420,"value":9810},"                >=",{"type":415,"tag":559,"props":9812,"children":9813},{"style":2846},[9814],{"type":420,"value":5204},{"type":415,"tag":559,"props":9816,"children":9817},{"style":583},[9818],{"type":420,"value":9819}," and",{"type":415,"tag":559,"props":9821,"children":9822},{"style":583},[9823],{"type":420,"value":9824}," \u003C",{"type":415,"tag":559,"props":9826,"children":9827},{"style":2846},[9828],{"type":420,"value":5310},{"type":415,"tag":559,"props":9830,"children":9831},{"style":583},[9832],{"type":420,"value":1861},{"type":415,"tag":559,"props":9834,"children":9835},{"style":583},[9836],{"type":420,"value":1434},{"type":415,"tag":559,"props":9838,"children":9839},{"style":822},[9840],{"type":420,"value":9841},"Bracing",{"type":415,"tag":559,"props":9843,"children":9844},{"style":583},[9845],{"type":420,"value":819},{"type":415,"tag":559,"props":9847,"children":9848},{"style":583},[9849],{"type":420,"value":605},{"type":415,"tag":559,"props":9851,"children":9852},{"class":561,"line":3349},[9853,9857,9861,9865,9869,9874,9878,9882,9887,9891],{"type":415,"tag":559,"props":9854,"children":9855},{"style":583},[9856],{"type":420,"value":9810},{"type":415,"tag":559,"props":9858,"children":9859},{"style":2846},[9860],{"type":420,"value":5310},{"type":415,"tag":559,"props":9862,"children":9863},{"style":583},[9864],{"type":420,"value":9819},{"type":415,"tag":559,"props":9866,"children":9867},{"style":583},[9868],{"type":420,"value":9824},{"type":415,"tag":559,"props":9870,"children":9871},{"style":2846},[9872],{"type":420,"value":9873}," 12",{"type":415,"tag":559,"props":9875,"children":9876},{"style":583},[9877],{"type":420,"value":1861},{"type":415,"tag":559,"props":9879,"children":9880},{"style":583},[9881],{"type":420,"value":1434},{"type":415,"tag":559,"props":9883,"children":9884},{"style":822},[9885],{"type":420,"value":9886},"Chilly",{"type":415,"tag":559,"props":9888,"children":9889},{"style":583},[9890],{"type":420,"value":819},{"type":415,"tag":559,"props":9892,"children":9893},{"style":583},[9894],{"type":420,"value":605},{"type":415,"tag":559,"props":9896,"children":9897},{"class":561,"line":3374},[9898,9902,9906,9910,9914,9919,9923,9927,9932,9936],{"type":415,"tag":559,"props":9899,"children":9900},{"style":583},[9901],{"type":420,"value":9810},{"type":415,"tag":559,"props":9903,"children":9904},{"style":2846},[9905],{"type":420,"value":9873},{"type":415,"tag":559,"props":9907,"children":9908},{"style":583},[9909],{"type":420,"value":9819},{"type":415,"tag":559,"props":9911,"children":9912},{"style":583},[9913],{"type":420,"value":9824},{"type":415,"tag":559,"props":9915,"children":9916},{"style":2846},[9917],{"type":420,"value":9918}," 18",{"type":415,"tag":559,"props":9920,"children":9921},{"style":583},[9922],{"type":420,"value":1861},{"type":415,"tag":559,"props":9924,"children":9925},{"style":583},[9926],{"type":420,"value":1434},{"type":415,"tag":559,"props":9928,"children":9929},{"style":822},[9930],{"type":420,"value":9931},"Cool",{"type":415,"tag":559,"props":9933,"children":9934},{"style":583},[9935],{"type":420,"value":819},{"type":415,"tag":559,"props":9937,"children":9938},{"style":583},[9939],{"type":420,"value":605},{"type":415,"tag":559,"props":9941,"children":9942},{"class":561,"line":3382},[9943,9947,9951,9955,9959,9964,9968,9972,9977,9981],{"type":415,"tag":559,"props":9944,"children":9945},{"style":583},[9946],{"type":420,"value":9810},{"type":415,"tag":559,"props":9948,"children":9949},{"style":2846},[9950],{"type":420,"value":9918},{"type":415,"tag":559,"props":9952,"children":9953},{"style":583},[9954],{"type":420,"value":9819},{"type":415,"tag":559,"props":9956,"children":9957},{"style":583},[9958],{"type":420,"value":9824},{"type":415,"tag":559,"props":9960,"children":9961},{"style":2846},[9962],{"type":420,"value":9963}," 24",{"type":415,"tag":559,"props":9965,"children":9966},{"style":583},[9967],{"type":420,"value":1861},{"type":415,"tag":559,"props":9969,"children":9970},{"style":583},[9971],{"type":420,"value":1434},{"type":415,"tag":559,"props":9973,"children":9974},{"style":822},[9975],{"type":420,"value":9976},"Mild",{"type":415,"tag":559,"props":9978,"children":9979},{"style":583},[9980],{"type":420,"value":819},{"type":415,"tag":559,"props":9982,"children":9983},{"style":583},[9984],{"type":420,"value":605},{"type":415,"tag":559,"props":9986,"children":9987},{"class":561,"line":3390},[9988,9992,9996,10000,10004,10009,10013,10017,10022,10026],{"type":415,"tag":559,"props":9989,"children":9990},{"style":583},[9991],{"type":420,"value":9810},{"type":415,"tag":559,"props":9993,"children":9994},{"style":2846},[9995],{"type":420,"value":9963},{"type":415,"tag":559,"props":9997,"children":9998},{"style":583},[9999],{"type":420,"value":9819},{"type":415,"tag":559,"props":10001,"children":10002},{"style":583},[10003],{"type":420,"value":9824},{"type":415,"tag":559,"props":10005,"children":10006},{"style":2846},[10007],{"type":420,"value":10008}," 30",{"type":415,"tag":559,"props":10010,"children":10011},{"style":583},[10012],{"type":420,"value":1861},{"type":415,"tag":559,"props":10014,"children":10015},{"style":583},[10016],{"type":420,"value":1434},{"type":415,"tag":559,"props":10018,"children":10019},{"style":822},[10020],{"type":420,"value":10021},"Warm",{"type":415,"tag":559,"props":10023,"children":10024},{"style":583},[10025],{"type":420,"value":819},{"type":415,"tag":559,"props":10027,"children":10028},{"style":583},[10029],{"type":420,"value":605},{"type":415,"tag":559,"props":10031,"children":10032},{"class":561,"line":3434},[10033,10037,10041,10045,10049,10054,10058,10062,10067,10071],{"type":415,"tag":559,"props":10034,"children":10035},{"style":583},[10036],{"type":420,"value":9810},{"type":415,"tag":559,"props":10038,"children":10039},{"style":2846},[10040],{"type":420,"value":10008},{"type":415,"tag":559,"props":10042,"children":10043},{"style":583},[10044],{"type":420,"value":9819},{"type":415,"tag":559,"props":10046,"children":10047},{"style":583},[10048],{"type":420,"value":9824},{"type":415,"tag":559,"props":10050,"children":10051},{"style":2846},[10052],{"type":420,"value":10053}," 35",{"type":415,"tag":559,"props":10055,"children":10056},{"style":583},[10057],{"type":420,"value":1861},{"type":415,"tag":559,"props":10059,"children":10060},{"style":583},[10061],{"type":420,"value":1434},{"type":415,"tag":559,"props":10063,"children":10064},{"style":822},[10065],{"type":420,"value":10066},"Balmy",{"type":415,"tag":559,"props":10068,"children":10069},{"style":583},[10070],{"type":420,"value":819},{"type":415,"tag":559,"props":10072,"children":10073},{"style":583},[10074],{"type":420,"value":605},{"type":415,"tag":559,"props":10076,"children":10077},{"class":561,"line":3442},[10078,10082,10086,10090,10094,10099,10103,10107,10112,10116],{"type":415,"tag":559,"props":10079,"children":10080},{"style":583},[10081],{"type":420,"value":9810},{"type":415,"tag":559,"props":10083,"children":10084},{"style":2846},[10085],{"type":420,"value":10053},{"type":415,"tag":559,"props":10087,"children":10088},{"style":583},[10089],{"type":420,"value":9819},{"type":415,"tag":559,"props":10091,"children":10092},{"style":583},[10093],{"type":420,"value":9824},{"type":415,"tag":559,"props":10095,"children":10096},{"style":2846},[10097],{"type":420,"value":10098}," 40",{"type":415,"tag":559,"props":10100,"children":10101},{"style":583},[10102],{"type":420,"value":1861},{"type":415,"tag":559,"props":10104,"children":10105},{"style":583},[10106],{"type":420,"value":1434},{"type":415,"tag":559,"props":10108,"children":10109},{"style":822},[10110],{"type":420,"value":10111},"Hot",{"type":415,"tag":559,"props":10113,"children":10114},{"style":583},[10115],{"type":420,"value":819},{"type":415,"tag":559,"props":10117,"children":10118},{"style":583},[10119],{"type":420,"value":605},{"type":415,"tag":559,"props":10121,"children":10122},{"class":561,"line":3498},[10123,10127,10131,10135,10139,10144,10148,10152,10157,10161],{"type":415,"tag":559,"props":10124,"children":10125},{"style":583},[10126],{"type":420,"value":9810},{"type":415,"tag":559,"props":10128,"children":10129},{"style":2846},[10130],{"type":420,"value":10098},{"type":415,"tag":559,"props":10132,"children":10133},{"style":583},[10134],{"type":420,"value":9819},{"type":415,"tag":559,"props":10136,"children":10137},{"style":583},[10138],{"type":420,"value":9824},{"type":415,"tag":559,"props":10140,"children":10141},{"style":2846},[10142],{"type":420,"value":10143}," 45",{"type":415,"tag":559,"props":10145,"children":10146},{"style":583},[10147],{"type":420,"value":1861},{"type":415,"tag":559,"props":10149,"children":10150},{"style":583},[10151],{"type":420,"value":1434},{"type":415,"tag":559,"props":10153,"children":10154},{"style":822},[10155],{"type":420,"value":10156},"Sweltering",{"type":415,"tag":559,"props":10158,"children":10159},{"style":583},[10160],{"type":420,"value":819},{"type":415,"tag":559,"props":10162,"children":10163},{"style":583},[10164],{"type":420,"value":605},{"type":415,"tag":559,"props":10166,"children":10167},{"class":561,"line":3542},[10168,10172,10176,10180,10184,10189,10193],{"type":415,"tag":559,"props":10169,"children":10170},{"style":583},[10171],{"type":420,"value":9810},{"type":415,"tag":559,"props":10173,"children":10174},{"style":2846},[10175],{"type":420,"value":10143},{"type":415,"tag":559,"props":10177,"children":10178},{"style":583},[10179],{"type":420,"value":1861},{"type":415,"tag":559,"props":10181,"children":10182},{"style":583},[10183],{"type":420,"value":1434},{"type":415,"tag":559,"props":10185,"children":10186},{"style":822},[10187],{"type":420,"value":10188},"Scorching",{"type":415,"tag":559,"props":10190,"children":10191},{"style":583},[10192],{"type":420,"value":819},{"type":415,"tag":559,"props":10194,"children":10195},{"style":583},[10196],{"type":420,"value":605},{"type":415,"tag":559,"props":10198,"children":10199},{"class":561,"line":3550},[10200,10205,10210,10214,10218],{"type":415,"tag":559,"props":10201,"children":10202},{"style":792},[10203],{"type":420,"value":10204},"                _ ",{"type":415,"tag":559,"props":10206,"children":10207},{"style":583},[10208],{"type":420,"value":10209},"=>",{"type":415,"tag":559,"props":10211,"children":10212},{"style":583},[10213],{"type":420,"value":1434},{"type":415,"tag":559,"props":10215,"children":10216},{"style":822},[10217],{"type":420,"value":10021},{"type":415,"tag":559,"props":10219,"children":10220},{"style":583},[10221],{"type":420,"value":10222},"\"\n",{"type":415,"tag":559,"props":10224,"children":10225},{"class":561,"line":3582},[10226],{"type":415,"tag":559,"props":10227,"children":10228},{"style":583},[10229],{"type":420,"value":10230},"            };\n",{"type":415,"tag":559,"props":10232,"children":10233},{"class":561,"line":3622},[10234,10238,10242,10246],{"type":415,"tag":559,"props":10235,"children":10236},{"style":745},[10237],{"type":420,"value":8218},{"type":415,"tag":559,"props":10239,"children":10240},{"style":792},[10241],{"type":420,"value":9648},{"type":415,"tag":559,"props":10243,"children":10244},{"style":583},[10245],{"type":420,"value":542},{"type":415,"tag":559,"props":10247,"children":10248},{"style":792},[10249],{"type":420,"value":10250},"List\n",{"type":415,"tag":559,"props":10252,"children":10253},{"class":561,"line":3654},[10254,10258,10262,10266,10271],{"type":415,"tag":559,"props":10255,"children":10256},{"style":583},[10257],{"type":420,"value":8274},{"type":415,"tag":559,"props":10259,"children":10260},{"style":883},[10261],{"type":420,"value":1932},{"type":415,"tag":559,"props":10263,"children":10264},{"style":583},[10265],{"type":420,"value":814},{"type":415,"tag":559,"props":10267,"children":10268},{"style":572},[10269],{"type":420,"value":10270},"x",{"type":415,"tag":559,"props":10272,"children":10273},{"style":583},[10274],{"type":420,"value":5741},{"type":415,"tag":559,"props":10276,"children":10277},{"class":561,"line":3662},[10278,10283],{"type":415,"tag":559,"props":10279,"children":10280},{"style":583},[10281],{"type":420,"value":10282},"                new",{"type":415,"tag":559,"props":10284,"children":10285},{"style":572},[10286],{"type":420,"value":10287}," WeatherForecast\n",{"type":415,"tag":559,"props":10289,"children":10290},{"class":561,"line":3730},[10291],{"type":415,"tag":559,"props":10292,"children":10293},{"style":583},[10294],{"type":420,"value":10295},"                {\n",{"type":415,"tag":559,"props":10297,"children":10298},{"class":561,"line":3738},[10299,10304,10308,10313,10317,10322,10326,10331,10335,10340,10344,10348,10352,10357,10361,10365],{"type":415,"tag":559,"props":10300,"children":10301},{"style":792},[10302],{"type":420,"value":10303},"                    Date ",{"type":415,"tag":559,"props":10305,"children":10306},{"style":583},[10307],{"type":420,"value":800},{"type":415,"tag":559,"props":10309,"children":10310},{"style":792},[10311],{"type":420,"value":10312}," DateOnly",{"type":415,"tag":559,"props":10314,"children":10315},{"style":583},[10316],{"type":420,"value":542},{"type":415,"tag":559,"props":10318,"children":10319},{"style":883},[10320],{"type":420,"value":10321},"FromDateTime",{"type":415,"tag":559,"props":10323,"children":10324},{"style":583},[10325],{"type":420,"value":814},{"type":415,"tag":559,"props":10327,"children":10328},{"style":792},[10329],{"type":420,"value":10330},"DateTimeOffset",{"type":415,"tag":559,"props":10332,"children":10333},{"style":583},[10334],{"type":420,"value":542},{"type":415,"tag":559,"props":10336,"children":10337},{"style":883},[10338],{"type":420,"value":10339},"FromUnixTimeSeconds",{"type":415,"tag":559,"props":10341,"children":10342},{"style":583},[10343],{"type":420,"value":814},{"type":415,"tag":559,"props":10345,"children":10346},{"style":792},[10347],{"type":420,"value":10270},{"type":415,"tag":559,"props":10349,"children":10350},{"style":583},[10351],{"type":420,"value":542},{"type":415,"tag":559,"props":10353,"children":10354},{"style":792},[10355],{"type":420,"value":10356},"Dt",{"type":415,"tag":559,"props":10358,"children":10359},{"style":583},[10360],{"type":420,"value":1439},{"type":415,"tag":559,"props":10362,"children":10363},{"style":792},[10364],{"type":420,"value":1298},{"type":415,"tag":559,"props":10366,"children":10367},{"style":583},[10368],{"type":420,"value":10369},"),\n",{"type":415,"tag":559,"props":10371,"children":10372},{"class":561,"line":3810},[10373,10378,10382,10387,10391,10396,10400,10404,10408,10413,10417,10422],{"type":415,"tag":559,"props":10374,"children":10375},{"style":792},[10376],{"type":420,"value":10377},"                    TemperatureC ",{"type":415,"tag":559,"props":10379,"children":10380},{"style":583},[10381],{"type":420,"value":800},{"type":415,"tag":559,"props":10383,"children":10384},{"style":792},[10385],{"type":420,"value":10386}," Convert",{"type":415,"tag":559,"props":10388,"children":10389},{"style":583},[10390],{"type":420,"value":542},{"type":415,"tag":559,"props":10392,"children":10393},{"style":883},[10394],{"type":420,"value":10395},"ToInt32",{"type":415,"tag":559,"props":10397,"children":10398},{"style":583},[10399],{"type":420,"value":814},{"type":415,"tag":559,"props":10401,"children":10402},{"style":792},[10403],{"type":420,"value":10270},{"type":415,"tag":559,"props":10405,"children":10406},{"style":583},[10407],{"type":420,"value":542},{"type":415,"tag":559,"props":10409,"children":10410},{"style":792},[10411],{"type":420,"value":10412},"Main",{"type":415,"tag":559,"props":10414,"children":10415},{"style":583},[10416],{"type":420,"value":542},{"type":415,"tag":559,"props":10418,"children":10419},{"style":792},[10420],{"type":420,"value":10421},"Temp",{"type":415,"tag":559,"props":10423,"children":10424},{"style":583},[10425],{"type":420,"value":10369},{"type":415,"tag":559,"props":10427,"children":10428},{"class":561,"line":3818},[10429,10434,10438,10442,10446,10450,10454,10458,10462,10466],{"type":415,"tag":559,"props":10430,"children":10431},{"style":792},[10432],{"type":420,"value":10433},"                    Summary ",{"type":415,"tag":559,"props":10435,"children":10436},{"style":583},[10437],{"type":420,"value":800},{"type":415,"tag":559,"props":10439,"children":10440},{"style":883},[10441],{"type":420,"value":9727},{"type":415,"tag":559,"props":10443,"children":10444},{"style":583},[10445],{"type":420,"value":814},{"type":415,"tag":559,"props":10447,"children":10448},{"style":792},[10449],{"type":420,"value":10270},{"type":415,"tag":559,"props":10451,"children":10452},{"style":583},[10453],{"type":420,"value":542},{"type":415,"tag":559,"props":10455,"children":10456},{"style":792},[10457],{"type":420,"value":10412},{"type":415,"tag":559,"props":10459,"children":10460},{"style":583},[10461],{"type":420,"value":542},{"type":415,"tag":559,"props":10463,"children":10464},{"style":792},[10465],{"type":420,"value":10421},{"type":415,"tag":559,"props":10467,"children":10468},{"style":583},[10469],{"type":420,"value":833},{"type":415,"tag":559,"props":10471,"children":10472},{"class":561,"line":3826},[10473],{"type":415,"tag":559,"props":10474,"children":10475},{"style":583},[10476],{"type":420,"value":10477},"                })\n",{"type":415,"tag":559,"props":10479,"children":10480},{"class":561,"line":3858},[10481,10485,10490],{"type":415,"tag":559,"props":10482,"children":10483},{"style":583},[10484],{"type":420,"value":8274},{"type":415,"tag":559,"props":10486,"children":10487},{"style":883},[10488],{"type":420,"value":10489},"ToArray",{"type":415,"tag":559,"props":10491,"children":10492},{"style":583},[10493],{"type":420,"value":1962},{"type":415,"tag":559,"props":10495,"children":10496},{"class":561,"line":3866},[10497],{"type":415,"tag":559,"props":10498,"children":10499},{"style":583},[10500],{"type":420,"value":2792},{"type":415,"tag":559,"props":10502,"children":10503},{"class":561,"line":3922},[10504],{"type":415,"tag":559,"props":10505,"children":10506},{"style":583},[10507],{"type":420,"value":1801},{"type":415,"tag":416,"props":10509,"children":10510},{},[10511],{"type":420,"value":10512},"The weather forecasts of a specific geolocation are retrieved. Indeed coordinates (corresponding to Bordeaux in France) are passed to the Open Weather Map API call. In C# 12, we can alias any type so we can introduce an alias \"Coordinates\" for the coordinates tuple:",{"type":415,"tag":549,"props":10514,"children":10516},{"className":551,"code":10515,"language":326,"meta":401,"style":401},"using Coordinates = (double Latitude, double Longitude);\n\npublic class OpenWeatherService : IWeatherService\n{\n    private readonly IOpenWeatherMapApi _openWeatherMapApi;\n    private static readonly Coordinates BordeauxCoordinates = (44.837789, -0.57918\n",[10517],{"type":415,"tag":555,"props":10518,"children":10519},{"__ignoreMap":401},[10520,10560,10567,10590,10597,10620],{"type":415,"tag":559,"props":10521,"children":10522},{"class":561,"line":562},[10523,10527,10532,10536,10540,10544,10548,10552,10556],{"type":415,"tag":559,"props":10524,"children":10525},{"style":2846},[10526],{"type":420,"value":748},{"type":415,"tag":559,"props":10528,"children":10529},{"style":572},[10530],{"type":420,"value":10531}," Coordinates",{"type":415,"tag":559,"props":10533,"children":10534},{"style":583},[10535],{"type":420,"value":763},{"type":415,"tag":559,"props":10537,"children":10538},{"style":583},[10539],{"type":420,"value":9458},{"type":415,"tag":559,"props":10541,"children":10542},{"style":572},[10543],{"type":420,"value":9463},{"type":415,"tag":559,"props":10545,"children":10546},{"style":583},[10547],{"type":420,"value":2312},{"type":415,"tag":559,"props":10549,"children":10550},{"style":583},[10551],{"type":420,"value":9472},{"type":415,"tag":559,"props":10553,"children":10554},{"style":572},[10555],{"type":420,"value":9477},{"type":415,"tag":559,"props":10557,"children":10558},{"style":583},[10559],{"type":420,"value":696},{"type":415,"tag":559,"props":10561,"children":10562},{"class":561,"line":589},[10563],{"type":415,"tag":559,"props":10564,"children":10565},{"emptyLinePlaceholder":847},[10566],{"type":420,"value":850},{"type":415,"tag":559,"props":10568,"children":10569},{"class":561,"line":608},[10570,10574,10578,10582,10586],{"type":415,"tag":559,"props":10571,"children":10572},{"style":566},[10573],{"type":420,"value":569},{"type":415,"tag":559,"props":10575,"children":10576},{"style":572},[10577],{"type":420,"value":5933},{"type":415,"tag":559,"props":10579,"children":10580},{"style":572},[10581],{"type":420,"value":9396},{"type":415,"tag":559,"props":10583,"children":10584},{"style":583},[10585],{"type":420,"value":2437},{"type":415,"tag":559,"props":10587,"children":10588},{"style":572},[10589],{"type":420,"value":9405},{"type":415,"tag":559,"props":10591,"children":10592},{"class":561,"line":626},[10593],{"type":415,"tag":559,"props":10594,"children":10595},{"style":583},[10596],{"type":420,"value":786},{"type":415,"tag":559,"props":10598,"children":10599},{"class":561,"line":643},[10600,10604,10608,10612,10616],{"type":415,"tag":559,"props":10601,"children":10602},{"style":566},[10603],{"type":420,"value":5962},{"type":415,"tag":559,"props":10605,"children":10606},{"style":566},[10607],{"type":420,"value":5967},{"type":415,"tag":559,"props":10609,"children":10610},{"style":572},[10611],{"type":420,"value":9428},{"type":415,"tag":559,"props":10613,"children":10614},{"style":572},[10615],{"type":420,"value":9433},{"type":415,"tag":559,"props":10617,"children":10618},{"style":583},[10619],{"type":420,"value":1509},{"type":415,"tag":559,"props":10621,"children":10622},{"class":561,"line":660},[10623,10627,10631,10635,10639,10643,10647,10651,10655,10659,10663],{"type":415,"tag":559,"props":10624,"children":10625},{"style":566},[10626],{"type":420,"value":5962},{"type":415,"tag":559,"props":10628,"children":10629},{"style":566},[10630],{"type":420,"value":9449},{"type":415,"tag":559,"props":10632,"children":10633},{"style":566},[10634],{"type":420,"value":5967},{"type":415,"tag":559,"props":10636,"children":10637},{"style":572},[10638],{"type":420,"value":10531},{"type":415,"tag":559,"props":10640,"children":10641},{"style":572},[10642],{"type":420,"value":9486},{"type":415,"tag":559,"props":10644,"children":10645},{"style":583},[10646],{"type":420,"value":763},{"type":415,"tag":559,"props":10648,"children":10649},{"style":583},[10650],{"type":420,"value":2710},{"type":415,"tag":559,"props":10652,"children":10653},{"style":2846},[10654],{"type":420,"value":9499},{"type":415,"tag":559,"props":10656,"children":10657},{"style":583},[10658],{"type":420,"value":2312},{"type":415,"tag":559,"props":10660,"children":10661},{"style":583},[10662],{"type":420,"value":8540},{"type":415,"tag":559,"props":10664,"children":10665},{"style":2846},[10666],{"type":420,"value":10667},"0.57918\n",{"type":415,"tag":416,"props":10669,"children":10670},{},[10671,10673,10678,10680,10687],{"type":420,"value":10672},"Once this call is done, results are mapped to the expected model ",{"type":415,"tag":555,"props":10674,"children":10676},{"className":10675},[],[10677],{"type":420,"value":9045},{"type":420,"value":10679},". A lambda expression is used to get the \"weather summary\" from a temperature. If we want to have a default summary, that's something we can do thanks to the support of ",{"type":415,"tag":434,"props":10681,"children":10684},{"href":10682,"rel":10683},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#default-lambda-parameters",[438],[10685],{"type":420,"value":10686},"default lambda parameters",{"type":420,"value":10688}," in C#12.",{"type":415,"tag":549,"props":10690,"children":10692},{"className":551,"code":10691,"language":326,"meta":401,"style":401},"var computeWeatherSummary = (double temperature, string defaultSummary = \"Warm\") =>\n    temperature switch\n    {\n        \u003C 0 => \"Freezing\",\n        >= 0 and \u003C 5 => \"Bracing\",\n        >= 5 and \u003C 12 => \"Chilly\",\n        >= 12 and \u003C 18 => \"Cool\",\n        >= 18 and \u003C 24 => \"Mild\",\n        >= 24 and \u003C 30 => \"Warm\",\n        >= 30 and \u003C 35 => \"Balmy\",\n        >= 35 and \u003C 40 => \"Hot\",\n        >= 40 and \u003C 45 => \"Sweltering\",\n        >= 45 => \"Scorching\",\n        _ => defaultSummary\n    };\n",[10693],{"type":415,"tag":555,"props":10694,"children":10695},{"__ignoreMap":401},[10696,10756,10768,10775,10807,10851,10894,10937,10980,11023,11066,11109,11152,11183,11200],{"type":415,"tag":559,"props":10697,"children":10698},{"class":561,"line":562},[10699,10703,10707,10711,10715,10719,10723,10727,10732,10736,10740,10744,10748,10752],{"type":415,"tag":559,"props":10700,"children":10701},{"style":572},[10702],{"type":420,"value":858},{"type":415,"tag":559,"props":10704,"children":10705},{"style":572},[10706],{"type":420,"value":9727},{"type":415,"tag":559,"props":10708,"children":10709},{"style":583},[10710],{"type":420,"value":763},{"type":415,"tag":559,"props":10712,"children":10713},{"style":583},[10714],{"type":420,"value":9458},{"type":415,"tag":559,"props":10716,"children":10717},{"style":572},[10718],{"type":420,"value":9740},{"type":415,"tag":559,"props":10720,"children":10721},{"style":583},[10722],{"type":420,"value":2312},{"type":415,"tag":559,"props":10724,"children":10725},{"style":583},[10726],{"type":420,"value":1129},{"type":415,"tag":559,"props":10728,"children":10729},{"style":572},[10730],{"type":420,"value":10731}," defaultSummary",{"type":415,"tag":559,"props":10733,"children":10734},{"style":583},[10735],{"type":420,"value":763},{"type":415,"tag":559,"props":10737,"children":10738},{"style":583},[10739],{"type":420,"value":1434},{"type":415,"tag":559,"props":10741,"children":10742},{"style":822},[10743],{"type":420,"value":10021},{"type":415,"tag":559,"props":10745,"children":10746},{"style":583},[10747],{"type":420,"value":819},{"type":415,"tag":559,"props":10749,"children":10750},{"style":583},[10751],{"type":420,"value":1468},{"type":415,"tag":559,"props":10753,"children":10754},{"style":583},[10755],{"type":420,"value":5741},{"type":415,"tag":559,"props":10757,"children":10758},{"class":561,"line":589},[10759,10764],{"type":415,"tag":559,"props":10760,"children":10761},{"style":792},[10762],{"type":420,"value":10763},"    temperature ",{"type":415,"tag":559,"props":10765,"children":10766},{"style":745},[10767],{"type":420,"value":9761},{"type":415,"tag":559,"props":10769,"children":10770},{"class":561,"line":608},[10771],{"type":415,"tag":559,"props":10772,"children":10773},{"style":583},[10774],{"type":420,"value":2737},{"type":415,"tag":559,"props":10776,"children":10777},{"class":561,"line":626},[10778,10783,10787,10791,10795,10799,10803],{"type":415,"tag":559,"props":10779,"children":10780},{"style":583},[10781],{"type":420,"value":10782},"        \u003C",{"type":415,"tag":559,"props":10784,"children":10785},{"style":2846},[10786],{"type":420,"value":5204},{"type":415,"tag":559,"props":10788,"children":10789},{"style":583},[10790],{"type":420,"value":1861},{"type":415,"tag":559,"props":10792,"children":10793},{"style":583},[10794],{"type":420,"value":1434},{"type":415,"tag":559,"props":10796,"children":10797},{"style":822},[10798],{"type":420,"value":9794},{"type":415,"tag":559,"props":10800,"children":10801},{"style":583},[10802],{"type":420,"value":819},{"type":415,"tag":559,"props":10804,"children":10805},{"style":583},[10806],{"type":420,"value":605},{"type":415,"tag":559,"props":10808,"children":10809},{"class":561,"line":643},[10810,10815,10819,10823,10827,10831,10835,10839,10843,10847],{"type":415,"tag":559,"props":10811,"children":10812},{"style":583},[10813],{"type":420,"value":10814},"        >=",{"type":415,"tag":559,"props":10816,"children":10817},{"style":2846},[10818],{"type":420,"value":5204},{"type":415,"tag":559,"props":10820,"children":10821},{"style":583},[10822],{"type":420,"value":9819},{"type":415,"tag":559,"props":10824,"children":10825},{"style":583},[10826],{"type":420,"value":9824},{"type":415,"tag":559,"props":10828,"children":10829},{"style":2846},[10830],{"type":420,"value":5310},{"type":415,"tag":559,"props":10832,"children":10833},{"style":583},[10834],{"type":420,"value":1861},{"type":415,"tag":559,"props":10836,"children":10837},{"style":583},[10838],{"type":420,"value":1434},{"type":415,"tag":559,"props":10840,"children":10841},{"style":822},[10842],{"type":420,"value":9841},{"type":415,"tag":559,"props":10844,"children":10845},{"style":583},[10846],{"type":420,"value":819},{"type":415,"tag":559,"props":10848,"children":10849},{"style":583},[10850],{"type":420,"value":605},{"type":415,"tag":559,"props":10852,"children":10853},{"class":561,"line":660},[10854,10858,10862,10866,10870,10874,10878,10882,10886,10890],{"type":415,"tag":559,"props":10855,"children":10856},{"style":583},[10857],{"type":420,"value":10814},{"type":415,"tag":559,"props":10859,"children":10860},{"style":2846},[10861],{"type":420,"value":5310},{"type":415,"tag":559,"props":10863,"children":10864},{"style":583},[10865],{"type":420,"value":9819},{"type":415,"tag":559,"props":10867,"children":10868},{"style":583},[10869],{"type":420,"value":9824},{"type":415,"tag":559,"props":10871,"children":10872},{"style":2846},[10873],{"type":420,"value":9873},{"type":415,"tag":559,"props":10875,"children":10876},{"style":583},[10877],{"type":420,"value":1861},{"type":415,"tag":559,"props":10879,"children":10880},{"style":583},[10881],{"type":420,"value":1434},{"type":415,"tag":559,"props":10883,"children":10884},{"style":822},[10885],{"type":420,"value":9886},{"type":415,"tag":559,"props":10887,"children":10888},{"style":583},[10889],{"type":420,"value":819},{"type":415,"tag":559,"props":10891,"children":10892},{"style":583},[10893],{"type":420,"value":605},{"type":415,"tag":559,"props":10895,"children":10896},{"class":561,"line":677},[10897,10901,10905,10909,10913,10917,10921,10925,10929,10933],{"type":415,"tag":559,"props":10898,"children":10899},{"style":583},[10900],{"type":420,"value":10814},{"type":415,"tag":559,"props":10902,"children":10903},{"style":2846},[10904],{"type":420,"value":9873},{"type":415,"tag":559,"props":10906,"children":10907},{"style":583},[10908],{"type":420,"value":9819},{"type":415,"tag":559,"props":10910,"children":10911},{"style":583},[10912],{"type":420,"value":9824},{"type":415,"tag":559,"props":10914,"children":10915},{"style":2846},[10916],{"type":420,"value":9918},{"type":415,"tag":559,"props":10918,"children":10919},{"style":583},[10920],{"type":420,"value":1861},{"type":415,"tag":559,"props":10922,"children":10923},{"style":583},[10924],{"type":420,"value":1434},{"type":415,"tag":559,"props":10926,"children":10927},{"style":822},[10928],{"type":420,"value":9931},{"type":415,"tag":559,"props":10930,"children":10931},{"style":583},[10932],{"type":420,"value":819},{"type":415,"tag":559,"props":10934,"children":10935},{"style":583},[10936],{"type":420,"value":605},{"type":415,"tag":559,"props":10938,"children":10939},{"class":561,"line":690},[10940,10944,10948,10952,10956,10960,10964,10968,10972,10976],{"type":415,"tag":559,"props":10941,"children":10942},{"style":583},[10943],{"type":420,"value":10814},{"type":415,"tag":559,"props":10945,"children":10946},{"style":2846},[10947],{"type":420,"value":9918},{"type":415,"tag":559,"props":10949,"children":10950},{"style":583},[10951],{"type":420,"value":9819},{"type":415,"tag":559,"props":10953,"children":10954},{"style":583},[10955],{"type":420,"value":9824},{"type":415,"tag":559,"props":10957,"children":10958},{"style":2846},[10959],{"type":420,"value":9963},{"type":415,"tag":559,"props":10961,"children":10962},{"style":583},[10963],{"type":420,"value":1861},{"type":415,"tag":559,"props":10965,"children":10966},{"style":583},[10967],{"type":420,"value":1434},{"type":415,"tag":559,"props":10969,"children":10970},{"style":822},[10971],{"type":420,"value":9976},{"type":415,"tag":559,"props":10973,"children":10974},{"style":583},[10975],{"type":420,"value":819},{"type":415,"tag":559,"props":10977,"children":10978},{"style":583},[10979],{"type":420,"value":605},{"type":415,"tag":559,"props":10981,"children":10982},{"class":561,"line":1089},[10983,10987,10991,10995,10999,11003,11007,11011,11015,11019],{"type":415,"tag":559,"props":10984,"children":10985},{"style":583},[10986],{"type":420,"value":10814},{"type":415,"tag":559,"props":10988,"children":10989},{"style":2846},[10990],{"type":420,"value":9963},{"type":415,"tag":559,"props":10992,"children":10993},{"style":583},[10994],{"type":420,"value":9819},{"type":415,"tag":559,"props":10996,"children":10997},{"style":583},[10998],{"type":420,"value":9824},{"type":415,"tag":559,"props":11000,"children":11001},{"style":2846},[11002],{"type":420,"value":10008},{"type":415,"tag":559,"props":11004,"children":11005},{"style":583},[11006],{"type":420,"value":1861},{"type":415,"tag":559,"props":11008,"children":11009},{"style":583},[11010],{"type":420,"value":1434},{"type":415,"tag":559,"props":11012,"children":11013},{"style":822},[11014],{"type":420,"value":10021},{"type":415,"tag":559,"props":11016,"children":11017},{"style":583},[11018],{"type":420,"value":819},{"type":415,"tag":559,"props":11020,"children":11021},{"style":583},[11022],{"type":420,"value":605},{"type":415,"tag":559,"props":11024,"children":11025},{"class":561,"line":1102},[11026,11030,11034,11038,11042,11046,11050,11054,11058,11062],{"type":415,"tag":559,"props":11027,"children":11028},{"style":583},[11029],{"type":420,"value":10814},{"type":415,"tag":559,"props":11031,"children":11032},{"style":2846},[11033],{"type":420,"value":10008},{"type":415,"tag":559,"props":11035,"children":11036},{"style":583},[11037],{"type":420,"value":9819},{"type":415,"tag":559,"props":11039,"children":11040},{"style":583},[11041],{"type":420,"value":9824},{"type":415,"tag":559,"props":11043,"children":11044},{"style":2846},[11045],{"type":420,"value":10053},{"type":415,"tag":559,"props":11047,"children":11048},{"style":583},[11049],{"type":420,"value":1861},{"type":415,"tag":559,"props":11051,"children":11052},{"style":583},[11053],{"type":420,"value":1434},{"type":415,"tag":559,"props":11055,"children":11056},{"style":822},[11057],{"type":420,"value":10066},{"type":415,"tag":559,"props":11059,"children":11060},{"style":583},[11061],{"type":420,"value":819},{"type":415,"tag":559,"props":11063,"children":11064},{"style":583},[11065],{"type":420,"value":605},{"type":415,"tag":559,"props":11067,"children":11068},{"class":561,"line":1110},[11069,11073,11077,11081,11085,11089,11093,11097,11101,11105],{"type":415,"tag":559,"props":11070,"children":11071},{"style":583},[11072],{"type":420,"value":10814},{"type":415,"tag":559,"props":11074,"children":11075},{"style":2846},[11076],{"type":420,"value":10053},{"type":415,"tag":559,"props":11078,"children":11079},{"style":583},[11080],{"type":420,"value":9819},{"type":415,"tag":559,"props":11082,"children":11083},{"style":583},[11084],{"type":420,"value":9824},{"type":415,"tag":559,"props":11086,"children":11087},{"style":2846},[11088],{"type":420,"value":10098},{"type":415,"tag":559,"props":11090,"children":11091},{"style":583},[11092],{"type":420,"value":1861},{"type":415,"tag":559,"props":11094,"children":11095},{"style":583},[11096],{"type":420,"value":1434},{"type":415,"tag":559,"props":11098,"children":11099},{"style":822},[11100],{"type":420,"value":10111},{"type":415,"tag":559,"props":11102,"children":11103},{"style":583},[11104],{"type":420,"value":819},{"type":415,"tag":559,"props":11106,"children":11107},{"style":583},[11108],{"type":420,"value":605},{"type":415,"tag":559,"props":11110,"children":11111},{"class":561,"line":1118},[11112,11116,11120,11124,11128,11132,11136,11140,11144,11148],{"type":415,"tag":559,"props":11113,"children":11114},{"style":583},[11115],{"type":420,"value":10814},{"type":415,"tag":559,"props":11117,"children":11118},{"style":2846},[11119],{"type":420,"value":10098},{"type":415,"tag":559,"props":11121,"children":11122},{"style":583},[11123],{"type":420,"value":9819},{"type":415,"tag":559,"props":11125,"children":11126},{"style":583},[11127],{"type":420,"value":9824},{"type":415,"tag":559,"props":11129,"children":11130},{"style":2846},[11131],{"type":420,"value":10143},{"type":415,"tag":559,"props":11133,"children":11134},{"style":583},[11135],{"type":420,"value":1861},{"type":415,"tag":559,"props":11137,"children":11138},{"style":583},[11139],{"type":420,"value":1434},{"type":415,"tag":559,"props":11141,"children":11142},{"style":822},[11143],{"type":420,"value":10156},{"type":415,"tag":559,"props":11145,"children":11146},{"style":583},[11147],{"type":420,"value":819},{"type":415,"tag":559,"props":11149,"children":11150},{"style":583},[11151],{"type":420,"value":605},{"type":415,"tag":559,"props":11153,"children":11154},{"class":561,"line":1171},[11155,11159,11163,11167,11171,11175,11179],{"type":415,"tag":559,"props":11156,"children":11157},{"style":583},[11158],{"type":420,"value":10814},{"type":415,"tag":559,"props":11160,"children":11161},{"style":2846},[11162],{"type":420,"value":10143},{"type":415,"tag":559,"props":11164,"children":11165},{"style":583},[11166],{"type":420,"value":1861},{"type":415,"tag":559,"props":11168,"children":11169},{"style":583},[11170],{"type":420,"value":1434},{"type":415,"tag":559,"props":11172,"children":11173},{"style":822},[11174],{"type":420,"value":10188},{"type":415,"tag":559,"props":11176,"children":11177},{"style":583},[11178],{"type":420,"value":819},{"type":415,"tag":559,"props":11180,"children":11181},{"style":583},[11182],{"type":420,"value":605},{"type":415,"tag":559,"props":11184,"children":11185},{"class":561,"line":1748},[11186,11191,11195],{"type":415,"tag":559,"props":11187,"children":11188},{"style":792},[11189],{"type":420,"value":11190},"        _ ",{"type":415,"tag":559,"props":11192,"children":11193},{"style":583},[11194],{"type":420,"value":10209},{"type":415,"tag":559,"props":11196,"children":11197},{"style":792},[11198],{"type":420,"value":11199}," defaultSummary\n",{"type":415,"tag":559,"props":11201,"children":11202},{"class":561,"line":1769},[11203],{"type":415,"tag":559,"props":11204,"children":11205},{"style":583},[11206],{"type":420,"value":11207},"    };\n",{"type":415,"tag":416,"props":11209,"children":11210},{},[11211,11216],{"type":415,"tag":555,"props":11212,"children":11214},{"className":11213},[],[11215],{"type":420,"value":9356},{"type":420,"value":11217}," does not have this logic because Summaries are randomly selected from an array containing possible summaries.",{"type":415,"tag":549,"props":11219,"children":11221},{"className":551,"code":11220,"language":326,"meta":401,"style":401},"private static readonly string[] Summaries = new [] { \"Freezing\", \"Bracing\", \"Chilly\", \"Cool\", \"Mild\", \"Warm\", \"Balmy\", \"Hot\", \"Sweltering\", \"Scorching\" };\n",[11222],{"type":415,"tag":555,"props":11223,"children":11224},{"__ignoreMap":401},[11225],{"type":415,"tag":559,"props":11226,"children":11227},{"class":561,"line":562},[11228,11233,11237,11241,11245,11250,11255,11259,11263,11268,11272,11276,11280,11284,11288,11292,11296,11300,11304,11308,11312,11316,11320,11324,11328,11332,11336,11340,11344,11348,11352,11356,11360,11364,11368,11372,11376,11380,11384,11388,11392,11396,11400,11404,11408,11412,11416,11420,11424,11428],{"type":415,"tag":559,"props":11229,"children":11230},{"style":566},[11231],{"type":420,"value":11232},"private",{"type":415,"tag":559,"props":11234,"children":11235},{"style":566},[11236],{"type":420,"value":9449},{"type":415,"tag":559,"props":11238,"children":11239},{"style":566},[11240],{"type":420,"value":5967},{"type":415,"tag":559,"props":11242,"children":11243},{"style":583},[11244],{"type":420,"value":1129},{"type":415,"tag":559,"props":11246,"children":11247},{"style":583},[11248],{"type":420,"value":11249},"[]",{"type":415,"tag":559,"props":11251,"children":11252},{"style":572},[11253],{"type":420,"value":11254}," Summaries",{"type":415,"tag":559,"props":11256,"children":11257},{"style":583},[11258],{"type":420,"value":763},{"type":415,"tag":559,"props":11260,"children":11261},{"style":583},[11262],{"type":420,"value":768},{"type":415,"tag":559,"props":11264,"children":11265},{"style":583},[11266],{"type":420,"value":11267}," []",{"type":415,"tag":559,"props":11269,"children":11270},{"style":583},[11271],{"type":420,"value":1144},{"type":415,"tag":559,"props":11273,"children":11274},{"style":583},[11275],{"type":420,"value":1434},{"type":415,"tag":559,"props":11277,"children":11278},{"style":822},[11279],{"type":420,"value":9794},{"type":415,"tag":559,"props":11281,"children":11282},{"style":583},[11283],{"type":420,"value":819},{"type":415,"tag":559,"props":11285,"children":11286},{"style":583},[11287],{"type":420,"value":2312},{"type":415,"tag":559,"props":11289,"children":11290},{"style":583},[11291],{"type":420,"value":1434},{"type":415,"tag":559,"props":11293,"children":11294},{"style":822},[11295],{"type":420,"value":9841},{"type":415,"tag":559,"props":11297,"children":11298},{"style":583},[11299],{"type":420,"value":819},{"type":415,"tag":559,"props":11301,"children":11302},{"style":583},[11303],{"type":420,"value":2312},{"type":415,"tag":559,"props":11305,"children":11306},{"style":583},[11307],{"type":420,"value":1434},{"type":415,"tag":559,"props":11309,"children":11310},{"style":822},[11311],{"type":420,"value":9886},{"type":415,"tag":559,"props":11313,"children":11314},{"style":583},[11315],{"type":420,"value":819},{"type":415,"tag":559,"props":11317,"children":11318},{"style":583},[11319],{"type":420,"value":2312},{"type":415,"tag":559,"props":11321,"children":11322},{"style":583},[11323],{"type":420,"value":1434},{"type":415,"tag":559,"props":11325,"children":11326},{"style":822},[11327],{"type":420,"value":9931},{"type":415,"tag":559,"props":11329,"children":11330},{"style":583},[11331],{"type":420,"value":819},{"type":415,"tag":559,"props":11333,"children":11334},{"style":583},[11335],{"type":420,"value":2312},{"type":415,"tag":559,"props":11337,"children":11338},{"style":583},[11339],{"type":420,"value":1434},{"type":415,"tag":559,"props":11341,"children":11342},{"style":822},[11343],{"type":420,"value":9976},{"type":415,"tag":559,"props":11345,"children":11346},{"style":583},[11347],{"type":420,"value":819},{"type":415,"tag":559,"props":11349,"children":11350},{"style":583},[11351],{"type":420,"value":2312},{"type":415,"tag":559,"props":11353,"children":11354},{"style":583},[11355],{"type":420,"value":1434},{"type":415,"tag":559,"props":11357,"children":11358},{"style":822},[11359],{"type":420,"value":10021},{"type":415,"tag":559,"props":11361,"children":11362},{"style":583},[11363],{"type":420,"value":819},{"type":415,"tag":559,"props":11365,"children":11366},{"style":583},[11367],{"type":420,"value":2312},{"type":415,"tag":559,"props":11369,"children":11370},{"style":583},[11371],{"type":420,"value":1434},{"type":415,"tag":559,"props":11373,"children":11374},{"style":822},[11375],{"type":420,"value":10066},{"type":415,"tag":559,"props":11377,"children":11378},{"style":583},[11379],{"type":420,"value":819},{"type":415,"tag":559,"props":11381,"children":11382},{"style":583},[11383],{"type":420,"value":2312},{"type":415,"tag":559,"props":11385,"children":11386},{"style":583},[11387],{"type":420,"value":1434},{"type":415,"tag":559,"props":11389,"children":11390},{"style":822},[11391],{"type":420,"value":10111},{"type":415,"tag":559,"props":11393,"children":11394},{"style":583},[11395],{"type":420,"value":819},{"type":415,"tag":559,"props":11397,"children":11398},{"style":583},[11399],{"type":420,"value":2312},{"type":415,"tag":559,"props":11401,"children":11402},{"style":583},[11403],{"type":420,"value":1434},{"type":415,"tag":559,"props":11405,"children":11406},{"style":822},[11407],{"type":420,"value":10156},{"type":415,"tag":559,"props":11409,"children":11410},{"style":583},[11411],{"type":420,"value":819},{"type":415,"tag":559,"props":11413,"children":11414},{"style":583},[11415],{"type":420,"value":2312},{"type":415,"tag":559,"props":11417,"children":11418},{"style":583},[11419],{"type":420,"value":1434},{"type":415,"tag":559,"props":11421,"children":11422},{"style":822},[11423],{"type":420,"value":10188},{"type":415,"tag":559,"props":11425,"children":11426},{"style":583},[11427],{"type":420,"value":819},{"type":415,"tag":559,"props":11429,"children":11430},{"style":583},[11431],{"type":420,"value":11432}," };\n",{"type":415,"tag":416,"props":11434,"children":11435},{},[11436,11438,11445],{"type":420,"value":11437},"With ",{"type":415,"tag":434,"props":11439,"children":11442},{"href":11440,"rel":11441},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#collection-expressions",[438],[11443],{"type":420,"value":11444},"collection expressions",{"type":420,"value":11446},", this array can be defined directly with square brackets.",{"type":415,"tag":549,"props":11448,"children":11450},{"className":551,"code":11449,"language":326,"meta":401,"style":401},"private static readonly string[] Summaries = [ \"Freezing\", \"Bracing\", \"Chilly\", \"Cool\", \"Mild\", \"Warm\", \"Balmy\", \"Hot\", \"Sweltering\", \"Scorching\"];\n",[11451],{"type":415,"tag":555,"props":11452,"children":11453},{"__ignoreMap":401},[11454],{"type":415,"tag":559,"props":11455,"children":11456},{"class":561,"line":562},[11457,11461,11465,11469,11473,11477,11481,11485,11490,11494,11498,11502,11506,11510,11514,11518,11522,11526,11530,11534,11538,11542,11546,11550,11554,11558,11562,11566,11570,11574,11578,11582,11586,11590,11594,11598,11602,11606,11610,11614,11618,11622,11626,11630,11634,11638,11642,11646],{"type":415,"tag":559,"props":11458,"children":11459},{"style":566},[11460],{"type":420,"value":11232},{"type":415,"tag":559,"props":11462,"children":11463},{"style":566},[11464],{"type":420,"value":9449},{"type":415,"tag":559,"props":11466,"children":11467},{"style":566},[11468],{"type":420,"value":5967},{"type":415,"tag":559,"props":11470,"children":11471},{"style":583},[11472],{"type":420,"value":1129},{"type":415,"tag":559,"props":11474,"children":11475},{"style":583},[11476],{"type":420,"value":11249},{"type":415,"tag":559,"props":11478,"children":11479},{"style":572},[11480],{"type":420,"value":11254},{"type":415,"tag":559,"props":11482,"children":11483},{"style":583},[11484],{"type":420,"value":763},{"type":415,"tag":559,"props":11486,"children":11487},{"style":583},[11488],{"type":420,"value":11489}," [",{"type":415,"tag":559,"props":11491,"children":11492},{"style":583},[11493],{"type":420,"value":1434},{"type":415,"tag":559,"props":11495,"children":11496},{"style":822},[11497],{"type":420,"value":9794},{"type":415,"tag":559,"props":11499,"children":11500},{"style":583},[11501],{"type":420,"value":819},{"type":415,"tag":559,"props":11503,"children":11504},{"style":583},[11505],{"type":420,"value":2312},{"type":415,"tag":559,"props":11507,"children":11508},{"style":583},[11509],{"type":420,"value":1434},{"type":415,"tag":559,"props":11511,"children":11512},{"style":822},[11513],{"type":420,"value":9841},{"type":415,"tag":559,"props":11515,"children":11516},{"style":583},[11517],{"type":420,"value":819},{"type":415,"tag":559,"props":11519,"children":11520},{"style":583},[11521],{"type":420,"value":2312},{"type":415,"tag":559,"props":11523,"children":11524},{"style":583},[11525],{"type":420,"value":1434},{"type":415,"tag":559,"props":11527,"children":11528},{"style":822},[11529],{"type":420,"value":9886},{"type":415,"tag":559,"props":11531,"children":11532},{"style":583},[11533],{"type":420,"value":819},{"type":415,"tag":559,"props":11535,"children":11536},{"style":583},[11537],{"type":420,"value":2312},{"type":415,"tag":559,"props":11539,"children":11540},{"style":583},[11541],{"type":420,"value":1434},{"type":415,"tag":559,"props":11543,"children":11544},{"style":822},[11545],{"type":420,"value":9931},{"type":415,"tag":559,"props":11547,"children":11548},{"style":583},[11549],{"type":420,"value":819},{"type":415,"tag":559,"props":11551,"children":11552},{"style":583},[11553],{"type":420,"value":2312},{"type":415,"tag":559,"props":11555,"children":11556},{"style":583},[11557],{"type":420,"value":1434},{"type":415,"tag":559,"props":11559,"children":11560},{"style":822},[11561],{"type":420,"value":9976},{"type":415,"tag":559,"props":11563,"children":11564},{"style":583},[11565],{"type":420,"value":819},{"type":415,"tag":559,"props":11567,"children":11568},{"style":583},[11569],{"type":420,"value":2312},{"type":415,"tag":559,"props":11571,"children":11572},{"style":583},[11573],{"type":420,"value":1434},{"type":415,"tag":559,"props":11575,"children":11576},{"style":822},[11577],{"type":420,"value":10021},{"type":415,"tag":559,"props":11579,"children":11580},{"style":583},[11581],{"type":420,"value":819},{"type":415,"tag":559,"props":11583,"children":11584},{"style":583},[11585],{"type":420,"value":2312},{"type":415,"tag":559,"props":11587,"children":11588},{"style":583},[11589],{"type":420,"value":1434},{"type":415,"tag":559,"props":11591,"children":11592},{"style":822},[11593],{"type":420,"value":10066},{"type":415,"tag":559,"props":11595,"children":11596},{"style":583},[11597],{"type":420,"value":819},{"type":415,"tag":559,"props":11599,"children":11600},{"style":583},[11601],{"type":420,"value":2312},{"type":415,"tag":559,"props":11603,"children":11604},{"style":583},[11605],{"type":420,"value":1434},{"type":415,"tag":559,"props":11607,"children":11608},{"style":822},[11609],{"type":420,"value":10111},{"type":415,"tag":559,"props":11611,"children":11612},{"style":583},[11613],{"type":420,"value":819},{"type":415,"tag":559,"props":11615,"children":11616},{"style":583},[11617],{"type":420,"value":2312},{"type":415,"tag":559,"props":11619,"children":11620},{"style":583},[11621],{"type":420,"value":1434},{"type":415,"tag":559,"props":11623,"children":11624},{"style":822},[11625],{"type":420,"value":10156},{"type":415,"tag":559,"props":11627,"children":11628},{"style":583},[11629],{"type":420,"value":819},{"type":415,"tag":559,"props":11631,"children":11632},{"style":583},[11633],{"type":420,"value":2312},{"type":415,"tag":559,"props":11635,"children":11636},{"style":583},[11637],{"type":420,"value":1434},{"type":415,"tag":559,"props":11639,"children":11640},{"style":822},[11641],{"type":420,"value":10188},{"type":415,"tag":559,"props":11643,"children":11644},{"style":583},[11645],{"type":420,"value":819},{"type":415,"tag":559,"props":11647,"children":11648},{"style":583},[11649],{"type":420,"value":11650},"];\n",{"type":415,"tag":416,"props":11652,"children":11653},{},[11654],{"type":420,"value":11655},"It would work with other types of collections as well. If we needed to have another list containing only cold summaries and avoid duplication between the two lists, we could also define the two lists and use the spread operator.",{"type":415,"tag":549,"props":11657,"children":11659},{"className":551,"code":11658,"language":326,"meta":401,"style":401}," private static readonly IList\u003Cstring> ColdAdjectives = [\"Freezing\", \"Bracing\", \"Chilly\", \"Cool\"];\n private static readonly string[] Summaries = [ ..ColdAdjectives, \"Mild\", \"Warm\", \"Balmy\", \"Hot\", \"Sweltering\", \"Scorching\"];\n",[11660],{"type":415,"tag":555,"props":11661,"children":11662},{"__ignoreMap":401},[11663,11773],{"type":415,"tag":559,"props":11664,"children":11665},{"class":561,"line":562},[11666,11671,11675,11679,11684,11688,11692,11696,11701,11705,11709,11713,11717,11721,11725,11729,11733,11737,11741,11745,11749,11753,11757,11761,11765,11769],{"type":415,"tag":559,"props":11667,"children":11668},{"style":566},[11669],{"type":420,"value":11670}," private",{"type":415,"tag":559,"props":11672,"children":11673},{"style":566},[11674],{"type":420,"value":9449},{"type":415,"tag":559,"props":11676,"children":11677},{"style":566},[11678],{"type":420,"value":5967},{"type":415,"tag":559,"props":11680,"children":11681},{"style":572},[11682],{"type":420,"value":11683}," IList",{"type":415,"tag":559,"props":11685,"children":11686},{"style":583},[11687],{"type":420,"value":891},{"type":415,"tag":559,"props":11689,"children":11690},{"style":583},[11691],{"type":420,"value":2015},{"type":415,"tag":559,"props":11693,"children":11694},{"style":583},[11695],{"type":420,"value":5985},{"type":415,"tag":559,"props":11697,"children":11698},{"style":572},[11699],{"type":420,"value":11700}," ColdAdjectives",{"type":415,"tag":559,"props":11702,"children":11703},{"style":583},[11704],{"type":420,"value":763},{"type":415,"tag":559,"props":11706,"children":11707},{"style":583},[11708],{"type":420,"value":11489},{"type":415,"tag":559,"props":11710,"children":11711},{"style":583},[11712],{"type":420,"value":819},{"type":415,"tag":559,"props":11714,"children":11715},{"style":822},[11716],{"type":420,"value":9794},{"type":415,"tag":559,"props":11718,"children":11719},{"style":583},[11720],{"type":420,"value":819},{"type":415,"tag":559,"props":11722,"children":11723},{"style":583},[11724],{"type":420,"value":2312},{"type":415,"tag":559,"props":11726,"children":11727},{"style":583},[11728],{"type":420,"value":1434},{"type":415,"tag":559,"props":11730,"children":11731},{"style":822},[11732],{"type":420,"value":9841},{"type":415,"tag":559,"props":11734,"children":11735},{"style":583},[11736],{"type":420,"value":819},{"type":415,"tag":559,"props":11738,"children":11739},{"style":583},[11740],{"type":420,"value":2312},{"type":415,"tag":559,"props":11742,"children":11743},{"style":583},[11744],{"type":420,"value":1434},{"type":415,"tag":559,"props":11746,"children":11747},{"style":822},[11748],{"type":420,"value":9886},{"type":415,"tag":559,"props":11750,"children":11751},{"style":583},[11752],{"type":420,"value":819},{"type":415,"tag":559,"props":11754,"children":11755},{"style":583},[11756],{"type":420,"value":2312},{"type":415,"tag":559,"props":11758,"children":11759},{"style":583},[11760],{"type":420,"value":1434},{"type":415,"tag":559,"props":11762,"children":11763},{"style":822},[11764],{"type":420,"value":9931},{"type":415,"tag":559,"props":11766,"children":11767},{"style":583},[11768],{"type":420,"value":819},{"type":415,"tag":559,"props":11770,"children":11771},{"style":583},[11772],{"type":420,"value":11650},{"type":415,"tag":559,"props":11774,"children":11775},{"class":561,"line":589},[11776,11780,11784,11788,11792,11796,11800,11804,11808,11813,11818,11822,11826,11830,11834,11838,11842,11846,11850,11854,11858,11862,11866,11870,11874,11878,11882,11886,11890,11894,11898,11902,11906,11910,11914],{"type":415,"tag":559,"props":11777,"children":11778},{"style":566},[11779],{"type":420,"value":11670},{"type":415,"tag":559,"props":11781,"children":11782},{"style":566},[11783],{"type":420,"value":9449},{"type":415,"tag":559,"props":11785,"children":11786},{"style":566},[11787],{"type":420,"value":5967},{"type":415,"tag":559,"props":11789,"children":11790},{"style":583},[11791],{"type":420,"value":1129},{"type":415,"tag":559,"props":11793,"children":11794},{"style":583},[11795],{"type":420,"value":11249},{"type":415,"tag":559,"props":11797,"children":11798},{"style":572},[11799],{"type":420,"value":11254},{"type":415,"tag":559,"props":11801,"children":11802},{"style":583},[11803],{"type":420,"value":763},{"type":415,"tag":559,"props":11805,"children":11806},{"style":583},[11807],{"type":420,"value":11489},{"type":415,"tag":559,"props":11809,"children":11810},{"style":583},[11811],{"type":420,"value":11812}," ..",{"type":415,"tag":559,"props":11814,"children":11815},{"style":792},[11816],{"type":420,"value":11817},"ColdAdjectives",{"type":415,"tag":559,"props":11819,"children":11820},{"style":583},[11821],{"type":420,"value":2312},{"type":415,"tag":559,"props":11823,"children":11824},{"style":583},[11825],{"type":420,"value":1434},{"type":415,"tag":559,"props":11827,"children":11828},{"style":822},[11829],{"type":420,"value":9976},{"type":415,"tag":559,"props":11831,"children":11832},{"style":583},[11833],{"type":420,"value":819},{"type":415,"tag":559,"props":11835,"children":11836},{"style":583},[11837],{"type":420,"value":2312},{"type":415,"tag":559,"props":11839,"children":11840},{"style":583},[11841],{"type":420,"value":1434},{"type":415,"tag":559,"props":11843,"children":11844},{"style":822},[11845],{"type":420,"value":10021},{"type":415,"tag":559,"props":11847,"children":11848},{"style":583},[11849],{"type":420,"value":819},{"type":415,"tag":559,"props":11851,"children":11852},{"style":583},[11853],{"type":420,"value":2312},{"type":415,"tag":559,"props":11855,"children":11856},{"style":583},[11857],{"type":420,"value":1434},{"type":415,"tag":559,"props":11859,"children":11860},{"style":822},[11861],{"type":420,"value":10066},{"type":415,"tag":559,"props":11863,"children":11864},{"style":583},[11865],{"type":420,"value":819},{"type":415,"tag":559,"props":11867,"children":11868},{"style":583},[11869],{"type":420,"value":2312},{"type":415,"tag":559,"props":11871,"children":11872},{"style":583},[11873],{"type":420,"value":1434},{"type":415,"tag":559,"props":11875,"children":11876},{"style":822},[11877],{"type":420,"value":10111},{"type":415,"tag":559,"props":11879,"children":11880},{"style":583},[11881],{"type":420,"value":819},{"type":415,"tag":559,"props":11883,"children":11884},{"style":583},[11885],{"type":420,"value":2312},{"type":415,"tag":559,"props":11887,"children":11888},{"style":583},[11889],{"type":420,"value":1434},{"type":415,"tag":559,"props":11891,"children":11892},{"style":822},[11893],{"type":420,"value":10156},{"type":415,"tag":559,"props":11895,"children":11896},{"style":583},[11897],{"type":420,"value":819},{"type":415,"tag":559,"props":11899,"children":11900},{"style":583},[11901],{"type":420,"value":2312},{"type":415,"tag":559,"props":11903,"children":11904},{"style":583},[11905],{"type":420,"value":1434},{"type":415,"tag":559,"props":11907,"children":11908},{"style":822},[11909],{"type":420,"value":10188},{"type":415,"tag":559,"props":11911,"children":11912},{"style":583},[11913],{"type":420,"value":819},{"type":415,"tag":559,"props":11915,"children":11916},{"style":583},[11917],{"type":420,"value":11650},{"type":415,"tag":416,"props":11919,"children":11920},{},[11921],{"type":420,"value":11922},"The last C# 12 thing we could do in this example is to take advantage of the new class (and structs) primary constructors that were previously limited to records.",{"type":415,"tag":416,"props":11924,"children":11925},{},[11926,11927,11932],{"type":420,"value":8781},{"type":415,"tag":555,"props":11928,"children":11930},{"className":11929},[],[11931],{"type":420,"value":9045},{"type":420,"value":11933}," class could become the following:",{"type":415,"tag":549,"props":11935,"children":11937},{"className":551,"code":11936,"language":326,"meta":401,"style":401},"namespace WeatherApi;\n\npublic class WeatherForecast(DateOnly date, int temperatureC, string? summary)\n{\n    public int TemperatureC { get; } = temperatureC;\n    \n    public DateOnly Date { get; } = date;\n    \n    public string? Summary { get; } = summary;\n    \n    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);\n}\n",[11938],{"type":415,"tag":555,"props":11939,"children":11940},{"__ignoreMap":401},[11941,11958,11965,12030,12037,12082,12089,12132,12139,12187,12194,12248],{"type":415,"tag":559,"props":11942,"children":11943},{"class":561,"line":562},[11944,11949,11954],{"type":415,"tag":559,"props":11945,"children":11946},{"style":572},[11947],{"type":420,"value":11948},"namespace",{"type":415,"tag":559,"props":11950,"children":11951},{"style":792},[11952],{"type":420,"value":11953}," WeatherApi",{"type":415,"tag":559,"props":11955,"children":11956},{"style":583},[11957],{"type":420,"value":1509},{"type":415,"tag":559,"props":11959,"children":11960},{"class":561,"line":589},[11961],{"type":415,"tag":559,"props":11962,"children":11963},{"emptyLinePlaceholder":847},[11964],{"type":420,"value":850},{"type":415,"tag":559,"props":11966,"children":11967},{"class":561,"line":608},[11968,11972,11976,11981,11985,11990,11995,11999,12004,12009,12013,12017,12021,12026],{"type":415,"tag":559,"props":11969,"children":11970},{"style":566},[11971],{"type":420,"value":569},{"type":415,"tag":559,"props":11973,"children":11974},{"style":572},[11975],{"type":420,"value":5933},{"type":415,"tag":559,"props":11977,"children":11978},{"style":572},[11979],{"type":420,"value":11980}," WeatherForecast",{"type":415,"tag":559,"props":11982,"children":11983},{"style":583},[11984],{"type":420,"value":814},{"type":415,"tag":559,"props":11986,"children":11987},{"style":572},[11988],{"type":420,"value":11989},"DateOnly",{"type":415,"tag":559,"props":11991,"children":11992},{"style":572},[11993],{"type":420,"value":11994}," date",{"type":415,"tag":559,"props":11996,"children":11997},{"style":583},[11998],{"type":420,"value":2312},{"type":415,"tag":559,"props":12000,"children":12001},{"style":583},[12002],{"type":420,"value":12003}," int",{"type":415,"tag":559,"props":12005,"children":12006},{"style":572},[12007],{"type":420,"value":12008}," temperatureC",{"type":415,"tag":559,"props":12010,"children":12011},{"style":583},[12012],{"type":420,"value":2312},{"type":415,"tag":559,"props":12014,"children":12015},{"style":583},[12016],{"type":420,"value":1129},{"type":415,"tag":559,"props":12018,"children":12019},{"style":583},[12020],{"type":420,"value":1134},{"type":415,"tag":559,"props":12022,"children":12023},{"style":572},[12024],{"type":420,"value":12025}," summary",{"type":415,"tag":559,"props":12027,"children":12028},{"style":583},[12029],{"type":420,"value":833},{"type":415,"tag":559,"props":12031,"children":12032},{"class":561,"line":626},[12033],{"type":415,"tag":559,"props":12034,"children":12035},{"style":583},[12036],{"type":420,"value":786},{"type":415,"tag":559,"props":12038,"children":12039},{"class":561,"line":643},[12040,12044,12048,12053,12057,12061,12065,12070,12074,12078],{"type":415,"tag":559,"props":12041,"children":12042},{"style":566},[12043],{"type":420,"value":1124},{"type":415,"tag":559,"props":12045,"children":12046},{"style":583},[12047],{"type":420,"value":12003},{"type":415,"tag":559,"props":12049,"children":12050},{"style":572},[12051],{"type":420,"value":12052}," TemperatureC",{"type":415,"tag":559,"props":12054,"children":12055},{"style":583},[12056],{"type":420,"value":1144},{"type":415,"tag":559,"props":12058,"children":12059},{"style":572},[12060],{"type":420,"value":1149},{"type":415,"tag":559,"props":12062,"children":12063},{"style":583},[12064],{"type":420,"value":1154},{"type":415,"tag":559,"props":12066,"children":12067},{"style":583},[12068],{"type":420,"value":12069}," }",{"type":415,"tag":559,"props":12071,"children":12072},{"style":583},[12073],{"type":420,"value":763},{"type":415,"tag":559,"props":12075,"children":12076},{"style":792},[12077],{"type":420,"value":12008},{"type":415,"tag":559,"props":12079,"children":12080},{"style":583},[12081],{"type":420,"value":1509},{"type":415,"tag":559,"props":12083,"children":12084},{"class":561,"line":660},[12085],{"type":415,"tag":559,"props":12086,"children":12087},{"style":792},[12088],{"type":420,"value":6508},{"type":415,"tag":559,"props":12090,"children":12091},{"class":561,"line":677},[12092,12096,12100,12104,12108,12112,12116,12120,12124,12128],{"type":415,"tag":559,"props":12093,"children":12094},{"style":566},[12095],{"type":420,"value":1124},{"type":415,"tag":559,"props":12097,"children":12098},{"style":572},[12099],{"type":420,"value":10312},{"type":415,"tag":559,"props":12101,"children":12102},{"style":572},[12103],{"type":420,"value":619},{"type":415,"tag":559,"props":12105,"children":12106},{"style":583},[12107],{"type":420,"value":1144},{"type":415,"tag":559,"props":12109,"children":12110},{"style":572},[12111],{"type":420,"value":1149},{"type":415,"tag":559,"props":12113,"children":12114},{"style":583},[12115],{"type":420,"value":1154},{"type":415,"tag":559,"props":12117,"children":12118},{"style":583},[12119],{"type":420,"value":12069},{"type":415,"tag":559,"props":12121,"children":12122},{"style":583},[12123],{"type":420,"value":763},{"type":415,"tag":559,"props":12125,"children":12126},{"style":792},[12127],{"type":420,"value":11994},{"type":415,"tag":559,"props":12129,"children":12130},{"style":583},[12131],{"type":420,"value":1509},{"type":415,"tag":559,"props":12133,"children":12134},{"class":561,"line":690},[12135],{"type":415,"tag":559,"props":12136,"children":12137},{"style":792},[12138],{"type":420,"value":6508},{"type":415,"tag":559,"props":12140,"children":12141},{"class":561,"line":1089},[12142,12146,12150,12154,12159,12163,12167,12171,12175,12179,12183],{"type":415,"tag":559,"props":12143,"children":12144},{"style":566},[12145],{"type":420,"value":1124},{"type":415,"tag":559,"props":12147,"children":12148},{"style":583},[12149],{"type":420,"value":1129},{"type":415,"tag":559,"props":12151,"children":12152},{"style":583},[12153],{"type":420,"value":1134},{"type":415,"tag":559,"props":12155,"children":12156},{"style":572},[12157],{"type":420,"value":12158}," Summary",{"type":415,"tag":559,"props":12160,"children":12161},{"style":583},[12162],{"type":420,"value":1144},{"type":415,"tag":559,"props":12164,"children":12165},{"style":572},[12166],{"type":420,"value":1149},{"type":415,"tag":559,"props":12168,"children":12169},{"style":583},[12170],{"type":420,"value":1154},{"type":415,"tag":559,"props":12172,"children":12173},{"style":583},[12174],{"type":420,"value":12069},{"type":415,"tag":559,"props":12176,"children":12177},{"style":583},[12178],{"type":420,"value":763},{"type":415,"tag":559,"props":12180,"children":12181},{"style":792},[12182],{"type":420,"value":12025},{"type":415,"tag":559,"props":12184,"children":12185},{"style":583},[12186],{"type":420,"value":1509},{"type":415,"tag":559,"props":12188,"children":12189},{"class":561,"line":1102},[12190],{"type":415,"tag":559,"props":12191,"children":12192},{"style":792},[12193],{"type":420,"value":6508},{"type":415,"tag":559,"props":12195,"children":12196},{"class":561,"line":1110},[12197,12201,12205,12210,12214,12219,12224,12229,12234,12239,12244],{"type":415,"tag":559,"props":12198,"children":12199},{"style":566},[12200],{"type":420,"value":1124},{"type":415,"tag":559,"props":12202,"children":12203},{"style":583},[12204],{"type":420,"value":12003},{"type":415,"tag":559,"props":12206,"children":12207},{"style":572},[12208],{"type":420,"value":12209}," TemperatureF",{"type":415,"tag":559,"props":12211,"children":12212},{"style":583},[12213],{"type":420,"value":1861},{"type":415,"tag":559,"props":12215,"children":12216},{"style":2846},[12217],{"type":420,"value":12218}," 32",{"type":415,"tag":559,"props":12220,"children":12221},{"style":583},[12222],{"type":420,"value":12223}," +",{"type":415,"tag":559,"props":12225,"children":12226},{"style":583},[12227],{"type":420,"value":12228}," (int)(",{"type":415,"tag":559,"props":12230,"children":12231},{"style":792},[12232],{"type":420,"value":12233},"TemperatureC ",{"type":415,"tag":559,"props":12235,"children":12236},{"style":583},[12237],{"type":420,"value":12238},"/",{"type":415,"tag":559,"props":12240,"children":12241},{"style":2846},[12242],{"type":420,"value":12243}," 0.5556",{"type":415,"tag":559,"props":12245,"children":12246},{"style":583},[12247],{"type":420,"value":696},{"type":415,"tag":559,"props":12249,"children":12250},{"class":561,"line":1118},[12251],{"type":415,"tag":559,"props":12252,"children":12253},{"style":583},[12254],{"type":420,"value":1801},{"type":415,"tag":1178,"props":12256,"children":12257},{"icon":1180},[12258],{"type":415,"tag":416,"props":12259,"children":12260},{},[12261],{"type":420,"value":12262},"I'm not sure this is completely relevant here, a record would probably be better but you get the idea.",{"type":415,"tag":416,"props":12264,"children":12265},{},[12266,12268,12274],{"type":420,"value":12267},"You can use primary constructors in any class, it will work as well with dependency injection. However, be aware that the services you used to assign to a private read-only field of your class won't be read-only anymore like ",{"type":415,"tag":555,"props":12269,"children":12271},{"className":12270},[],[12272],{"type":420,"value":12273},"weatherService",{"type":420,"value":12275}," in this example:",{"type":415,"tag":549,"props":12277,"children":12279},{"className":551,"code":12278,"language":326,"meta":401,"style":401},"public class WeatherForecastController(IWeatherService weatherService, ILogger\u003CWeatherForecastController> logger) : ControllerBase\n{\n    [HttpGet(Name = \"GetWeatherForecast\")]\n    [ProducesResponseType(typeof(WeatherForecast), StatusCodes.Status200OK)]\n    public Task\u003CWeatherForecast[]> Get()\n    {\n        return weatherService.GetWeatherForecasts();\n    }\n}\n",[12280],{"type":415,"tag":555,"props":12281,"children":12282},{"__ignoreMap":401},[12283,12346,12353,12392,12431,12462,12469,12492,12499],{"type":415,"tag":559,"props":12284,"children":12285},{"class":561,"line":562},[12286,12290,12294,12298,12302,12306,12310,12314,12318,12322,12326,12330,12334,12338,12342],{"type":415,"tag":559,"props":12287,"children":12288},{"style":566},[12289],{"type":420,"value":569},{"type":415,"tag":559,"props":12291,"children":12292},{"style":572},[12293],{"type":420,"value":5933},{"type":415,"tag":559,"props":12295,"children":12296},{"style":572},[12297],{"type":420,"value":8864},{"type":415,"tag":559,"props":12299,"children":12300},{"style":583},[12301],{"type":420,"value":814},{"type":415,"tag":559,"props":12303,"children":12304},{"style":572},[12305],{"type":420,"value":8739},{"type":415,"tag":559,"props":12307,"children":12308},{"style":572},[12309],{"type":420,"value":8936},{"type":415,"tag":559,"props":12311,"children":12312},{"style":583},[12313],{"type":420,"value":2312},{"type":415,"tag":559,"props":12315,"children":12316},{"style":572},[12317],{"type":420,"value":5972},{"type":415,"tag":559,"props":12319,"children":12320},{"style":583},[12321],{"type":420,"value":891},{"type":415,"tag":559,"props":12323,"children":12324},{"style":572},[12325],{"type":420,"value":8787},{"type":415,"tag":559,"props":12327,"children":12328},{"style":583},[12329],{"type":420,"value":5985},{"type":415,"tag":559,"props":12331,"children":12332},{"style":572},[12333],{"type":420,"value":6063},{"type":415,"tag":559,"props":12335,"children":12336},{"style":583},[12337],{"type":420,"value":1468},{"type":415,"tag":559,"props":12339,"children":12340},{"style":583},[12341],{"type":420,"value":2437},{"type":415,"tag":559,"props":12343,"children":12344},{"style":572},[12345],{"type":420,"value":8873},{"type":415,"tag":559,"props":12347,"children":12348},{"class":561,"line":589},[12349],{"type":415,"tag":559,"props":12350,"children":12351},{"style":583},[12352],{"type":420,"value":786},{"type":415,"tag":559,"props":12354,"children":12355},{"class":561,"line":608},[12356,12360,12364,12368,12372,12376,12380,12384,12388],{"type":415,"tag":559,"props":12357,"children":12358},{"style":583},[12359],{"type":420,"value":8989},{"type":415,"tag":559,"props":12361,"children":12362},{"style":572},[12363],{"type":420,"value":8994},{"type":415,"tag":559,"props":12365,"children":12366},{"style":583},[12367],{"type":420,"value":814},{"type":415,"tag":559,"props":12369,"children":12370},{"style":572},[12371],{"type":420,"value":1412},{"type":415,"tag":559,"props":12373,"children":12374},{"style":583},[12375],{"type":420,"value":763},{"type":415,"tag":559,"props":12377,"children":12378},{"style":583},[12379],{"type":420,"value":1434},{"type":415,"tag":559,"props":12381,"children":12382},{"style":822},[12383],{"type":420,"value":9015},{"type":415,"tag":559,"props":12385,"children":12386},{"style":583},[12387],{"type":420,"value":819},{"type":415,"tag":559,"props":12389,"children":12390},{"style":583},[12391],{"type":420,"value":8848},{"type":415,"tag":559,"props":12393,"children":12394},{"class":561,"line":626},[12395,12399,12403,12407,12411,12415,12419,12423,12427],{"type":415,"tag":559,"props":12396,"children":12397},{"style":583},[12398],{"type":420,"value":8989},{"type":415,"tag":559,"props":12400,"children":12401},{"style":572},[12402],{"type":420,"value":9035},{"type":415,"tag":559,"props":12404,"children":12405},{"style":583},[12406],{"type":420,"value":9040},{"type":415,"tag":559,"props":12408,"children":12409},{"style":572},[12410],{"type":420,"value":9045},{"type":415,"tag":559,"props":12412,"children":12413},{"style":583},[12414],{"type":420,"value":9050},{"type":415,"tag":559,"props":12416,"children":12417},{"style":792},[12418],{"type":420,"value":9055},{"type":415,"tag":559,"props":12420,"children":12421},{"style":583},[12422],{"type":420,"value":542},{"type":415,"tag":559,"props":12424,"children":12425},{"style":792},[12426],{"type":420,"value":9064},{"type":415,"tag":559,"props":12428,"children":12429},{"style":583},[12430],{"type":420,"value":8848},{"type":415,"tag":559,"props":12432,"children":12433},{"class":561,"line":643},[12434,12438,12442,12446,12450,12454,12458],{"type":415,"tag":559,"props":12435,"children":12436},{"style":566},[12437],{"type":420,"value":1124},{"type":415,"tag":559,"props":12439,"children":12440},{"style":572},[12441],{"type":420,"value":2006},{"type":415,"tag":559,"props":12443,"children":12444},{"style":583},[12445],{"type":420,"value":891},{"type":415,"tag":559,"props":12447,"children":12448},{"style":572},[12449],{"type":420,"value":9045},{"type":415,"tag":559,"props":12451,"children":12452},{"style":583},[12453],{"type":420,"value":9092},{"type":415,"tag":559,"props":12455,"children":12456},{"style":883},[12457],{"type":420,"value":9097},{"type":415,"tag":559,"props":12459,"children":12460},{"style":583},[12461],{"type":420,"value":778},{"type":415,"tag":559,"props":12463,"children":12464},{"class":561,"line":660},[12465],{"type":415,"tag":559,"props":12466,"children":12467},{"style":583},[12468],{"type":420,"value":2737},{"type":415,"tag":559,"props":12470,"children":12471},{"class":561,"line":677},[12472,12476,12480,12484,12488],{"type":415,"tag":559,"props":12473,"children":12474},{"style":745},[12475],{"type":420,"value":8218},{"type":415,"tag":559,"props":12477,"children":12478},{"style":792},[12479],{"type":420,"value":8936},{"type":415,"tag":559,"props":12481,"children":12482},{"style":583},[12483],{"type":420,"value":542},{"type":415,"tag":559,"props":12485,"children":12486},{"style":883},[12487],{"type":420,"value":9128},{"type":415,"tag":559,"props":12489,"children":12490},{"style":583},[12491],{"type":420,"value":1962},{"type":415,"tag":559,"props":12493,"children":12494},{"class":561,"line":690},[12495],{"type":415,"tag":559,"props":12496,"children":12497},{"style":583},[12498],{"type":420,"value":2792},{"type":415,"tag":559,"props":12500,"children":12501},{"class":561,"line":1089},[12502],{"type":415,"tag":559,"props":12503,"children":12504},{"style":583},[12505],{"type":420,"value":1801},{"type":415,"tag":416,"props":12507,"children":12508},{},[12509,12511,12516,12518,12524,12526,12533],{"type":420,"value":12510},"Having 2 different implementations of the ",{"type":415,"tag":555,"props":12512,"children":12514},{"className":12513},[],[12515],{"type":420,"value":8739},{"type":420,"value":12517}," is great, but what if you need one of them in some part of your code? The one you will have injected in your class is the last one registered in the DI container, but that may not be the one you want. You could get all of them by injecting ",{"type":415,"tag":555,"props":12519,"children":12521},{"className":12520},[],[12522],{"type":420,"value":12523},"IEnumerable\u003CIWeatherService>",{"type":420,"value":12525}," and selecting the one you need. You could also create a sort of factory to retrieve the correct instance. Yet in .NET 8, you don't need to worry about all that because you have the ",{"type":415,"tag":434,"props":12527,"children":12530},{"href":12528,"rel":12529},"https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#keyed-di-services",[438],[12531],{"type":420,"value":12532},"keyed DI Services",{"type":420,"value":542},{"type":415,"tag":416,"props":12535,"children":12536},{},[12537],{"type":420,"value":12538},"Specifying a key (that can be anything, not necessarily a string) is done when registering the services in the DI container.",{"type":415,"tag":549,"props":12540,"children":12542},{"className":551,"code":12541,"language":326,"meta":401,"style":401},"builder.Services.AddKeyedTransient\u003CIWeatherService, RandomWeatherService>(\"random\");\nbuilder.Services.AddKeyedTransient\u003CIWeatherService, OpenWeatherService>(\"api\");\n",[12543],{"type":415,"tag":555,"props":12544,"children":12545},{"__ignoreMap":401},[12546,12608],{"type":415,"tag":559,"props":12547,"children":12548},{"class":561,"line":562},[12549,12553,12557,12561,12565,12570,12574,12578,12582,12587,12591,12595,12600,12604],{"type":415,"tag":559,"props":12550,"children":12551},{"style":792},[12552],{"type":420,"value":5671},{"type":415,"tag":559,"props":12554,"children":12555},{"style":583},[12556],{"type":420,"value":542},{"type":415,"tag":559,"props":12558,"children":12559},{"style":792},[12560],{"type":420,"value":5680},{"type":415,"tag":559,"props":12562,"children":12563},{"style":583},[12564],{"type":420,"value":542},{"type":415,"tag":559,"props":12566,"children":12567},{"style":883},[12568],{"type":420,"value":12569},"AddKeyedTransient",{"type":415,"tag":559,"props":12571,"children":12572},{"style":583},[12573],{"type":420,"value":891},{"type":415,"tag":559,"props":12575,"children":12576},{"style":572},[12577],{"type":420,"value":8739},{"type":415,"tag":559,"props":12579,"children":12580},{"style":583},[12581],{"type":420,"value":2312},{"type":415,"tag":559,"props":12583,"children":12584},{"style":572},[12585],{"type":420,"value":12586}," RandomWeatherService",{"type":415,"tag":559,"props":12588,"children":12589},{"style":583},[12590],{"type":420,"value":2680},{"type":415,"tag":559,"props":12592,"children":12593},{"style":583},[12594],{"type":420,"value":819},{"type":415,"tag":559,"props":12596,"children":12597},{"style":822},[12598],{"type":420,"value":12599},"random",{"type":415,"tag":559,"props":12601,"children":12602},{"style":583},[12603],{"type":420,"value":819},{"type":415,"tag":559,"props":12605,"children":12606},{"style":583},[12607],{"type":420,"value":696},{"type":415,"tag":559,"props":12609,"children":12610},{"class":561,"line":589},[12611,12615,12619,12623,12627,12631,12635,12639,12643,12647,12651,12655,12660,12664],{"type":415,"tag":559,"props":12612,"children":12613},{"style":792},[12614],{"type":420,"value":5671},{"type":415,"tag":559,"props":12616,"children":12617},{"style":583},[12618],{"type":420,"value":542},{"type":415,"tag":559,"props":12620,"children":12621},{"style":792},[12622],{"type":420,"value":5680},{"type":415,"tag":559,"props":12624,"children":12625},{"style":583},[12626],{"type":420,"value":542},{"type":415,"tag":559,"props":12628,"children":12629},{"style":883},[12630],{"type":420,"value":12569},{"type":415,"tag":559,"props":12632,"children":12633},{"style":583},[12634],{"type":420,"value":891},{"type":415,"tag":559,"props":12636,"children":12637},{"style":572},[12638],{"type":420,"value":8739},{"type":415,"tag":559,"props":12640,"children":12641},{"style":583},[12642],{"type":420,"value":2312},{"type":415,"tag":559,"props":12644,"children":12645},{"style":572},[12646],{"type":420,"value":9396},{"type":415,"tag":559,"props":12648,"children":12649},{"style":583},[12650],{"type":420,"value":2680},{"type":415,"tag":559,"props":12652,"children":12653},{"style":583},[12654],{"type":420,"value":819},{"type":415,"tag":559,"props":12656,"children":12657},{"style":822},[12658],{"type":420,"value":12659},"api",{"type":415,"tag":559,"props":12661,"children":12662},{"style":583},[12663],{"type":420,"value":819},{"type":415,"tag":559,"props":12665,"children":12666},{"style":583},[12667],{"type":420,"value":696},{"type":415,"tag":416,"props":12669,"children":12670},{},[12671],{"type":420,"value":12672},"With this key, retrieving a specific implementation becomes easy.",{"type":415,"tag":549,"props":12674,"children":12676},{"className":551,"code":12675,"language":326,"meta":401,"style":401},"    public WeatherForecastController([FromKeyedServices(\"random\")] IWeatherService weatherService, ILogger\u003CWeatherForecastController> logger)\n    {\n        _logger = logger;\n        _weatherService = weatherService;\n    }\n",[12677],{"type":415,"tag":555,"props":12678,"children":12679},{"__ignoreMap":401},[12680,12755,12762,12781,12800],{"type":415,"tag":559,"props":12681,"children":12682},{"class":561,"line":562},[12683,12687,12691,12696,12701,12705,12709,12713,12717,12722,12727,12731,12735,12739,12743,12747,12751],{"type":415,"tag":559,"props":12684,"children":12685},{"style":566},[12686],{"type":420,"value":1124},{"type":415,"tag":559,"props":12688,"children":12689},{"style":883},[12690],{"type":420,"value":8864},{"type":415,"tag":559,"props":12692,"children":12693},{"style":583},[12694],{"type":420,"value":12695},"([",{"type":415,"tag":559,"props":12697,"children":12698},{"style":883},[12699],{"type":420,"value":12700},"FromKeyedServices",{"type":415,"tag":559,"props":12702,"children":12703},{"style":583},[12704],{"type":420,"value":814},{"type":415,"tag":559,"props":12706,"children":12707},{"style":583},[12708],{"type":420,"value":819},{"type":415,"tag":559,"props":12710,"children":12711},{"style":822},[12712],{"type":420,"value":12599},{"type":415,"tag":559,"props":12714,"children":12715},{"style":583},[12716],{"type":420,"value":819},{"type":415,"tag":559,"props":12718,"children":12719},{"style":583},[12720],{"type":420,"value":12721},")]",{"type":415,"tag":559,"props":12723,"children":12724},{"style":792},[12725],{"type":420,"value":12726}," IWeatherService weatherService",{"type":415,"tag":559,"props":12728,"children":12729},{"style":583},[12730],{"type":420,"value":2312},{"type":415,"tag":559,"props":12732,"children":12733},{"style":792},[12734],{"type":420,"value":5972},{"type":415,"tag":559,"props":12736,"children":12737},{"style":583},[12738],{"type":420,"value":891},{"type":415,"tag":559,"props":12740,"children":12741},{"style":792},[12742],{"type":420,"value":8787},{"type":415,"tag":559,"props":12744,"children":12745},{"style":583},[12746],{"type":420,"value":5985},{"type":415,"tag":559,"props":12748,"children":12749},{"style":792},[12750],{"type":420,"value":6063},{"type":415,"tag":559,"props":12752,"children":12753},{"style":583},[12754],{"type":420,"value":833},{"type":415,"tag":559,"props":12756,"children":12757},{"class":561,"line":589},[12758],{"type":415,"tag":559,"props":12759,"children":12760},{"style":583},[12761],{"type":420,"value":2737},{"type":415,"tag":559,"props":12763,"children":12764},{"class":561,"line":608},[12765,12769,12773,12777],{"type":415,"tag":559,"props":12766,"children":12767},{"style":792},[12768],{"type":420,"value":6095},{"type":415,"tag":559,"props":12770,"children":12771},{"style":583},[12772],{"type":420,"value":800},{"type":415,"tag":559,"props":12774,"children":12775},{"style":792},[12776],{"type":420,"value":6063},{"type":415,"tag":559,"props":12778,"children":12779},{"style":583},[12780],{"type":420,"value":1509},{"type":415,"tag":559,"props":12782,"children":12783},{"class":561,"line":626},[12784,12788,12792,12796],{"type":415,"tag":559,"props":12785,"children":12786},{"style":792},[12787],{"type":420,"value":8955},{"type":415,"tag":559,"props":12789,"children":12790},{"style":583},[12791],{"type":420,"value":800},{"type":415,"tag":559,"props":12793,"children":12794},{"style":792},[12795],{"type":420,"value":8936},{"type":415,"tag":559,"props":12797,"children":12798},{"style":583},[12799],{"type":420,"value":1509},{"type":415,"tag":559,"props":12801,"children":12802},{"class":561,"line":643},[12803],{"type":415,"tag":559,"props":12804,"children":12805},{"style":583},[12806],{"type":420,"value":2792},{"type":415,"tag":416,"props":12808,"children":12809},{},[12810,12812,12819],{"type":420,"value":12811},"I did not discuss the code that requests the Open Weather Map API. It's quite simple thanks to the uses of ",{"type":415,"tag":434,"props":12813,"children":12816},{"href":12814,"rel":12815},"https://github.com/reactiveui/refit",[438],[12817],{"type":420,"value":12818},"Refit",{"type":420,"value":542},{"type":415,"tag":549,"props":12821,"children":12823},{"className":551,"code":12822,"language":326,"meta":401,"style":401},"using Refit;\n\nnamespace WeatherApi.Services.OpenWeatherMap;\n\npublic interface IOpenWeatherMapApi\n{\n    [Get(\"/forecast?lat={latitude}&lon={longitude}&units=metric\")]\n    Task\u003CWeatherMapResponse> GetWeatherForecast(double latitude, double longitude);\n}\n\npublic record WeatherMapResponse(IList\u003CWeatherMapForecast> List);\n\npublic record WeatherMapForecast(int Dt, WeatherMapMain Main);\n\npublic record WeatherMapMain(double Temp);\n",[12824],{"type":415,"tag":555,"props":12825,"children":12826},{"__ignoreMap":401},[12827,12843,12850,12882,12889,12906,12913,12946,12999,13006,13013,13060,13067,13111,13118],{"type":415,"tag":559,"props":12828,"children":12829},{"class":561,"line":562},[12830,12834,12839],{"type":415,"tag":559,"props":12831,"children":12832},{"style":2846},[12833],{"type":420,"value":748},{"type":415,"tag":559,"props":12835,"children":12836},{"style":792},[12837],{"type":420,"value":12838}," Refit",{"type":415,"tag":559,"props":12840,"children":12841},{"style":583},[12842],{"type":420,"value":1509},{"type":415,"tag":559,"props":12844,"children":12845},{"class":561,"line":589},[12846],{"type":415,"tag":559,"props":12847,"children":12848},{"emptyLinePlaceholder":847},[12849],{"type":420,"value":850},{"type":415,"tag":559,"props":12851,"children":12852},{"class":561,"line":608},[12853,12857,12861,12865,12869,12873,12878],{"type":415,"tag":559,"props":12854,"children":12855},{"style":572},[12856],{"type":420,"value":11948},{"type":415,"tag":559,"props":12858,"children":12859},{"style":792},[12860],{"type":420,"value":11953},{"type":415,"tag":559,"props":12862,"children":12863},{"style":583},[12864],{"type":420,"value":542},{"type":415,"tag":559,"props":12866,"children":12867},{"style":792},[12868],{"type":420,"value":5680},{"type":415,"tag":559,"props":12870,"children":12871},{"style":583},[12872],{"type":420,"value":542},{"type":415,"tag":559,"props":12874,"children":12875},{"style":792},[12876],{"type":420,"value":12877},"OpenWeatherMap",{"type":415,"tag":559,"props":12879,"children":12880},{"style":583},[12881],{"type":420,"value":1509},{"type":415,"tag":559,"props":12883,"children":12884},{"class":561,"line":626},[12885],{"type":415,"tag":559,"props":12886,"children":12887},{"emptyLinePlaceholder":847},[12888],{"type":420,"value":850},{"type":415,"tag":559,"props":12890,"children":12891},{"class":561,"line":643},[12892,12896,12901],{"type":415,"tag":559,"props":12893,"children":12894},{"style":566},[12895],{"type":420,"value":569},{"type":415,"tag":559,"props":12897,"children":12898},{"style":572},[12899],{"type":420,"value":12900}," interface",{"type":415,"tag":559,"props":12902,"children":12903},{"style":572},[12904],{"type":420,"value":12905}," IOpenWeatherMapApi\n",{"type":415,"tag":559,"props":12907,"children":12908},{"class":561,"line":660},[12909],{"type":415,"tag":559,"props":12910,"children":12911},{"style":583},[12912],{"type":420,"value":786},{"type":415,"tag":559,"props":12914,"children":12915},{"class":561,"line":677},[12916,12920,12925,12929,12933,12938,12942],{"type":415,"tag":559,"props":12917,"children":12918},{"style":583},[12919],{"type":420,"value":8989},{"type":415,"tag":559,"props":12921,"children":12922},{"style":572},[12923],{"type":420,"value":12924},"Get",{"type":415,"tag":559,"props":12926,"children":12927},{"style":583},[12928],{"type":420,"value":814},{"type":415,"tag":559,"props":12930,"children":12931},{"style":583},[12932],{"type":420,"value":819},{"type":415,"tag":559,"props":12934,"children":12935},{"style":822},[12936],{"type":420,"value":12937},"/forecast?lat={latitude}&lon={longitude}&units=metric",{"type":415,"tag":559,"props":12939,"children":12940},{"style":583},[12941],{"type":420,"value":819},{"type":415,"tag":559,"props":12943,"children":12944},{"style":583},[12945],{"type":420,"value":8848},{"type":415,"tag":559,"props":12947,"children":12948},{"class":561,"line":690},[12949,12954,12958,12963,12967,12972,12977,12982,12986,12990,12995],{"type":415,"tag":559,"props":12950,"children":12951},{"style":572},[12952],{"type":420,"value":12953},"    Task",{"type":415,"tag":559,"props":12955,"children":12956},{"style":583},[12957],{"type":420,"value":891},{"type":415,"tag":559,"props":12959,"children":12960},{"style":572},[12961],{"type":420,"value":12962},"WeatherMapResponse",{"type":415,"tag":559,"props":12964,"children":12965},{"style":583},[12966],{"type":420,"value":5985},{"type":415,"tag":559,"props":12968,"children":12969},{"style":883},[12970],{"type":420,"value":12971}," GetWeatherForecast",{"type":415,"tag":559,"props":12973,"children":12974},{"style":583},[12975],{"type":420,"value":12976},"(double",{"type":415,"tag":559,"props":12978,"children":12979},{"style":572},[12980],{"type":420,"value":12981}," latitude",{"type":415,"tag":559,"props":12983,"children":12984},{"style":583},[12985],{"type":420,"value":2312},{"type":415,"tag":559,"props":12987,"children":12988},{"style":583},[12989],{"type":420,"value":9472},{"type":415,"tag":559,"props":12991,"children":12992},{"style":572},[12993],{"type":420,"value":12994}," longitude",{"type":415,"tag":559,"props":12996,"children":12997},{"style":583},[12998],{"type":420,"value":696},{"type":415,"tag":559,"props":13000,"children":13001},{"class":561,"line":1089},[13002],{"type":415,"tag":559,"props":13003,"children":13004},{"style":583},[13005],{"type":420,"value":1801},{"type":415,"tag":559,"props":13007,"children":13008},{"class":561,"line":1102},[13009],{"type":415,"tag":559,"props":13010,"children":13011},{"emptyLinePlaceholder":847},[13012],{"type":420,"value":850},{"type":415,"tag":559,"props":13014,"children":13015},{"class":561,"line":1110},[13016,13020,13024,13029,13033,13038,13042,13047,13051,13056],{"type":415,"tag":559,"props":13017,"children":13018},{"style":566},[13019],{"type":420,"value":569},{"type":415,"tag":559,"props":13021,"children":13022},{"style":572},[13023],{"type":420,"value":575},{"type":415,"tag":559,"props":13025,"children":13026},{"style":572},[13027],{"type":420,"value":13028}," WeatherMapResponse",{"type":415,"tag":559,"props":13030,"children":13031},{"style":583},[13032],{"type":420,"value":814},{"type":415,"tag":559,"props":13034,"children":13035},{"style":572},[13036],{"type":420,"value":13037},"IList",{"type":415,"tag":559,"props":13039,"children":13040},{"style":583},[13041],{"type":420,"value":891},{"type":415,"tag":559,"props":13043,"children":13044},{"style":572},[13045],{"type":420,"value":13046},"WeatherMapForecast",{"type":415,"tag":559,"props":13048,"children":13049},{"style":583},[13050],{"type":420,"value":5985},{"type":415,"tag":559,"props":13052,"children":13053},{"style":572},[13054],{"type":420,"value":13055}," List",{"type":415,"tag":559,"props":13057,"children":13058},{"style":583},[13059],{"type":420,"value":696},{"type":415,"tag":559,"props":13061,"children":13062},{"class":561,"line":1118},[13063],{"type":415,"tag":559,"props":13064,"children":13065},{"emptyLinePlaceholder":847},[13066],{"type":420,"value":850},{"type":415,"tag":559,"props":13068,"children":13069},{"class":561,"line":1171},[13070,13074,13078,13083,13088,13093,13097,13102,13107],{"type":415,"tag":559,"props":13071,"children":13072},{"style":566},[13073],{"type":420,"value":569},{"type":415,"tag":559,"props":13075,"children":13076},{"style":572},[13077],{"type":420,"value":575},{"type":415,"tag":559,"props":13079,"children":13080},{"style":572},[13081],{"type":420,"value":13082}," WeatherMapForecast",{"type":415,"tag":559,"props":13084,"children":13085},{"style":583},[13086],{"type":420,"value":13087},"(int",{"type":415,"tag":559,"props":13089,"children":13090},{"style":572},[13091],{"type":420,"value":13092}," Dt",{"type":415,"tag":559,"props":13094,"children":13095},{"style":583},[13096],{"type":420,"value":2312},{"type":415,"tag":559,"props":13098,"children":13099},{"style":572},[13100],{"type":420,"value":13101}," WeatherMapMain",{"type":415,"tag":559,"props":13103,"children":13104},{"style":572},[13105],{"type":420,"value":13106}," Main",{"type":415,"tag":559,"props":13108,"children":13109},{"style":583},[13110],{"type":420,"value":696},{"type":415,"tag":559,"props":13112,"children":13113},{"class":561,"line":1748},[13114],{"type":415,"tag":559,"props":13115,"children":13116},{"emptyLinePlaceholder":847},[13117],{"type":420,"value":850},{"type":415,"tag":559,"props":13119,"children":13120},{"class":561,"line":1769},[13121,13125,13129,13133,13137,13142],{"type":415,"tag":559,"props":13122,"children":13123},{"style":566},[13124],{"type":420,"value":569},{"type":415,"tag":559,"props":13126,"children":13127},{"style":572},[13128],{"type":420,"value":575},{"type":415,"tag":559,"props":13130,"children":13131},{"style":572},[13132],{"type":420,"value":13101},{"type":415,"tag":559,"props":13134,"children":13135},{"style":583},[13136],{"type":420,"value":12976},{"type":415,"tag":559,"props":13138,"children":13139},{"style":572},[13140],{"type":420,"value":13141}," Temp",{"type":415,"tag":559,"props":13143,"children":13144},{"style":583},[13145],{"type":420,"value":696},{"type":415,"tag":416,"props":13147,"children":13148},{},[13149,13151,13157],{"type":420,"value":13150},"I created an HTTP Message Handler to take care of adding the Open Weather Map API key to the requests. This API key and the URL to the API come from the configuration and are mapped to a configuration object ",{"type":415,"tag":555,"props":13152,"children":13154},{"className":13153},[],[13155],{"type":420,"value":13156},"WeatherMapConfiguration",{"type":420,"value":542},{"type":415,"tag":416,"props":13159,"children":13160},{},[13161,13163,13170,13172,13179],{"type":420,"value":13162},"In .NET 8, we can use ",{"type":415,"tag":434,"props":13164,"children":13167},{"href":13165,"rel":13166},"https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#data-validation",[438],[13168],{"type":420,"value":13169},"data validation attributes",{"type":420,"value":13171}," for data like configuration options. There is also a ",{"type":415,"tag":434,"props":13173,"children":13176},{"href":13174,"rel":13175},"https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#options-validation",[438],[13177],{"type":420,"value":13178},"source code generator",{"type":420,"value":13180}," that can implement the validation logic:",{"type":415,"tag":549,"props":13182,"children":13184},{"className":551,"code":13183,"language":326,"meta":401,"style":401},"namespace WeatherApi.Services.OpenWeatherMap;\n\npublic class WeatherMapConfiguration\n{\n    [Required]\n    public required string ApiKey { get; init; }\n\n    [Required]\n    [Url]\n    public required string Uri { get; init; }\n    \n}\n\n[OptionsValidator]\npublic partial class WeatherMapConfigurationValidator : IValidateOptions\u003CWeatherMapConfiguration>\n{\n}\n",[13185],{"type":415,"tag":555,"props":13186,"children":13187},{"__ignoreMap":401},[13188,13219,13226,13242,13249,13265,13311,13318,13333,13348,13391,13398,13405,13412,13428,13471,13478],{"type":415,"tag":559,"props":13189,"children":13190},{"class":561,"line":562},[13191,13195,13199,13203,13207,13211,13215],{"type":415,"tag":559,"props":13192,"children":13193},{"style":572},[13194],{"type":420,"value":11948},{"type":415,"tag":559,"props":13196,"children":13197},{"style":792},[13198],{"type":420,"value":11953},{"type":415,"tag":559,"props":13200,"children":13201},{"style":583},[13202],{"type":420,"value":542},{"type":415,"tag":559,"props":13204,"children":13205},{"style":792},[13206],{"type":420,"value":5680},{"type":415,"tag":559,"props":13208,"children":13209},{"style":583},[13210],{"type":420,"value":542},{"type":415,"tag":559,"props":13212,"children":13213},{"style":792},[13214],{"type":420,"value":12877},{"type":415,"tag":559,"props":13216,"children":13217},{"style":583},[13218],{"type":420,"value":1509},{"type":415,"tag":559,"props":13220,"children":13221},{"class":561,"line":589},[13222],{"type":415,"tag":559,"props":13223,"children":13224},{"emptyLinePlaceholder":847},[13225],{"type":420,"value":850},{"type":415,"tag":559,"props":13227,"children":13228},{"class":561,"line":608},[13229,13233,13237],{"type":415,"tag":559,"props":13230,"children":13231},{"style":566},[13232],{"type":420,"value":569},{"type":415,"tag":559,"props":13234,"children":13235},{"style":572},[13236],{"type":420,"value":5933},{"type":415,"tag":559,"props":13238,"children":13239},{"style":572},[13240],{"type":420,"value":13241}," WeatherMapConfiguration\n",{"type":415,"tag":559,"props":13243,"children":13244},{"class":561,"line":626},[13245],{"type":415,"tag":559,"props":13246,"children":13247},{"style":583},[13248],{"type":420,"value":786},{"type":415,"tag":559,"props":13250,"children":13251},{"class":561,"line":643},[13252,13256,13261],{"type":415,"tag":559,"props":13253,"children":13254},{"style":583},[13255],{"type":420,"value":8989},{"type":415,"tag":559,"props":13257,"children":13258},{"style":572},[13259],{"type":420,"value":13260},"Required",{"type":415,"tag":559,"props":13262,"children":13263},{"style":583},[13264],{"type":420,"value":8814},{"type":415,"tag":559,"props":13266,"children":13267},{"class":561,"line":660},[13268,13272,13277,13281,13286,13290,13294,13298,13303,13307],{"type":415,"tag":559,"props":13269,"children":13270},{"style":566},[13271],{"type":420,"value":1124},{"type":415,"tag":559,"props":13273,"children":13274},{"style":566},[13275],{"type":420,"value":13276}," required",{"type":415,"tag":559,"props":13278,"children":13279},{"style":583},[13280],{"type":420,"value":1129},{"type":415,"tag":559,"props":13282,"children":13283},{"style":572},[13284],{"type":420,"value":13285}," ApiKey",{"type":415,"tag":559,"props":13287,"children":13288},{"style":583},[13289],{"type":420,"value":1144},{"type":415,"tag":559,"props":13291,"children":13292},{"style":572},[13293],{"type":420,"value":1149},{"type":415,"tag":559,"props":13295,"children":13296},{"style":583},[13297],{"type":420,"value":1154},{"type":415,"tag":559,"props":13299,"children":13300},{"style":572},[13301],{"type":420,"value":13302}," init",{"type":415,"tag":559,"props":13304,"children":13305},{"style":583},[13306],{"type":420,"value":1154},{"type":415,"tag":559,"props":13308,"children":13309},{"style":583},[13310],{"type":420,"value":1168},{"type":415,"tag":559,"props":13312,"children":13313},{"class":561,"line":677},[13314],{"type":415,"tag":559,"props":13315,"children":13316},{"emptyLinePlaceholder":847},[13317],{"type":420,"value":850},{"type":415,"tag":559,"props":13319,"children":13320},{"class":561,"line":690},[13321,13325,13329],{"type":415,"tag":559,"props":13322,"children":13323},{"style":583},[13324],{"type":420,"value":8989},{"type":415,"tag":559,"props":13326,"children":13327},{"style":572},[13328],{"type":420,"value":13260},{"type":415,"tag":559,"props":13330,"children":13331},{"style":583},[13332],{"type":420,"value":8814},{"type":415,"tag":559,"props":13334,"children":13335},{"class":561,"line":1089},[13336,13340,13344],{"type":415,"tag":559,"props":13337,"children":13338},{"style":583},[13339],{"type":420,"value":8989},{"type":415,"tag":559,"props":13341,"children":13342},{"style":572},[13343],{"type":420,"value":3342},{"type":415,"tag":559,"props":13345,"children":13346},{"style":583},[13347],{"type":420,"value":8814},{"type":415,"tag":559,"props":13349,"children":13350},{"class":561,"line":1102},[13351,13355,13359,13363,13367,13371,13375,13379,13383,13387],{"type":415,"tag":559,"props":13352,"children":13353},{"style":566},[13354],{"type":420,"value":1124},{"type":415,"tag":559,"props":13356,"children":13357},{"style":566},[13358],{"type":420,"value":13276},{"type":415,"tag":559,"props":13360,"children":13361},{"style":583},[13362],{"type":420,"value":1129},{"type":415,"tag":559,"props":13364,"children":13365},{"style":572},[13366],{"type":420,"value":809},{"type":415,"tag":559,"props":13368,"children":13369},{"style":583},[13370],{"type":420,"value":1144},{"type":415,"tag":559,"props":13372,"children":13373},{"style":572},[13374],{"type":420,"value":1149},{"type":415,"tag":559,"props":13376,"children":13377},{"style":583},[13378],{"type":420,"value":1154},{"type":415,"tag":559,"props":13380,"children":13381},{"style":572},[13382],{"type":420,"value":13302},{"type":415,"tag":559,"props":13384,"children":13385},{"style":583},[13386],{"type":420,"value":1154},{"type":415,"tag":559,"props":13388,"children":13389},{"style":583},[13390],{"type":420,"value":1168},{"type":415,"tag":559,"props":13392,"children":13393},{"class":561,"line":1110},[13394],{"type":415,"tag":559,"props":13395,"children":13396},{"style":792},[13397],{"type":420,"value":6508},{"type":415,"tag":559,"props":13399,"children":13400},{"class":561,"line":1118},[13401],{"type":415,"tag":559,"props":13402,"children":13403},{"style":583},[13404],{"type":420,"value":1801},{"type":415,"tag":559,"props":13406,"children":13407},{"class":561,"line":1171},[13408],{"type":415,"tag":559,"props":13409,"children":13410},{"emptyLinePlaceholder":847},[13411],{"type":420,"value":850},{"type":415,"tag":559,"props":13413,"children":13414},{"class":561,"line":1748},[13415,13419,13424],{"type":415,"tag":559,"props":13416,"children":13417},{"style":583},[13418],{"type":420,"value":8804},{"type":415,"tag":559,"props":13420,"children":13421},{"style":572},[13422],{"type":420,"value":13423},"OptionsValidator",{"type":415,"tag":559,"props":13425,"children":13426},{"style":583},[13427],{"type":420,"value":8814},{"type":415,"tag":559,"props":13429,"children":13430},{"class":561,"line":1769},[13431,13435,13440,13444,13449,13453,13458,13462,13466],{"type":415,"tag":559,"props":13432,"children":13433},{"style":566},[13434],{"type":420,"value":569},{"type":415,"tag":559,"props":13436,"children":13437},{"style":566},[13438],{"type":420,"value":13439}," partial",{"type":415,"tag":559,"props":13441,"children":13442},{"style":572},[13443],{"type":420,"value":5933},{"type":415,"tag":559,"props":13445,"children":13446},{"style":572},[13447],{"type":420,"value":13448}," WeatherMapConfigurationValidator",{"type":415,"tag":559,"props":13450,"children":13451},{"style":583},[13452],{"type":420,"value":2437},{"type":415,"tag":559,"props":13454,"children":13455},{"style":572},[13456],{"type":420,"value":13457}," IValidateOptions",{"type":415,"tag":559,"props":13459,"children":13460},{"style":583},[13461],{"type":420,"value":891},{"type":415,"tag":559,"props":13463,"children":13464},{"style":572},[13465],{"type":420,"value":13156},{"type":415,"tag":559,"props":13467,"children":13468},{"style":583},[13469],{"type":420,"value":13470},">\n",{"type":415,"tag":559,"props":13472,"children":13473},{"class":561,"line":1786},[13474],{"type":415,"tag":559,"props":13475,"children":13476},{"style":583},[13477],{"type":420,"value":786},{"type":415,"tag":559,"props":13479,"children":13480},{"class":561,"line":1795},[13481],{"type":415,"tag":559,"props":13482,"children":13483},{"style":583},[13484],{"type":420,"value":1801},{"type":415,"tag":416,"props":13486,"children":13487},{},[13488,13490,13495,13497,13502],{"type":420,"value":13489},"This way we can make sure that the configuration contains the API Key and the URI that has the ",{"type":415,"tag":555,"props":13491,"children":13493},{"className":13492},[],[13494],{"type":420,"value":3342},{"type":420,"value":13496}," format. The configuration in the ",{"type":415,"tag":555,"props":13498,"children":13500},{"className":13499},[],[13501],{"type":420,"value":2831},{"type":420,"value":13503}," looks like that:",{"type":415,"tag":549,"props":13505,"children":13507},{"className":551,"code":13506,"language":326,"meta":401,"style":401},"builder.Services.Configure\u003CWeatherMapConfiguration>(builder.Configuration.GetSection(\"WeatherMap\"));\nbuilder.Services.AddSingleton\u003CIValidateOptions\u003CWeatherMapConfiguration>, WeatherMapConfigurationValidator>();\n\nbuilder.Services.AddTransient\u003CApiKeyHandler>();\nbuilder.Services.AddRefitClient\u003CIOpenWeatherMapApi>()\n    .ConfigureHttpClient((provider, client) =>\n    {\n        var configuration = provider.GetRequiredService\u003CIOptions\u003CWeatherMapConfiguration>>().Value;\n        client.BaseAddress = new Uri(configuration.Uri);\n    })\n    .AddHttpMessageHandler\u003CApiKeyHandler>();\n",[13508],{"type":415,"tag":555,"props":13509,"children":13510},{"__ignoreMap":401},[13511,13588,13642,13649,13686,13723,13762,13769,13826,13876,13884],{"type":415,"tag":559,"props":13512,"children":13513},{"class":561,"line":562},[13514,13518,13522,13526,13530,13535,13539,13543,13547,13551,13555,13559,13563,13567,13571,13575,13580,13584],{"type":415,"tag":559,"props":13515,"children":13516},{"style":792},[13517],{"type":420,"value":5671},{"type":415,"tag":559,"props":13519,"children":13520},{"style":583},[13521],{"type":420,"value":542},{"type":415,"tag":559,"props":13523,"children":13524},{"style":792},[13525],{"type":420,"value":5680},{"type":415,"tag":559,"props":13527,"children":13528},{"style":583},[13529],{"type":420,"value":542},{"type":415,"tag":559,"props":13531,"children":13532},{"style":883},[13533],{"type":420,"value":13534},"Configure",{"type":415,"tag":559,"props":13536,"children":13537},{"style":583},[13538],{"type":420,"value":891},{"type":415,"tag":559,"props":13540,"children":13541},{"style":572},[13542],{"type":420,"value":13156},{"type":415,"tag":559,"props":13544,"children":13545},{"style":583},[13546],{"type":420,"value":2680},{"type":415,"tag":559,"props":13548,"children":13549},{"style":792},[13550],{"type":420,"value":5671},{"type":415,"tag":559,"props":13552,"children":13553},{"style":583},[13554],{"type":420,"value":542},{"type":415,"tag":559,"props":13556,"children":13557},{"style":792},[13558],{"type":420,"value":263},{"type":415,"tag":559,"props":13560,"children":13561},{"style":583},[13562],{"type":420,"value":542},{"type":415,"tag":559,"props":13564,"children":13565},{"style":883},[13566],{"type":420,"value":7561},{"type":415,"tag":559,"props":13568,"children":13569},{"style":583},[13570],{"type":420,"value":814},{"type":415,"tag":559,"props":13572,"children":13573},{"style":583},[13574],{"type":420,"value":819},{"type":415,"tag":559,"props":13576,"children":13577},{"style":822},[13578],{"type":420,"value":13579},"WeatherMap",{"type":415,"tag":559,"props":13581,"children":13582},{"style":583},[13583],{"type":420,"value":819},{"type":415,"tag":559,"props":13585,"children":13586},{"style":583},[13587],{"type":420,"value":5796},{"type":415,"tag":559,"props":13589,"children":13590},{"class":561,"line":589},[13591,13595,13599,13603,13607,13612,13616,13621,13625,13629,13634,13638],{"type":415,"tag":559,"props":13592,"children":13593},{"style":792},[13594],{"type":420,"value":5671},{"type":415,"tag":559,"props":13596,"children":13597},{"style":583},[13598],{"type":420,"value":542},{"type":415,"tag":559,"props":13600,"children":13601},{"style":792},[13602],{"type":420,"value":5680},{"type":415,"tag":559,"props":13604,"children":13605},{"style":583},[13606],{"type":420,"value":542},{"type":415,"tag":559,"props":13608,"children":13609},{"style":883},[13610],{"type":420,"value":13611},"AddSingleton",{"type":415,"tag":559,"props":13613,"children":13614},{"style":583},[13615],{"type":420,"value":891},{"type":415,"tag":559,"props":13617,"children":13618},{"style":572},[13619],{"type":420,"value":13620},"IValidateOptions",{"type":415,"tag":559,"props":13622,"children":13623},{"style":583},[13624],{"type":420,"value":891},{"type":415,"tag":559,"props":13626,"children":13627},{"style":572},[13628],{"type":420,"value":13156},{"type":415,"tag":559,"props":13630,"children":13631},{"style":583},[13632],{"type":420,"value":13633},">,",{"type":415,"tag":559,"props":13635,"children":13636},{"style":572},[13637],{"type":420,"value":13448},{"type":415,"tag":559,"props":13639,"children":13640},{"style":583},[13641],{"type":420,"value":5703},{"type":415,"tag":559,"props":13643,"children":13644},{"class":561,"line":608},[13645],{"type":415,"tag":559,"props":13646,"children":13647},{"emptyLinePlaceholder":847},[13648],{"type":420,"value":850},{"type":415,"tag":559,"props":13650,"children":13651},{"class":561,"line":626},[13652,13656,13660,13664,13668,13673,13677,13682],{"type":415,"tag":559,"props":13653,"children":13654},{"style":792},[13655],{"type":420,"value":5671},{"type":415,"tag":559,"props":13657,"children":13658},{"style":583},[13659],{"type":420,"value":542},{"type":415,"tag":559,"props":13661,"children":13662},{"style":792},[13663],{"type":420,"value":5680},{"type":415,"tag":559,"props":13665,"children":13666},{"style":583},[13667],{"type":420,"value":542},{"type":415,"tag":559,"props":13669,"children":13670},{"style":883},[13671],{"type":420,"value":13672},"AddTransient",{"type":415,"tag":559,"props":13674,"children":13675},{"style":583},[13676],{"type":420,"value":891},{"type":415,"tag":559,"props":13678,"children":13679},{"style":572},[13680],{"type":420,"value":13681},"ApiKeyHandler",{"type":415,"tag":559,"props":13683,"children":13684},{"style":583},[13685],{"type":420,"value":5703},{"type":415,"tag":559,"props":13687,"children":13688},{"class":561,"line":643},[13689,13693,13697,13701,13705,13710,13714,13718],{"type":415,"tag":559,"props":13690,"children":13691},{"style":792},[13692],{"type":420,"value":5671},{"type":415,"tag":559,"props":13694,"children":13695},{"style":583},[13696],{"type":420,"value":542},{"type":415,"tag":559,"props":13698,"children":13699},{"style":792},[13700],{"type":420,"value":5680},{"type":415,"tag":559,"props":13702,"children":13703},{"style":583},[13704],{"type":420,"value":542},{"type":415,"tag":559,"props":13706,"children":13707},{"style":883},[13708],{"type":420,"value":13709},"AddRefitClient",{"type":415,"tag":559,"props":13711,"children":13712},{"style":583},[13713],{"type":420,"value":891},{"type":415,"tag":559,"props":13715,"children":13716},{"style":572},[13717],{"type":420,"value":9543},{"type":415,"tag":559,"props":13719,"children":13720},{"style":583},[13721],{"type":420,"value":13722},">()\n",{"type":415,"tag":559,"props":13724,"children":13725},{"class":561,"line":660},[13726,13730,13735,13740,13745,13749,13754,13758],{"type":415,"tag":559,"props":13727,"children":13728},{"style":583},[13729],{"type":420,"value":1842},{"type":415,"tag":559,"props":13731,"children":13732},{"style":883},[13733],{"type":420,"value":13734},"ConfigureHttpClient",{"type":415,"tag":559,"props":13736,"children":13737},{"style":583},[13738],{"type":420,"value":13739},"((",{"type":415,"tag":559,"props":13741,"children":13742},{"style":572},[13743],{"type":420,"value":13744},"provider",{"type":415,"tag":559,"props":13746,"children":13747},{"style":583},[13748],{"type":420,"value":2312},{"type":415,"tag":559,"props":13750,"children":13751},{"style":572},[13752],{"type":420,"value":13753}," client",{"type":415,"tag":559,"props":13755,"children":13756},{"style":583},[13757],{"type":420,"value":1468},{"type":415,"tag":559,"props":13759,"children":13760},{"style":583},[13761],{"type":420,"value":5741},{"type":415,"tag":559,"props":13763,"children":13764},{"class":561,"line":677},[13765],{"type":415,"tag":559,"props":13766,"children":13767},{"style":583},[13768],{"type":420,"value":2737},{"type":415,"tag":559,"props":13770,"children":13771},{"class":561,"line":690},[13772,13776,13781,13785,13790,13794,13798,13802,13806,13810,13814,13818,13822],{"type":415,"tag":559,"props":13773,"children":13774},{"style":572},[13775],{"type":420,"value":2745},{"type":415,"tag":559,"props":13777,"children":13778},{"style":572},[13779],{"type":420,"value":13780}," configuration",{"type":415,"tag":559,"props":13782,"children":13783},{"style":583},[13784],{"type":420,"value":763},{"type":415,"tag":559,"props":13786,"children":13787},{"style":792},[13788],{"type":420,"value":13789}," provider",{"type":415,"tag":559,"props":13791,"children":13792},{"style":583},[13793],{"type":420,"value":542},{"type":415,"tag":559,"props":13795,"children":13796},{"style":883},[13797],{"type":420,"value":8179},{"type":415,"tag":559,"props":13799,"children":13800},{"style":583},[13801],{"type":420,"value":891},{"type":415,"tag":559,"props":13803,"children":13804},{"style":572},[13805],{"type":420,"value":8188},{"type":415,"tag":559,"props":13807,"children":13808},{"style":583},[13809],{"type":420,"value":891},{"type":415,"tag":559,"props":13811,"children":13812},{"style":572},[13813],{"type":420,"value":13156},{"type":415,"tag":559,"props":13815,"children":13816},{"style":583},[13817],{"type":420,"value":8201},{"type":415,"tag":559,"props":13819,"children":13820},{"style":792},[13821],{"type":420,"value":8206},{"type":415,"tag":559,"props":13823,"children":13824},{"style":583},[13825],{"type":420,"value":1509},{"type":415,"tag":559,"props":13827,"children":13828},{"class":561,"line":1089},[13829,13834,13838,13843,13847,13851,13855,13859,13863,13867,13872],{"type":415,"tag":559,"props":13830,"children":13831},{"style":792},[13832],{"type":420,"value":13833},"        client",{"type":415,"tag":559,"props":13835,"children":13836},{"style":583},[13837],{"type":420,"value":542},{"type":415,"tag":559,"props":13839,"children":13840},{"style":792},[13841],{"type":420,"value":13842},"BaseAddress ",{"type":415,"tag":559,"props":13844,"children":13845},{"style":583},[13846],{"type":420,"value":800},{"type":415,"tag":559,"props":13848,"children":13849},{"style":583},[13850],{"type":420,"value":768},{"type":415,"tag":559,"props":13852,"children":13853},{"style":572},[13854],{"type":420,"value":809},{"type":415,"tag":559,"props":13856,"children":13857},{"style":583},[13858],{"type":420,"value":814},{"type":415,"tag":559,"props":13860,"children":13861},{"style":792},[13862],{"type":420,"value":262},{"type":415,"tag":559,"props":13864,"children":13865},{"style":583},[13866],{"type":420,"value":542},{"type":415,"tag":559,"props":13868,"children":13869},{"style":792},[13870],{"type":420,"value":13871},"Uri",{"type":415,"tag":559,"props":13873,"children":13874},{"style":583},[13875],{"type":420,"value":696},{"type":415,"tag":559,"props":13877,"children":13878},{"class":561,"line":1102},[13879],{"type":415,"tag":559,"props":13880,"children":13881},{"style":583},[13882],{"type":420,"value":13883},"    })\n",{"type":415,"tag":559,"props":13885,"children":13886},{"class":561,"line":1110},[13887,13891,13896,13900,13904],{"type":415,"tag":559,"props":13888,"children":13889},{"style":583},[13890],{"type":420,"value":1842},{"type":415,"tag":559,"props":13892,"children":13893},{"style":883},[13894],{"type":420,"value":13895},"AddHttpMessageHandler",{"type":415,"tag":559,"props":13897,"children":13898},{"style":583},[13899],{"type":420,"value":891},{"type":415,"tag":559,"props":13901,"children":13902},{"style":572},[13903],{"type":420,"value":13681},{"type":415,"tag":559,"props":13905,"children":13906},{"style":583},[13907],{"type":420,"value":5703},{"type":415,"tag":422,"props":13909,"children":13911},{"id":13910},"a-few-closing-words",[13912],{"type":420,"value":13913},"A few closing words",{"type":415,"tag":416,"props":13915,"children":13916},{},[13917],{"type":420,"value":13918},"Here is the recap of what we talked about:",{"type":420,"value":13920},"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",{"type":415,"tag":13922,"props":13923,"children":13924},"table",{},[13925,13944],{"type":415,"tag":13926,"props":13927,"children":13928},"thead",{},[13929],{"type":415,"tag":13930,"props":13931,"children":13932},"tr",{},[13933,13939],{"type":415,"tag":13934,"props":13935,"children":13936},"th",{},[13937],{"type":420,"value":13938},"Feature",{"type":415,"tag":13934,"props":13940,"children":13941},{},[13942],{"type":420,"value":13943},"Area",{"type":415,"tag":13945,"props":13946,"children":13947},"tbody",{},[13948,13966,13984,14000,14016,14033,14051,14067],{"type":415,"tag":13930,"props":13949,"children":13950},{},[13951,13961],{"type":415,"tag":13952,"props":13953,"children":13954},"td",{},[13955],{"type":415,"tag":434,"props":13956,"children":13958},{"href":9162,"rel":13957},[438],[13959],{"type":420,"value":13960},"Support for generic attributes",{"type":415,"tag":13952,"props":13962,"children":13963},{},[13964],{"type":420,"value":13965},".NET 8",{"type":415,"tag":13930,"props":13967,"children":13968},{},[13969,13979],{"type":415,"tag":13952,"props":13970,"children":13971},{},[13972],{"type":415,"tag":434,"props":13973,"children":13976},{"href":13974,"rel":13975},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#primary-constructors",[438],[13977],{"type":420,"value":13978},"Primary constructors",{"type":415,"tag":13952,"props":13980,"children":13981},{},[13982],{"type":420,"value":13983},"C# 12",{"type":415,"tag":13930,"props":13985,"children":13986},{},[13987,13996],{"type":415,"tag":13952,"props":13988,"children":13989},{},[13990],{"type":415,"tag":434,"props":13991,"children":13993},{"href":11440,"rel":13992},[438],[13994],{"type":420,"value":13995},"Collection expressions",{"type":415,"tag":13952,"props":13997,"children":13998},{},[13999],{"type":420,"value":13983},{"type":415,"tag":13930,"props":14001,"children":14002},{},[14003,14012],{"type":415,"tag":13952,"props":14004,"children":14005},{},[14006],{"type":415,"tag":434,"props":14007,"children":14009},{"href":10682,"rel":14008},[438],[14010],{"type":420,"value":14011},"Optional parameters in lambda expressions",{"type":415,"tag":13952,"props":14013,"children":14014},{},[14015],{"type":420,"value":13983},{"type":415,"tag":13930,"props":14017,"children":14018},{},[14019,14029],{"type":415,"tag":13952,"props":14020,"children":14021},{},[14022],{"type":415,"tag":434,"props":14023,"children":14026},{"href":14024,"rel":14025},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#alias-any-type",[438],[14027],{"type":420,"value":14028},"Alias any type",{"type":415,"tag":13952,"props":14030,"children":14031},{},[14032],{"type":420,"value":13983},{"type":415,"tag":13930,"props":14034,"children":14035},{},[14036,14046],{"type":415,"tag":13952,"props":14037,"children":14038},{},[14039],{"type":415,"tag":434,"props":14040,"children":14043},{"href":14041,"rel":14042},"https://learn.microsoft.com/en-us/visualstudio/debugger/using-the-debuggerdisplay-attribute",[438],[14044],{"type":420,"value":14045},"Debug customization attributes on ASP.NET Core types      ",{"type":415,"tag":13952,"props":14047,"children":14048},{},[14049],{"type":420,"value":14050},"ASP.NET Core 8",{"type":415,"tag":13930,"props":14052,"children":14053},{},[14054,14063],{"type":415,"tag":13952,"props":14055,"children":14056},{},[14057],{"type":415,"tag":434,"props":14058,"children":14060},{"href":13174,"rel":14059},[438],[14061],{"type":420,"value":14062},"Options validation",{"type":415,"tag":13952,"props":14064,"children":14065},{},[14066],{"type":420,"value":13965},{"type":415,"tag":13930,"props":14068,"children":14069},{},[14070,14079],{"type":415,"tag":13952,"props":14071,"children":14072},{},[14073],{"type":415,"tag":434,"props":14074,"children":14076},{"href":12528,"rel":14075},[438],[14077],{"type":420,"value":14078},"Keyed DI Services",{"type":415,"tag":13952,"props":14080,"children":14081},{},[14082],{"type":420,"value":13965},{"type":415,"tag":416,"props":14084,"children":14085},{},[14086,14088,14094,14096,14101,14103,14109],{"type":420,"value":14087},"There are many more interesting features in ",{"type":415,"tag":434,"props":14089,"children":14092},{"href":14090,"rel":14091},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12",[438],[14093],{"type":420,"value":13983},{"type":420,"value":14095},", ",{"type":415,"tag":434,"props":14097,"children":14099},{"href":12528,"rel":14098},[438],[14100],{"type":420,"value":13965},{"type":420,"value":14102},", or ",{"type":415,"tag":434,"props":14104,"children":14107},{"href":14105,"rel":14106},"https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0",[438],[14108],{"type":420,"value":14050},{"type":420,"value":14110},". Yet, the ones I introduced in this article are the ones I will probably use the most.",{"type":415,"tag":416,"props":14112,"children":14113},{},[14114,14116,14122,14124,14130],{"type":420,"value":14115},"You can find the complete code sample ",{"type":415,"tag":434,"props":14117,"children":14120},{"href":14118,"rel":14119},"https://github.com/TechWatching/CodeAppAndInfraInDotnet8",[438],[14121],{"type":420,"value":540},{"type":420,"value":14123},". The repository also contains a folder ",{"type":415,"tag":555,"props":14125,"children":14127},{"className":14126},[],[14128],{"type":420,"value":14129},"infra",{"type":420,"value":14131}," to set up the Azure infrastructure to host this API. 2 IaC solutions that use .NET are shown: one using Azure SDK and one using Pulumi.",{"type":415,"tag":416,"props":14133,"children":14134},{},[14135,14137,14144],{"type":420,"value":14136},"This article was published as part of the ",{"type":415,"tag":434,"props":14138,"children":14141},{"href":14139,"rel":14140},"https://www.csadvent.christmas/",[438],[14142],{"type":420,"value":14143},"C# Advent 2023",{"type":420,"value":14145}," which is a nice initiative. Make sure to check the other blog articles on the advent calendar.",{"type":415,"tag":5406,"props":14147,"children":14148},{},[14149],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":14151},[14152,14153,14154],{"id":8444,"depth":589,"text":8447},{"id":8712,"depth":589,"text":8715},{"id":13910,"depth":589,"text":13913},"content:1.posts:56.playing-with-dotnet8.md","1.posts/56.playing-with-dotnet8.md",{"_path":169,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":168,"description":14158,"lead":14159,"date":14160,"image":14161,"badge":14163,"tags":14164,"body":14165,"_type":5421,"_id":18350,"_source":5423,"_file":18351,"_extension":5425},"If you are deploying your application to Azure from Azure Pipelines, you might want to leverage the ability to do so without using secrets thanks to Workload identity federation. In this article, I will demonstrate how to automate the configuration of your Azure DevOps project, with everything pre-configured to securely deploy applications to Azure.","Azure DevOps Workload identity federation (OIDC) with Pulumi","2023-09-21T00:00:00.000Z",{"src":14162},"/images/azuredevopsoidc.webp",{"label":266},[228,233,307,374,312,315,376,239],{"type":412,"children":14166,"toc":18337},[14167,14171,14177,14191,14204,14209,14230,14239,14257,14269,14274,14286,14291,14296,14304,14313,14318,14323,14333,14339,14346,14351,14414,14426,14485,14490,14529,14534,14579,14585,14590,14628,14642,14678,14702,14707,15058,15063,15077,15187,15192,15457,15496,15502,15516,15804,15817,15972,15977,15999,16215,16221,16226,16244,16249,16725,16740,16745,17062,17075,17081,17086,17099,17336,17341,17595,17600,17871,17876,18061,18066,18225,18238,18269,18278,18283,18289,18302,18307,18312,18317,18333],{"type":415,"tag":416,"props":14168,"children":14169},{},[14170],{"type":420,"value":14158},{"type":415,"tag":422,"props":14172,"children":14174},{"id":14173},"why-should-you-use-workload-identity-federation-for-your-deployment-pipelines",[14175],{"type":420,"value":14176},"Why should you use Workload Identity Federation for your deployment pipelines?",{"type":415,"tag":416,"props":14178,"children":14179},{},[14180,14182,14189],{"type":420,"value":14181},"I already wrote about the ",{"type":415,"tag":434,"props":14183,"children":14186},{"href":14184,"rel":14185},"https://www.techwatching.dev/posts/azure-ready-github-repository#the-problem-with-secret-credentials",[438],[14187],{"type":420,"value":14188},"problem of secret credentials",{"type":420,"value":14190},", but let me remind you 2 reasons why I think you should always avoid using secrets in your deployment pipelines:",{"type":415,"tag":5376,"props":14192,"children":14193},{},[14194,14199],{"type":415,"tag":5380,"props":14195,"children":14196},{},[14197],{"type":420,"value":14198},"It's more secure if you don't need a secret to authenticate to Azure",{"type":415,"tag":5380,"props":14200,"children":14201},{},[14202],{"type":420,"value":14203},"It's more practical if you don't need to handle secret rotation when secrets expire",{"type":415,"tag":416,"props":14205,"children":14206},{},[14207],{"type":420,"value":14208},"This is true whatever the CI/CD platform you are using.",{"type":415,"tag":416,"props":14210,"children":14211},{},[14212,14219,14221,14228],{"type":415,"tag":434,"props":14213,"children":14216},{"href":14214,"rel":14215},"https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation",[438],[14217],{"type":420,"value":14218},"Workload identity federation",{"type":420,"value":14220}," leverages OpenID Connect to solve these problems and avoid using secrets in your pipelines to authenticate to Azure. I previously published ",{"type":415,"tag":434,"props":14222,"children":14225},{"href":14223,"rel":14224},"https://www.techwatching.dev/posts/azure-ready-github-repository",[438],[14226],{"type":420,"value":14227},"an article about using Azure OpenID Connect with Pulumi in GitHub Actions",{"type":420,"value":14229},", but that also works with Azure Pipelines.",{"type":415,"tag":416,"props":14231,"children":14232},{},[14233],{"type":415,"tag":934,"props":14234,"children":14238},{"alt":14235,"className":14236,"src":14237},"Workload Identity Federation for Azure DevOps",[938,8504],"/posts/images/azuredevopsoidc_schema_1.webp",[],{"type":415,"tag":1178,"props":14240,"children":14242},{"icon":14241},"i-heroicons-information-circle",[14243],{"type":415,"tag":416,"props":14244,"children":14245},{},[14246,14248,14255],{"type":420,"value":14247},"Microsoft has announced the ",{"type":415,"tag":434,"props":14249,"children":14252},{"href":14250,"rel":14251},"https://devblogs.microsoft.com/devops/public-preview-of-workload-identity-federation-for-azure-pipelines/",[438],[14253],{"type":420,"value":14254},"public preview of Workload identity federation for Azure Pipelines",{"type":420,"value":14256}," on the 11th September 2023.",{"type":415,"tag":422,"props":14258,"children":14260},{"id":14259},"how-can-you-use-workload-identity-federation-to-deploy-to-azure-from-azure-pipelines",[14261,14263],{"type":420,"value":14262},"How can you use ",{"type":415,"tag":14264,"props":14265,"children":14266},"strong",{},[14267],{"type":420,"value":14268},"Workload Identity Federation to deploy to Azure from Azure Pipelines?",{"type":415,"tag":416,"props":14270,"children":14271},{},[14272],{"type":420,"value":14273},"Azure Pipelines tasks use service connections to authenticate with external services. Specifically, for Azure, it is necessary to create an Azure Resource Manager service connection.",{"type":415,"tag":416,"props":14275,"children":14276},{},[14277,14279,14285],{"type":420,"value":14278},"You can create an Azure Resource Manager service connection that uses workload identity federation by configuring it in your Azure DevOps organization portal (check the documentation ",{"type":415,"tag":434,"props":14280,"children":14283},{"href":14281,"rel":14282},"https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops#create-an-azure-resource-manager-service-connection-using-workload-identity-federation",[438],[14284],{"type":420,"value":540},{"type":420,"value":1439},{"type":415,"tag":416,"props":14287,"children":14288},{},[14289],{"type":420,"value":14290},"Or ... you can automate that using Infrastructure as Code 😉.",{"type":415,"tag":416,"props":14292,"children":14293},{},[14294],{"type":420,"value":14295},"Yet, who wants to manually configure things from a wizard when everything can be automated in versioned code? So let's go the IaC way.",{"type":415,"tag":1178,"props":14297,"children":14298},{"icon":1180},[14299],{"type":415,"tag":416,"props":14300,"children":14301},{},[14302],{"type":420,"value":14303},"All kidding aside, I genuinely believe that there are many advantages to provisioning your Azure DevOps projects and their associated resources (Repos, Service Connections, policies, pipelines, ...) using Infrastructure as Code. It takes time to properly configure Azure DevOps projects, and if they are often organized similarly, it's more efficient to automate their configuration rather than doing it manually.",{"type":415,"tag":416,"props":14305,"children":14306},{},[14307],{"type":415,"tag":934,"props":14308,"children":14312},{"alt":14309,"className":14310,"src":14311},"Diagram to deploy from Azure Pipelines to Azure",[938,8504],"/posts/images/azuredevopsoidc_schema_2.webp",[],{"type":415,"tag":416,"props":14314,"children":14315},{},[14316],{"type":420,"value":14317},"I will use Pulumi and its Azure DevOps provider to provision the necessary resources. The infrastructure as code will be written in C# but you could easily convert the C# code to any language that Pulumi supports (like TypeScript, I am a big fan of using TypeScript to write infrastructure code 🔥).",{"type":415,"tag":416,"props":14319,"children":14320},{},[14321],{"type":420,"value":14322},"Here is the complete solution to implement:",{"type":415,"tag":416,"props":14324,"children":14325},{},[14326],{"type":415,"tag":934,"props":14327,"children":14332},{"alt":14328,"className":14329,"src":14330,"width":14331},"Schema of the complete solution",[938,8504],"/posts/images/azuredevopsoidc_schema_3.webp",1000,[],{"type":415,"tag":422,"props":14334,"children":14336},{"id":14335},"automate-the-configuration-of-workload-identity-federation-in-azure-devops",[14337],{"type":420,"value":14338},"Automate the configuration of Workload identity federation in Azure DevOps",{"type":415,"tag":14340,"props":14341,"children":14343},"h3",{"id":14342},"create-the-pulumi-net-project",[14344],{"type":420,"value":14345},"Create the Pulumi .NET project",{"type":415,"tag":416,"props":14347,"children":14348},{},[14349],{"type":420,"value":14350},"Let's start by scaffolding a new Pulumi project using .NET:",{"type":415,"tag":549,"props":14352,"children":14356},{"className":14353,"code":14354,"language":14355,"meta":401,"style":401},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pulumi new csharp -n AzureDevOpsWorkloadIdentity -s dev -d \"A program to set up an Azure-Ready Azure DevOps repository\"\n","bash",[14357],{"type":415,"tag":555,"props":14358,"children":14359},{"__ignoreMap":401},[14360],{"type":415,"tag":559,"props":14361,"children":14362},{"class":561,"line":562},[14363,14367,14371,14376,14381,14386,14391,14396,14401,14405,14410],{"type":415,"tag":559,"props":14364,"children":14365},{"style":572},[14366],{"type":420,"value":311},{"type":415,"tag":559,"props":14368,"children":14369},{"style":822},[14370],{"type":420,"value":768},{"type":415,"tag":559,"props":14372,"children":14373},{"style":822},[14374],{"type":420,"value":14375}," csharp",{"type":415,"tag":559,"props":14377,"children":14378},{"style":822},[14379],{"type":420,"value":14380}," -n",{"type":415,"tag":559,"props":14382,"children":14383},{"style":822},[14384],{"type":420,"value":14385}," AzureDevOpsWorkloadIdentity",{"type":415,"tag":559,"props":14387,"children":14388},{"style":822},[14389],{"type":420,"value":14390}," -s",{"type":415,"tag":559,"props":14392,"children":14393},{"style":822},[14394],{"type":420,"value":14395}," dev",{"type":415,"tag":559,"props":14397,"children":14398},{"style":822},[14399],{"type":420,"value":14400}," -d",{"type":415,"tag":559,"props":14402,"children":14403},{"style":583},[14404],{"type":420,"value":1434},{"type":415,"tag":559,"props":14406,"children":14407},{"style":822},[14408],{"type":420,"value":14409},"A program to set up an Azure-Ready Azure DevOps repository",{"type":415,"tag":559,"props":14411,"children":14412},{"style":583},[14413],{"type":420,"value":10222},{"type":415,"tag":416,"props":14415,"children":14416},{},[14417,14419,14424],{"type":420,"value":14418},"This command creates a new pulumi project and stack from the ",{"type":415,"tag":555,"props":14420,"children":14422},{"className":14421},[],[14423],{"type":420,"value":326},{"type":420,"value":14425}," template:",{"type":415,"tag":5376,"props":14427,"children":14428},{},[14429,14450,14467],{"type":415,"tag":5380,"props":14430,"children":14431},{},[14432,14434,14440,14442,14448],{"type":420,"value":14433},"The name of the project \"",{"type":415,"tag":14435,"props":14436,"children":14437},"em",{},[14438],{"type":420,"value":14439},"AzureDevOpsWorkloadIdentity",{"type":420,"value":14441},"\" is specified using the ",{"type":415,"tag":555,"props":14443,"children":14445},{"className":14444},[],[14446],{"type":420,"value":14447},"-n",{"type":420,"value":14449}," option",{"type":415,"tag":5380,"props":14451,"children":14452},{},[14453,14455,14459,14460,14466],{"type":420,"value":14454},"The description of the project \"",{"type":415,"tag":14435,"props":14456,"children":14457},{},[14458],{"type":420,"value":14409},{"type":420,"value":14441},{"type":415,"tag":555,"props":14461,"children":14463},{"className":14462},[],[14464],{"type":420,"value":14465},"-d",{"type":420,"value":14449},{"type":415,"tag":5380,"props":14468,"children":14469},{},[14470,14472,14477,14478,14484],{"type":420,"value":14471},"The stack of the project \"",{"type":415,"tag":14435,"props":14473,"children":14474},{},[14475],{"type":420,"value":14476},"dev",{"type":420,"value":14441},{"type":415,"tag":555,"props":14479,"children":14481},{"className":14480},[],[14482],{"type":420,"value":14483},"-s",{"type":420,"value":14449},{"type":415,"tag":416,"props":14486,"children":14487},{},[14488],{"type":420,"value":14489},"This project will need 3 different providers:",{"type":415,"tag":5376,"props":14491,"children":14492},{},[14493,14505,14518],{"type":415,"tag":5380,"props":14494,"children":14495},{},[14496,14498],{"type":420,"value":14497},"the ",{"type":415,"tag":434,"props":14499,"children":14502},{"href":14500,"rel":14501},"https://www.pulumi.com/registry/packages/azure-native/",[438],[14503],{"type":420,"value":14504},"Azure Native provider",{"type":415,"tag":5380,"props":14506,"children":14507},{},[14508,14509,14516],{"type":420,"value":14497},{"type":415,"tag":434,"props":14510,"children":14513},{"href":14511,"rel":14512},"https://www.pulumi.com/registry/packages/azuread/",[438],[14514],{"type":420,"value":14515},"Azure Active Directory provider",{"type":420,"value":14517}," (provider for Microsoft Entra ID)",{"type":415,"tag":5380,"props":14519,"children":14520},{},[14521,14522],{"type":420,"value":14497},{"type":415,"tag":434,"props":14523,"children":14526},{"href":14524,"rel":14525},"https://www.pulumi.com/registry/packages/azuredevops/",[438],[14527],{"type":420,"value":14528},"Azure DevOps provider",{"type":415,"tag":416,"props":14530,"children":14531},{},[14532],{"type":420,"value":14533},"So we can add the following Nuget packages to our project:",{"type":415,"tag":5376,"props":14535,"children":14536},{},[14537,14551,14565],{"type":415,"tag":5380,"props":14538,"children":14539},{},[14540],{"type":415,"tag":434,"props":14541,"children":14544},{"href":14542,"rel":14543},"https://www.nuget.org/packages/Pulumi.AzureNative",[438],[14545],{"type":415,"tag":555,"props":14546,"children":14548},{"className":14547},[],[14549],{"type":420,"value":14550},"Pulumi.AzureNative",{"type":415,"tag":5380,"props":14552,"children":14553},{},[14554],{"type":415,"tag":434,"props":14555,"children":14558},{"href":14556,"rel":14557},"https://www.nuget.org/packages/Pulumi.AzureAD",[438],[14559],{"type":415,"tag":555,"props":14560,"children":14562},{"className":14561},[],[14563],{"type":420,"value":14564},"Pulumi.AzureAD",{"type":415,"tag":5380,"props":14566,"children":14567},{},[14568],{"type":415,"tag":434,"props":14569,"children":14572},{"href":14570,"rel":14571},"https://www.nuget.org/packages/Pulumi.AzureDevOps",[438],[14573],{"type":415,"tag":555,"props":14574,"children":14576},{"className":14575},[],[14577],{"type":420,"value":14578},"Pulumi.AzureDevOps",{"type":415,"tag":14340,"props":14580,"children":14582},{"id":14581},"create-the-azure-devops-project",[14583],{"type":420,"value":14584},"Create the Azure DevOps project",{"type":415,"tag":416,"props":14586,"children":14587},{},[14588],{"type":420,"value":14589},"First, we must select the Azure DevOps organization where we wish to create a project and set its URL in our Pulumi configuration.",{"type":415,"tag":549,"props":14591,"children":14593},{"className":14353,"code":14592,"language":14355,"meta":401,"style":401},"pulumi config set azuredevops:orgServiceUrl XXXXXXXXXXXXXX --secret\n",[14594],{"type":415,"tag":555,"props":14595,"children":14596},{"__ignoreMap":401},[14597],{"type":415,"tag":559,"props":14598,"children":14599},{"class":561,"line":562},[14600,14604,14609,14613,14618,14623],{"type":415,"tag":559,"props":14601,"children":14602},{"style":572},[14603],{"type":420,"value":311},{"type":415,"tag":559,"props":14605,"children":14606},{"style":822},[14607],{"type":420,"value":14608}," config",{"type":415,"tag":559,"props":14610,"children":14611},{"style":822},[14612],{"type":420,"value":1159},{"type":415,"tag":559,"props":14614,"children":14615},{"style":822},[14616],{"type":420,"value":14617}," azuredevops:orgServiceUrl",{"type":415,"tag":559,"props":14619,"children":14620},{"style":822},[14621],{"type":420,"value":14622}," XXXXXXXXXXXXXX",{"type":415,"tag":559,"props":14624,"children":14625},{"style":822},[14626],{"type":420,"value":14627}," --secret\n",{"type":415,"tag":416,"props":14629,"children":14630},{},[14631,14633,14640],{"type":420,"value":14632},"Second, we need to supply the necessary Azure DevOps credentials. For that, we can ",{"type":415,"tag":434,"props":14634,"children":14637},{"href":14635,"rel":14636},"https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows#create-a-pat",[438],[14638],{"type":420,"value":14639},"create a personal access token",{"type":420,"value":14641}," and add it to our Pulumi configuration.",{"type":415,"tag":549,"props":14643,"children":14645},{"className":14353,"code":14644,"language":14355,"meta":401,"style":401},"pulumi config set azuredevops:personalAccessToken YYYYYYYYYYYYYY --secret\n",[14646],{"type":415,"tag":555,"props":14647,"children":14648},{"__ignoreMap":401},[14649],{"type":415,"tag":559,"props":14650,"children":14651},{"class":561,"line":562},[14652,14656,14660,14664,14669,14674],{"type":415,"tag":559,"props":14653,"children":14654},{"style":572},[14655],{"type":420,"value":311},{"type":415,"tag":559,"props":14657,"children":14658},{"style":822},[14659],{"type":420,"value":14608},{"type":415,"tag":559,"props":14661,"children":14662},{"style":822},[14663],{"type":420,"value":1159},{"type":415,"tag":559,"props":14665,"children":14666},{"style":822},[14667],{"type":420,"value":14668}," azuredevops:personalAccessToken",{"type":415,"tag":559,"props":14670,"children":14671},{"style":822},[14672],{"type":420,"value":14673}," YYYYYYYYYYYYYY",{"type":415,"tag":559,"props":14675,"children":14676},{"style":822},[14677],{"type":420,"value":14627},{"type":415,"tag":1178,"props":14679,"children":14681},{"icon":14680},"i-fluent-emoji-flat-locked-with-key",[14682],{"type":415,"tag":416,"props":14683,"children":14684},{},[14685,14687,14693,14695,14700],{"type":420,"value":14686},"I followed the documentation but to be honest, I don't think it's necessary to include the ",{"type":415,"tag":555,"props":14688,"children":14690},{"className":14689},[],[14691],{"type":420,"value":14692},"--secret",{"type":420,"value":14694}," option for the organization URL as it's not really a sensitive value that needs to be encrypted. However, ",{"type":415,"tag":14264,"props":14696,"children":14697},{},[14698],{"type":420,"value":14699},"it's mandatory to include it for the access token",{"type":420,"value":14701}," so that we can safely commit the configuration files without creating security risks.",{"type":415,"tag":416,"props":14703,"children":14704},{},[14705],{"type":420,"value":14706},"Third, we can create the DevOps project:",{"type":415,"tag":549,"props":14708,"children":14710},{"className":551,"code":14709,"language":326,"meta":401,"style":401},"var project = new Project(\"AzureReadyADOProject\", new()\n{\n    Description = \"New project with everything correctly configured to provision Azure resources or deploy applications to Azure\",\n    Features = new()\n    {\n        [\"boards\"] = \"disabled\",\n        [\"repositories\"] = \"enabled\",\n        [\"pipelines\"] = \"enabled\",\n        [\"testplans\"] = \"disabled\",\n        [\"artifacts\"] = \"disabled\"\n    },\n});\n",[14711],{"type":415,"tag":555,"props":14712,"children":14713},{"__ignoreMap":401},[14714,14765,14772,14801,14817,14824,14871,14916,14959,15003,15043,15051],{"type":415,"tag":559,"props":14715,"children":14716},{"class":561,"line":562},[14717,14721,14726,14730,14734,14739,14743,14747,14752,14756,14760],{"type":415,"tag":559,"props":14718,"children":14719},{"style":572},[14720],{"type":420,"value":858},{"type":415,"tag":559,"props":14722,"children":14723},{"style":572},[14724],{"type":420,"value":14725}," project",{"type":415,"tag":559,"props":14727,"children":14728},{"style":583},[14729],{"type":420,"value":763},{"type":415,"tag":559,"props":14731,"children":14732},{"style":583},[14733],{"type":420,"value":768},{"type":415,"tag":559,"props":14735,"children":14736},{"style":572},[14737],{"type":420,"value":14738}," Project",{"type":415,"tag":559,"props":14740,"children":14741},{"style":583},[14742],{"type":420,"value":814},{"type":415,"tag":559,"props":14744,"children":14745},{"style":583},[14746],{"type":420,"value":819},{"type":415,"tag":559,"props":14748,"children":14749},{"style":822},[14750],{"type":420,"value":14751},"AzureReadyADOProject",{"type":415,"tag":559,"props":14753,"children":14754},{"style":583},[14755],{"type":420,"value":819},{"type":415,"tag":559,"props":14757,"children":14758},{"style":583},[14759],{"type":420,"value":2312},{"type":415,"tag":559,"props":14761,"children":14762},{"style":583},[14763],{"type":420,"value":14764}," new()\n",{"type":415,"tag":559,"props":14766,"children":14767},{"class":561,"line":589},[14768],{"type":415,"tag":559,"props":14769,"children":14770},{"style":583},[14771],{"type":420,"value":786},{"type":415,"tag":559,"props":14773,"children":14774},{"class":561,"line":608},[14775,14780,14784,14788,14793,14797],{"type":415,"tag":559,"props":14776,"children":14777},{"style":792},[14778],{"type":420,"value":14779},"    Description ",{"type":415,"tag":559,"props":14781,"children":14782},{"style":583},[14783],{"type":420,"value":800},{"type":415,"tag":559,"props":14785,"children":14786},{"style":583},[14787],{"type":420,"value":1434},{"type":415,"tag":559,"props":14789,"children":14790},{"style":822},[14791],{"type":420,"value":14792},"New project with everything correctly configured to provision Azure resources or deploy applications to Azure",{"type":415,"tag":559,"props":14794,"children":14795},{"style":583},[14796],{"type":420,"value":819},{"type":415,"tag":559,"props":14798,"children":14799},{"style":583},[14800],{"type":420,"value":605},{"type":415,"tag":559,"props":14802,"children":14803},{"class":561,"line":626},[14804,14809,14813],{"type":415,"tag":559,"props":14805,"children":14806},{"style":792},[14807],{"type":420,"value":14808},"    Features ",{"type":415,"tag":559,"props":14810,"children":14811},{"style":583},[14812],{"type":420,"value":800},{"type":415,"tag":559,"props":14814,"children":14815},{"style":583},[14816],{"type":420,"value":14764},{"type":415,"tag":559,"props":14818,"children":14819},{"class":561,"line":643},[14820],{"type":415,"tag":559,"props":14821,"children":14822},{"style":583},[14823],{"type":420,"value":2737},{"type":415,"tag":559,"props":14825,"children":14826},{"class":561,"line":660},[14827,14832,14836,14841,14845,14850,14854,14858,14863,14867],{"type":415,"tag":559,"props":14828,"children":14829},{"style":583},[14830],{"type":420,"value":14831},"        [",{"type":415,"tag":559,"props":14833,"children":14834},{"style":583},[14835],{"type":420,"value":819},{"type":415,"tag":559,"props":14837,"children":14838},{"style":822},[14839],{"type":420,"value":14840},"boards",{"type":415,"tag":559,"props":14842,"children":14843},{"style":583},[14844],{"type":420,"value":819},{"type":415,"tag":559,"props":14846,"children":14847},{"style":583},[14848],{"type":420,"value":14849},"]",{"type":415,"tag":559,"props":14851,"children":14852},{"style":583},[14853],{"type":420,"value":763},{"type":415,"tag":559,"props":14855,"children":14856},{"style":583},[14857],{"type":420,"value":1434},{"type":415,"tag":559,"props":14859,"children":14860},{"style":822},[14861],{"type":420,"value":14862},"disabled",{"type":415,"tag":559,"props":14864,"children":14865},{"style":583},[14866],{"type":420,"value":819},{"type":415,"tag":559,"props":14868,"children":14869},{"style":583},[14870],{"type":420,"value":605},{"type":415,"tag":559,"props":14872,"children":14873},{"class":561,"line":677},[14874,14878,14882,14887,14891,14895,14899,14903,14908,14912],{"type":415,"tag":559,"props":14875,"children":14876},{"style":583},[14877],{"type":420,"value":14831},{"type":415,"tag":559,"props":14879,"children":14880},{"style":583},[14881],{"type":420,"value":819},{"type":415,"tag":559,"props":14883,"children":14884},{"style":822},[14885],{"type":420,"value":14886},"repositories",{"type":415,"tag":559,"props":14888,"children":14889},{"style":583},[14890],{"type":420,"value":819},{"type":415,"tag":559,"props":14892,"children":14893},{"style":583},[14894],{"type":420,"value":14849},{"type":415,"tag":559,"props":14896,"children":14897},{"style":583},[14898],{"type":420,"value":763},{"type":415,"tag":559,"props":14900,"children":14901},{"style":583},[14902],{"type":420,"value":1434},{"type":415,"tag":559,"props":14904,"children":14905},{"style":822},[14906],{"type":420,"value":14907},"enabled",{"type":415,"tag":559,"props":14909,"children":14910},{"style":583},[14911],{"type":420,"value":819},{"type":415,"tag":559,"props":14913,"children":14914},{"style":583},[14915],{"type":420,"value":605},{"type":415,"tag":559,"props":14917,"children":14918},{"class":561,"line":690},[14919,14923,14927,14931,14935,14939,14943,14947,14951,14955],{"type":415,"tag":559,"props":14920,"children":14921},{"style":583},[14922],{"type":420,"value":14831},{"type":415,"tag":559,"props":14924,"children":14925},{"style":583},[14926],{"type":420,"value":819},{"type":415,"tag":559,"props":14928,"children":14929},{"style":822},[14930],{"type":420,"value":367},{"type":415,"tag":559,"props":14932,"children":14933},{"style":583},[14934],{"type":420,"value":819},{"type":415,"tag":559,"props":14936,"children":14937},{"style":583},[14938],{"type":420,"value":14849},{"type":415,"tag":559,"props":14940,"children":14941},{"style":583},[14942],{"type":420,"value":763},{"type":415,"tag":559,"props":14944,"children":14945},{"style":583},[14946],{"type":420,"value":1434},{"type":415,"tag":559,"props":14948,"children":14949},{"style":822},[14950],{"type":420,"value":14907},{"type":415,"tag":559,"props":14952,"children":14953},{"style":583},[14954],{"type":420,"value":819},{"type":415,"tag":559,"props":14956,"children":14957},{"style":583},[14958],{"type":420,"value":605},{"type":415,"tag":559,"props":14960,"children":14961},{"class":561,"line":1089},[14962,14966,14970,14975,14979,14983,14987,14991,14995,14999],{"type":415,"tag":559,"props":14963,"children":14964},{"style":583},[14965],{"type":420,"value":14831},{"type":415,"tag":559,"props":14967,"children":14968},{"style":583},[14969],{"type":420,"value":819},{"type":415,"tag":559,"props":14971,"children":14972},{"style":822},[14973],{"type":420,"value":14974},"testplans",{"type":415,"tag":559,"props":14976,"children":14977},{"style":583},[14978],{"type":420,"value":819},{"type":415,"tag":559,"props":14980,"children":14981},{"style":583},[14982],{"type":420,"value":14849},{"type":415,"tag":559,"props":14984,"children":14985},{"style":583},[14986],{"type":420,"value":763},{"type":415,"tag":559,"props":14988,"children":14989},{"style":583},[14990],{"type":420,"value":1434},{"type":415,"tag":559,"props":14992,"children":14993},{"style":822},[14994],{"type":420,"value":14862},{"type":415,"tag":559,"props":14996,"children":14997},{"style":583},[14998],{"type":420,"value":819},{"type":415,"tag":559,"props":15000,"children":15001},{"style":583},[15002],{"type":420,"value":605},{"type":415,"tag":559,"props":15004,"children":15005},{"class":561,"line":1102},[15006,15010,15014,15019,15023,15027,15031,15035,15039],{"type":415,"tag":559,"props":15007,"children":15008},{"style":583},[15009],{"type":420,"value":14831},{"type":415,"tag":559,"props":15011,"children":15012},{"style":583},[15013],{"type":420,"value":819},{"type":415,"tag":559,"props":15015,"children":15016},{"style":822},[15017],{"type":420,"value":15018},"artifacts",{"type":415,"tag":559,"props":15020,"children":15021},{"style":583},[15022],{"type":420,"value":819},{"type":415,"tag":559,"props":15024,"children":15025},{"style":583},[15026],{"type":420,"value":14849},{"type":415,"tag":559,"props":15028,"children":15029},{"style":583},[15030],{"type":420,"value":763},{"type":415,"tag":559,"props":15032,"children":15033},{"style":583},[15034],{"type":420,"value":1434},{"type":415,"tag":559,"props":15036,"children":15037},{"style":822},[15038],{"type":420,"value":14862},{"type":415,"tag":559,"props":15040,"children":15041},{"style":583},[15042],{"type":420,"value":10222},{"type":415,"tag":559,"props":15044,"children":15045},{"class":561,"line":1110},[15046],{"type":415,"tag":559,"props":15047,"children":15048},{"style":583},[15049],{"type":420,"value":15050},"    },\n",{"type":415,"tag":559,"props":15052,"children":15053},{"class":561,"line":1118},[15054],{"type":415,"tag":559,"props":15055,"children":15056},{"style":583},[15057],{"type":420,"value":5833},{"type":415,"tag":416,"props":15059,"children":15060},{},[15061],{"type":420,"value":15062},"I intentionally disabled Azure Boards, Azure Test Plans, and Azure Artifacts as we only need Azure Repos and Azure Pipelines for this demo but you can enable what you need for your projects.",{"type":415,"tag":416,"props":15064,"children":15065},{},[15066,15068,15075],{"type":420,"value":15067},"By default, when we create an Azure DevOps project, a ",{"type":415,"tag":434,"props":15069,"children":15072},{"href":15070,"rel":15071},"https://www.pulumi.com/registry/packages/azuredevops/api-docs/git/",[438],[15073],{"type":420,"value":15074},"Git repository",{"type":420,"value":15076}," is created for us with the same name as the project. This repository can be retrieved using the following code:",{"type":415,"tag":549,"props":15078,"children":15080},{"className":551,"code":15079,"language":326,"meta":401,"style":401},"var repository = GetGitRepository.Invoke(new()\n{\n    ProjectId = project.Id,\n    Name = project.Name\n});\n",[15081],{"type":415,"tag":555,"props":15082,"children":15083},{"__ignoreMap":401},[15084,15119,15126,15155,15180],{"type":415,"tag":559,"props":15085,"children":15086},{"class":561,"line":562},[15087,15091,15096,15100,15105,15109,15114],{"type":415,"tag":559,"props":15088,"children":15089},{"style":572},[15090],{"type":420,"value":858},{"type":415,"tag":559,"props":15092,"children":15093},{"style":572},[15094],{"type":420,"value":15095}," repository",{"type":415,"tag":559,"props":15097,"children":15098},{"style":583},[15099],{"type":420,"value":763},{"type":415,"tag":559,"props":15101,"children":15102},{"style":792},[15103],{"type":420,"value":15104}," GetGitRepository",{"type":415,"tag":559,"props":15106,"children":15107},{"style":583},[15108],{"type":420,"value":542},{"type":415,"tag":559,"props":15110,"children":15111},{"style":883},[15112],{"type":420,"value":15113},"Invoke",{"type":415,"tag":559,"props":15115,"children":15116},{"style":583},[15117],{"type":420,"value":15118},"(new()\n",{"type":415,"tag":559,"props":15120,"children":15121},{"class":561,"line":589},[15122],{"type":415,"tag":559,"props":15123,"children":15124},{"style":583},[15125],{"type":420,"value":786},{"type":415,"tag":559,"props":15127,"children":15128},{"class":561,"line":608},[15129,15134,15138,15142,15146,15151],{"type":415,"tag":559,"props":15130,"children":15131},{"style":792},[15132],{"type":420,"value":15133},"    ProjectId ",{"type":415,"tag":559,"props":15135,"children":15136},{"style":583},[15137],{"type":420,"value":800},{"type":415,"tag":559,"props":15139,"children":15140},{"style":792},[15141],{"type":420,"value":14725},{"type":415,"tag":559,"props":15143,"children":15144},{"style":583},[15145],{"type":420,"value":542},{"type":415,"tag":559,"props":15147,"children":15148},{"style":792},[15149],{"type":420,"value":15150},"Id",{"type":415,"tag":559,"props":15152,"children":15153},{"style":583},[15154],{"type":420,"value":605},{"type":415,"tag":559,"props":15156,"children":15157},{"class":561,"line":626},[15158,15163,15167,15171,15175],{"type":415,"tag":559,"props":15159,"children":15160},{"style":792},[15161],{"type":420,"value":15162},"    Name ",{"type":415,"tag":559,"props":15164,"children":15165},{"style":583},[15166],{"type":420,"value":800},{"type":415,"tag":559,"props":15168,"children":15169},{"style":792},[15170],{"type":420,"value":14725},{"type":415,"tag":559,"props":15172,"children":15173},{"style":583},[15174],{"type":420,"value":542},{"type":415,"tag":559,"props":15176,"children":15177},{"style":792},[15178],{"type":420,"value":15179},"Name\n",{"type":415,"tag":559,"props":15181,"children":15182},{"class":561,"line":643},[15183],{"type":415,"tag":559,"props":15184,"children":15185},{"style":583},[15186],{"type":420,"value":5833},{"type":415,"tag":416,"props":15188,"children":15189},{},[15190],{"type":420,"value":15191},"We can also choose to create a new Git repository like this:",{"type":415,"tag":549,"props":15193,"children":15195},{"className":551,"code":15194,"language":326,"meta":401,"style":401},"var repository = new Git(\"AzureReadyADORepository\", new()\n{\n    ProjectId = project.Id,\n    Initialization = new GitInitializationArgs()\n    {\n        InitType = \"Clean\",\n        SourceType = \"Git\",\n        SourceUrl = \"https://repo.com\",\n        ServiceConnectionId = \"\"\n    },\n    DefaultBranch = \"refs/heads/main\"\n});\n",[15196],{"type":415,"tag":555,"props":15197,"children":15198},{"__ignoreMap":401},[15199,15248,15255,15282,15307,15314,15343,15372,15401,15418,15425,15450],{"type":415,"tag":559,"props":15200,"children":15201},{"class":561,"line":562},[15202,15206,15210,15214,15218,15223,15227,15231,15236,15240,15244],{"type":415,"tag":559,"props":15203,"children":15204},{"style":572},[15205],{"type":420,"value":858},{"type":415,"tag":559,"props":15207,"children":15208},{"style":572},[15209],{"type":420,"value":15095},{"type":415,"tag":559,"props":15211,"children":15212},{"style":583},[15213],{"type":420,"value":763},{"type":415,"tag":559,"props":15215,"children":15216},{"style":583},[15217],{"type":420,"value":768},{"type":415,"tag":559,"props":15219,"children":15220},{"style":572},[15221],{"type":420,"value":15222}," Git",{"type":415,"tag":559,"props":15224,"children":15225},{"style":583},[15226],{"type":420,"value":814},{"type":415,"tag":559,"props":15228,"children":15229},{"style":583},[15230],{"type":420,"value":819},{"type":415,"tag":559,"props":15232,"children":15233},{"style":822},[15234],{"type":420,"value":15235},"AzureReadyADORepository",{"type":415,"tag":559,"props":15237,"children":15238},{"style":583},[15239],{"type":420,"value":819},{"type":415,"tag":559,"props":15241,"children":15242},{"style":583},[15243],{"type":420,"value":2312},{"type":415,"tag":559,"props":15245,"children":15246},{"style":583},[15247],{"type":420,"value":14764},{"type":415,"tag":559,"props":15249,"children":15250},{"class":561,"line":589},[15251],{"type":415,"tag":559,"props":15252,"children":15253},{"style":583},[15254],{"type":420,"value":786},{"type":415,"tag":559,"props":15256,"children":15257},{"class":561,"line":608},[15258,15262,15266,15270,15274,15278],{"type":415,"tag":559,"props":15259,"children":15260},{"style":792},[15261],{"type":420,"value":15133},{"type":415,"tag":559,"props":15263,"children":15264},{"style":583},[15265],{"type":420,"value":800},{"type":415,"tag":559,"props":15267,"children":15268},{"style":792},[15269],{"type":420,"value":14725},{"type":415,"tag":559,"props":15271,"children":15272},{"style":583},[15273],{"type":420,"value":542},{"type":415,"tag":559,"props":15275,"children":15276},{"style":792},[15277],{"type":420,"value":15150},{"type":415,"tag":559,"props":15279,"children":15280},{"style":583},[15281],{"type":420,"value":605},{"type":415,"tag":559,"props":15283,"children":15284},{"class":561,"line":626},[15285,15290,15294,15298,15303],{"type":415,"tag":559,"props":15286,"children":15287},{"style":792},[15288],{"type":420,"value":15289},"    Initialization ",{"type":415,"tag":559,"props":15291,"children":15292},{"style":583},[15293],{"type":420,"value":800},{"type":415,"tag":559,"props":15295,"children":15296},{"style":583},[15297],{"type":420,"value":768},{"type":415,"tag":559,"props":15299,"children":15300},{"style":572},[15301],{"type":420,"value":15302}," GitInitializationArgs",{"type":415,"tag":559,"props":15304,"children":15305},{"style":583},[15306],{"type":420,"value":778},{"type":415,"tag":559,"props":15308,"children":15309},{"class":561,"line":643},[15310],{"type":415,"tag":559,"props":15311,"children":15312},{"style":583},[15313],{"type":420,"value":2737},{"type":415,"tag":559,"props":15315,"children":15316},{"class":561,"line":660},[15317,15322,15326,15330,15335,15339],{"type":415,"tag":559,"props":15318,"children":15319},{"style":792},[15320],{"type":420,"value":15321},"        InitType ",{"type":415,"tag":559,"props":15323,"children":15324},{"style":583},[15325],{"type":420,"value":800},{"type":415,"tag":559,"props":15327,"children":15328},{"style":583},[15329],{"type":420,"value":1434},{"type":415,"tag":559,"props":15331,"children":15332},{"style":822},[15333],{"type":420,"value":15334},"Clean",{"type":415,"tag":559,"props":15336,"children":15337},{"style":583},[15338],{"type":420,"value":819},{"type":415,"tag":559,"props":15340,"children":15341},{"style":583},[15342],{"type":420,"value":605},{"type":415,"tag":559,"props":15344,"children":15345},{"class":561,"line":677},[15346,15351,15355,15359,15364,15368],{"type":415,"tag":559,"props":15347,"children":15348},{"style":792},[15349],{"type":420,"value":15350},"        SourceType ",{"type":415,"tag":559,"props":15352,"children":15353},{"style":583},[15354],{"type":420,"value":800},{"type":415,"tag":559,"props":15356,"children":15357},{"style":583},[15358],{"type":420,"value":1434},{"type":415,"tag":559,"props":15360,"children":15361},{"style":822},[15362],{"type":420,"value":15363},"Git",{"type":415,"tag":559,"props":15365,"children":15366},{"style":583},[15367],{"type":420,"value":819},{"type":415,"tag":559,"props":15369,"children":15370},{"style":583},[15371],{"type":420,"value":605},{"type":415,"tag":559,"props":15373,"children":15374},{"class":561,"line":690},[15375,15380,15384,15388,15393,15397],{"type":415,"tag":559,"props":15376,"children":15377},{"style":792},[15378],{"type":420,"value":15379},"        SourceUrl ",{"type":415,"tag":559,"props":15381,"children":15382},{"style":583},[15383],{"type":420,"value":800},{"type":415,"tag":559,"props":15385,"children":15386},{"style":583},[15387],{"type":420,"value":1434},{"type":415,"tag":559,"props":15389,"children":15390},{"style":822},[15391],{"type":420,"value":15392},"https://repo.com",{"type":415,"tag":559,"props":15394,"children":15395},{"style":583},[15396],{"type":420,"value":819},{"type":415,"tag":559,"props":15398,"children":15399},{"style":583},[15400],{"type":420,"value":605},{"type":415,"tag":559,"props":15402,"children":15403},{"class":561,"line":1089},[15404,15409,15413],{"type":415,"tag":559,"props":15405,"children":15406},{"style":792},[15407],{"type":420,"value":15408},"        ServiceConnectionId ",{"type":415,"tag":559,"props":15410,"children":15411},{"style":583},[15412],{"type":420,"value":800},{"type":415,"tag":559,"props":15414,"children":15415},{"style":583},[15416],{"type":420,"value":15417}," \"\"\n",{"type":415,"tag":559,"props":15419,"children":15420},{"class":561,"line":1102},[15421],{"type":415,"tag":559,"props":15422,"children":15423},{"style":583},[15424],{"type":420,"value":15050},{"type":415,"tag":559,"props":15426,"children":15427},{"class":561,"line":1110},[15428,15433,15437,15441,15446],{"type":415,"tag":559,"props":15429,"children":15430},{"style":792},[15431],{"type":420,"value":15432},"    DefaultBranch ",{"type":415,"tag":559,"props":15434,"children":15435},{"style":583},[15436],{"type":420,"value":800},{"type":415,"tag":559,"props":15438,"children":15439},{"style":583},[15440],{"type":420,"value":1434},{"type":415,"tag":559,"props":15442,"children":15443},{"style":822},[15444],{"type":420,"value":15445},"refs/heads/main",{"type":415,"tag":559,"props":15447,"children":15448},{"style":583},[15449],{"type":420,"value":10222},{"type":415,"tag":559,"props":15451,"children":15452},{"class":561,"line":1118},[15453],{"type":415,"tag":559,"props":15454,"children":15455},{"style":583},[15456],{"type":420,"value":5833},{"type":415,"tag":1178,"props":15458,"children":15459},{"icon":14241},[15460],{"type":415,"tag":416,"props":15461,"children":15462},{},[15463,15465,15471,15472,15478,15480,15486,15488,15494],{"type":420,"value":15464},"We should not have to set the ",{"type":415,"tag":555,"props":15466,"children":15468},{"className":15467},[],[15469],{"type":420,"value":15470},"SourceType",{"type":420,"value":14095},{"type":415,"tag":555,"props":15473,"children":15475},{"className":15474},[],[15476],{"type":420,"value":15477},"SourceUrl",{"type":420,"value":15479}," and ",{"type":415,"tag":555,"props":15481,"children":15483},{"className":15482},[],[15484],{"type":420,"value":15485},"ServiceConnectionId",{"type":420,"value":15487}," properties as we are initializing a clean Git repository, not importing one, but it's a workaround because of this ",{"type":415,"tag":434,"props":15489,"children":15492},{"href":15490,"rel":15491},"https://github.com/pulumi/pulumi-azuredevops/issues/66",[438],[15493],{"type":420,"value":7952},{"type":420,"value":15495}," on the provider.",{"type":415,"tag":14340,"props":15497,"children":15499},{"id":15498},"configure-the-arm-service-connection-in-azure-devops",[15500],{"type":420,"value":15501},"Configure the ARM Service Connection in Azure DevOps",{"type":415,"tag":416,"props":15503,"children":15504},{},[15505,15507,15514],{"type":420,"value":15506},"In the Azure DevOps provider, the Azure Resource Manager service connection is called a ",{"type":415,"tag":434,"props":15508,"children":15511},{"href":15509,"rel":15510},"https://www.pulumi.com/registry/packages/azuredevops/api-docs/serviceendpointazurerm/#workload-identity-federation-manual-azurerm-service-endpoint-subscription-scoped",[438],[15512],{"type":420,"value":15513},"ServiceEndpointAzureRM",{"type":420,"value":15515},". We can create such a resource like this:",{"type":415,"tag":549,"props":15517,"children":15519},{"className":551,"code":15518,"language":326,"meta":401,"style":401},"var serviceConnection = new ServiceEndpointAzureRM(\"AzureServiceConnection\", new()\n{\n    ProjectId = project.Id,\n    ServiceEndpointName = \"azure-with-oidc\",\n    ServiceEndpointAuthenticationScheme = \"WorkloadIdentityFederation\",\n    AzurermSpnTenantid = tenantId,\n    AzurermSubscriptionId = subscriptionId,\n    AzurermSubscriptionName = subscriptionName,\n    Credentials = new ServiceEndpointAzureRMCredentialsArgs()\n    {\n        Serviceprincipalid = servicePrincipal.ApplicationId,\n    }\n});\n",[15520],{"type":415,"tag":555,"props":15521,"children":15522},{"__ignoreMap":401},[15523,15573,15580,15607,15636,15665,15686,15707,15728,15753,15760,15790,15797],{"type":415,"tag":559,"props":15524,"children":15525},{"class":561,"line":562},[15526,15530,15535,15539,15543,15548,15552,15556,15561,15565,15569],{"type":415,"tag":559,"props":15527,"children":15528},{"style":572},[15529],{"type":420,"value":858},{"type":415,"tag":559,"props":15531,"children":15532},{"style":572},[15533],{"type":420,"value":15534}," serviceConnection",{"type":415,"tag":559,"props":15536,"children":15537},{"style":583},[15538],{"type":420,"value":763},{"type":415,"tag":559,"props":15540,"children":15541},{"style":583},[15542],{"type":420,"value":768},{"type":415,"tag":559,"props":15544,"children":15545},{"style":572},[15546],{"type":420,"value":15547}," ServiceEndpointAzureRM",{"type":415,"tag":559,"props":15549,"children":15550},{"style":583},[15551],{"type":420,"value":814},{"type":415,"tag":559,"props":15553,"children":15554},{"style":583},[15555],{"type":420,"value":819},{"type":415,"tag":559,"props":15557,"children":15558},{"style":822},[15559],{"type":420,"value":15560},"AzureServiceConnection",{"type":415,"tag":559,"props":15562,"children":15563},{"style":583},[15564],{"type":420,"value":819},{"type":415,"tag":559,"props":15566,"children":15567},{"style":583},[15568],{"type":420,"value":2312},{"type":415,"tag":559,"props":15570,"children":15571},{"style":583},[15572],{"type":420,"value":14764},{"type":415,"tag":559,"props":15574,"children":15575},{"class":561,"line":589},[15576],{"type":415,"tag":559,"props":15577,"children":15578},{"style":583},[15579],{"type":420,"value":786},{"type":415,"tag":559,"props":15581,"children":15582},{"class":561,"line":608},[15583,15587,15591,15595,15599,15603],{"type":415,"tag":559,"props":15584,"children":15585},{"style":792},[15586],{"type":420,"value":15133},{"type":415,"tag":559,"props":15588,"children":15589},{"style":583},[15590],{"type":420,"value":800},{"type":415,"tag":559,"props":15592,"children":15593},{"style":792},[15594],{"type":420,"value":14725},{"type":415,"tag":559,"props":15596,"children":15597},{"style":583},[15598],{"type":420,"value":542},{"type":415,"tag":559,"props":15600,"children":15601},{"style":792},[15602],{"type":420,"value":15150},{"type":415,"tag":559,"props":15604,"children":15605},{"style":583},[15606],{"type":420,"value":605},{"type":415,"tag":559,"props":15608,"children":15609},{"class":561,"line":626},[15610,15615,15619,15623,15628,15632],{"type":415,"tag":559,"props":15611,"children":15612},{"style":792},[15613],{"type":420,"value":15614},"    ServiceEndpointName ",{"type":415,"tag":559,"props":15616,"children":15617},{"style":583},[15618],{"type":420,"value":800},{"type":415,"tag":559,"props":15620,"children":15621},{"style":583},[15622],{"type":420,"value":1434},{"type":415,"tag":559,"props":15624,"children":15625},{"style":822},[15626],{"type":420,"value":15627},"azure-with-oidc",{"type":415,"tag":559,"props":15629,"children":15630},{"style":583},[15631],{"type":420,"value":819},{"type":415,"tag":559,"props":15633,"children":15634},{"style":583},[15635],{"type":420,"value":605},{"type":415,"tag":559,"props":15637,"children":15638},{"class":561,"line":643},[15639,15644,15648,15652,15657,15661],{"type":415,"tag":559,"props":15640,"children":15641},{"style":792},[15642],{"type":420,"value":15643},"    ServiceEndpointAuthenticationScheme ",{"type":415,"tag":559,"props":15645,"children":15646},{"style":583},[15647],{"type":420,"value":800},{"type":415,"tag":559,"props":15649,"children":15650},{"style":583},[15651],{"type":420,"value":1434},{"type":415,"tag":559,"props":15653,"children":15654},{"style":822},[15655],{"type":420,"value":15656},"WorkloadIdentityFederation",{"type":415,"tag":559,"props":15658,"children":15659},{"style":583},[15660],{"type":420,"value":819},{"type":415,"tag":559,"props":15662,"children":15663},{"style":583},[15664],{"type":420,"value":605},{"type":415,"tag":559,"props":15666,"children":15667},{"class":561,"line":660},[15668,15673,15677,15682],{"type":415,"tag":559,"props":15669,"children":15670},{"style":792},[15671],{"type":420,"value":15672},"    AzurermSpnTenantid ",{"type":415,"tag":559,"props":15674,"children":15675},{"style":583},[15676],{"type":420,"value":800},{"type":415,"tag":559,"props":15678,"children":15679},{"style":792},[15680],{"type":420,"value":15681}," tenantId",{"type":415,"tag":559,"props":15683,"children":15684},{"style":583},[15685],{"type":420,"value":605},{"type":415,"tag":559,"props":15687,"children":15688},{"class":561,"line":677},[15689,15694,15698,15703],{"type":415,"tag":559,"props":15690,"children":15691},{"style":792},[15692],{"type":420,"value":15693},"    AzurermSubscriptionId ",{"type":415,"tag":559,"props":15695,"children":15696},{"style":583},[15697],{"type":420,"value":800},{"type":415,"tag":559,"props":15699,"children":15700},{"style":792},[15701],{"type":420,"value":15702}," subscriptionId",{"type":415,"tag":559,"props":15704,"children":15705},{"style":583},[15706],{"type":420,"value":605},{"type":415,"tag":559,"props":15708,"children":15709},{"class":561,"line":690},[15710,15715,15719,15724],{"type":415,"tag":559,"props":15711,"children":15712},{"style":792},[15713],{"type":420,"value":15714},"    AzurermSubscriptionName ",{"type":415,"tag":559,"props":15716,"children":15717},{"style":583},[15718],{"type":420,"value":800},{"type":415,"tag":559,"props":15720,"children":15721},{"style":792},[15722],{"type":420,"value":15723}," subscriptionName",{"type":415,"tag":559,"props":15725,"children":15726},{"style":583},[15727],{"type":420,"value":605},{"type":415,"tag":559,"props":15729,"children":15730},{"class":561,"line":1089},[15731,15736,15740,15744,15749],{"type":415,"tag":559,"props":15732,"children":15733},{"style":792},[15734],{"type":420,"value":15735},"    Credentials ",{"type":415,"tag":559,"props":15737,"children":15738},{"style":583},[15739],{"type":420,"value":800},{"type":415,"tag":559,"props":15741,"children":15742},{"style":583},[15743],{"type":420,"value":768},{"type":415,"tag":559,"props":15745,"children":15746},{"style":572},[15747],{"type":420,"value":15748}," ServiceEndpointAzureRMCredentialsArgs",{"type":415,"tag":559,"props":15750,"children":15751},{"style":583},[15752],{"type":420,"value":778},{"type":415,"tag":559,"props":15754,"children":15755},{"class":561,"line":1102},[15756],{"type":415,"tag":559,"props":15757,"children":15758},{"style":583},[15759],{"type":420,"value":2737},{"type":415,"tag":559,"props":15761,"children":15762},{"class":561,"line":1110},[15763,15768,15772,15777,15781,15786],{"type":415,"tag":559,"props":15764,"children":15765},{"style":792},[15766],{"type":420,"value":15767},"        Serviceprincipalid ",{"type":415,"tag":559,"props":15769,"children":15770},{"style":583},[15771],{"type":420,"value":800},{"type":415,"tag":559,"props":15773,"children":15774},{"style":792},[15775],{"type":420,"value":15776}," servicePrincipal",{"type":415,"tag":559,"props":15778,"children":15779},{"style":583},[15780],{"type":420,"value":542},{"type":415,"tag":559,"props":15782,"children":15783},{"style":792},[15784],{"type":420,"value":15785},"ApplicationId",{"type":415,"tag":559,"props":15787,"children":15788},{"style":583},[15789],{"type":420,"value":605},{"type":415,"tag":559,"props":15791,"children":15792},{"class":561,"line":1118},[15793],{"type":415,"tag":559,"props":15794,"children":15795},{"style":583},[15796],{"type":420,"value":2792},{"type":415,"tag":559,"props":15798,"children":15799},{"class":561,"line":1171},[15800],{"type":415,"tag":559,"props":15801,"children":15802},{"style":583},[15803],{"type":420,"value":5833},{"type":415,"tag":416,"props":15805,"children":15806},{},[15807,15809,15815],{"type":420,"value":15808},"Do not worry about the service principal, we will see in the next section how to create it. The tenant and the subscription identifiers can be retrieved from the current configuration of the Azure Native provider (using the ",{"type":415,"tag":555,"props":15810,"children":15812},{"className":15811},[],[15813],{"type":420,"value":15814},"GetClientConfig.Invoke",{"type":420,"value":15816}," function):",{"type":415,"tag":549,"props":15818,"children":15820},{"className":551,"code":15819,"language":326,"meta":401,"style":401},"var azureConfig = GetClientConfig.Invoke();\nvar tenantId = azureConfig.Apply(c => c.tenantId);\nvar subscriptionId = azureConfig.Apply(c => c.SubscriptionId);\n",[15821],{"type":415,"tag":555,"props":15822,"children":15823},{"__ignoreMap":401},[15824,15857,15916],{"type":415,"tag":559,"props":15825,"children":15826},{"class":561,"line":562},[15827,15831,15836,15840,15845,15849,15853],{"type":415,"tag":559,"props":15828,"children":15829},{"style":572},[15830],{"type":420,"value":858},{"type":415,"tag":559,"props":15832,"children":15833},{"style":572},[15834],{"type":420,"value":15835}," azureConfig",{"type":415,"tag":559,"props":15837,"children":15838},{"style":583},[15839],{"type":420,"value":763},{"type":415,"tag":559,"props":15841,"children":15842},{"style":792},[15843],{"type":420,"value":15844}," GetClientConfig",{"type":415,"tag":559,"props":15846,"children":15847},{"style":583},[15848],{"type":420,"value":542},{"type":415,"tag":559,"props":15850,"children":15851},{"style":883},[15852],{"type":420,"value":15113},{"type":415,"tag":559,"props":15854,"children":15855},{"style":583},[15856],{"type":420,"value":1962},{"type":415,"tag":559,"props":15858,"children":15859},{"class":561,"line":589},[15860,15864,15868,15872,15876,15880,15885,15889,15894,15898,15903,15907,15912],{"type":415,"tag":559,"props":15861,"children":15862},{"style":572},[15863],{"type":420,"value":858},{"type":415,"tag":559,"props":15865,"children":15866},{"style":572},[15867],{"type":420,"value":15681},{"type":415,"tag":559,"props":15869,"children":15870},{"style":583},[15871],{"type":420,"value":763},{"type":415,"tag":559,"props":15873,"children":15874},{"style":792},[15875],{"type":420,"value":15835},{"type":415,"tag":559,"props":15877,"children":15878},{"style":583},[15879],{"type":420,"value":542},{"type":415,"tag":559,"props":15881,"children":15882},{"style":883},[15883],{"type":420,"value":15884},"Apply",{"type":415,"tag":559,"props":15886,"children":15887},{"style":583},[15888],{"type":420,"value":814},{"type":415,"tag":559,"props":15890,"children":15891},{"style":572},[15892],{"type":420,"value":15893},"c",{"type":415,"tag":559,"props":15895,"children":15896},{"style":583},[15897],{"type":420,"value":1861},{"type":415,"tag":559,"props":15899,"children":15900},{"style":792},[15901],{"type":420,"value":15902}," c",{"type":415,"tag":559,"props":15904,"children":15905},{"style":583},[15906],{"type":420,"value":542},{"type":415,"tag":559,"props":15908,"children":15909},{"style":792},[15910],{"type":420,"value":15911},"tenantId",{"type":415,"tag":559,"props":15913,"children":15914},{"style":583},[15915],{"type":420,"value":696},{"type":415,"tag":559,"props":15917,"children":15918},{"class":561,"line":608},[15919,15923,15927,15931,15935,15939,15943,15947,15951,15955,15959,15963,15968],{"type":415,"tag":559,"props":15920,"children":15921},{"style":572},[15922],{"type":420,"value":858},{"type":415,"tag":559,"props":15924,"children":15925},{"style":572},[15926],{"type":420,"value":15702},{"type":415,"tag":559,"props":15928,"children":15929},{"style":583},[15930],{"type":420,"value":763},{"type":415,"tag":559,"props":15932,"children":15933},{"style":792},[15934],{"type":420,"value":15835},{"type":415,"tag":559,"props":15936,"children":15937},{"style":583},[15938],{"type":420,"value":542},{"type":415,"tag":559,"props":15940,"children":15941},{"style":883},[15942],{"type":420,"value":15884},{"type":415,"tag":559,"props":15944,"children":15945},{"style":583},[15946],{"type":420,"value":814},{"type":415,"tag":559,"props":15948,"children":15949},{"style":572},[15950],{"type":420,"value":15893},{"type":415,"tag":559,"props":15952,"children":15953},{"style":583},[15954],{"type":420,"value":1861},{"type":415,"tag":559,"props":15956,"children":15957},{"style":792},[15958],{"type":420,"value":15902},{"type":415,"tag":559,"props":15960,"children":15961},{"style":583},[15962],{"type":420,"value":542},{"type":415,"tag":559,"props":15964,"children":15965},{"style":792},[15966],{"type":420,"value":15967},"SubscriptionId",{"type":415,"tag":559,"props":15969,"children":15970},{"style":583},[15971],{"type":420,"value":696},{"type":415,"tag":416,"props":15973,"children":15974},{},[15975],{"type":420,"value":15976},"For the subscription name, it's more complicated as we don't have it, and no easy way to retrieve it. To be frank, I think having to provide the subscription name while we already provide the subscription identifier is completely useless but that's how the Azure DevOps provider works.",{"type":415,"tag":416,"props":15978,"children":15979},{},[15980,15982,15989,15991,15997],{"type":420,"value":15981},"The Azure Classic provider offers a ",{"type":415,"tag":434,"props":15983,"children":15986},{"href":15984,"rel":15985},"https://www.pulumi.com/registry/packages/azure/api-docs/core/getsubscription/#azure-core-getsubscription",[438],[15987],{"type":420,"value":15988},"function",{"type":420,"value":15990}," to get a subscription by its identifier but it's not available in the Azure Native provider. I don't want to add the Azure Classic provider to my project solely for this purpose. However, it's not a big deal as it allows us to experience one of the advantages of using Pulumi: when something is not available you can just implement it or use any library that can help you, such as the ",{"type":415,"tag":434,"props":15992,"children":15995},{"href":15993,"rel":15994},"https://www.nuget.org/packages/Azure.ResourceManager",[438],[15996],{"type":420,"value":302},{"type":420,"value":15998}," in this case.",{"type":415,"tag":549,"props":16000,"children":16002},{"className":551,"code":16001,"language":326,"meta":401,"style":401},"var subscriptionName = subscriptionId.Apply(s =>\n{\n    var armClient = new ArmClient(new DefaultAzureCredential());\n    var subscription = armClient.GetSubscriptionResource(new ResourceIdentifier($\"/subscriptions/{s}\")).Get();\n    return subscription.Value.Data.DisplayName;\n});\n",[16003],{"type":415,"tag":555,"props":16004,"children":16005},{"__ignoreMap":401},[16006,16046,16053,16090,16167,16208],{"type":415,"tag":559,"props":16007,"children":16008},{"class":561,"line":562},[16009,16013,16017,16021,16025,16029,16033,16037,16042],{"type":415,"tag":559,"props":16010,"children":16011},{"style":572},[16012],{"type":420,"value":858},{"type":415,"tag":559,"props":16014,"children":16015},{"style":572},[16016],{"type":420,"value":15723},{"type":415,"tag":559,"props":16018,"children":16019},{"style":583},[16020],{"type":420,"value":763},{"type":415,"tag":559,"props":16022,"children":16023},{"style":792},[16024],{"type":420,"value":15702},{"type":415,"tag":559,"props":16026,"children":16027},{"style":583},[16028],{"type":420,"value":542},{"type":415,"tag":559,"props":16030,"children":16031},{"style":883},[16032],{"type":420,"value":15884},{"type":415,"tag":559,"props":16034,"children":16035},{"style":583},[16036],{"type":420,"value":814},{"type":415,"tag":559,"props":16038,"children":16039},{"style":572},[16040],{"type":420,"value":16041},"s",{"type":415,"tag":559,"props":16043,"children":16044},{"style":583},[16045],{"type":420,"value":5741},{"type":415,"tag":559,"props":16047,"children":16048},{"class":561,"line":589},[16049],{"type":415,"tag":559,"props":16050,"children":16051},{"style":583},[16052],{"type":420,"value":786},{"type":415,"tag":559,"props":16054,"children":16055},{"class":561,"line":608},[16056,16060,16065,16069,16073,16078,16082,16086],{"type":415,"tag":559,"props":16057,"children":16058},{"style":572},[16059],{"type":420,"value":1257},{"type":415,"tag":559,"props":16061,"children":16062},{"style":572},[16063],{"type":420,"value":16064}," armClient",{"type":415,"tag":559,"props":16066,"children":16067},{"style":583},[16068],{"type":420,"value":763},{"type":415,"tag":559,"props":16070,"children":16071},{"style":583},[16072],{"type":420,"value":768},{"type":415,"tag":559,"props":16074,"children":16075},{"style":572},[16076],{"type":420,"value":16077}," ArmClient",{"type":415,"tag":559,"props":16079,"children":16080},{"style":583},[16081],{"type":420,"value":5770},{"type":415,"tag":559,"props":16083,"children":16084},{"style":572},[16085],{"type":420,"value":5821},{"type":415,"tag":559,"props":16087,"children":16088},{"style":583},[16089],{"type":420,"value":1312},{"type":415,"tag":559,"props":16091,"children":16092},{"class":561,"line":626},[16093,16097,16102,16106,16110,16114,16119,16123,16128,16132,16137,16142,16146,16150,16154,16159,16163],{"type":415,"tag":559,"props":16094,"children":16095},{"style":572},[16096],{"type":420,"value":1257},{"type":415,"tag":559,"props":16098,"children":16099},{"style":572},[16100],{"type":420,"value":16101}," subscription",{"type":415,"tag":559,"props":16103,"children":16104},{"style":583},[16105],{"type":420,"value":763},{"type":415,"tag":559,"props":16107,"children":16108},{"style":792},[16109],{"type":420,"value":16064},{"type":415,"tag":559,"props":16111,"children":16112},{"style":583},[16113],{"type":420,"value":542},{"type":415,"tag":559,"props":16115,"children":16116},{"style":883},[16117],{"type":420,"value":16118},"GetSubscriptionResource",{"type":415,"tag":559,"props":16120,"children":16121},{"style":583},[16122],{"type":420,"value":5770},{"type":415,"tag":559,"props":16124,"children":16125},{"style":572},[16126],{"type":420,"value":16127}," ResourceIdentifier",{"type":415,"tag":559,"props":16129,"children":16130},{"style":583},[16131],{"type":420,"value":814},{"type":415,"tag":559,"props":16133,"children":16134},{"style":583},[16135],{"type":420,"value":16136},"$\"",{"type":415,"tag":559,"props":16138,"children":16139},{"style":822},[16140],{"type":420,"value":16141},"/subscriptions/",{"type":415,"tag":559,"props":16143,"children":16144},{"style":583},[16145],{"type":420,"value":2397},{"type":415,"tag":559,"props":16147,"children":16148},{"style":792},[16149],{"type":420,"value":16041},{"type":415,"tag":559,"props":16151,"children":16152},{"style":583},[16153],{"type":420,"value":1602},{"type":415,"tag":559,"props":16155,"children":16156},{"style":583},[16157],{"type":420,"value":16158},")).",{"type":415,"tag":559,"props":16160,"children":16161},{"style":883},[16162],{"type":420,"value":12924},{"type":415,"tag":559,"props":16164,"children":16165},{"style":583},[16166],{"type":420,"value":1962},{"type":415,"tag":559,"props":16168,"children":16169},{"class":561,"line":643},[16170,16174,16178,16182,16186,16190,16195,16199,16204],{"type":415,"tag":559,"props":16171,"children":16172},{"style":745},[16173],{"type":420,"value":1517},{"type":415,"tag":559,"props":16175,"children":16176},{"style":792},[16177],{"type":420,"value":16101},{"type":415,"tag":559,"props":16179,"children":16180},{"style":583},[16181],{"type":420,"value":542},{"type":415,"tag":559,"props":16183,"children":16184},{"style":792},[16185],{"type":420,"value":8206},{"type":415,"tag":559,"props":16187,"children":16188},{"style":583},[16189],{"type":420,"value":542},{"type":415,"tag":559,"props":16191,"children":16192},{"style":792},[16193],{"type":420,"value":16194},"Data",{"type":415,"tag":559,"props":16196,"children":16197},{"style":583},[16198],{"type":420,"value":542},{"type":415,"tag":559,"props":16200,"children":16201},{"style":792},[16202],{"type":420,"value":16203},"DisplayName",{"type":415,"tag":559,"props":16205,"children":16206},{"style":583},[16207],{"type":420,"value":1509},{"type":415,"tag":559,"props":16209,"children":16210},{"class":561,"line":660},[16211],{"type":415,"tag":559,"props":16212,"children":16213},{"style":583},[16214],{"type":420,"value":5833},{"type":415,"tag":14340,"props":16216,"children":16218},{"id":16217},"set-up-the-necessary-microsoft-entra-id-resources",[16219],{"type":420,"value":16220},"Set up the necessary Microsoft Entra ID resources",{"type":415,"tag":416,"props":16222,"children":16223},{},[16224],{"type":420,"value":16225},"We need to set up the following resources in Microsoft Entra ID:",{"type":415,"tag":5376,"props":16227,"children":16228},{},[16229,16234,16239],{"type":415,"tag":5380,"props":16230,"children":16231},{},[16232],{"type":420,"value":16233},"an Application that represents the Azure DevOps service connection identity",{"type":415,"tag":5380,"props":16235,"children":16236},{},[16237],{"type":420,"value":16238},"a Service Principal (related to the application above) that has the contributor role on the Azure subscription",{"type":415,"tag":5380,"props":16240,"children":16241},{},[16242],{"type":420,"value":16243},"credentials for the CI/CD pipeline to authenticate to Azure on behalf of this Microsoft Entra ID application",{"type":415,"tag":416,"props":16245,"children":16246},{},[16247],{"type":420,"value":16248},"Let's take care of the first 2 points:",{"type":415,"tag":549,"props":16250,"children":16252},{"className":551,"code":16251,"language":326,"meta":401,"style":401},"var azureConfig = GetClientConfig.Invoke();\nvar aadApplication = new Application(\"ADOAzureReadyApp\", new()\n{\n    DisplayName = \"ADO Azure Ready App\"\n});\nvar servicePrincipal  = new ServicePrincipal(\"AzureReadyServicePrincipal\", new()\n{\n    ApplicationId = aadApplication.ApplicationId,\n});\n\nvar subscriptionId = azureConfig.Apply(c => c.SubscriptionId);\nnew RoleAssignment(\"contributor\", new()\n{\n    PrincipalId= servicePrincipal.Id,\n    PrincipalType= PrincipalType.ServicePrincipal,\n    RoleDefinitionId = AzureBuiltInRoles.Contributor,\n    Scope = Output.Format($\"/subscriptions/{subscriptionId}\")\n});\n",[16253],{"type":415,"tag":555,"props":16254,"children":16255},{"__ignoreMap":401},[16256,16287,16337,16344,16369,16376,16426,16433,16461,16468,16475,16530,16568,16575,16603,16633,16663,16718],{"type":415,"tag":559,"props":16257,"children":16258},{"class":561,"line":562},[16259,16263,16267,16271,16275,16279,16283],{"type":415,"tag":559,"props":16260,"children":16261},{"style":572},[16262],{"type":420,"value":858},{"type":415,"tag":559,"props":16264,"children":16265},{"style":572},[16266],{"type":420,"value":15835},{"type":415,"tag":559,"props":16268,"children":16269},{"style":583},[16270],{"type":420,"value":763},{"type":415,"tag":559,"props":16272,"children":16273},{"style":792},[16274],{"type":420,"value":15844},{"type":415,"tag":559,"props":16276,"children":16277},{"style":583},[16278],{"type":420,"value":542},{"type":415,"tag":559,"props":16280,"children":16281},{"style":883},[16282],{"type":420,"value":15113},{"type":415,"tag":559,"props":16284,"children":16285},{"style":583},[16286],{"type":420,"value":1962},{"type":415,"tag":559,"props":16288,"children":16289},{"class":561,"line":589},[16290,16294,16299,16303,16307,16312,16316,16320,16325,16329,16333],{"type":415,"tag":559,"props":16291,"children":16292},{"style":572},[16293],{"type":420,"value":858},{"type":415,"tag":559,"props":16295,"children":16296},{"style":572},[16297],{"type":420,"value":16298}," aadApplication",{"type":415,"tag":559,"props":16300,"children":16301},{"style":583},[16302],{"type":420,"value":763},{"type":415,"tag":559,"props":16304,"children":16305},{"style":583},[16306],{"type":420,"value":768},{"type":415,"tag":559,"props":16308,"children":16309},{"style":572},[16310],{"type":420,"value":16311}," Application",{"type":415,"tag":559,"props":16313,"children":16314},{"style":583},[16315],{"type":420,"value":814},{"type":415,"tag":559,"props":16317,"children":16318},{"style":583},[16319],{"type":420,"value":819},{"type":415,"tag":559,"props":16321,"children":16322},{"style":822},[16323],{"type":420,"value":16324},"ADOAzureReadyApp",{"type":415,"tag":559,"props":16326,"children":16327},{"style":583},[16328],{"type":420,"value":819},{"type":415,"tag":559,"props":16330,"children":16331},{"style":583},[16332],{"type":420,"value":2312},{"type":415,"tag":559,"props":16334,"children":16335},{"style":583},[16336],{"type":420,"value":14764},{"type":415,"tag":559,"props":16338,"children":16339},{"class":561,"line":608},[16340],{"type":415,"tag":559,"props":16341,"children":16342},{"style":583},[16343],{"type":420,"value":786},{"type":415,"tag":559,"props":16345,"children":16346},{"class":561,"line":626},[16347,16352,16356,16360,16365],{"type":415,"tag":559,"props":16348,"children":16349},{"style":792},[16350],{"type":420,"value":16351},"    DisplayName ",{"type":415,"tag":559,"props":16353,"children":16354},{"style":583},[16355],{"type":420,"value":800},{"type":415,"tag":559,"props":16357,"children":16358},{"style":583},[16359],{"type":420,"value":1434},{"type":415,"tag":559,"props":16361,"children":16362},{"style":822},[16363],{"type":420,"value":16364},"ADO Azure Ready App",{"type":415,"tag":559,"props":16366,"children":16367},{"style":583},[16368],{"type":420,"value":10222},{"type":415,"tag":559,"props":16370,"children":16371},{"class":561,"line":643},[16372],{"type":415,"tag":559,"props":16373,"children":16374},{"style":583},[16375],{"type":420,"value":5833},{"type":415,"tag":559,"props":16377,"children":16378},{"class":561,"line":660},[16379,16383,16387,16392,16396,16401,16405,16409,16414,16418,16422],{"type":415,"tag":559,"props":16380,"children":16381},{"style":572},[16382],{"type":420,"value":858},{"type":415,"tag":559,"props":16384,"children":16385},{"style":572},[16386],{"type":420,"value":15776},{"type":415,"tag":559,"props":16388,"children":16389},{"style":583},[16390],{"type":420,"value":16391},"  =",{"type":415,"tag":559,"props":16393,"children":16394},{"style":583},[16395],{"type":420,"value":768},{"type":415,"tag":559,"props":16397,"children":16398},{"style":572},[16399],{"type":420,"value":16400}," ServicePrincipal",{"type":415,"tag":559,"props":16402,"children":16403},{"style":583},[16404],{"type":420,"value":814},{"type":415,"tag":559,"props":16406,"children":16407},{"style":583},[16408],{"type":420,"value":819},{"type":415,"tag":559,"props":16410,"children":16411},{"style":822},[16412],{"type":420,"value":16413},"AzureReadyServicePrincipal",{"type":415,"tag":559,"props":16415,"children":16416},{"style":583},[16417],{"type":420,"value":819},{"type":415,"tag":559,"props":16419,"children":16420},{"style":583},[16421],{"type":420,"value":2312},{"type":415,"tag":559,"props":16423,"children":16424},{"style":583},[16425],{"type":420,"value":14764},{"type":415,"tag":559,"props":16427,"children":16428},{"class":561,"line":677},[16429],{"type":415,"tag":559,"props":16430,"children":16431},{"style":583},[16432],{"type":420,"value":786},{"type":415,"tag":559,"props":16434,"children":16435},{"class":561,"line":690},[16436,16441,16445,16449,16453,16457],{"type":415,"tag":559,"props":16437,"children":16438},{"style":792},[16439],{"type":420,"value":16440},"    ApplicationId ",{"type":415,"tag":559,"props":16442,"children":16443},{"style":583},[16444],{"type":420,"value":800},{"type":415,"tag":559,"props":16446,"children":16447},{"style":792},[16448],{"type":420,"value":16298},{"type":415,"tag":559,"props":16450,"children":16451},{"style":583},[16452],{"type":420,"value":542},{"type":415,"tag":559,"props":16454,"children":16455},{"style":792},[16456],{"type":420,"value":15785},{"type":415,"tag":559,"props":16458,"children":16459},{"style":583},[16460],{"type":420,"value":605},{"type":415,"tag":559,"props":16462,"children":16463},{"class":561,"line":1089},[16464],{"type":415,"tag":559,"props":16465,"children":16466},{"style":583},[16467],{"type":420,"value":5833},{"type":415,"tag":559,"props":16469,"children":16470},{"class":561,"line":1102},[16471],{"type":415,"tag":559,"props":16472,"children":16473},{"emptyLinePlaceholder":847},[16474],{"type":420,"value":850},{"type":415,"tag":559,"props":16476,"children":16477},{"class":561,"line":1110},[16478,16482,16486,16490,16494,16498,16502,16506,16510,16514,16518,16522,16526],{"type":415,"tag":559,"props":16479,"children":16480},{"style":572},[16481],{"type":420,"value":858},{"type":415,"tag":559,"props":16483,"children":16484},{"style":572},[16485],{"type":420,"value":15702},{"type":415,"tag":559,"props":16487,"children":16488},{"style":583},[16489],{"type":420,"value":763},{"type":415,"tag":559,"props":16491,"children":16492},{"style":792},[16493],{"type":420,"value":15835},{"type":415,"tag":559,"props":16495,"children":16496},{"style":583},[16497],{"type":420,"value":542},{"type":415,"tag":559,"props":16499,"children":16500},{"style":883},[16501],{"type":420,"value":15884},{"type":415,"tag":559,"props":16503,"children":16504},{"style":583},[16505],{"type":420,"value":814},{"type":415,"tag":559,"props":16507,"children":16508},{"style":572},[16509],{"type":420,"value":15893},{"type":415,"tag":559,"props":16511,"children":16512},{"style":583},[16513],{"type":420,"value":1861},{"type":415,"tag":559,"props":16515,"children":16516},{"style":792},[16517],{"type":420,"value":15902},{"type":415,"tag":559,"props":16519,"children":16520},{"style":583},[16521],{"type":420,"value":542},{"type":415,"tag":559,"props":16523,"children":16524},{"style":792},[16525],{"type":420,"value":15967},{"type":415,"tag":559,"props":16527,"children":16528},{"style":583},[16529],{"type":420,"value":696},{"type":415,"tag":559,"props":16531,"children":16532},{"class":561,"line":1118},[16533,16538,16543,16547,16551,16556,16560,16564],{"type":415,"tag":559,"props":16534,"children":16535},{"style":566},[16536],{"type":420,"value":16537},"new",{"type":415,"tag":559,"props":16539,"children":16540},{"style":883},[16541],{"type":420,"value":16542}," RoleAssignment",{"type":415,"tag":559,"props":16544,"children":16545},{"style":583},[16546],{"type":420,"value":814},{"type":415,"tag":559,"props":16548,"children":16549},{"style":583},[16550],{"type":420,"value":819},{"type":415,"tag":559,"props":16552,"children":16553},{"style":822},[16554],{"type":420,"value":16555},"contributor",{"type":415,"tag":559,"props":16557,"children":16558},{"style":583},[16559],{"type":420,"value":819},{"type":415,"tag":559,"props":16561,"children":16562},{"style":583},[16563],{"type":420,"value":2312},{"type":415,"tag":559,"props":16565,"children":16566},{"style":583},[16567],{"type":420,"value":14764},{"type":415,"tag":559,"props":16569,"children":16570},{"class":561,"line":1171},[16571],{"type":415,"tag":559,"props":16572,"children":16573},{"style":583},[16574],{"type":420,"value":786},{"type":415,"tag":559,"props":16576,"children":16577},{"class":561,"line":1748},[16578,16583,16587,16591,16595,16599],{"type":415,"tag":559,"props":16579,"children":16580},{"style":792},[16581],{"type":420,"value":16582},"    PrincipalId",{"type":415,"tag":559,"props":16584,"children":16585},{"style":583},[16586],{"type":420,"value":800},{"type":415,"tag":559,"props":16588,"children":16589},{"style":792},[16590],{"type":420,"value":15776},{"type":415,"tag":559,"props":16592,"children":16593},{"style":583},[16594],{"type":420,"value":542},{"type":415,"tag":559,"props":16596,"children":16597},{"style":792},[16598],{"type":420,"value":15150},{"type":415,"tag":559,"props":16600,"children":16601},{"style":583},[16602],{"type":420,"value":605},{"type":415,"tag":559,"props":16604,"children":16605},{"class":561,"line":1769},[16606,16611,16615,16620,16624,16629],{"type":415,"tag":559,"props":16607,"children":16608},{"style":792},[16609],{"type":420,"value":16610},"    PrincipalType",{"type":415,"tag":559,"props":16612,"children":16613},{"style":583},[16614],{"type":420,"value":800},{"type":415,"tag":559,"props":16616,"children":16617},{"style":792},[16618],{"type":420,"value":16619}," PrincipalType",{"type":415,"tag":559,"props":16621,"children":16622},{"style":583},[16623],{"type":420,"value":542},{"type":415,"tag":559,"props":16625,"children":16626},{"style":792},[16627],{"type":420,"value":16628},"ServicePrincipal",{"type":415,"tag":559,"props":16630,"children":16631},{"style":583},[16632],{"type":420,"value":605},{"type":415,"tag":559,"props":16634,"children":16635},{"class":561,"line":1786},[16636,16641,16645,16650,16654,16659],{"type":415,"tag":559,"props":16637,"children":16638},{"style":792},[16639],{"type":420,"value":16640},"    RoleDefinitionId ",{"type":415,"tag":559,"props":16642,"children":16643},{"style":583},[16644],{"type":420,"value":800},{"type":415,"tag":559,"props":16646,"children":16647},{"style":792},[16648],{"type":420,"value":16649}," AzureBuiltInRoles",{"type":415,"tag":559,"props":16651,"children":16652},{"style":583},[16653],{"type":420,"value":542},{"type":415,"tag":559,"props":16655,"children":16656},{"style":792},[16657],{"type":420,"value":16658},"Contributor",{"type":415,"tag":559,"props":16660,"children":16661},{"style":583},[16662],{"type":420,"value":605},{"type":415,"tag":559,"props":16664,"children":16665},{"class":561,"line":1795},[16666,16671,16675,16680,16684,16689,16693,16697,16701,16705,16710,16714],{"type":415,"tag":559,"props":16667,"children":16668},{"style":792},[16669],{"type":420,"value":16670},"    Scope ",{"type":415,"tag":559,"props":16672,"children":16673},{"style":583},[16674],{"type":420,"value":800},{"type":415,"tag":559,"props":16676,"children":16677},{"style":792},[16678],{"type":420,"value":16679}," Output",{"type":415,"tag":559,"props":16681,"children":16682},{"style":583},[16683],{"type":420,"value":542},{"type":415,"tag":559,"props":16685,"children":16686},{"style":883},[16687],{"type":420,"value":16688},"Format",{"type":415,"tag":559,"props":16690,"children":16691},{"style":583},[16692],{"type":420,"value":814},{"type":415,"tag":559,"props":16694,"children":16695},{"style":583},[16696],{"type":420,"value":16136},{"type":415,"tag":559,"props":16698,"children":16699},{"style":822},[16700],{"type":420,"value":16141},{"type":415,"tag":559,"props":16702,"children":16703},{"style":583},[16704],{"type":420,"value":2397},{"type":415,"tag":559,"props":16706,"children":16707},{"style":792},[16708],{"type":420,"value":16709},"subscriptionId",{"type":415,"tag":559,"props":16711,"children":16712},{"style":583},[16713],{"type":420,"value":1602},{"type":415,"tag":559,"props":16715,"children":16716},{"style":583},[16717],{"type":420,"value":833},{"type":415,"tag":559,"props":16719,"children":16720},{"class":561,"line":3289},[16721],{"type":415,"tag":559,"props":16722,"children":16723},{"style":583},[16724],{"type":420,"value":5833},{"type":415,"tag":1178,"props":16726,"children":16727},{"icon":14241},[16728],{"type":415,"tag":416,"props":16729,"children":16730},{},[16731,16733],{"type":420,"value":16732},"It's worth mentioning that using an Application and its associated Service Principal is not the only way to proceed, we could have created instead a ",{"type":415,"tag":434,"props":16734,"children":16737},{"href":16735,"rel":16736},"https://www.pulumi.com/registry/packages/azure-native/api-docs/managedidentity/userassignedidentity/",[438],[16738],{"type":420,"value":16739},"User Assigned Identity",{"type":415,"tag":416,"props":16741,"children":16742},{},[16743],{"type":420,"value":16744},"Now that everything is created, we can create the Federated identity credentials:",{"type":415,"tag":549,"props":16746,"children":16748},{"className":551,"code":16747,"language":326,"meta":401,"style":401},"new ApplicationFederatedIdentityCredential(\"ADOAzureReadyAppFederatedIdentityCredential\", new() \n{\n    ApplicationObjectId = aadApplication.ObjectId,\n    DisplayName = \"AzureReadyDeploys\",\n    Description = \"Deployments for azure-ready-repository\",\n    Audiences = new(){\"api://AzureADTokenExchange\" },\n    Issuer = serviceConnection.WorkloadIdentityFederationIssuer,\n    Subject = Output.Format($\"sc://{organisationName}/{project.Name}/{serviceConnection.ServiceEndpointName}\")\n});\n",[16749],{"type":415,"tag":555,"props":16750,"children":16751},{"__ignoreMap":401},[16752,16794,16801,16830,16858,16886,16921,16950,17055],{"type":415,"tag":559,"props":16753,"children":16754},{"class":561,"line":562},[16755,16759,16764,16768,16772,16777,16781,16785,16790],{"type":415,"tag":559,"props":16756,"children":16757},{"style":566},[16758],{"type":420,"value":16537},{"type":415,"tag":559,"props":16760,"children":16761},{"style":883},[16762],{"type":420,"value":16763}," ApplicationFederatedIdentityCredential",{"type":415,"tag":559,"props":16765,"children":16766},{"style":583},[16767],{"type":420,"value":814},{"type":415,"tag":559,"props":16769,"children":16770},{"style":583},[16771],{"type":420,"value":819},{"type":415,"tag":559,"props":16773,"children":16774},{"style":822},[16775],{"type":420,"value":16776},"ADOAzureReadyAppFederatedIdentityCredential",{"type":415,"tag":559,"props":16778,"children":16779},{"style":583},[16780],{"type":420,"value":819},{"type":415,"tag":559,"props":16782,"children":16783},{"style":583},[16784],{"type":420,"value":2312},{"type":415,"tag":559,"props":16786,"children":16787},{"style":583},[16788],{"type":420,"value":16789}," new()",{"type":415,"tag":559,"props":16791,"children":16792},{"style":792},[16793],{"type":420,"value":1473},{"type":415,"tag":559,"props":16795,"children":16796},{"class":561,"line":589},[16797],{"type":415,"tag":559,"props":16798,"children":16799},{"style":583},[16800],{"type":420,"value":786},{"type":415,"tag":559,"props":16802,"children":16803},{"class":561,"line":608},[16804,16809,16813,16817,16821,16826],{"type":415,"tag":559,"props":16805,"children":16806},{"style":792},[16807],{"type":420,"value":16808},"    ApplicationObjectId ",{"type":415,"tag":559,"props":16810,"children":16811},{"style":583},[16812],{"type":420,"value":800},{"type":415,"tag":559,"props":16814,"children":16815},{"style":792},[16816],{"type":420,"value":16298},{"type":415,"tag":559,"props":16818,"children":16819},{"style":583},[16820],{"type":420,"value":542},{"type":415,"tag":559,"props":16822,"children":16823},{"style":792},[16824],{"type":420,"value":16825},"ObjectId",{"type":415,"tag":559,"props":16827,"children":16828},{"style":583},[16829],{"type":420,"value":605},{"type":415,"tag":559,"props":16831,"children":16832},{"class":561,"line":626},[16833,16837,16841,16845,16850,16854],{"type":415,"tag":559,"props":16834,"children":16835},{"style":792},[16836],{"type":420,"value":16351},{"type":415,"tag":559,"props":16838,"children":16839},{"style":583},[16840],{"type":420,"value":800},{"type":415,"tag":559,"props":16842,"children":16843},{"style":583},[16844],{"type":420,"value":1434},{"type":415,"tag":559,"props":16846,"children":16847},{"style":822},[16848],{"type":420,"value":16849},"AzureReadyDeploys",{"type":415,"tag":559,"props":16851,"children":16852},{"style":583},[16853],{"type":420,"value":819},{"type":415,"tag":559,"props":16855,"children":16856},{"style":583},[16857],{"type":420,"value":605},{"type":415,"tag":559,"props":16859,"children":16860},{"class":561,"line":643},[16861,16865,16869,16873,16878,16882],{"type":415,"tag":559,"props":16862,"children":16863},{"style":792},[16864],{"type":420,"value":14779},{"type":415,"tag":559,"props":16866,"children":16867},{"style":583},[16868],{"type":420,"value":800},{"type":415,"tag":559,"props":16870,"children":16871},{"style":583},[16872],{"type":420,"value":1434},{"type":415,"tag":559,"props":16874,"children":16875},{"style":822},[16876],{"type":420,"value":16877},"Deployments for azure-ready-repository",{"type":415,"tag":559,"props":16879,"children":16880},{"style":583},[16881],{"type":420,"value":819},{"type":415,"tag":559,"props":16883,"children":16884},{"style":583},[16885],{"type":420,"value":605},{"type":415,"tag":559,"props":16887,"children":16888},{"class":561,"line":660},[16889,16894,16898,16903,16907,16912,16916],{"type":415,"tag":559,"props":16890,"children":16891},{"style":792},[16892],{"type":420,"value":16893},"    Audiences ",{"type":415,"tag":559,"props":16895,"children":16896},{"style":583},[16897],{"type":420,"value":800},{"type":415,"tag":559,"props":16899,"children":16900},{"style":583},[16901],{"type":420,"value":16902}," new(){",{"type":415,"tag":559,"props":16904,"children":16905},{"style":583},[16906],{"type":420,"value":819},{"type":415,"tag":559,"props":16908,"children":16909},{"style":822},[16910],{"type":420,"value":16911},"api://AzureADTokenExchange",{"type":415,"tag":559,"props":16913,"children":16914},{"style":583},[16915],{"type":420,"value":819},{"type":415,"tag":559,"props":16917,"children":16918},{"style":583},[16919],{"type":420,"value":16920}," },\n",{"type":415,"tag":559,"props":16922,"children":16923},{"class":561,"line":677},[16924,16929,16933,16937,16941,16946],{"type":415,"tag":559,"props":16925,"children":16926},{"style":792},[16927],{"type":420,"value":16928},"    Issuer ",{"type":415,"tag":559,"props":16930,"children":16931},{"style":583},[16932],{"type":420,"value":800},{"type":415,"tag":559,"props":16934,"children":16935},{"style":792},[16936],{"type":420,"value":15534},{"type":415,"tag":559,"props":16938,"children":16939},{"style":583},[16940],{"type":420,"value":542},{"type":415,"tag":559,"props":16942,"children":16943},{"style":792},[16944],{"type":420,"value":16945},"WorkloadIdentityFederationIssuer",{"type":415,"tag":559,"props":16947,"children":16948},{"style":583},[16949],{"type":420,"value":605},{"type":415,"tag":559,"props":16951,"children":16952},{"class":561,"line":690},[16953,16958,16962,16966,16970,16974,16978,16982,16987,16991,16996,17000,17004,17008,17013,17017,17021,17025,17029,17033,17038,17042,17047,17051],{"type":415,"tag":559,"props":16954,"children":16955},{"style":792},[16956],{"type":420,"value":16957},"    Subject ",{"type":415,"tag":559,"props":16959,"children":16960},{"style":583},[16961],{"type":420,"value":800},{"type":415,"tag":559,"props":16963,"children":16964},{"style":792},[16965],{"type":420,"value":16679},{"type":415,"tag":559,"props":16967,"children":16968},{"style":583},[16969],{"type":420,"value":542},{"type":415,"tag":559,"props":16971,"children":16972},{"style":883},[16973],{"type":420,"value":16688},{"type":415,"tag":559,"props":16975,"children":16976},{"style":583},[16977],{"type":420,"value":814},{"type":415,"tag":559,"props":16979,"children":16980},{"style":583},[16981],{"type":420,"value":16136},{"type":415,"tag":559,"props":16983,"children":16984},{"style":822},[16985],{"type":420,"value":16986},"sc://",{"type":415,"tag":559,"props":16988,"children":16989},{"style":583},[16990],{"type":420,"value":2397},{"type":415,"tag":559,"props":16992,"children":16993},{"style":792},[16994],{"type":420,"value":16995},"organisationName",{"type":415,"tag":559,"props":16997,"children":16998},{"style":583},[16999],{"type":420,"value":1580},{"type":415,"tag":559,"props":17001,"children":17002},{"style":822},[17003],{"type":420,"value":12238},{"type":415,"tag":559,"props":17005,"children":17006},{"style":583},[17007],{"type":420,"value":2397},{"type":415,"tag":559,"props":17009,"children":17010},{"style":792},[17011],{"type":420,"value":17012},"project",{"type":415,"tag":559,"props":17014,"children":17015},{"style":583},[17016],{"type":420,"value":542},{"type":415,"tag":559,"props":17018,"children":17019},{"style":792},[17020],{"type":420,"value":1412},{"type":415,"tag":559,"props":17022,"children":17023},{"style":583},[17024],{"type":420,"value":1580},{"type":415,"tag":559,"props":17026,"children":17027},{"style":822},[17028],{"type":420,"value":12238},{"type":415,"tag":559,"props":17030,"children":17031},{"style":583},[17032],{"type":420,"value":2397},{"type":415,"tag":559,"props":17034,"children":17035},{"style":792},[17036],{"type":420,"value":17037},"serviceConnection",{"type":415,"tag":559,"props":17039,"children":17040},{"style":583},[17041],{"type":420,"value":542},{"type":415,"tag":559,"props":17043,"children":17044},{"style":792},[17045],{"type":420,"value":17046},"ServiceEndpointName",{"type":415,"tag":559,"props":17048,"children":17049},{"style":583},[17050],{"type":420,"value":1602},{"type":415,"tag":559,"props":17052,"children":17053},{"style":583},[17054],{"type":420,"value":833},{"type":415,"tag":559,"props":17056,"children":17057},{"class":561,"line":1089},[17058],{"type":415,"tag":559,"props":17059,"children":17060},{"style":583},[17061],{"type":420,"value":5833},{"type":415,"tag":416,"props":17063,"children":17064},{},[17065,17067,17073],{"type":420,"value":17066},"You can observe that the federation subject adheres to a particular format (",{"type":415,"tag":555,"props":17068,"children":17070},{"className":17069},[],[17071],{"type":420,"value":17072},"sc://\u003Corg>/\u003Cproject>/\u003Cservice connection name>",{"type":420,"value":17074},"), which identifies the service connection authorized for authentication with Azure.",{"type":415,"tag":14340,"props":17076,"children":17078},{"id":17077},"create-the-deployment-pipeline",[17079],{"type":420,"value":17080},"Create the deployment pipeline",{"type":415,"tag":416,"props":17082,"children":17083},{},[17084],{"type":420,"value":17085},"We have completed the configuration of an ARM Service Connection that employs Workload Identity Federation for authentication with Azure. While we could stop at this point, it would be nice to automate the creation of a pipeline that utilizes this service connection and seize the opportunity to ensure everything works properly.",{"type":415,"tag":416,"props":17087,"children":17088},{},[17089,17091,17097],{"type":420,"value":17090},"For this purpose, I have written a very simple YAML pipeline that runs the ",{"type":415,"tag":555,"props":17092,"children":17094},{"className":17093},[],[17095],{"type":420,"value":17096},"AzureCLI",{"type":420,"value":17098}," task to show information about the Azure subscription associated with the previously created service connection.",{"type":415,"tag":549,"props":17100,"children":17102},{"className":551,"code":17101,"language":326,"meta":401,"style":401},"trigger:\n  - main\n\npool:\n  vmImage: ubuntu-latest\n\nsteps:\n  - task: AzureCLI@2\n    inputs:\n      azureSubscription: 'azure-with-oidc'\n      scriptType: 'pscore'\n      scriptLocation: 'inlineScript'\n      inlineScript: 'az account show --query id -o tsv'\n",[17103],{"type":415,"tag":555,"props":17104,"children":17105},{"__ignoreMap":401},[17106,17119,17132,17139,17151,17178,17185,17197,17223,17235,17261,17286,17311],{"type":415,"tag":559,"props":17107,"children":17108},{"class":561,"line":562},[17109,17114],{"type":415,"tag":559,"props":17110,"children":17111},{"style":572},[17112],{"type":420,"value":17113},"trigger",{"type":415,"tag":559,"props":17115,"children":17116},{"style":583},[17117],{"type":420,"value":17118},":\n",{"type":415,"tag":559,"props":17120,"children":17121},{"class":561,"line":589},[17122,17127],{"type":415,"tag":559,"props":17123,"children":17124},{"style":583},[17125],{"type":420,"value":17126},"  -",{"type":415,"tag":559,"props":17128,"children":17129},{"style":792},[17130],{"type":420,"value":17131}," main\n",{"type":415,"tag":559,"props":17133,"children":17134},{"class":561,"line":608},[17135],{"type":415,"tag":559,"props":17136,"children":17137},{"emptyLinePlaceholder":847},[17138],{"type":420,"value":850},{"type":415,"tag":559,"props":17140,"children":17141},{"class":561,"line":626},[17142,17147],{"type":415,"tag":559,"props":17143,"children":17144},{"style":572},[17145],{"type":420,"value":17146},"pool",{"type":415,"tag":559,"props":17148,"children":17149},{"style":583},[17150],{"type":420,"value":17118},{"type":415,"tag":559,"props":17152,"children":17153},{"class":561,"line":643},[17154,17159,17163,17168,17173],{"type":415,"tag":559,"props":17155,"children":17156},{"style":572},[17157],{"type":420,"value":17158},"  vmImage",{"type":415,"tag":559,"props":17160,"children":17161},{"style":583},[17162],{"type":420,"value":1206},{"type":415,"tag":559,"props":17164,"children":17165},{"style":792},[17166],{"type":420,"value":17167}," ubuntu",{"type":415,"tag":559,"props":17169,"children":17170},{"style":583},[17171],{"type":420,"value":17172},"-",{"type":415,"tag":559,"props":17174,"children":17175},{"style":792},[17176],{"type":420,"value":17177},"latest\n",{"type":415,"tag":559,"props":17179,"children":17180},{"class":561,"line":660},[17181],{"type":415,"tag":559,"props":17182,"children":17183},{"emptyLinePlaceholder":847},[17184],{"type":420,"value":850},{"type":415,"tag":559,"props":17186,"children":17187},{"class":561,"line":677},[17188,17193],{"type":415,"tag":559,"props":17189,"children":17190},{"style":572},[17191],{"type":420,"value":17192},"steps",{"type":415,"tag":559,"props":17194,"children":17195},{"style":583},[17196],{"type":420,"value":17118},{"type":415,"tag":559,"props":17198,"children":17199},{"class":561,"line":690},[17200,17204,17209,17213,17218],{"type":415,"tag":559,"props":17201,"children":17202},{"style":583},[17203],{"type":420,"value":17126},{"type":415,"tag":559,"props":17205,"children":17206},{"style":572},[17207],{"type":420,"value":17208}," task",{"type":415,"tag":559,"props":17210,"children":17211},{"style":583},[17212],{"type":420,"value":1206},{"type":415,"tag":559,"props":17214,"children":17215},{"style":792},[17216],{"type":420,"value":17217}," AzureCLI@",{"type":415,"tag":559,"props":17219,"children":17220},{"style":2846},[17221],{"type":420,"value":17222},"2\n",{"type":415,"tag":559,"props":17224,"children":17225},{"class":561,"line":1089},[17226,17231],{"type":415,"tag":559,"props":17227,"children":17228},{"style":572},[17229],{"type":420,"value":17230},"    inputs",{"type":415,"tag":559,"props":17232,"children":17233},{"style":583},[17234],{"type":420,"value":17118},{"type":415,"tag":559,"props":17236,"children":17237},{"class":561,"line":1102},[17238,17243,17247,17252,17256],{"type":415,"tag":559,"props":17239,"children":17240},{"style":572},[17241],{"type":420,"value":17242},"      azureSubscription",{"type":415,"tag":559,"props":17244,"children":17245},{"style":583},[17246],{"type":420,"value":1206},{"type":415,"tag":559,"props":17248,"children":17249},{"style":583},[17250],{"type":420,"value":17251}," '",{"type":415,"tag":559,"props":17253,"children":17254},{"style":822},[17255],{"type":420,"value":15627},{"type":415,"tag":559,"props":17257,"children":17258},{"style":583},[17259],{"type":420,"value":17260},"'\n",{"type":415,"tag":559,"props":17262,"children":17263},{"class":561,"line":1110},[17264,17269,17273,17277,17282],{"type":415,"tag":559,"props":17265,"children":17266},{"style":572},[17267],{"type":420,"value":17268},"      scriptType",{"type":415,"tag":559,"props":17270,"children":17271},{"style":583},[17272],{"type":420,"value":1206},{"type":415,"tag":559,"props":17274,"children":17275},{"style":583},[17276],{"type":420,"value":17251},{"type":415,"tag":559,"props":17278,"children":17279},{"style":822},[17280],{"type":420,"value":17281},"pscore",{"type":415,"tag":559,"props":17283,"children":17284},{"style":583},[17285],{"type":420,"value":17260},{"type":415,"tag":559,"props":17287,"children":17288},{"class":561,"line":1118},[17289,17294,17298,17302,17307],{"type":415,"tag":559,"props":17290,"children":17291},{"style":572},[17292],{"type":420,"value":17293},"      scriptLocation",{"type":415,"tag":559,"props":17295,"children":17296},{"style":583},[17297],{"type":420,"value":1206},{"type":415,"tag":559,"props":17299,"children":17300},{"style":583},[17301],{"type":420,"value":17251},{"type":415,"tag":559,"props":17303,"children":17304},{"style":822},[17305],{"type":420,"value":17306},"inlineScript",{"type":415,"tag":559,"props":17308,"children":17309},{"style":583},[17310],{"type":420,"value":17260},{"type":415,"tag":559,"props":17312,"children":17313},{"class":561,"line":1171},[17314,17319,17323,17327,17332],{"type":415,"tag":559,"props":17315,"children":17316},{"style":572},[17317],{"type":420,"value":17318},"      inlineScript",{"type":415,"tag":559,"props":17320,"children":17321},{"style":583},[17322],{"type":420,"value":1206},{"type":415,"tag":559,"props":17324,"children":17325},{"style":583},[17326],{"type":420,"value":17251},{"type":415,"tag":559,"props":17328,"children":17329},{"style":822},[17330],{"type":420,"value":17331},"az account show --query id -o tsv",{"type":415,"tag":559,"props":17333,"children":17334},{"style":583},[17335],{"type":420,"value":17260},{"type":415,"tag":416,"props":17337,"children":17338},{},[17339],{"type":420,"value":17340},"We can add this file in the Git repository:",{"type":415,"tag":549,"props":17342,"children":17344},{"className":551,"code":17343,"language":326,"meta":401,"style":401},"var pipelineFile = new GitRepositoryFile(\"AzurePipeline\", new()\n{\n    File = \"azure-pipelines.yaml\",\n    RepositoryId = repository.Apply(r => r.Id),\n    CommitMessage = \"Add preconfigured pipeline file\",\n    Content = File.ReadAllText(\"azure-pipelines.yml\"),\n    Branch = \"refs/heads/main\"\n});\n",[17345],{"type":415,"tag":555,"props":17346,"children":17347},{"__ignoreMap":401},[17348,17398,17405,17434,17488,17517,17564,17588],{"type":415,"tag":559,"props":17349,"children":17350},{"class":561,"line":562},[17351,17355,17360,17364,17368,17373,17377,17381,17386,17390,17394],{"type":415,"tag":559,"props":17352,"children":17353},{"style":572},[17354],{"type":420,"value":858},{"type":415,"tag":559,"props":17356,"children":17357},{"style":572},[17358],{"type":420,"value":17359}," pipelineFile",{"type":415,"tag":559,"props":17361,"children":17362},{"style":583},[17363],{"type":420,"value":763},{"type":415,"tag":559,"props":17365,"children":17366},{"style":583},[17367],{"type":420,"value":768},{"type":415,"tag":559,"props":17369,"children":17370},{"style":572},[17371],{"type":420,"value":17372}," GitRepositoryFile",{"type":415,"tag":559,"props":17374,"children":17375},{"style":583},[17376],{"type":420,"value":814},{"type":415,"tag":559,"props":17378,"children":17379},{"style":583},[17380],{"type":420,"value":819},{"type":415,"tag":559,"props":17382,"children":17383},{"style":822},[17384],{"type":420,"value":17385},"AzurePipeline",{"type":415,"tag":559,"props":17387,"children":17388},{"style":583},[17389],{"type":420,"value":819},{"type":415,"tag":559,"props":17391,"children":17392},{"style":583},[17393],{"type":420,"value":2312},{"type":415,"tag":559,"props":17395,"children":17396},{"style":583},[17397],{"type":420,"value":14764},{"type":415,"tag":559,"props":17399,"children":17400},{"class":561,"line":589},[17401],{"type":415,"tag":559,"props":17402,"children":17403},{"style":583},[17404],{"type":420,"value":786},{"type":415,"tag":559,"props":17406,"children":17407},{"class":561,"line":608},[17408,17413,17417,17421,17426,17430],{"type":415,"tag":559,"props":17409,"children":17410},{"style":792},[17411],{"type":420,"value":17412},"    File ",{"type":415,"tag":559,"props":17414,"children":17415},{"style":583},[17416],{"type":420,"value":800},{"type":415,"tag":559,"props":17418,"children":17419},{"style":583},[17420],{"type":420,"value":1434},{"type":415,"tag":559,"props":17422,"children":17423},{"style":822},[17424],{"type":420,"value":17425},"azure-pipelines.yaml",{"type":415,"tag":559,"props":17427,"children":17428},{"style":583},[17429],{"type":420,"value":819},{"type":415,"tag":559,"props":17431,"children":17432},{"style":583},[17433],{"type":420,"value":605},{"type":415,"tag":559,"props":17435,"children":17436},{"class":561,"line":626},[17437,17442,17446,17450,17454,17458,17462,17467,17471,17476,17480,17484],{"type":415,"tag":559,"props":17438,"children":17439},{"style":792},[17440],{"type":420,"value":17441},"    RepositoryId ",{"type":415,"tag":559,"props":17443,"children":17444},{"style":583},[17445],{"type":420,"value":800},{"type":415,"tag":559,"props":17447,"children":17448},{"style":792},[17449],{"type":420,"value":15095},{"type":415,"tag":559,"props":17451,"children":17452},{"style":583},[17453],{"type":420,"value":542},{"type":415,"tag":559,"props":17455,"children":17456},{"style":883},[17457],{"type":420,"value":15884},{"type":415,"tag":559,"props":17459,"children":17460},{"style":583},[17461],{"type":420,"value":814},{"type":415,"tag":559,"props":17463,"children":17464},{"style":572},[17465],{"type":420,"value":17466},"r",{"type":415,"tag":559,"props":17468,"children":17469},{"style":583},[17470],{"type":420,"value":1861},{"type":415,"tag":559,"props":17472,"children":17473},{"style":792},[17474],{"type":420,"value":17475}," r",{"type":415,"tag":559,"props":17477,"children":17478},{"style":583},[17479],{"type":420,"value":542},{"type":415,"tag":559,"props":17481,"children":17482},{"style":792},[17483],{"type":420,"value":15150},{"type":415,"tag":559,"props":17485,"children":17486},{"style":583},[17487],{"type":420,"value":10369},{"type":415,"tag":559,"props":17489,"children":17490},{"class":561,"line":643},[17491,17496,17500,17504,17509,17513],{"type":415,"tag":559,"props":17492,"children":17493},{"style":792},[17494],{"type":420,"value":17495},"    CommitMessage ",{"type":415,"tag":559,"props":17497,"children":17498},{"style":583},[17499],{"type":420,"value":800},{"type":415,"tag":559,"props":17501,"children":17502},{"style":583},[17503],{"type":420,"value":1434},{"type":415,"tag":559,"props":17505,"children":17506},{"style":822},[17507],{"type":420,"value":17508},"Add preconfigured pipeline file",{"type":415,"tag":559,"props":17510,"children":17511},{"style":583},[17512],{"type":420,"value":819},{"type":415,"tag":559,"props":17514,"children":17515},{"style":583},[17516],{"type":420,"value":605},{"type":415,"tag":559,"props":17518,"children":17519},{"class":561,"line":660},[17520,17525,17529,17534,17538,17543,17547,17551,17556,17560],{"type":415,"tag":559,"props":17521,"children":17522},{"style":792},[17523],{"type":420,"value":17524},"    Content ",{"type":415,"tag":559,"props":17526,"children":17527},{"style":583},[17528],{"type":420,"value":800},{"type":415,"tag":559,"props":17530,"children":17531},{"style":792},[17532],{"type":420,"value":17533}," File",{"type":415,"tag":559,"props":17535,"children":17536},{"style":583},[17537],{"type":420,"value":542},{"type":415,"tag":559,"props":17539,"children":17540},{"style":883},[17541],{"type":420,"value":17542},"ReadAllText",{"type":415,"tag":559,"props":17544,"children":17545},{"style":583},[17546],{"type":420,"value":814},{"type":415,"tag":559,"props":17548,"children":17549},{"style":583},[17550],{"type":420,"value":819},{"type":415,"tag":559,"props":17552,"children":17553},{"style":822},[17554],{"type":420,"value":17555},"azure-pipelines.yml",{"type":415,"tag":559,"props":17557,"children":17558},{"style":583},[17559],{"type":420,"value":819},{"type":415,"tag":559,"props":17561,"children":17562},{"style":583},[17563],{"type":420,"value":10369},{"type":415,"tag":559,"props":17565,"children":17566},{"class":561,"line":677},[17567,17572,17576,17580,17584],{"type":415,"tag":559,"props":17568,"children":17569},{"style":792},[17570],{"type":420,"value":17571},"    Branch ",{"type":415,"tag":559,"props":17573,"children":17574},{"style":583},[17575],{"type":420,"value":800},{"type":415,"tag":559,"props":17577,"children":17578},{"style":583},[17579],{"type":420,"value":1434},{"type":415,"tag":559,"props":17581,"children":17582},{"style":822},[17583],{"type":420,"value":15445},{"type":415,"tag":559,"props":17585,"children":17586},{"style":583},[17587],{"type":420,"value":10222},{"type":415,"tag":559,"props":17589,"children":17590},{"class":561,"line":690},[17591],{"type":415,"tag":559,"props":17592,"children":17593},{"style":583},[17594],{"type":420,"value":5833},{"type":415,"tag":416,"props":17596,"children":17597},{},[17598],{"type":420,"value":17599},"Now, we have to create the pipeline itself:",{"type":415,"tag":549,"props":17601,"children":17603},{"className":551,"code":17602,"language":326,"meta":401,"style":401},"var pipeline = new BuildDefinition(\"deployToAzure\", new()\n{\n    ProjectId = project.Id,\n    Repository = new BuildDefinitionRepositoryArgs()\n    {\n        RepoId = repository.Apply(r => r.Id),\n        BranchName = \"refs/heads/main\",\n        YmlPath = pipelineFile.File,\n        RepoType = \"TfsGit\"\n    }\n});\n",[17604],{"type":415,"tag":555,"props":17605,"children":17606},{"__ignoreMap":401},[17607,17657,17664,17691,17716,17723,17775,17803,17832,17857,17864],{"type":415,"tag":559,"props":17608,"children":17609},{"class":561,"line":562},[17610,17614,17619,17623,17627,17632,17636,17640,17645,17649,17653],{"type":415,"tag":559,"props":17611,"children":17612},{"style":572},[17613],{"type":420,"value":858},{"type":415,"tag":559,"props":17615,"children":17616},{"style":572},[17617],{"type":420,"value":17618}," pipeline",{"type":415,"tag":559,"props":17620,"children":17621},{"style":583},[17622],{"type":420,"value":763},{"type":415,"tag":559,"props":17624,"children":17625},{"style":583},[17626],{"type":420,"value":768},{"type":415,"tag":559,"props":17628,"children":17629},{"style":572},[17630],{"type":420,"value":17631}," BuildDefinition",{"type":415,"tag":559,"props":17633,"children":17634},{"style":583},[17635],{"type":420,"value":814},{"type":415,"tag":559,"props":17637,"children":17638},{"style":583},[17639],{"type":420,"value":819},{"type":415,"tag":559,"props":17641,"children":17642},{"style":822},[17643],{"type":420,"value":17644},"deployToAzure",{"type":415,"tag":559,"props":17646,"children":17647},{"style":583},[17648],{"type":420,"value":819},{"type":415,"tag":559,"props":17650,"children":17651},{"style":583},[17652],{"type":420,"value":2312},{"type":415,"tag":559,"props":17654,"children":17655},{"style":583},[17656],{"type":420,"value":14764},{"type":415,"tag":559,"props":17658,"children":17659},{"class":561,"line":589},[17660],{"type":415,"tag":559,"props":17661,"children":17662},{"style":583},[17663],{"type":420,"value":786},{"type":415,"tag":559,"props":17665,"children":17666},{"class":561,"line":608},[17667,17671,17675,17679,17683,17687],{"type":415,"tag":559,"props":17668,"children":17669},{"style":792},[17670],{"type":420,"value":15133},{"type":415,"tag":559,"props":17672,"children":17673},{"style":583},[17674],{"type":420,"value":800},{"type":415,"tag":559,"props":17676,"children":17677},{"style":792},[17678],{"type":420,"value":14725},{"type":415,"tag":559,"props":17680,"children":17681},{"style":583},[17682],{"type":420,"value":542},{"type":415,"tag":559,"props":17684,"children":17685},{"style":792},[17686],{"type":420,"value":15150},{"type":415,"tag":559,"props":17688,"children":17689},{"style":583},[17690],{"type":420,"value":605},{"type":415,"tag":559,"props":17692,"children":17693},{"class":561,"line":626},[17694,17699,17703,17707,17712],{"type":415,"tag":559,"props":17695,"children":17696},{"style":792},[17697],{"type":420,"value":17698},"    Repository ",{"type":415,"tag":559,"props":17700,"children":17701},{"style":583},[17702],{"type":420,"value":800},{"type":415,"tag":559,"props":17704,"children":17705},{"style":583},[17706],{"type":420,"value":768},{"type":415,"tag":559,"props":17708,"children":17709},{"style":572},[17710],{"type":420,"value":17711}," BuildDefinitionRepositoryArgs",{"type":415,"tag":559,"props":17713,"children":17714},{"style":583},[17715],{"type":420,"value":778},{"type":415,"tag":559,"props":17717,"children":17718},{"class":561,"line":643},[17719],{"type":415,"tag":559,"props":17720,"children":17721},{"style":583},[17722],{"type":420,"value":2737},{"type":415,"tag":559,"props":17724,"children":17725},{"class":561,"line":660},[17726,17731,17735,17739,17743,17747,17751,17755,17759,17763,17767,17771],{"type":415,"tag":559,"props":17727,"children":17728},{"style":792},[17729],{"type":420,"value":17730},"        RepoId ",{"type":415,"tag":559,"props":17732,"children":17733},{"style":583},[17734],{"type":420,"value":800},{"type":415,"tag":559,"props":17736,"children":17737},{"style":792},[17738],{"type":420,"value":15095},{"type":415,"tag":559,"props":17740,"children":17741},{"style":583},[17742],{"type":420,"value":542},{"type":415,"tag":559,"props":17744,"children":17745},{"style":883},[17746],{"type":420,"value":15884},{"type":415,"tag":559,"props":17748,"children":17749},{"style":583},[17750],{"type":420,"value":814},{"type":415,"tag":559,"props":17752,"children":17753},{"style":572},[17754],{"type":420,"value":17466},{"type":415,"tag":559,"props":17756,"children":17757},{"style":583},[17758],{"type":420,"value":1861},{"type":415,"tag":559,"props":17760,"children":17761},{"style":792},[17762],{"type":420,"value":17475},{"type":415,"tag":559,"props":17764,"children":17765},{"style":583},[17766],{"type":420,"value":542},{"type":415,"tag":559,"props":17768,"children":17769},{"style":792},[17770],{"type":420,"value":15150},{"type":415,"tag":559,"props":17772,"children":17773},{"style":583},[17774],{"type":420,"value":10369},{"type":415,"tag":559,"props":17776,"children":17777},{"class":561,"line":677},[17778,17783,17787,17791,17795,17799],{"type":415,"tag":559,"props":17779,"children":17780},{"style":792},[17781],{"type":420,"value":17782},"        BranchName ",{"type":415,"tag":559,"props":17784,"children":17785},{"style":583},[17786],{"type":420,"value":800},{"type":415,"tag":559,"props":17788,"children":17789},{"style":583},[17790],{"type":420,"value":1434},{"type":415,"tag":559,"props":17792,"children":17793},{"style":822},[17794],{"type":420,"value":15445},{"type":415,"tag":559,"props":17796,"children":17797},{"style":583},[17798],{"type":420,"value":819},{"type":415,"tag":559,"props":17800,"children":17801},{"style":583},[17802],{"type":420,"value":605},{"type":415,"tag":559,"props":17804,"children":17805},{"class":561,"line":690},[17806,17811,17815,17819,17823,17828],{"type":415,"tag":559,"props":17807,"children":17808},{"style":792},[17809],{"type":420,"value":17810},"        YmlPath ",{"type":415,"tag":559,"props":17812,"children":17813},{"style":583},[17814],{"type":420,"value":800},{"type":415,"tag":559,"props":17816,"children":17817},{"style":792},[17818],{"type":420,"value":17359},{"type":415,"tag":559,"props":17820,"children":17821},{"style":583},[17822],{"type":420,"value":542},{"type":415,"tag":559,"props":17824,"children":17825},{"style":792},[17826],{"type":420,"value":17827},"File",{"type":415,"tag":559,"props":17829,"children":17830},{"style":583},[17831],{"type":420,"value":605},{"type":415,"tag":559,"props":17833,"children":17834},{"class":561,"line":1089},[17835,17840,17844,17848,17853],{"type":415,"tag":559,"props":17836,"children":17837},{"style":792},[17838],{"type":420,"value":17839},"        RepoType ",{"type":415,"tag":559,"props":17841,"children":17842},{"style":583},[17843],{"type":420,"value":800},{"type":415,"tag":559,"props":17845,"children":17846},{"style":583},[17847],{"type":420,"value":1434},{"type":415,"tag":559,"props":17849,"children":17850},{"style":822},[17851],{"type":420,"value":17852},"TfsGit",{"type":415,"tag":559,"props":17854,"children":17855},{"style":583},[17856],{"type":420,"value":10222},{"type":415,"tag":559,"props":17858,"children":17859},{"class":561,"line":1102},[17860],{"type":415,"tag":559,"props":17861,"children":17862},{"style":583},[17863],{"type":420,"value":2792},{"type":415,"tag":559,"props":17865,"children":17866},{"class":561,"line":1110},[17867],{"type":415,"tag":559,"props":17868,"children":17869},{"style":583},[17870],{"type":420,"value":5833},{"type":415,"tag":416,"props":17872,"children":17873},{},[17874],{"type":420,"value":17875},"To complete the automation process, we can authorize the pipeline to utilize the service connection, eliminating the need for manual intervention through the portal:",{"type":415,"tag":549,"props":17877,"children":17879},{"className":551,"code":17878,"language":326,"meta":401,"style":401},"new PipelineAuthorization(\"azureOidcPipelineAuthorization\", new()\n{\n    ProjectId = project.Id,\n    Type = \"endpoint\",\n    PipelineId = pipeline.Id.Apply(int.Parse),\n    ResourceId = serviceConnection.Id\n});\n",[17880],{"type":415,"tag":555,"props":17881,"children":17882},{"__ignoreMap":401},[17883,17920,17927,17954,17983,18029,18054],{"type":415,"tag":559,"props":17884,"children":17885},{"class":561,"line":562},[17886,17890,17895,17899,17903,17908,17912,17916],{"type":415,"tag":559,"props":17887,"children":17888},{"style":566},[17889],{"type":420,"value":16537},{"type":415,"tag":559,"props":17891,"children":17892},{"style":883},[17893],{"type":420,"value":17894}," PipelineAuthorization",{"type":415,"tag":559,"props":17896,"children":17897},{"style":583},[17898],{"type":420,"value":814},{"type":415,"tag":559,"props":17900,"children":17901},{"style":583},[17902],{"type":420,"value":819},{"type":415,"tag":559,"props":17904,"children":17905},{"style":822},[17906],{"type":420,"value":17907},"azureOidcPipelineAuthorization",{"type":415,"tag":559,"props":17909,"children":17910},{"style":583},[17911],{"type":420,"value":819},{"type":415,"tag":559,"props":17913,"children":17914},{"style":583},[17915],{"type":420,"value":2312},{"type":415,"tag":559,"props":17917,"children":17918},{"style":583},[17919],{"type":420,"value":14764},{"type":415,"tag":559,"props":17921,"children":17922},{"class":561,"line":589},[17923],{"type":415,"tag":559,"props":17924,"children":17925},{"style":583},[17926],{"type":420,"value":786},{"type":415,"tag":559,"props":17928,"children":17929},{"class":561,"line":608},[17930,17934,17938,17942,17946,17950],{"type":415,"tag":559,"props":17931,"children":17932},{"style":792},[17933],{"type":420,"value":15133},{"type":415,"tag":559,"props":17935,"children":17936},{"style":583},[17937],{"type":420,"value":800},{"type":415,"tag":559,"props":17939,"children":17940},{"style":792},[17941],{"type":420,"value":14725},{"type":415,"tag":559,"props":17943,"children":17944},{"style":583},[17945],{"type":420,"value":542},{"type":415,"tag":559,"props":17947,"children":17948},{"style":792},[17949],{"type":420,"value":15150},{"type":415,"tag":559,"props":17951,"children":17952},{"style":583},[17953],{"type":420,"value":605},{"type":415,"tag":559,"props":17955,"children":17956},{"class":561,"line":626},[17957,17962,17966,17970,17975,17979],{"type":415,"tag":559,"props":17958,"children":17959},{"style":792},[17960],{"type":420,"value":17961},"    Type ",{"type":415,"tag":559,"props":17963,"children":17964},{"style":583},[17965],{"type":420,"value":800},{"type":415,"tag":559,"props":17967,"children":17968},{"style":583},[17969],{"type":420,"value":1434},{"type":415,"tag":559,"props":17971,"children":17972},{"style":822},[17973],{"type":420,"value":17974},"endpoint",{"type":415,"tag":559,"props":17976,"children":17977},{"style":583},[17978],{"type":420,"value":819},{"type":415,"tag":559,"props":17980,"children":17981},{"style":583},[17982],{"type":420,"value":605},{"type":415,"tag":559,"props":17984,"children":17985},{"class":561,"line":643},[17986,17991,17995,17999,18003,18007,18011,18015,18020,18025],{"type":415,"tag":559,"props":17987,"children":17988},{"style":792},[17989],{"type":420,"value":17990},"    PipelineId ",{"type":415,"tag":559,"props":17992,"children":17993},{"style":583},[17994],{"type":420,"value":800},{"type":415,"tag":559,"props":17996,"children":17997},{"style":792},[17998],{"type":420,"value":17618},{"type":415,"tag":559,"props":18000,"children":18001},{"style":583},[18002],{"type":420,"value":542},{"type":415,"tag":559,"props":18004,"children":18005},{"style":792},[18006],{"type":420,"value":15150},{"type":415,"tag":559,"props":18008,"children":18009},{"style":583},[18010],{"type":420,"value":542},{"type":415,"tag":559,"props":18012,"children":18013},{"style":883},[18014],{"type":420,"value":15884},{"type":415,"tag":559,"props":18016,"children":18017},{"style":583},[18018],{"type":420,"value":18019},"(int.",{"type":415,"tag":559,"props":18021,"children":18022},{"style":792},[18023],{"type":420,"value":18024},"Parse",{"type":415,"tag":559,"props":18026,"children":18027},{"style":583},[18028],{"type":420,"value":10369},{"type":415,"tag":559,"props":18030,"children":18031},{"class":561,"line":660},[18032,18037,18041,18045,18049],{"type":415,"tag":559,"props":18033,"children":18034},{"style":792},[18035],{"type":420,"value":18036},"    ResourceId ",{"type":415,"tag":559,"props":18038,"children":18039},{"style":583},[18040],{"type":420,"value":800},{"type":415,"tag":559,"props":18042,"children":18043},{"style":792},[18044],{"type":420,"value":15534},{"type":415,"tag":559,"props":18046,"children":18047},{"style":583},[18048],{"type":420,"value":542},{"type":415,"tag":559,"props":18050,"children":18051},{"style":792},[18052],{"type":420,"value":18053},"Id\n",{"type":415,"tag":559,"props":18055,"children":18056},{"class":561,"line":677},[18057],{"type":415,"tag":559,"props":18058,"children":18059},{"style":583},[18060],{"type":420,"value":5833},{"type":415,"tag":416,"props":18062,"children":18063},{},[18064],{"type":420,"value":18065},"The last thing we can do is create a stack output to expose the URL of the created pipeline:",{"type":415,"tag":549,"props":18067,"children":18069},{"className":551,"code":18068,"language":326,"meta":401,"style":401},"return new Dictionary\u003Cstring, object?>\n{\n    [\"pipelineUrl\"] = Output.Format($\"{organizationUrl}{project.Name}/_build?definitionId={pipeline.Id}\")\n};\n",[18070],{"type":415,"tag":555,"props":18071,"children":18072},{"__ignoreMap":401},[18073,18107,18114,18218],{"type":415,"tag":559,"props":18074,"children":18075},{"class":561,"line":562},[18076,18081,18085,18090,18094,18098,18102],{"type":415,"tag":559,"props":18077,"children":18078},{"style":745},[18079],{"type":420,"value":18080},"return",{"type":415,"tag":559,"props":18082,"children":18083},{"style":583},[18084],{"type":420,"value":768},{"type":415,"tag":559,"props":18086,"children":18087},{"style":572},[18088],{"type":420,"value":18089}," Dictionary",{"type":415,"tag":559,"props":18091,"children":18092},{"style":583},[18093],{"type":420,"value":891},{"type":415,"tag":559,"props":18095,"children":18096},{"style":583},[18097],{"type":420,"value":2015},{"type":415,"tag":559,"props":18099,"children":18100},{"style":583},[18101],{"type":420,"value":2312},{"type":415,"tag":559,"props":18103,"children":18104},{"style":583},[18105],{"type":420,"value":18106}," object?>\n",{"type":415,"tag":559,"props":18108,"children":18109},{"class":561,"line":589},[18110],{"type":415,"tag":559,"props":18111,"children":18112},{"style":583},[18113],{"type":420,"value":786},{"type":415,"tag":559,"props":18115,"children":18116},{"class":561,"line":608},[18117,18121,18125,18130,18134,18138,18142,18146,18150,18154,18158,18163,18168,18172,18176,18180,18184,18188,18193,18197,18202,18206,18210,18214],{"type":415,"tag":559,"props":18118,"children":18119},{"style":583},[18120],{"type":420,"value":8989},{"type":415,"tag":559,"props":18122,"children":18123},{"style":583},[18124],{"type":420,"value":819},{"type":415,"tag":559,"props":18126,"children":18127},{"style":822},[18128],{"type":420,"value":18129},"pipelineUrl",{"type":415,"tag":559,"props":18131,"children":18132},{"style":583},[18133],{"type":420,"value":819},{"type":415,"tag":559,"props":18135,"children":18136},{"style":583},[18137],{"type":420,"value":14849},{"type":415,"tag":559,"props":18139,"children":18140},{"style":583},[18141],{"type":420,"value":763},{"type":415,"tag":559,"props":18143,"children":18144},{"style":792},[18145],{"type":420,"value":16679},{"type":415,"tag":559,"props":18147,"children":18148},{"style":583},[18149],{"type":420,"value":542},{"type":415,"tag":559,"props":18151,"children":18152},{"style":883},[18153],{"type":420,"value":16688},{"type":415,"tag":559,"props":18155,"children":18156},{"style":583},[18157],{"type":420,"value":814},{"type":415,"tag":559,"props":18159,"children":18160},{"style":583},[18161],{"type":420,"value":18162},"$\"{",{"type":415,"tag":559,"props":18164,"children":18165},{"style":792},[18166],{"type":420,"value":18167},"organizationUrl",{"type":415,"tag":559,"props":18169,"children":18170},{"style":583},[18171],{"type":420,"value":2415},{"type":415,"tag":559,"props":18173,"children":18174},{"style":792},[18175],{"type":420,"value":17012},{"type":415,"tag":559,"props":18177,"children":18178},{"style":583},[18179],{"type":420,"value":542},{"type":415,"tag":559,"props":18181,"children":18182},{"style":792},[18183],{"type":420,"value":1412},{"type":415,"tag":559,"props":18185,"children":18186},{"style":583},[18187],{"type":420,"value":1580},{"type":415,"tag":559,"props":18189,"children":18190},{"style":822},[18191],{"type":420,"value":18192},"/_build?definitionId=",{"type":415,"tag":559,"props":18194,"children":18195},{"style":583},[18196],{"type":420,"value":2397},{"type":415,"tag":559,"props":18198,"children":18199},{"style":792},[18200],{"type":420,"value":18201},"pipeline",{"type":415,"tag":559,"props":18203,"children":18204},{"style":583},[18205],{"type":420,"value":542},{"type":415,"tag":559,"props":18207,"children":18208},{"style":792},[18209],{"type":420,"value":15150},{"type":415,"tag":559,"props":18211,"children":18212},{"style":583},[18213],{"type":420,"value":1602},{"type":415,"tag":559,"props":18215,"children":18216},{"style":583},[18217],{"type":420,"value":833},{"type":415,"tag":559,"props":18219,"children":18220},{"class":561,"line":626},[18221],{"type":415,"tag":559,"props":18222,"children":18223},{"style":583},[18224],{"type":420,"value":841},{"type":415,"tag":416,"props":18226,"children":18227},{},[18228,18230,18236],{"type":420,"value":18229},"Now we can execute the ",{"type":415,"tag":555,"props":18231,"children":18233},{"className":18232},[],[18234],{"type":420,"value":18235},"pulumi up",{"type":420,"value":18237}," command to provision all these resources and then open the pipeline page in our browser to test the pipeline.",{"type":415,"tag":1178,"props":18239,"children":18240},{"icon":5363},[18241],{"type":415,"tag":416,"props":18242,"children":18243},{},[18244,18246,18252,18254,18261,18263],{"type":420,"value":18245},"On Windows, you can use the ",{"type":415,"tag":555,"props":18247,"children":18249},{"className":18248},[],[18250],{"type":420,"value":18251},"start $(pulumi stack output pipelineUrl)",{"type":420,"value":18253}," command to directly open the browser on the pipeline page. If you are using ",{"type":415,"tag":434,"props":18255,"children":18258},{"href":18256,"rel":18257},"https://www.nushell.sh/",[438],[18259],{"type":420,"value":18260},"Nushell",{"type":420,"value":18262}," the command will be ",{"type":415,"tag":555,"props":18264,"children":18266},{"className":18265},[],[18267],{"type":420,"value":18268},"pulumi stack output pipelineUrl | start $in",{"type":415,"tag":416,"props":18270,"children":18271},{},[18272],{"type":415,"tag":934,"props":18273,"children":18277},{"alt":18274,"className":18275,"src":18276},"Results of the pipeline run in Azure DevOps",[938,8504],"/posts/images/azuredevopsoidc_portal.webp",[],{"type":415,"tag":416,"props":18279,"children":18280},{},[18281],{"type":420,"value":18282},"Everything is working as expected.",{"type":415,"tag":422,"props":18284,"children":18286},{"id":18285},"to-conclude",[18287],{"type":420,"value":18288},"To conclude",{"type":415,"tag":416,"props":18290,"children":18291},{},[18292,18294,18300],{"type":420,"value":18293},"In this article, we demonstrated how to automate the configuration of an Azure DevOps project using Workload Identity Federation for secure deployments to Azure. We covered the provisioning of the Microsoft Entra ID and Azure DevOps resources necessary to make this work. It's very similar to ",{"type":415,"tag":434,"props":18295,"children":18297},{"href":14223,"rel":18296},[438],[18298],{"type":420,"value":18299},"what can be done for GitHub",{"type":420,"value":18301}," but with the specificities of Azure DevOps.",{"type":415,"tag":416,"props":18303,"children":18304},{},[18305],{"type":420,"value":18306},"It was an opportunity for me to work with the Azure DevOps provider. Even if it does the job, I must admit I was somewhat disappointed with the developer experience which I found to be not very intuitive, with poorly named resources and an overreliance on strings as parameters. I assume that the Azure DevOps APIs are primarily responsible for this, as they are what the provider calls upon.",{"type":415,"tag":416,"props":18308,"children":18309},{},[18310],{"type":420,"value":18311},"One thing I find interesting with Azure DevOps is that YAML pipelines do not need to be updated to take advantage of workload identity federation as long as the Azure Pipelines tasks you are using support it and your ARM service connection has been converted to workload identity federation.",{"type":415,"tag":416,"props":18313,"children":18314},{},[18315],{"type":420,"value":18316},"Anyway, regardless of the CI/CD platform you are using, I believe that employing Workload Identity Federation to deploy code to Azure from pipelines is the right approach.",{"type":415,"tag":416,"props":18318,"children":18319},{},[18320,18322,18332],{"type":420,"value":18321},"You can find the complete source code used for this article ",{"type":415,"tag":434,"props":18323,"children":18326},{"href":18324,"rel":18325},"https://github.com/TechWatching/AzureDevOpsWorkloadIdentity",[438],[18327],{"type":415,"tag":14264,"props":18328,"children":18329},{},[18330],{"type":420,"value":18331},"in this GitHub repository",{"type":420,"value":542},{"type":415,"tag":5406,"props":18334,"children":18335},{},[18336],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":18338},[18339,18340,18342,18349],{"id":14173,"depth":589,"text":14176},{"id":14259,"depth":589,"text":18341},"How can you use Workload Identity Federation to deploy to Azure from Azure Pipelines?",{"id":14335,"depth":589,"text":14338,"children":18343},[18344,18345,18346,18347,18348],{"id":14342,"depth":608,"text":14345},{"id":14581,"depth":608,"text":14584},{"id":15498,"depth":608,"text":15501},{"id":16217,"depth":608,"text":16220},{"id":17077,"depth":608,"text":17080},{"id":18285,"depth":589,"text":18288},"content:1.posts:54.ado-workload-identity-federation.md","1.posts/54.ado-workload-identity-federation.md",{"_path":142,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":141,"description":18353,"lead":18354,"date":18355,"image":18356,"badge":18358,"tags":18359,"body":18360,"_type":5421,"_id":22685,"_source":5423,"_file":22686,"_extension":5425},"Today is a great time to be a developer:","Pushing an ASP.NET Core API to Azure using .NET from provisioning to deployment","2022-12-18T00:00:00.000Z",{"src":18357},"/images/trees_1.jpg",{"label":266},[239,365,312,368,315,266,228],{"type":412,"children":18361,"toc":22656},[18362,18366,18389,18394,18399,18404,18410,18415,18420,18425,18431,18436,18446,18451,18472,18481,18486,18495,18500,18508,18517,18522,18528,18534,18539,18557,18562,18585,18591,18596,18605,18610,18633,18642,18647,18665,18677,18696,18705,18711,18716,18725,18730,18735,18751,18757,18763,18768,18777,18799,18807,18812,18818,18823,19036,19041,19192,19198,19220,19346,19352,19381,19584,19590,19610,19924,19941,19970,20033,20052,20058,20064,20083,20092,20100,20112,20118,20123,20148,20786,20791,20799,20805,20810,20823,20837,20955,20972,20986,21268,21281,21287,21299,21575,21581,21594,21607,21816,21821,22431,22448,22453,22458,22464,22469,22478,22491,22500,22508,22513,22522,22527,22536,22542,22548,22553,22585,22599,22605,22610,22631,22636,22641,22647,22652],{"type":415,"tag":416,"props":18363,"children":18364},{},[18365],{"type":420,"value":18353},{"type":415,"tag":5376,"props":18367,"children":18368},{},[18369,18374,18379,18384],{"type":415,"tag":5380,"props":18370,"children":18371},{},[18372],{"type":420,"value":18373},"there are plenty of languages and frameworks to choose from to build an application",{"type":415,"tag":5380,"props":18375,"children":18376},{},[18377],{"type":420,"value":18378},"there are very powerful IDEs and tools to help us write, analyze, refactor, test and debug code",{"type":415,"tag":5380,"props":18380,"children":18381},{},[18382],{"type":420,"value":18383},"there are many nice CI/CD platforms that allow us to package and deploy our applications anywhere",{"type":415,"tag":5380,"props":18385,"children":18386},{},[18387],{"type":420,"value":18388},"thanks to cloud platforms and infrastructure as code we can provision infrastructure on-demand in an automated way",{"type":415,"tag":416,"props":18390,"children":18391},{},[18392],{"type":420,"value":18393},"Yet, sometimes it seems quite complex and time-consuming to deploy an application in the cloud.",{"type":415,"tag":416,"props":18395,"children":18396},{},[18397],{"type":420,"value":18398},"As a .NET developer, do I really need to master YAML, and Domain Specific Languages like HCL to deploy a simple ASP.NET Core API in Azure? Should I forget about local debugging when developing CI/CD pipelines? Do I have to learn everything from scratch each time I use another CI/CD platform?",{"type":415,"tag":416,"props":18400,"children":18401},{},[18402],{"type":420,"value":18403},"Thanks to Nuke and Pulumi, I don't think so and that is what we are going to talk about in this article.",{"type":415,"tag":422,"props":18405,"children":18407},{"id":18406},"the-scenario",[18408],{"type":420,"value":18409},"The scenario",{"type":415,"tag":416,"props":18411,"children":18412},{},[18413],{"type":420,"value":18414},"They are already lots of great articles about Pulumi or Nuke, so I won't spend time explaining what they are and why you should use them. Instead, I will show you how you can use them together with an example.",{"type":415,"tag":416,"props":18416,"children":18417},{},[18418],{"type":420,"value":18419},"My scenario is the following: I have a very basic ASP.NET Core API that I want to deploy to Azure App Service using a CI/CD pipeline.",{"type":415,"tag":416,"props":18421,"children":18422},{},[18423],{"type":420,"value":18424},"To do that, I want to use my existing .NET skills and code everything with the language and tools I know and love.",{"type":415,"tag":422,"props":18426,"children":18428},{"id":18427},"steps-of-the-cicd-pipeline",[18429],{"type":420,"value":18430},"Steps of the CI/CD pipeline",{"type":415,"tag":416,"props":18432,"children":18433},{},[18434],{"type":420,"value":18435},"There are often two main steps (or stages or whatever you call them) in a CI / CD pipeline: the packaging and the deployment.",{"type":415,"tag":416,"props":18437,"children":18438},{},[18439],{"type":415,"tag":934,"props":18440,"children":18445},{"alt":18441,"className":18442,"src":18443,"width":18444},"Diagram with package and deploy steps.",[938,8504],"/posts/images/pulumi_met_nuke_1.png",600,[],{"type":415,"tag":416,"props":18447,"children":18448},{},[18449],{"type":420,"value":18450},"To package a .NET application, we have to first restore the dependencies, then compile the application and publish it. So my Package step is composed of 3 steps.",{"type":415,"tag":1178,"props":18452,"children":18453},{"icon":1180},[18454],{"type":415,"tag":416,"props":18455,"children":18456},{},[18457,18459,18470],{"type":420,"value":18458},"A ",{"type":415,"tag":434,"props":18460,"children":18463},{"href":18461,"rel":18462},"https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish#description",[438],[18464],{"type":415,"tag":555,"props":18465,"children":18467},{"className":18466},[],[18468],{"type":420,"value":18469},"dotnet publish",{"type":420,"value":18471}," does an implicit restore and build the application so only one step could be used but I like separating these steps for clarity. Moreover it is sometimes needed, for instance when you are restoring packages from private Nuget feeds.",{"type":415,"tag":416,"props":18473,"children":18474},{},[18475],{"type":415,"tag":934,"props":18476,"children":18480},{"alt":18477,"className":18478,"src":18479,"width":14331},"Diagram with restore, compile, publish and deploy steps.",[938,8504],"/posts/images/pulumi_met_nuke_2.png",[],{"type":415,"tag":416,"props":18482,"children":18483},{},[18484],{"type":420,"value":18485},"I said the application needed to be deployed to Azure App Service but I don't have an existing Azure App Service resource, and I don't want to manually create one. So I also need a step to deploy the infrastructure",{"type":415,"tag":416,"props":18487,"children":18488},{},[18489],{"type":415,"tag":934,"props":18490,"children":18494},{"alt":18491,"className":18492,"src":18493,"width":14331},"Diagram with restore, compile, publish, deploy and provision infra steps.",[938,8504],"/posts/images/pulumi_met_nuke_3.png",[],{"type":415,"tag":416,"props":18496,"children":18497},{},[18498],{"type":420,"value":18499},"It seems fine. I will just add another optional step at the beginning to clean the temporary files I could have created on previous builds.",{"type":415,"tag":1178,"props":18501,"children":18502},{"icon":5363},[18503],{"type":415,"tag":416,"props":18504,"children":18505},{},[18506],{"type":420,"value":18507},"If your pipeline runs on a hosted agent/runner (managed by the CI/CD platform you use), the Clean step might not be very useful but I intend to also run this pipeline locally.",{"type":415,"tag":416,"props":18509,"children":18510},{},[18511],{"type":415,"tag":934,"props":18512,"children":18516},{"alt":18513,"className":18514,"src":18515},"Diagram with clean, restore, compile, publish, deploy and provision infra steps.",[938,8504],"/posts/images/pulumi_met_nuke_4.png",[],{"type":415,"tag":416,"props":18518,"children":18519},{},[18520],{"type":420,"value":18521},"Now, that we know the different steps of our pipeline, let's get to the code.",{"type":415,"tag":422,"props":18523,"children":18525},{"id":18524},"getting-started-with-the-code",[18526],{"type":420,"value":18527},"Getting started with the code",{"type":415,"tag":14340,"props":18529,"children":18531},{"id":18530},"code-organization",[18532],{"type":420,"value":18533},"Code organization",{"type":415,"tag":416,"props":18535,"children":18536},{},[18537],{"type":420,"value":18538},"I put all the code in the same Git repository because:",{"type":415,"tag":5376,"props":18540,"children":18541},{},[18542,18547,18552],{"type":415,"tag":5380,"props":18543,"children":18544},{},[18545],{"type":420,"value":18546},"it makes sense as everything is linked",{"type":415,"tag":5380,"props":18548,"children":18549},{},[18550],{"type":420,"value":18551},"it's easier to maintain (all the code in one place)",{"type":415,"tag":5380,"props":18553,"children":18554},{},[18555],{"type":420,"value":18556},"it's easier to version (one tag on one commit in one repository)",{"type":415,"tag":416,"props":18558,"children":18559},{},[18560],{"type":420,"value":18561},"I chose to organize my repository with the following folders:",{"type":415,"tag":5376,"props":18563,"children":18564},{},[18565,18570,18575,18580],{"type":415,"tag":5380,"props":18566,"children":18567},{},[18568],{"type":420,"value":18569},"📁 src ➡️ for the application code of the API",{"type":415,"tag":5380,"props":18571,"children":18572},{},[18573],{"type":420,"value":18574},"📁 infra ➡️ for the infrastructure code that provisions the App Service",{"type":415,"tag":5380,"props":18576,"children":18577},{},[18578],{"type":420,"value":18579},"📁 build ➡️ for pipeline code that builds and deploys the application",{"type":415,"tag":5380,"props":18581,"children":18582},{},[18583],{"type":420,"value":18584},"📁 artifacts ➡️ for the package created by the pipeline",{"type":415,"tag":14340,"props":18586,"children":18588},{"id":18587},"create-the-c-projects",[18589],{"type":420,"value":18590},"Create the C# projects",{"type":415,"tag":416,"props":18592,"children":18593},{},[18594],{"type":420,"value":18595},"To create the API project, we just use the default ASP.NET Core API template in .NET 7 that creates a simple Weather API.",{"type":415,"tag":416,"props":18597,"children":18598},{},[18599],{"type":415,"tag":934,"props":18600,"children":18604},{"alt":18601,"className":18602,"src":18603},"IDE folder explorer of an ASP.NET Core API template.",[938,8504],"/posts/images/pulumi_met_nuke_5.png",[],{"type":415,"tag":416,"props":18606,"children":18607},{},[18608],{"type":420,"value":18609},"I can initialize the infrastructure project using the Pulumi CLI new command with the azure C# template:",{"type":415,"tag":549,"props":18611,"children":18613},{"className":14353,"code":18612,"language":14355,"meta":401,"style":401},"pulumi new azure-csharp\n",[18614],{"type":415,"tag":555,"props":18615,"children":18616},{"__ignoreMap":401},[18617],{"type":415,"tag":559,"props":18618,"children":18619},{"class":561,"line":562},[18620,18624,18628],{"type":415,"tag":559,"props":18621,"children":18622},{"style":572},[18623],{"type":420,"value":311},{"type":415,"tag":559,"props":18625,"children":18626},{"style":822},[18627],{"type":420,"value":768},{"type":415,"tag":559,"props":18629,"children":18630},{"style":822},[18631],{"type":420,"value":18632}," azure-csharp\n",{"type":415,"tag":416,"props":18634,"children":18635},{},[18636],{"type":415,"tag":934,"props":18637,"children":18641},{"alt":18638,"className":18639,"src":18640},"IDE folder explorer focused on the infra folder containing the Pulumi project.",[938,8504],"/posts/images/pulumi_met_nuke_6.png",[],{"type":415,"tag":416,"props":18643,"children":18644},{},[18645],{"type":420,"value":18646},"I will show later how to modify the code of the template to provision an App Service.",{"type":415,"tag":18648,"props":18649,"children":18650},"blockquote",{},[18651],{"type":415,"tag":416,"props":18652,"children":18653},{},[18654,18656,18663],{"type":420,"value":18655},"You can check Pulumi ",{"type":415,"tag":434,"props":18657,"children":18660},{"href":18658,"rel":18659},"https://www.pulumi.com/docs/get-started/azure/",[438],[18661],{"type":420,"value":18662},"Getting Started with Azure",{"type":420,"value":18664}," tutorial to see how to set up your environment and start creating Azure resources in C# (or in another language).",{"type":415,"tag":416,"props":18666,"children":18667},{},[18668,18670,18676],{"type":420,"value":18669},"To initialize the build project, we can use Nuke's .NET global tool as explained in the ",{"type":415,"tag":434,"props":18671,"children":18674},{"href":18672,"rel":18673},"https://nuke.build/docs/getting-started/setup/",[438],[18675],{"type":420,"value":5512},{"type":420,"value":1206},{"type":415,"tag":549,"props":18678,"children":18680},{"className":14353,"code":18679,"language":14355,"meta":401,"style":401},"nuke :setup\n",[18681],{"type":415,"tag":555,"props":18682,"children":18683},{"__ignoreMap":401},[18684],{"type":415,"tag":559,"props":18685,"children":18686},{"class":561,"line":562},[18687,18691],{"type":415,"tag":559,"props":18688,"children":18689},{"style":572},[18690],{"type":420,"value":364},{"type":415,"tag":559,"props":18692,"children":18693},{"style":822},[18694],{"type":420,"value":18695}," :setup\n",{"type":415,"tag":416,"props":18697,"children":18698},{},[18699],{"type":415,"tag":934,"props":18700,"children":18704},{"alt":18701,"className":18702,"src":18703},"IDE folder explorer focused on the build folder containing the Nuke project.",[938,8504],"/posts/images/pulumi_met_nuke_7.png",[],{"type":415,"tag":14340,"props":18706,"children":18708},{"id":18707},"everything-in-net",[18709],{"type":420,"value":18710},"Everything in .NET",{"type":415,"tag":416,"props":18712,"children":18713},{},[18714],{"type":420,"value":18715},"What I like about using Pulumi (in .NET) and Nuke is that all the code is just C# code.  My infrastructure project and my build project are standard .NET console applications. And I can open the 3 projects (API, infrastructure, and build) in the same solution in my preferred IDE.",{"type":415,"tag":416,"props":18717,"children":18718},{},[18719],{"type":415,"tag":934,"props":18720,"children":18724},{"alt":18721,"className":18722,"src":18723},"IDE solution explorer witht the infra, build and api projects.",[938,8504],"/posts/images/pulumi_met_nuke_8.png",[],{"type":415,"tag":416,"props":18726,"children":18727},{},[18728],{"type":420,"value":18729},"Why does it matter? Because any .NET developer in a team would be able to understand and maintain this code. How many times have you seen a project slow down because the person responsible for the infrastructure code written in YAML, JSON, Bicep, or HCL was on vacation or ill? How often have you been stuck because the only few people in the team that knew how to modify the YAML pipelines were not available?",{"type":415,"tag":416,"props":18731,"children":18732},{},[18733],{"type":420,"value":18734},"But it's not a question of knowledge only. It's also because the developer experience of writing build or infrastructure code in .NET is much better than writing code in YAML or other declarative \"languages\".",{"type":415,"tag":1178,"props":18736,"children":18737},{"icon":1180},[18738],{"type":415,"tag":416,"props":18739,"children":18740},{},[18741,18743,18749],{"type":420,"value":18742},"I talk a lot about the benefits of using programming languages for infrastructure code in my article \"",{"type":415,"tag":434,"props":18744,"children":18747},{"href":18745,"rel":18746},"https://www.techwatching.dev/posts/pulumi-vs-terraform",[438],[18748],{"type":420,"value":114},{"type":420,"value":18750},"\" if you have not read it yet.",{"type":415,"tag":422,"props":18752,"children":18754},{"id":18753},"implementing-the-pipeline-steps-from-clean-to-publish",[18755],{"type":420,"value":18756},"Implementing the pipeline steps from Clean to Publish",{"type":415,"tag":14340,"props":18758,"children":18760},{"id":18759},"the-nuke-pipeline",[18761],{"type":420,"value":18762},"The Nuke pipeline",{"type":415,"tag":416,"props":18764,"children":18765},{},[18766],{"type":420,"value":18767},"Here is what looks like the default build project after its creation:",{"type":415,"tag":416,"props":18769,"children":18770},{},[18771],{"type":415,"tag":934,"props":18772,"children":18776},{"alt":18773,"className":18774,"src":18775},"Buidl code file with the build steps opened in the IDE.",[938,8504],"/posts/images/pulumi_met_nuke_9.png",[],{"type":415,"tag":416,"props":18778,"children":18779},{},[18780,18782,18788,18790,18797],{"type":420,"value":18781},"The main method is contained in a ",{"type":415,"tag":555,"props":18783,"children":18785},{"className":18784},[],[18786],{"type":420,"value":18787},"Build.cs",{"type":420,"value":18789}," file. This file contains the steps of the pipeline that are called ",{"type":415,"tag":434,"props":18791,"children":18794},{"href":18792,"rel":18793},"https://nuke.build/docs/fundamentals/targets/",[438],[18795],{"type":420,"value":18796},"Target",{"type":420,"value":18798}," in Nuke. We can set the dependencies between targets.",{"type":415,"tag":1178,"props":18800,"children":18801},{"icon":5363},[18802],{"type":415,"tag":416,"props":18803,"children":18804},{},[18805],{"type":420,"value":18806},"The build project is a .NET console application so it works out of the box in any .NET IDE or from the command line. But to be more productive you can install a plugin for your IDE that will add snippets and a way to easily debug each target individually.",{"type":415,"tag":416,"props":18808,"children":18809},{},[18810],{"type":420,"value":18811},"As you see we can define properties with the attribute Parameter if we need to pass parameters to our pipeline, like the Configuration parameter.",{"type":415,"tag":14340,"props":18813,"children":18815},{"id":18814},"the-clean-target",[18816],{"type":420,"value":18817},"The Clean target",{"type":415,"tag":416,"props":18819,"children":18820},{},[18821],{"type":420,"value":18822},"We can define the Clean target like that:",{"type":415,"tag":549,"props":18824,"children":18826},{"className":551,"code":18825,"language":326,"meta":401,"style":401},"Target Clean => _ => _  \n    .Before(Restore)  \n    .Executes(() =>  \n    {  \n        SourceDirectory.GlobDirectories(\"*/bin\", \"*/obj\").ForEach(DeleteDirectory);  \n        EnsureCleanDirectory(ArtifactsDirectory);  \n    });\n",[18827],{"type":415,"tag":555,"props":18828,"children":18829},{"__ignoreMap":401},[18830,18859,18889,18914,18926,19004,19029],{"type":415,"tag":559,"props":18831,"children":18832},{"class":561,"line":562},[18833,18838,18842,18846,18850,18854],{"type":415,"tag":559,"props":18834,"children":18835},{"style":792},[18836],{"type":420,"value":18837},"Target ",{"type":415,"tag":559,"props":18839,"children":18840},{"style":572},[18841],{"type":420,"value":15334},{"type":415,"tag":559,"props":18843,"children":18844},{"style":583},[18845],{"type":420,"value":1861},{"type":415,"tag":559,"props":18847,"children":18848},{"style":572},[18849],{"type":420,"value":8126},{"type":415,"tag":559,"props":18851,"children":18852},{"style":583},[18853],{"type":420,"value":1861},{"type":415,"tag":559,"props":18855,"children":18856},{"style":792},[18857],{"type":420,"value":18858}," _  \n",{"type":415,"tag":559,"props":18860,"children":18861},{"class":561,"line":589},[18862,18866,18871,18875,18880,18884],{"type":415,"tag":559,"props":18863,"children":18864},{"style":583},[18865],{"type":420,"value":1842},{"type":415,"tag":559,"props":18867,"children":18868},{"style":883},[18869],{"type":420,"value":18870},"Before",{"type":415,"tag":559,"props":18872,"children":18873},{"style":583},[18874],{"type":420,"value":814},{"type":415,"tag":559,"props":18876,"children":18877},{"style":792},[18878],{"type":420,"value":18879},"Restore",{"type":415,"tag":559,"props":18881,"children":18882},{"style":583},[18883],{"type":420,"value":1468},{"type":415,"tag":559,"props":18885,"children":18886},{"style":792},[18887],{"type":420,"value":18888},"  \n",{"type":415,"tag":559,"props":18890,"children":18891},{"class":561,"line":608},[18892,18896,18901,18906,18910],{"type":415,"tag":559,"props":18893,"children":18894},{"style":583},[18895],{"type":420,"value":1842},{"type":415,"tag":559,"props":18897,"children":18898},{"style":883},[18899],{"type":420,"value":18900},"Executes",{"type":415,"tag":559,"props":18902,"children":18903},{"style":583},[18904],{"type":420,"value":18905},"(()",{"type":415,"tag":559,"props":18907,"children":18908},{"style":583},[18909],{"type":420,"value":1861},{"type":415,"tag":559,"props":18911,"children":18912},{"style":792},[18913],{"type":420,"value":18888},{"type":415,"tag":559,"props":18915,"children":18916},{"class":561,"line":626},[18917,18922],{"type":415,"tag":559,"props":18918,"children":18919},{"style":583},[18920],{"type":420,"value":18921},"    {",{"type":415,"tag":559,"props":18923,"children":18924},{"style":792},[18925],{"type":420,"value":18888},{"type":415,"tag":559,"props":18927,"children":18928},{"class":561,"line":643},[18929,18934,18938,18943,18947,18951,18956,18960,18964,18968,18973,18977,18981,18986,18990,18995,19000],{"type":415,"tag":559,"props":18930,"children":18931},{"style":792},[18932],{"type":420,"value":18933},"        SourceDirectory",{"type":415,"tag":559,"props":18935,"children":18936},{"style":583},[18937],{"type":420,"value":542},{"type":415,"tag":559,"props":18939,"children":18940},{"style":883},[18941],{"type":420,"value":18942},"GlobDirectories",{"type":415,"tag":559,"props":18944,"children":18945},{"style":583},[18946],{"type":420,"value":814},{"type":415,"tag":559,"props":18948,"children":18949},{"style":583},[18950],{"type":420,"value":819},{"type":415,"tag":559,"props":18952,"children":18953},{"style":822},[18954],{"type":420,"value":18955},"*/bin",{"type":415,"tag":559,"props":18957,"children":18958},{"style":583},[18959],{"type":420,"value":819},{"type":415,"tag":559,"props":18961,"children":18962},{"style":583},[18963],{"type":420,"value":2312},{"type":415,"tag":559,"props":18965,"children":18966},{"style":583},[18967],{"type":420,"value":1434},{"type":415,"tag":559,"props":18969,"children":18970},{"style":822},[18971],{"type":420,"value":18972},"*/obj",{"type":415,"tag":559,"props":18974,"children":18975},{"style":583},[18976],{"type":420,"value":819},{"type":415,"tag":559,"props":18978,"children":18979},{"style":583},[18980],{"type":420,"value":1439},{"type":415,"tag":559,"props":18982,"children":18983},{"style":883},[18984],{"type":420,"value":18985},"ForEach",{"type":415,"tag":559,"props":18987,"children":18988},{"style":583},[18989],{"type":420,"value":814},{"type":415,"tag":559,"props":18991,"children":18992},{"style":792},[18993],{"type":420,"value":18994},"DeleteDirectory",{"type":415,"tag":559,"props":18996,"children":18997},{"style":583},[18998],{"type":420,"value":18999},");",{"type":415,"tag":559,"props":19001,"children":19002},{"style":792},[19003],{"type":420,"value":18888},{"type":415,"tag":559,"props":19005,"children":19006},{"class":561,"line":660},[19007,19012,19016,19021,19025],{"type":415,"tag":559,"props":19008,"children":19009},{"style":883},[19010],{"type":420,"value":19011},"        EnsureCleanDirectory",{"type":415,"tag":559,"props":19013,"children":19014},{"style":583},[19015],{"type":420,"value":814},{"type":415,"tag":559,"props":19017,"children":19018},{"style":792},[19019],{"type":420,"value":19020},"ArtifactsDirectory",{"type":415,"tag":559,"props":19022,"children":19023},{"style":583},[19024],{"type":420,"value":18999},{"type":415,"tag":559,"props":19026,"children":19027},{"style":792},[19028],{"type":420,"value":18888},{"type":415,"tag":559,"props":19030,"children":19031},{"class":561,"line":677},[19032],{"type":415,"tag":559,"props":19033,"children":19034},{"style":583},[19035],{"type":420,"value":7416},{"type":415,"tag":416,"props":19037,"children":19038},{},[19039],{"type":420,"value":19040},"This code deletes all the bin and obj directories of the source directory. It also deletes the content in the artifacts directory. Nuke overloads the division operator to allow us to easily define paths in the project.",{"type":415,"tag":549,"props":19042,"children":19044},{"className":551,"code":19043,"language":326,"meta":401,"style":401},"AbsolutePath SourceDirectory => RootDirectory / \"src\";  \n  \nAbsolutePath InfrastructureDirectory => RootDirectory / \"infra\";  \n  \nAbsolutePath ArtifactsDirectory => RootDirectory / \"artifacts\";\n",[19045],{"type":415,"tag":555,"props":19046,"children":19047},{"__ignoreMap":401},[19048,19095,19102,19146,19153],{"type":415,"tag":559,"props":19049,"children":19050},{"class":561,"line":562},[19051,19056,19061,19065,19070,19074,19078,19083,19087,19091],{"type":415,"tag":559,"props":19052,"children":19053},{"style":792},[19054],{"type":420,"value":19055},"AbsolutePath ",{"type":415,"tag":559,"props":19057,"children":19058},{"style":572},[19059],{"type":420,"value":19060},"SourceDirectory",{"type":415,"tag":559,"props":19062,"children":19063},{"style":583},[19064],{"type":420,"value":1861},{"type":415,"tag":559,"props":19066,"children":19067},{"style":792},[19068],{"type":420,"value":19069}," RootDirectory ",{"type":415,"tag":559,"props":19071,"children":19072},{"style":583},[19073],{"type":420,"value":12238},{"type":415,"tag":559,"props":19075,"children":19076},{"style":583},[19077],{"type":420,"value":1434},{"type":415,"tag":559,"props":19079,"children":19080},{"style":822},[19081],{"type":420,"value":19082},"src",{"type":415,"tag":559,"props":19084,"children":19085},{"style":583},[19086],{"type":420,"value":819},{"type":415,"tag":559,"props":19088,"children":19089},{"style":583},[19090],{"type":420,"value":1154},{"type":415,"tag":559,"props":19092,"children":19093},{"style":792},[19094],{"type":420,"value":18888},{"type":415,"tag":559,"props":19096,"children":19097},{"class":561,"line":589},[19098],{"type":415,"tag":559,"props":19099,"children":19100},{"style":792},[19101],{"type":420,"value":18888},{"type":415,"tag":559,"props":19103,"children":19104},{"class":561,"line":608},[19105,19109,19114,19118,19122,19126,19130,19134,19138,19142],{"type":415,"tag":559,"props":19106,"children":19107},{"style":792},[19108],{"type":420,"value":19055},{"type":415,"tag":559,"props":19110,"children":19111},{"style":572},[19112],{"type":420,"value":19113},"InfrastructureDirectory",{"type":415,"tag":559,"props":19115,"children":19116},{"style":583},[19117],{"type":420,"value":1861},{"type":415,"tag":559,"props":19119,"children":19120},{"style":792},[19121],{"type":420,"value":19069},{"type":415,"tag":559,"props":19123,"children":19124},{"style":583},[19125],{"type":420,"value":12238},{"type":415,"tag":559,"props":19127,"children":19128},{"style":583},[19129],{"type":420,"value":1434},{"type":415,"tag":559,"props":19131,"children":19132},{"style":822},[19133],{"type":420,"value":14129},{"type":415,"tag":559,"props":19135,"children":19136},{"style":583},[19137],{"type":420,"value":819},{"type":415,"tag":559,"props":19139,"children":19140},{"style":583},[19141],{"type":420,"value":1154},{"type":415,"tag":559,"props":19143,"children":19144},{"style":792},[19145],{"type":420,"value":18888},{"type":415,"tag":559,"props":19147,"children":19148},{"class":561,"line":626},[19149],{"type":415,"tag":559,"props":19150,"children":19151},{"style":792},[19152],{"type":420,"value":18888},{"type":415,"tag":559,"props":19154,"children":19155},{"class":561,"line":643},[19156,19160,19164,19168,19172,19176,19180,19184,19188],{"type":415,"tag":559,"props":19157,"children":19158},{"style":792},[19159],{"type":420,"value":19055},{"type":415,"tag":559,"props":19161,"children":19162},{"style":572},[19163],{"type":420,"value":19020},{"type":415,"tag":559,"props":19165,"children":19166},{"style":583},[19167],{"type":420,"value":1861},{"type":415,"tag":559,"props":19169,"children":19170},{"style":792},[19171],{"type":420,"value":19069},{"type":415,"tag":559,"props":19173,"children":19174},{"style":583},[19175],{"type":420,"value":12238},{"type":415,"tag":559,"props":19177,"children":19178},{"style":583},[19179],{"type":420,"value":1434},{"type":415,"tag":559,"props":19181,"children":19182},{"style":822},[19183],{"type":420,"value":15018},{"type":415,"tag":559,"props":19185,"children":19186},{"style":583},[19187],{"type":420,"value":819},{"type":415,"tag":559,"props":19189,"children":19190},{"style":583},[19191],{"type":420,"value":1509},{"type":415,"tag":14340,"props":19193,"children":19195},{"id":19194},"the-restore-target",[19196],{"type":420,"value":19197},"The Restore target",{"type":415,"tag":416,"props":19199,"children":19200},{},[19201,19203,19209,19211,19218],{"type":420,"value":19202},"To restore .NET dependencies, we can use the ",{"type":415,"tag":555,"props":19204,"children":19206},{"className":19205},[],[19207],{"type":420,"value":19208},"dotnet restore",{"type":420,"value":19210}," command. Nuke supports ",{"type":415,"tag":434,"props":19212,"children":19215},{"href":19213,"rel":19214},"https://nuke.build/docs/common/cli-tools/",[438],[19216],{"type":420,"value":19217},"executing CLI tools",{"type":420,"value":19219}," and has even auto-generated CLI wrappers for some common tools like dotnet CLI to use a Fluent API instead of string interpolation to pass parameters.",{"type":415,"tag":549,"props":19221,"children":19223},{"className":551,"code":19222,"language":326,"meta":401,"style":401},"Target Restore => _ => _  \n    .Executes(() =>  \n    {  \n        DotNetRestore(_ => _.SetProjectFile(Solution));  \n    });\n",[19224],{"type":415,"tag":555,"props":19225,"children":19226},{"__ignoreMap":401},[19227,19254,19277,19288,19339],{"type":415,"tag":559,"props":19228,"children":19229},{"class":561,"line":562},[19230,19234,19238,19242,19246,19250],{"type":415,"tag":559,"props":19231,"children":19232},{"style":792},[19233],{"type":420,"value":18837},{"type":415,"tag":559,"props":19235,"children":19236},{"style":572},[19237],{"type":420,"value":18879},{"type":415,"tag":559,"props":19239,"children":19240},{"style":583},[19241],{"type":420,"value":1861},{"type":415,"tag":559,"props":19243,"children":19244},{"style":572},[19245],{"type":420,"value":8126},{"type":415,"tag":559,"props":19247,"children":19248},{"style":583},[19249],{"type":420,"value":1861},{"type":415,"tag":559,"props":19251,"children":19252},{"style":792},[19253],{"type":420,"value":18858},{"type":415,"tag":559,"props":19255,"children":19256},{"class":561,"line":589},[19257,19261,19265,19269,19273],{"type":415,"tag":559,"props":19258,"children":19259},{"style":583},[19260],{"type":420,"value":1842},{"type":415,"tag":559,"props":19262,"children":19263},{"style":883},[19264],{"type":420,"value":18900},{"type":415,"tag":559,"props":19266,"children":19267},{"style":583},[19268],{"type":420,"value":18905},{"type":415,"tag":559,"props":19270,"children":19271},{"style":583},[19272],{"type":420,"value":1861},{"type":415,"tag":559,"props":19274,"children":19275},{"style":792},[19276],{"type":420,"value":18888},{"type":415,"tag":559,"props":19278,"children":19279},{"class":561,"line":608},[19280,19284],{"type":415,"tag":559,"props":19281,"children":19282},{"style":583},[19283],{"type":420,"value":18921},{"type":415,"tag":559,"props":19285,"children":19286},{"style":792},[19287],{"type":420,"value":18888},{"type":415,"tag":559,"props":19289,"children":19290},{"class":561,"line":626},[19291,19296,19300,19304,19308,19312,19316,19321,19325,19330,19335],{"type":415,"tag":559,"props":19292,"children":19293},{"style":883},[19294],{"type":420,"value":19295},"        DotNetRestore",{"type":415,"tag":559,"props":19297,"children":19298},{"style":583},[19299],{"type":420,"value":814},{"type":415,"tag":559,"props":19301,"children":19302},{"style":572},[19303],{"type":420,"value":8117},{"type":415,"tag":559,"props":19305,"children":19306},{"style":583},[19307],{"type":420,"value":1861},{"type":415,"tag":559,"props":19309,"children":19310},{"style":792},[19311],{"type":420,"value":8126},{"type":415,"tag":559,"props":19313,"children":19314},{"style":583},[19315],{"type":420,"value":542},{"type":415,"tag":559,"props":19317,"children":19318},{"style":883},[19319],{"type":420,"value":19320},"SetProjectFile",{"type":415,"tag":559,"props":19322,"children":19323},{"style":583},[19324],{"type":420,"value":814},{"type":415,"tag":559,"props":19326,"children":19327},{"style":792},[19328],{"type":420,"value":19329},"Solution",{"type":415,"tag":559,"props":19331,"children":19332},{"style":583},[19333],{"type":420,"value":19334},"));",{"type":415,"tag":559,"props":19336,"children":19337},{"style":792},[19338],{"type":420,"value":18888},{"type":415,"tag":559,"props":19340,"children":19341},{"class":561,"line":643},[19342],{"type":415,"tag":559,"props":19343,"children":19344},{"style":583},[19345],{"type":420,"value":7416},{"type":415,"tag":14340,"props":19347,"children":19349},{"id":19348},"the-compile-target",[19350],{"type":420,"value":19351},"The Compile target",{"type":415,"tag":416,"props":19353,"children":19354},{},[19355,19357,19363,19365,19371,19373,19379],{"type":420,"value":19356},"The compile target uses the ",{"type":415,"tag":555,"props":19358,"children":19360},{"className":19359},[],[19361],{"type":420,"value":19362},"dotnet build",{"type":420,"value":19364}," command. We can start to see the benefits of using this Fluent API that provides us with autocompletion and documentation. For instance, as we already restored the dependencies in the previous step, we can set the ",{"type":415,"tag":555,"props":19366,"children":19368},{"className":19367},[],[19369],{"type":420,"value":19370},"--no-restore",{"type":420,"value":19372}," option using the ",{"type":415,"tag":555,"props":19374,"children":19376},{"className":19375},[],[19377],{"type":420,"value":19378},"EnableNoRestore",{"type":420,"value":19380}," auto-generated method.",{"type":415,"tag":549,"props":19382,"children":19384},{"className":551,"code":19383,"language":326,"meta":401,"style":401},"Target Compile => _ => _  \n    .DependsOn(Restore)  \n    .Executes(() =>  \n    {  \n        DotNetBuild(_ => _  \n            .SetProjectFile(Solution)  \n            .SetConfiguration(Configuration)  \n            .EnableNoRestore());  \n    });\n",[19385],{"type":415,"tag":555,"props":19386,"children":19387},{"__ignoreMap":401},[19388,19416,19444,19467,19478,19502,19529,19557,19577],{"type":415,"tag":559,"props":19389,"children":19390},{"class":561,"line":562},[19391,19395,19400,19404,19408,19412],{"type":415,"tag":559,"props":19392,"children":19393},{"style":792},[19394],{"type":420,"value":18837},{"type":415,"tag":559,"props":19396,"children":19397},{"style":572},[19398],{"type":420,"value":19399},"Compile",{"type":415,"tag":559,"props":19401,"children":19402},{"style":583},[19403],{"type":420,"value":1861},{"type":415,"tag":559,"props":19405,"children":19406},{"style":572},[19407],{"type":420,"value":8126},{"type":415,"tag":559,"props":19409,"children":19410},{"style":583},[19411],{"type":420,"value":1861},{"type":415,"tag":559,"props":19413,"children":19414},{"style":792},[19415],{"type":420,"value":18858},{"type":415,"tag":559,"props":19417,"children":19418},{"class":561,"line":589},[19419,19423,19428,19432,19436,19440],{"type":415,"tag":559,"props":19420,"children":19421},{"style":583},[19422],{"type":420,"value":1842},{"type":415,"tag":559,"props":19424,"children":19425},{"style":883},[19426],{"type":420,"value":19427},"DependsOn",{"type":415,"tag":559,"props":19429,"children":19430},{"style":583},[19431],{"type":420,"value":814},{"type":415,"tag":559,"props":19433,"children":19434},{"style":792},[19435],{"type":420,"value":18879},{"type":415,"tag":559,"props":19437,"children":19438},{"style":583},[19439],{"type":420,"value":1468},{"type":415,"tag":559,"props":19441,"children":19442},{"style":792},[19443],{"type":420,"value":18888},{"type":415,"tag":559,"props":19445,"children":19446},{"class":561,"line":608},[19447,19451,19455,19459,19463],{"type":415,"tag":559,"props":19448,"children":19449},{"style":583},[19450],{"type":420,"value":1842},{"type":415,"tag":559,"props":19452,"children":19453},{"style":883},[19454],{"type":420,"value":18900},{"type":415,"tag":559,"props":19456,"children":19457},{"style":583},[19458],{"type":420,"value":18905},{"type":415,"tag":559,"props":19460,"children":19461},{"style":583},[19462],{"type":420,"value":1861},{"type":415,"tag":559,"props":19464,"children":19465},{"style":792},[19466],{"type":420,"value":18888},{"type":415,"tag":559,"props":19468,"children":19469},{"class":561,"line":626},[19470,19474],{"type":415,"tag":559,"props":19471,"children":19472},{"style":583},[19473],{"type":420,"value":18921},{"type":415,"tag":559,"props":19475,"children":19476},{"style":792},[19477],{"type":420,"value":18888},{"type":415,"tag":559,"props":19479,"children":19480},{"class":561,"line":643},[19481,19486,19490,19494,19498],{"type":415,"tag":559,"props":19482,"children":19483},{"style":883},[19484],{"type":420,"value":19485},"        DotNetBuild",{"type":415,"tag":559,"props":19487,"children":19488},{"style":583},[19489],{"type":420,"value":814},{"type":415,"tag":559,"props":19491,"children":19492},{"style":572},[19493],{"type":420,"value":8117},{"type":415,"tag":559,"props":19495,"children":19496},{"style":583},[19497],{"type":420,"value":1861},{"type":415,"tag":559,"props":19499,"children":19500},{"style":792},[19501],{"type":420,"value":18858},{"type":415,"tag":559,"props":19503,"children":19504},{"class":561,"line":660},[19505,19509,19513,19517,19521,19525],{"type":415,"tag":559,"props":19506,"children":19507},{"style":583},[19508],{"type":420,"value":8274},{"type":415,"tag":559,"props":19510,"children":19511},{"style":883},[19512],{"type":420,"value":19320},{"type":415,"tag":559,"props":19514,"children":19515},{"style":583},[19516],{"type":420,"value":814},{"type":415,"tag":559,"props":19518,"children":19519},{"style":792},[19520],{"type":420,"value":19329},{"type":415,"tag":559,"props":19522,"children":19523},{"style":583},[19524],{"type":420,"value":1468},{"type":415,"tag":559,"props":19526,"children":19527},{"style":792},[19528],{"type":420,"value":18888},{"type":415,"tag":559,"props":19530,"children":19531},{"class":561,"line":677},[19532,19536,19541,19545,19549,19553],{"type":415,"tag":559,"props":19533,"children":19534},{"style":583},[19535],{"type":420,"value":8274},{"type":415,"tag":559,"props":19537,"children":19538},{"style":883},[19539],{"type":420,"value":19540},"SetConfiguration",{"type":415,"tag":559,"props":19542,"children":19543},{"style":583},[19544],{"type":420,"value":814},{"type":415,"tag":559,"props":19546,"children":19547},{"style":792},[19548],{"type":420,"value":263},{"type":415,"tag":559,"props":19550,"children":19551},{"style":583},[19552],{"type":420,"value":1468},{"type":415,"tag":559,"props":19554,"children":19555},{"style":792},[19556],{"type":420,"value":18888},{"type":415,"tag":559,"props":19558,"children":19559},{"class":561,"line":690},[19560,19564,19568,19573],{"type":415,"tag":559,"props":19561,"children":19562},{"style":583},[19563],{"type":420,"value":8274},{"type":415,"tag":559,"props":19565,"children":19566},{"style":883},[19567],{"type":420,"value":19378},{"type":415,"tag":559,"props":19569,"children":19570},{"style":583},[19571],{"type":420,"value":19572},"());",{"type":415,"tag":559,"props":19574,"children":19575},{"style":792},[19576],{"type":420,"value":18888},{"type":415,"tag":559,"props":19578,"children":19579},{"class":561,"line":1089},[19580],{"type":415,"tag":559,"props":19581,"children":19582},{"style":583},[19583],{"type":420,"value":7416},{"type":415,"tag":14340,"props":19585,"children":19587},{"id":19586},"the-publish-target",[19588],{"type":420,"value":19589},"The Publish target",{"type":415,"tag":416,"props":19591,"children":19592},{},[19593,19595,19600,19602,19608],{"type":420,"value":19594},"The publish target uses the ",{"type":415,"tag":555,"props":19596,"children":19598},{"className":19597},[],[19599],{"type":420,"value":18469},{"type":420,"value":19601}," command and then creates a zip ",{"type":415,"tag":555,"props":19603,"children":19605},{"className":19604},[],[19606],{"type":420,"value":19607},"api.zip",{"type":420,"value":19609}," of the resulting package in the artifacts directory.",{"type":415,"tag":549,"props":19611,"children":19613},{"className":551,"code":19612,"language":326,"meta":401,"style":401},"Target Publish => _ => _  \n    .DependsOn(Clean, Compile)  \n    .Executes(() =>  \n    {  \n        DotNetPublish(_ => _  \n            .SetProject(Solution.CSharpEverything_Api)  \n            .SetConfiguration(Configuration)  \n            .EnableNoBuild()  \n            .SetOutput(ApiPackageDirectory));  \n  \n        ZipFile.CreateFromDirectory(ApiPackageDirectory, ArtifactsDirectory / \"api.zip\");  \n    });\n",[19614],{"type":415,"tag":555,"props":19615,"children":19616},{"__ignoreMap":401},[19617,19645,19681,19704,19715,19739,19776,19803,19823,19852,19859,19917],{"type":415,"tag":559,"props":19618,"children":19619},{"class":561,"line":562},[19620,19624,19629,19633,19637,19641],{"type":415,"tag":559,"props":19621,"children":19622},{"style":792},[19623],{"type":420,"value":18837},{"type":415,"tag":559,"props":19625,"children":19626},{"style":572},[19627],{"type":420,"value":19628},"Publish",{"type":415,"tag":559,"props":19630,"children":19631},{"style":583},[19632],{"type":420,"value":1861},{"type":415,"tag":559,"props":19634,"children":19635},{"style":572},[19636],{"type":420,"value":8126},{"type":415,"tag":559,"props":19638,"children":19639},{"style":583},[19640],{"type":420,"value":1861},{"type":415,"tag":559,"props":19642,"children":19643},{"style":792},[19644],{"type":420,"value":18858},{"type":415,"tag":559,"props":19646,"children":19647},{"class":561,"line":589},[19648,19652,19656,19660,19664,19668,19673,19677],{"type":415,"tag":559,"props":19649,"children":19650},{"style":583},[19651],{"type":420,"value":1842},{"type":415,"tag":559,"props":19653,"children":19654},{"style":883},[19655],{"type":420,"value":19427},{"type":415,"tag":559,"props":19657,"children":19658},{"style":583},[19659],{"type":420,"value":814},{"type":415,"tag":559,"props":19661,"children":19662},{"style":792},[19663],{"type":420,"value":15334},{"type":415,"tag":559,"props":19665,"children":19666},{"style":583},[19667],{"type":420,"value":2312},{"type":415,"tag":559,"props":19669,"children":19670},{"style":792},[19671],{"type":420,"value":19672}," Compile",{"type":415,"tag":559,"props":19674,"children":19675},{"style":583},[19676],{"type":420,"value":1468},{"type":415,"tag":559,"props":19678,"children":19679},{"style":792},[19680],{"type":420,"value":18888},{"type":415,"tag":559,"props":19682,"children":19683},{"class":561,"line":608},[19684,19688,19692,19696,19700],{"type":415,"tag":559,"props":19685,"children":19686},{"style":583},[19687],{"type":420,"value":1842},{"type":415,"tag":559,"props":19689,"children":19690},{"style":883},[19691],{"type":420,"value":18900},{"type":415,"tag":559,"props":19693,"children":19694},{"style":583},[19695],{"type":420,"value":18905},{"type":415,"tag":559,"props":19697,"children":19698},{"style":583},[19699],{"type":420,"value":1861},{"type":415,"tag":559,"props":19701,"children":19702},{"style":792},[19703],{"type":420,"value":18888},{"type":415,"tag":559,"props":19705,"children":19706},{"class":561,"line":626},[19707,19711],{"type":415,"tag":559,"props":19708,"children":19709},{"style":583},[19710],{"type":420,"value":18921},{"type":415,"tag":559,"props":19712,"children":19713},{"style":792},[19714],{"type":420,"value":18888},{"type":415,"tag":559,"props":19716,"children":19717},{"class":561,"line":643},[19718,19723,19727,19731,19735],{"type":415,"tag":559,"props":19719,"children":19720},{"style":883},[19721],{"type":420,"value":19722},"        DotNetPublish",{"type":415,"tag":559,"props":19724,"children":19725},{"style":583},[19726],{"type":420,"value":814},{"type":415,"tag":559,"props":19728,"children":19729},{"style":572},[19730],{"type":420,"value":8117},{"type":415,"tag":559,"props":19732,"children":19733},{"style":583},[19734],{"type":420,"value":1861},{"type":415,"tag":559,"props":19736,"children":19737},{"style":792},[19738],{"type":420,"value":18858},{"type":415,"tag":559,"props":19740,"children":19741},{"class":561,"line":660},[19742,19746,19751,19755,19759,19763,19768,19772],{"type":415,"tag":559,"props":19743,"children":19744},{"style":583},[19745],{"type":420,"value":8274},{"type":415,"tag":559,"props":19747,"children":19748},{"style":883},[19749],{"type":420,"value":19750},"SetProject",{"type":415,"tag":559,"props":19752,"children":19753},{"style":583},[19754],{"type":420,"value":814},{"type":415,"tag":559,"props":19756,"children":19757},{"style":792},[19758],{"type":420,"value":19329},{"type":415,"tag":559,"props":19760,"children":19761},{"style":583},[19762],{"type":420,"value":542},{"type":415,"tag":559,"props":19764,"children":19765},{"style":792},[19766],{"type":420,"value":19767},"CSharpEverything_Api",{"type":415,"tag":559,"props":19769,"children":19770},{"style":583},[19771],{"type":420,"value":1468},{"type":415,"tag":559,"props":19773,"children":19774},{"style":792},[19775],{"type":420,"value":18888},{"type":415,"tag":559,"props":19777,"children":19778},{"class":561,"line":677},[19779,19783,19787,19791,19795,19799],{"type":415,"tag":559,"props":19780,"children":19781},{"style":583},[19782],{"type":420,"value":8274},{"type":415,"tag":559,"props":19784,"children":19785},{"style":883},[19786],{"type":420,"value":19540},{"type":415,"tag":559,"props":19788,"children":19789},{"style":583},[19790],{"type":420,"value":814},{"type":415,"tag":559,"props":19792,"children":19793},{"style":792},[19794],{"type":420,"value":263},{"type":415,"tag":559,"props":19796,"children":19797},{"style":583},[19798],{"type":420,"value":1468},{"type":415,"tag":559,"props":19800,"children":19801},{"style":792},[19802],{"type":420,"value":18888},{"type":415,"tag":559,"props":19804,"children":19805},{"class":561,"line":690},[19806,19810,19815,19819],{"type":415,"tag":559,"props":19807,"children":19808},{"style":583},[19809],{"type":420,"value":8274},{"type":415,"tag":559,"props":19811,"children":19812},{"style":883},[19813],{"type":420,"value":19814},"EnableNoBuild",{"type":415,"tag":559,"props":19816,"children":19817},{"style":583},[19818],{"type":420,"value":1888},{"type":415,"tag":559,"props":19820,"children":19821},{"style":792},[19822],{"type":420,"value":18888},{"type":415,"tag":559,"props":19824,"children":19825},{"class":561,"line":1089},[19826,19830,19835,19839,19844,19848],{"type":415,"tag":559,"props":19827,"children":19828},{"style":583},[19829],{"type":420,"value":8274},{"type":415,"tag":559,"props":19831,"children":19832},{"style":883},[19833],{"type":420,"value":19834},"SetOutput",{"type":415,"tag":559,"props":19836,"children":19837},{"style":583},[19838],{"type":420,"value":814},{"type":415,"tag":559,"props":19840,"children":19841},{"style":792},[19842],{"type":420,"value":19843},"ApiPackageDirectory",{"type":415,"tag":559,"props":19845,"children":19846},{"style":583},[19847],{"type":420,"value":19334},{"type":415,"tag":559,"props":19849,"children":19850},{"style":792},[19851],{"type":420,"value":18888},{"type":415,"tag":559,"props":19853,"children":19854},{"class":561,"line":1102},[19855],{"type":415,"tag":559,"props":19856,"children":19857},{"style":792},[19858],{"type":420,"value":18888},{"type":415,"tag":559,"props":19860,"children":19861},{"class":561,"line":1110},[19862,19867,19871,19876,19880,19884,19888,19893,19897,19901,19905,19909,19913],{"type":415,"tag":559,"props":19863,"children":19864},{"style":792},[19865],{"type":420,"value":19866},"        ZipFile",{"type":415,"tag":559,"props":19868,"children":19869},{"style":583},[19870],{"type":420,"value":542},{"type":415,"tag":559,"props":19872,"children":19873},{"style":883},[19874],{"type":420,"value":19875},"CreateFromDirectory",{"type":415,"tag":559,"props":19877,"children":19878},{"style":583},[19879],{"type":420,"value":814},{"type":415,"tag":559,"props":19881,"children":19882},{"style":792},[19883],{"type":420,"value":19843},{"type":415,"tag":559,"props":19885,"children":19886},{"style":583},[19887],{"type":420,"value":2312},{"type":415,"tag":559,"props":19889,"children":19890},{"style":792},[19891],{"type":420,"value":19892}," ArtifactsDirectory ",{"type":415,"tag":559,"props":19894,"children":19895},{"style":583},[19896],{"type":420,"value":12238},{"type":415,"tag":559,"props":19898,"children":19899},{"style":583},[19900],{"type":420,"value":1434},{"type":415,"tag":559,"props":19902,"children":19903},{"style":822},[19904],{"type":420,"value":19607},{"type":415,"tag":559,"props":19906,"children":19907},{"style":583},[19908],{"type":420,"value":819},{"type":415,"tag":559,"props":19910,"children":19911},{"style":583},[19912],{"type":420,"value":18999},{"type":415,"tag":559,"props":19914,"children":19915},{"style":792},[19916],{"type":420,"value":18888},{"type":415,"tag":559,"props":19918,"children":19919},{"class":561,"line":1118},[19920],{"type":415,"tag":559,"props":19921,"children":19922},{"style":583},[19923],{"type":420,"value":7416},{"type":415,"tag":1178,"props":19925,"children":19926},{"icon":5363},[19927],{"type":415,"tag":416,"props":19928,"children":19929},{},[19930,19932,19939],{"type":420,"value":19931},"If you need more compressing archives options, you can check ",{"type":415,"tag":434,"props":19933,"children":19936},{"href":19934,"rel":19935},"https://nuke.build/docs/common/compression/#compressing-archives",[438],[19937],{"type":420,"value":19938},"Nuke documentation",{"type":420,"value":19940},", they have some utilities to do more complex scenarios.",{"type":415,"tag":416,"props":19942,"children":19943},{},[19944,19946,19953,19955,19960,19962,19968],{"type":420,"value":19945},"You may have noted on the line where I set the project that I have ",{"type":415,"tag":434,"props":19947,"children":19950},{"href":19948,"rel":19949},"https://nuke.build/docs/common/solution-project-model/#strong-typed-project-access",[438],[19951],{"type":420,"value":19952},"strong-typed access to the projects in my solution",{"type":420,"value":19954},". This is possible by adding this field with the ",{"type":415,"tag":555,"props":19956,"children":19958},{"className":19957},[],[19959],{"type":420,"value":19329},{"type":420,"value":19961}," attribute and its ",{"type":415,"tag":555,"props":19963,"children":19965},{"className":19964},[],[19966],{"type":420,"value":19967},"GenerateProjects",{"type":420,"value":19969}," property set to true.",{"type":415,"tag":549,"props":19971,"children":19973},{"className":551,"code":19972,"language":326,"meta":401,"style":401},"[Solution(GenerateProjects = true)]  \nreadonly Solution Solution;\n",[19974],{"type":415,"tag":555,"props":19975,"children":19976},{"__ignoreMap":401},[19977,20012],{"type":415,"tag":559,"props":19978,"children":19979},{"class":561,"line":562},[19980,19984,19988,19992,19996,20000,20004,20008],{"type":415,"tag":559,"props":19981,"children":19982},{"style":583},[19983],{"type":420,"value":8804},{"type":415,"tag":559,"props":19985,"children":19986},{"style":572},[19987],{"type":420,"value":19329},{"type":415,"tag":559,"props":19989,"children":19990},{"style":583},[19991],{"type":420,"value":814},{"type":415,"tag":559,"props":19993,"children":19994},{"style":572},[19995],{"type":420,"value":19967},{"type":415,"tag":559,"props":19997,"children":19998},{"style":583},[19999],{"type":420,"value":763},{"type":415,"tag":559,"props":20001,"children":20002},{"style":6887},[20003],{"type":420,"value":6890},{"type":415,"tag":559,"props":20005,"children":20006},{"style":583},[20007],{"type":420,"value":12721},{"type":415,"tag":559,"props":20009,"children":20010},{"style":792},[20011],{"type":420,"value":18888},{"type":415,"tag":559,"props":20013,"children":20014},{"class":561,"line":589},[20015,20020,20025,20029],{"type":415,"tag":559,"props":20016,"children":20017},{"style":566},[20018],{"type":420,"value":20019},"readonly",{"type":415,"tag":559,"props":20021,"children":20022},{"style":572},[20023],{"type":420,"value":20024}," Solution",{"type":415,"tag":559,"props":20026,"children":20027},{"style":572},[20028],{"type":420,"value":20024},{"type":415,"tag":559,"props":20030,"children":20031},{"style":583},[20032],{"type":420,"value":1509},{"type":415,"tag":20034,"props":20035,"children":20037},"calout",{"icon":20036},"i-fluent-emoji-magic-wand",[20038],{"type":415,"tag":416,"props":20039,"children":20040},{},[20041,20043,20050],{"type":420,"value":20042},"It looks like magic but it's not! Nuke uses a ",{"type":415,"tag":434,"props":20044,"children":20047},{"href":20045,"rel":20046},"https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview",[438],[20048],{"type":420,"value":20049},"source generator",{"type":420,"value":20051},"  to do that behind the scenes.",{"type":415,"tag":422,"props":20053,"children":20055},{"id":20054},"provisioning-the-app-service-with-pulumi",[20056],{"type":420,"value":20057},"Provisioning the App Service with Pulumi",{"type":415,"tag":14340,"props":20059,"children":20061},{"id":20060},"the-pulumi-project",[20062],{"type":420,"value":20063},"The Pulumi project",{"type":415,"tag":416,"props":20065,"children":20066},{},[20067,20069,20074,20076,20082],{"type":420,"value":20068},"By default, the infrastructure code is contained in the ",{"type":415,"tag":555,"props":20070,"children":20072},{"className":20071},[],[20073],{"type":420,"value":2831},{"type":420,"value":20075}," file of our project. The resources to provision are declared in the lambda in parameter of the ",{"type":415,"tag":555,"props":20077,"children":20079},{"className":20078},[],[20080],{"type":420,"value":20081},"Deployment.RunAsync",{"type":420,"value":6716},{"type":415,"tag":416,"props":20084,"children":20085},{},[20086],{"type":415,"tag":934,"props":20087,"children":20091},{"alt":20088,"className":20089,"src":20090},"Pulumi program file opened in the IDE.",[938,8504],"/posts/images/pulumi_met_nuke_10.png",[],{"type":415,"tag":1178,"props":20093,"children":20094},{"icon":1180},[20095],{"type":415,"tag":416,"props":20096,"children":20097},{},[20098],{"type":420,"value":20099},"The project uses the top-level statement feature of C#.",{"type":415,"tag":416,"props":20101,"children":20102},{},[20103,20105,20110],{"type":420,"value":20104},"As we don't have many resources to declare for our scenario we will keep all the code in the ",{"type":415,"tag":555,"props":20106,"children":20108},{"className":20107},[],[20109],{"type":420,"value":2831},{"type":420,"value":20111}," file but that is not what you would do in a more complex project.",{"type":415,"tag":14340,"props":20113,"children":20115},{"id":20114},"azure-resources-to-provision",[20116],{"type":420,"value":20117},"Azure resources to provision",{"type":415,"tag":416,"props":20119,"children":20120},{},[20121],{"type":420,"value":20122},"There are 3 Azure resources we need to create in our stack (instance of a Pulumi program):",{"type":415,"tag":5376,"props":20124,"children":20125},{},[20126,20131,20143],{"type":415,"tag":5380,"props":20127,"children":20128},{},[20129],{"type":420,"value":20130},"a resource group to contain the different Azure resources",{"type":415,"tag":5380,"props":20132,"children":20133},{},[20134,20136],{"type":420,"value":20135},"an App Service Plan which ",{"type":415,"tag":434,"props":20137,"children":20140},{"href":20138,"rel":20139},"https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans",[438],[20141],{"type":420,"value":20142},"defines the set of compute resources for a web app to run",{"type":415,"tag":5380,"props":20144,"children":20145},{},[20146],{"type":420,"value":20147},"a Web App / App Service which is where the API will be deployed",{"type":415,"tag":549,"props":20149,"children":20151},{"className":551,"code":20150,"language":326,"meta":401,"style":401},"var resourceGroup = new ResourceGroup($\"rg-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\");  \n  \nvar appServicePlan = new AppServicePlan($\"plan-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\", new AppServicePlanArgs  \n{  \n    ResourceGroupName = resourceGroup.Name,  \n    Kind = \"App\",  \n    Sku = new SkuDescriptionArgs  \n    {  \n        Tier = \"Basic\",  \n        Name = \"B1\",  \n    },  \n});  \n  \nvar appService = new WebApp($\"app-{Deployment.Instance.ProjectName}-{Deployment.Instance.StackName}\", new WebAppArgs   \n{   \n    ResourceGroupName = resourceGroup.Name,  \n    ServerFarmId = appServicePlan.Id  \n});\n",[20152],{"type":415,"tag":555,"props":20153,"children":20154},{"__ignoreMap":401},[20155,20265,20272,20387,20398,20430,20463,20488,20499,20532,20565,20577,20589,20596,20712,20723,20754,20779],{"type":415,"tag":559,"props":20156,"children":20157},{"class":561,"line":562},[20158,20162,20167,20171,20175,20180,20184,20188,20193,20197,20202,20206,20211,20215,20220,20224,20228,20232,20236,20240,20244,20248,20253,20257,20261],{"type":415,"tag":559,"props":20159,"children":20160},{"style":572},[20161],{"type":420,"value":858},{"type":415,"tag":559,"props":20163,"children":20164},{"style":572},[20165],{"type":420,"value":20166}," resourceGroup",{"type":415,"tag":559,"props":20168,"children":20169},{"style":583},[20170],{"type":420,"value":763},{"type":415,"tag":559,"props":20172,"children":20173},{"style":583},[20174],{"type":420,"value":768},{"type":415,"tag":559,"props":20176,"children":20177},{"style":572},[20178],{"type":420,"value":20179}," ResourceGroup",{"type":415,"tag":559,"props":20181,"children":20182},{"style":583},[20183],{"type":420,"value":814},{"type":415,"tag":559,"props":20185,"children":20186},{"style":583},[20187],{"type":420,"value":16136},{"type":415,"tag":559,"props":20189,"children":20190},{"style":822},[20191],{"type":420,"value":20192},"rg-",{"type":415,"tag":559,"props":20194,"children":20195},{"style":583},[20196],{"type":420,"value":2397},{"type":415,"tag":559,"props":20198,"children":20199},{"style":792},[20200],{"type":420,"value":20201},"Deployment",{"type":415,"tag":559,"props":20203,"children":20204},{"style":583},[20205],{"type":420,"value":542},{"type":415,"tag":559,"props":20207,"children":20208},{"style":792},[20209],{"type":420,"value":20210},"Instance",{"type":415,"tag":559,"props":20212,"children":20213},{"style":583},[20214],{"type":420,"value":542},{"type":415,"tag":559,"props":20216,"children":20217},{"style":792},[20218],{"type":420,"value":20219},"ProjectName",{"type":415,"tag":559,"props":20221,"children":20222},{"style":583},[20223],{"type":420,"value":1580},{"type":415,"tag":559,"props":20225,"children":20226},{"style":822},[20227],{"type":420,"value":17172},{"type":415,"tag":559,"props":20229,"children":20230},{"style":583},[20231],{"type":420,"value":2397},{"type":415,"tag":559,"props":20233,"children":20234},{"style":792},[20235],{"type":420,"value":20201},{"type":415,"tag":559,"props":20237,"children":20238},{"style":583},[20239],{"type":420,"value":542},{"type":415,"tag":559,"props":20241,"children":20242},{"style":792},[20243],{"type":420,"value":20210},{"type":415,"tag":559,"props":20245,"children":20246},{"style":583},[20247],{"type":420,"value":542},{"type":415,"tag":559,"props":20249,"children":20250},{"style":792},[20251],{"type":420,"value":20252},"StackName",{"type":415,"tag":559,"props":20254,"children":20255},{"style":583},[20256],{"type":420,"value":1602},{"type":415,"tag":559,"props":20258,"children":20259},{"style":583},[20260],{"type":420,"value":18999},{"type":415,"tag":559,"props":20262,"children":20263},{"style":792},[20264],{"type":420,"value":18888},{"type":415,"tag":559,"props":20266,"children":20267},{"class":561,"line":589},[20268],{"type":415,"tag":559,"props":20269,"children":20270},{"style":792},[20271],{"type":420,"value":18888},{"type":415,"tag":559,"props":20273,"children":20274},{"class":561,"line":608},[20275,20279,20284,20288,20292,20297,20301,20305,20310,20314,20318,20322,20326,20330,20334,20338,20342,20346,20350,20354,20358,20362,20366,20370,20374,20378,20383],{"type":415,"tag":559,"props":20276,"children":20277},{"style":572},[20278],{"type":420,"value":858},{"type":415,"tag":559,"props":20280,"children":20281},{"style":572},[20282],{"type":420,"value":20283}," appServicePlan",{"type":415,"tag":559,"props":20285,"children":20286},{"style":583},[20287],{"type":420,"value":763},{"type":415,"tag":559,"props":20289,"children":20290},{"style":583},[20291],{"type":420,"value":768},{"type":415,"tag":559,"props":20293,"children":20294},{"style":572},[20295],{"type":420,"value":20296}," AppServicePlan",{"type":415,"tag":559,"props":20298,"children":20299},{"style":583},[20300],{"type":420,"value":814},{"type":415,"tag":559,"props":20302,"children":20303},{"style":583},[20304],{"type":420,"value":16136},{"type":415,"tag":559,"props":20306,"children":20307},{"style":822},[20308],{"type":420,"value":20309},"plan-",{"type":415,"tag":559,"props":20311,"children":20312},{"style":583},[20313],{"type":420,"value":2397},{"type":415,"tag":559,"props":20315,"children":20316},{"style":792},[20317],{"type":420,"value":20201},{"type":415,"tag":559,"props":20319,"children":20320},{"style":583},[20321],{"type":420,"value":542},{"type":415,"tag":559,"props":20323,"children":20324},{"style":792},[20325],{"type":420,"value":20210},{"type":415,"tag":559,"props":20327,"children":20328},{"style":583},[20329],{"type":420,"value":542},{"type":415,"tag":559,"props":20331,"children":20332},{"style":792},[20333],{"type":420,"value":20219},{"type":415,"tag":559,"props":20335,"children":20336},{"style":583},[20337],{"type":420,"value":1580},{"type":415,"tag":559,"props":20339,"children":20340},{"style":822},[20341],{"type":420,"value":17172},{"type":415,"tag":559,"props":20343,"children":20344},{"style":583},[20345],{"type":420,"value":2397},{"type":415,"tag":559,"props":20347,"children":20348},{"style":792},[20349],{"type":420,"value":20201},{"type":415,"tag":559,"props":20351,"children":20352},{"style":583},[20353],{"type":420,"value":542},{"type":415,"tag":559,"props":20355,"children":20356},{"style":792},[20357],{"type":420,"value":20210},{"type":415,"tag":559,"props":20359,"children":20360},{"style":583},[20361],{"type":420,"value":542},{"type":415,"tag":559,"props":20363,"children":20364},{"style":792},[20365],{"type":420,"value":20252},{"type":415,"tag":559,"props":20367,"children":20368},{"style":583},[20369],{"type":420,"value":1602},{"type":415,"tag":559,"props":20371,"children":20372},{"style":583},[20373],{"type":420,"value":2312},{"type":415,"tag":559,"props":20375,"children":20376},{"style":583},[20377],{"type":420,"value":768},{"type":415,"tag":559,"props":20379,"children":20380},{"style":572},[20381],{"type":420,"value":20382}," AppServicePlanArgs",{"type":415,"tag":559,"props":20384,"children":20385},{"style":792},[20386],{"type":420,"value":18888},{"type":415,"tag":559,"props":20388,"children":20389},{"class":561,"line":626},[20390,20394],{"type":415,"tag":559,"props":20391,"children":20392},{"style":583},[20393],{"type":420,"value":2397},{"type":415,"tag":559,"props":20395,"children":20396},{"style":792},[20397],{"type":420,"value":18888},{"type":415,"tag":559,"props":20399,"children":20400},{"class":561,"line":643},[20401,20406,20410,20414,20418,20422,20426],{"type":415,"tag":559,"props":20402,"children":20403},{"style":792},[20404],{"type":420,"value":20405},"    ResourceGroupName ",{"type":415,"tag":559,"props":20407,"children":20408},{"style":583},[20409],{"type":420,"value":800},{"type":415,"tag":559,"props":20411,"children":20412},{"style":792},[20413],{"type":420,"value":20166},{"type":415,"tag":559,"props":20415,"children":20416},{"style":583},[20417],{"type":420,"value":542},{"type":415,"tag":559,"props":20419,"children":20420},{"style":792},[20421],{"type":420,"value":1412},{"type":415,"tag":559,"props":20423,"children":20424},{"style":583},[20425],{"type":420,"value":2312},{"type":415,"tag":559,"props":20427,"children":20428},{"style":792},[20429],{"type":420,"value":18888},{"type":415,"tag":559,"props":20431,"children":20432},{"class":561,"line":660},[20433,20438,20442,20446,20451,20455,20459],{"type":415,"tag":559,"props":20434,"children":20435},{"style":792},[20436],{"type":420,"value":20437},"    Kind ",{"type":415,"tag":559,"props":20439,"children":20440},{"style":583},[20441],{"type":420,"value":800},{"type":415,"tag":559,"props":20443,"children":20444},{"style":583},[20445],{"type":420,"value":1434},{"type":415,"tag":559,"props":20447,"children":20448},{"style":822},[20449],{"type":420,"value":20450},"App",{"type":415,"tag":559,"props":20452,"children":20453},{"style":583},[20454],{"type":420,"value":819},{"type":415,"tag":559,"props":20456,"children":20457},{"style":583},[20458],{"type":420,"value":2312},{"type":415,"tag":559,"props":20460,"children":20461},{"style":792},[20462],{"type":420,"value":18888},{"type":415,"tag":559,"props":20464,"children":20465},{"class":561,"line":677},[20466,20471,20475,20479,20484],{"type":415,"tag":559,"props":20467,"children":20468},{"style":792},[20469],{"type":420,"value":20470},"    Sku ",{"type":415,"tag":559,"props":20472,"children":20473},{"style":583},[20474],{"type":420,"value":800},{"type":415,"tag":559,"props":20476,"children":20477},{"style":583},[20478],{"type":420,"value":768},{"type":415,"tag":559,"props":20480,"children":20481},{"style":572},[20482],{"type":420,"value":20483}," SkuDescriptionArgs",{"type":415,"tag":559,"props":20485,"children":20486},{"style":792},[20487],{"type":420,"value":18888},{"type":415,"tag":559,"props":20489,"children":20490},{"class":561,"line":690},[20491,20495],{"type":415,"tag":559,"props":20492,"children":20493},{"style":583},[20494],{"type":420,"value":18921},{"type":415,"tag":559,"props":20496,"children":20497},{"style":792},[20498],{"type":420,"value":18888},{"type":415,"tag":559,"props":20500,"children":20501},{"class":561,"line":1089},[20502,20507,20511,20515,20520,20524,20528],{"type":415,"tag":559,"props":20503,"children":20504},{"style":792},[20505],{"type":420,"value":20506},"        Tier ",{"type":415,"tag":559,"props":20508,"children":20509},{"style":583},[20510],{"type":420,"value":800},{"type":415,"tag":559,"props":20512,"children":20513},{"style":583},[20514],{"type":420,"value":1434},{"type":415,"tag":559,"props":20516,"children":20517},{"style":822},[20518],{"type":420,"value":20519},"Basic",{"type":415,"tag":559,"props":20521,"children":20522},{"style":583},[20523],{"type":420,"value":819},{"type":415,"tag":559,"props":20525,"children":20526},{"style":583},[20527],{"type":420,"value":2312},{"type":415,"tag":559,"props":20529,"children":20530},{"style":792},[20531],{"type":420,"value":18888},{"type":415,"tag":559,"props":20533,"children":20534},{"class":561,"line":1102},[20535,20540,20544,20548,20553,20557,20561],{"type":415,"tag":559,"props":20536,"children":20537},{"style":792},[20538],{"type":420,"value":20539},"        Name ",{"type":415,"tag":559,"props":20541,"children":20542},{"style":583},[20543],{"type":420,"value":800},{"type":415,"tag":559,"props":20545,"children":20546},{"style":583},[20547],{"type":420,"value":1434},{"type":415,"tag":559,"props":20549,"children":20550},{"style":822},[20551],{"type":420,"value":20552},"B1",{"type":415,"tag":559,"props":20554,"children":20555},{"style":583},[20556],{"type":420,"value":819},{"type":415,"tag":559,"props":20558,"children":20559},{"style":583},[20560],{"type":420,"value":2312},{"type":415,"tag":559,"props":20562,"children":20563},{"style":792},[20564],{"type":420,"value":18888},{"type":415,"tag":559,"props":20566,"children":20567},{"class":561,"line":1110},[20568,20573],{"type":415,"tag":559,"props":20569,"children":20570},{"style":583},[20571],{"type":420,"value":20572},"    },",{"type":415,"tag":559,"props":20574,"children":20575},{"style":792},[20576],{"type":420,"value":18888},{"type":415,"tag":559,"props":20578,"children":20579},{"class":561,"line":1118},[20580,20585],{"type":415,"tag":559,"props":20581,"children":20582},{"style":583},[20583],{"type":420,"value":20584},"});",{"type":415,"tag":559,"props":20586,"children":20587},{"style":792},[20588],{"type":420,"value":18888},{"type":415,"tag":559,"props":20590,"children":20591},{"class":561,"line":1171},[20592],{"type":415,"tag":559,"props":20593,"children":20594},{"style":792},[20595],{"type":420,"value":18888},{"type":415,"tag":559,"props":20597,"children":20598},{"class":561,"line":1748},[20599,20603,20608,20612,20616,20621,20625,20629,20634,20638,20642,20646,20650,20654,20658,20662,20666,20670,20674,20678,20682,20686,20690,20694,20698,20702,20707],{"type":415,"tag":559,"props":20600,"children":20601},{"style":572},[20602],{"type":420,"value":858},{"type":415,"tag":559,"props":20604,"children":20605},{"style":572},[20606],{"type":420,"value":20607}," appService",{"type":415,"tag":559,"props":20609,"children":20610},{"style":583},[20611],{"type":420,"value":763},{"type":415,"tag":559,"props":20613,"children":20614},{"style":583},[20615],{"type":420,"value":768},{"type":415,"tag":559,"props":20617,"children":20618},{"style":572},[20619],{"type":420,"value":20620}," WebApp",{"type":415,"tag":559,"props":20622,"children":20623},{"style":583},[20624],{"type":420,"value":814},{"type":415,"tag":559,"props":20626,"children":20627},{"style":583},[20628],{"type":420,"value":16136},{"type":415,"tag":559,"props":20630,"children":20631},{"style":822},[20632],{"type":420,"value":20633},"app-",{"type":415,"tag":559,"props":20635,"children":20636},{"style":583},[20637],{"type":420,"value":2397},{"type":415,"tag":559,"props":20639,"children":20640},{"style":792},[20641],{"type":420,"value":20201},{"type":415,"tag":559,"props":20643,"children":20644},{"style":583},[20645],{"type":420,"value":542},{"type":415,"tag":559,"props":20647,"children":20648},{"style":792},[20649],{"type":420,"value":20210},{"type":415,"tag":559,"props":20651,"children":20652},{"style":583},[20653],{"type":420,"value":542},{"type":415,"tag":559,"props":20655,"children":20656},{"style":792},[20657],{"type":420,"value":20219},{"type":415,"tag":559,"props":20659,"children":20660},{"style":583},[20661],{"type":420,"value":1580},{"type":415,"tag":559,"props":20663,"children":20664},{"style":822},[20665],{"type":420,"value":17172},{"type":415,"tag":559,"props":20667,"children":20668},{"style":583},[20669],{"type":420,"value":2397},{"type":415,"tag":559,"props":20671,"children":20672},{"style":792},[20673],{"type":420,"value":20201},{"type":415,"tag":559,"props":20675,"children":20676},{"style":583},[20677],{"type":420,"value":542},{"type":415,"tag":559,"props":20679,"children":20680},{"style":792},[20681],{"type":420,"value":20210},{"type":415,"tag":559,"props":20683,"children":20684},{"style":583},[20685],{"type":420,"value":542},{"type":415,"tag":559,"props":20687,"children":20688},{"style":792},[20689],{"type":420,"value":20252},{"type":415,"tag":559,"props":20691,"children":20692},{"style":583},[20693],{"type":420,"value":1602},{"type":415,"tag":559,"props":20695,"children":20696},{"style":583},[20697],{"type":420,"value":2312},{"type":415,"tag":559,"props":20699,"children":20700},{"style":583},[20701],{"type":420,"value":768},{"type":415,"tag":559,"props":20703,"children":20704},{"style":572},[20705],{"type":420,"value":20706}," WebAppArgs",{"type":415,"tag":559,"props":20708,"children":20709},{"style":792},[20710],{"type":420,"value":20711},"   \n",{"type":415,"tag":559,"props":20713,"children":20714},{"class":561,"line":1769},[20715,20719],{"type":415,"tag":559,"props":20716,"children":20717},{"style":583},[20718],{"type":420,"value":2397},{"type":415,"tag":559,"props":20720,"children":20721},{"style":792},[20722],{"type":420,"value":20711},{"type":415,"tag":559,"props":20724,"children":20725},{"class":561,"line":1786},[20726,20730,20734,20738,20742,20746,20750],{"type":415,"tag":559,"props":20727,"children":20728},{"style":792},[20729],{"type":420,"value":20405},{"type":415,"tag":559,"props":20731,"children":20732},{"style":583},[20733],{"type":420,"value":800},{"type":415,"tag":559,"props":20735,"children":20736},{"style":792},[20737],{"type":420,"value":20166},{"type":415,"tag":559,"props":20739,"children":20740},{"style":583},[20741],{"type":420,"value":542},{"type":415,"tag":559,"props":20743,"children":20744},{"style":792},[20745],{"type":420,"value":1412},{"type":415,"tag":559,"props":20747,"children":20748},{"style":583},[20749],{"type":420,"value":2312},{"type":415,"tag":559,"props":20751,"children":20752},{"style":792},[20753],{"type":420,"value":18888},{"type":415,"tag":559,"props":20755,"children":20756},{"class":561,"line":1795},[20757,20762,20766,20770,20774],{"type":415,"tag":559,"props":20758,"children":20759},{"style":792},[20760],{"type":420,"value":20761},"    ServerFarmId ",{"type":415,"tag":559,"props":20763,"children":20764},{"style":583},[20765],{"type":420,"value":800},{"type":415,"tag":559,"props":20767,"children":20768},{"style":792},[20769],{"type":420,"value":20283},{"type":415,"tag":559,"props":20771,"children":20772},{"style":583},[20773],{"type":420,"value":542},{"type":415,"tag":559,"props":20775,"children":20776},{"style":792},[20777],{"type":420,"value":20778},"Id  \n",{"type":415,"tag":559,"props":20780,"children":20781},{"class":561,"line":3289},[20782],{"type":415,"tag":559,"props":20783,"children":20784},{"style":583},[20785],{"type":420,"value":5833},{"type":415,"tag":416,"props":20787,"children":20788},{},[20789],{"type":420,"value":20790},"The code is quite simple, and because we are writing C# in our IDE, we have autocompletion and everything we need to make writing the infrastructure code easier.",{"type":415,"tag":1178,"props":20792,"children":20793},{"icon":5363},[20794],{"type":415,"tag":416,"props":20795,"children":20796},{},[20797],{"type":420,"value":20798},"If you are used to Azure Bicep or ARM templates, the names of the classes or properties will look familiar to you. It's because we are using Azure Native, which is a Pulumi native provider that is generated from Azure APIs.",{"type":415,"tag":14340,"props":20800,"children":20802},{"id":20801},"stack-outputs",[20803],{"type":420,"value":20804},"Stack outputs",{"type":415,"tag":416,"props":20806,"children":20807},{},[20808],{"type":420,"value":20809},"Provisioning the cloud resources we need is great but we have to think about the next step which is to deploy our API on these resources. So what will we need for that?",{"type":415,"tag":416,"props":20811,"children":20812},{},[20813,20815,20821],{"type":420,"value":20814},"First, we will need to have the name of the provisioned App Service. That's easy it's the property Name of the ",{"type":415,"tag":555,"props":20816,"children":20818},{"className":20817},[],[20819],{"type":420,"value":20820},"appService",{"type":420,"value":20822}," variable.",{"type":415,"tag":416,"props":20824,"children":20825},{},[20826,20828,20835],{"type":420,"value":20827},"Second, because we are going to use the Kudu API to zip deploy our application to the App Service, we will need the ",{"type":415,"tag":434,"props":20829,"children":20832},{"href":20830,"rel":20831},"https://github.com/projectkudu/kudu/wiki/Deployment-credentials#site-credentials-aka-publish-profile-credentials",[438],[20833],{"type":420,"value":20834},"site credentials (aka the Publishing Profile Credentials)",{"type":420,"value":20836},". These can be retrieved in the Pulumi program using the following code:",{"type":415,"tag":549,"props":20838,"children":20840},{"className":551,"code":20839,"language":326,"meta":401,"style":401},"var publishingCredentials = ListWebAppPublishingCredentials.Invoke(new()  \n{  \n    ResourceGroupName = resourceGroup.Name,  \n    Name = appService.Name  \n});\n",[20841],{"type":415,"tag":555,"props":20842,"children":20843},{"__ignoreMap":401},[20844,20882,20893,20924,20948],{"type":415,"tag":559,"props":20845,"children":20846},{"class":561,"line":562},[20847,20851,20856,20860,20865,20869,20873,20878],{"type":415,"tag":559,"props":20848,"children":20849},{"style":572},[20850],{"type":420,"value":858},{"type":415,"tag":559,"props":20852,"children":20853},{"style":572},[20854],{"type":420,"value":20855}," publishingCredentials",{"type":415,"tag":559,"props":20857,"children":20858},{"style":583},[20859],{"type":420,"value":763},{"type":415,"tag":559,"props":20861,"children":20862},{"style":792},[20863],{"type":420,"value":20864}," ListWebAppPublishingCredentials",{"type":415,"tag":559,"props":20866,"children":20867},{"style":583},[20868],{"type":420,"value":542},{"type":415,"tag":559,"props":20870,"children":20871},{"style":883},[20872],{"type":420,"value":15113},{"type":415,"tag":559,"props":20874,"children":20875},{"style":583},[20876],{"type":420,"value":20877},"(new()",{"type":415,"tag":559,"props":20879,"children":20880},{"style":792},[20881],{"type":420,"value":18888},{"type":415,"tag":559,"props":20883,"children":20884},{"class":561,"line":589},[20885,20889],{"type":415,"tag":559,"props":20886,"children":20887},{"style":583},[20888],{"type":420,"value":2397},{"type":415,"tag":559,"props":20890,"children":20891},{"style":792},[20892],{"type":420,"value":18888},{"type":415,"tag":559,"props":20894,"children":20895},{"class":561,"line":608},[20896,20900,20904,20908,20912,20916,20920],{"type":415,"tag":559,"props":20897,"children":20898},{"style":792},[20899],{"type":420,"value":20405},{"type":415,"tag":559,"props":20901,"children":20902},{"style":583},[20903],{"type":420,"value":800},{"type":415,"tag":559,"props":20905,"children":20906},{"style":792},[20907],{"type":420,"value":20166},{"type":415,"tag":559,"props":20909,"children":20910},{"style":583},[20911],{"type":420,"value":542},{"type":415,"tag":559,"props":20913,"children":20914},{"style":792},[20915],{"type":420,"value":1412},{"type":415,"tag":559,"props":20917,"children":20918},{"style":583},[20919],{"type":420,"value":2312},{"type":415,"tag":559,"props":20921,"children":20922},{"style":792},[20923],{"type":420,"value":18888},{"type":415,"tag":559,"props":20925,"children":20926},{"class":561,"line":626},[20927,20931,20935,20939,20943],{"type":415,"tag":559,"props":20928,"children":20929},{"style":792},[20930],{"type":420,"value":15162},{"type":415,"tag":559,"props":20932,"children":20933},{"style":583},[20934],{"type":420,"value":800},{"type":415,"tag":559,"props":20936,"children":20937},{"style":792},[20938],{"type":420,"value":20607},{"type":415,"tag":559,"props":20940,"children":20941},{"style":583},[20942],{"type":420,"value":542},{"type":415,"tag":559,"props":20944,"children":20945},{"style":792},[20946],{"type":420,"value":20947},"Name  \n",{"type":415,"tag":559,"props":20949,"children":20950},{"class":561,"line":643},[20951],{"type":415,"tag":559,"props":20952,"children":20953},{"style":583},[20954],{"type":420,"value":5833},{"type":415,"tag":1178,"props":20956,"children":20957},{"icon":1180},[20958],{"type":415,"tag":416,"props":20959,"children":20960},{},[20961,20963,20970],{"type":420,"value":20962},"Using the Kudu API is just one of the ",{"type":415,"tag":434,"props":20964,"children":20967},{"href":20965,"rel":20966},"https://learn.microsoft.com/en-us/azure/app-service/deploy-zip?tabs=cli#deploy-a-zip-package",[438],[20968],{"type":420,"value":20969},"many ways",{"type":420,"value":20971}," to deploy a zip package to an App Service. I could have chosen another way like using the Azure CLI, in that case retrieving the site credentials would not have been needed.",{"type":415,"tag":416,"props":20973,"children":20974},{},[20975,20977,20984],{"type":420,"value":20976},"Pulumi, like Terraform, has this concept of stack ",{"type":415,"tag":434,"props":20978,"children":20981},{"href":20979,"rel":20980},"https://www.pulumi.com/docs/intro/concepts/stack/#outputs",[438],[20982],{"type":420,"value":20983},"output",{"type":420,"value":20985},"  where outputs are information about your stack/infrastructure that you want to expose. That is exactly what we need to export our App Service name and our site credentials so that they can be retrieved later by the Nuke code that will take care of the application deployment. To export these values we can return them in a Dictionary like that:",{"type":415,"tag":549,"props":20987,"children":20989},{"className":551,"code":20988,"language":326,"meta":401,"style":401},"return new Dictionary\u003Cstring, object?>  \n{  \n    [\"publishingUsername\"] = Output.CreateSecret(publishingCredentials.Apply(c => c.PublishingUserName)),  \n    [\"publishingUserPassword\"] = Output.CreateSecret(publishingCredentials.Apply(c => c.PublishingPassword)),  \n    [\"appServiceName\"] = appService.Name  \n};\n",[20990],{"type":415,"tag":555,"props":20991,"children":20992},{"__ignoreMap":401},[20993,21029,21040,21132,21221,21261],{"type":415,"tag":559,"props":20994,"children":20995},{"class":561,"line":562},[20996,21000,21004,21008,21012,21016,21020,21025],{"type":415,"tag":559,"props":20997,"children":20998},{"style":745},[20999],{"type":420,"value":18080},{"type":415,"tag":559,"props":21001,"children":21002},{"style":583},[21003],{"type":420,"value":768},{"type":415,"tag":559,"props":21005,"children":21006},{"style":572},[21007],{"type":420,"value":18089},{"type":415,"tag":559,"props":21009,"children":21010},{"style":583},[21011],{"type":420,"value":891},{"type":415,"tag":559,"props":21013,"children":21014},{"style":583},[21015],{"type":420,"value":2015},{"type":415,"tag":559,"props":21017,"children":21018},{"style":583},[21019],{"type":420,"value":2312},{"type":415,"tag":559,"props":21021,"children":21022},{"style":583},[21023],{"type":420,"value":21024}," object?>",{"type":415,"tag":559,"props":21026,"children":21027},{"style":792},[21028],{"type":420,"value":18888},{"type":415,"tag":559,"props":21030,"children":21031},{"class":561,"line":589},[21032,21036],{"type":415,"tag":559,"props":21033,"children":21034},{"style":583},[21035],{"type":420,"value":2397},{"type":415,"tag":559,"props":21037,"children":21038},{"style":792},[21039],{"type":420,"value":18888},{"type":415,"tag":559,"props":21041,"children":21042},{"class":561,"line":608},[21043,21047,21051,21056,21060,21064,21068,21072,21076,21081,21085,21090,21094,21098,21102,21106,21110,21114,21118,21123,21128],{"type":415,"tag":559,"props":21044,"children":21045},{"style":583},[21046],{"type":420,"value":8989},{"type":415,"tag":559,"props":21048,"children":21049},{"style":583},[21050],{"type":420,"value":819},{"type":415,"tag":559,"props":21052,"children":21053},{"style":822},[21054],{"type":420,"value":21055},"publishingUsername",{"type":415,"tag":559,"props":21057,"children":21058},{"style":583},[21059],{"type":420,"value":819},{"type":415,"tag":559,"props":21061,"children":21062},{"style":583},[21063],{"type":420,"value":14849},{"type":415,"tag":559,"props":21065,"children":21066},{"style":583},[21067],{"type":420,"value":763},{"type":415,"tag":559,"props":21069,"children":21070},{"style":792},[21071],{"type":420,"value":16679},{"type":415,"tag":559,"props":21073,"children":21074},{"style":583},[21075],{"type":420,"value":542},{"type":415,"tag":559,"props":21077,"children":21078},{"style":883},[21079],{"type":420,"value":21080},"CreateSecret",{"type":415,"tag":559,"props":21082,"children":21083},{"style":583},[21084],{"type":420,"value":814},{"type":415,"tag":559,"props":21086,"children":21087},{"style":792},[21088],{"type":420,"value":21089},"publishingCredentials",{"type":415,"tag":559,"props":21091,"children":21092},{"style":583},[21093],{"type":420,"value":542},{"type":415,"tag":559,"props":21095,"children":21096},{"style":883},[21097],{"type":420,"value":15884},{"type":415,"tag":559,"props":21099,"children":21100},{"style":583},[21101],{"type":420,"value":814},{"type":415,"tag":559,"props":21103,"children":21104},{"style":572},[21105],{"type":420,"value":15893},{"type":415,"tag":559,"props":21107,"children":21108},{"style":583},[21109],{"type":420,"value":1861},{"type":415,"tag":559,"props":21111,"children":21112},{"style":792},[21113],{"type":420,"value":15902},{"type":415,"tag":559,"props":21115,"children":21116},{"style":583},[21117],{"type":420,"value":542},{"type":415,"tag":559,"props":21119,"children":21120},{"style":792},[21121],{"type":420,"value":21122},"PublishingUserName",{"type":415,"tag":559,"props":21124,"children":21125},{"style":583},[21126],{"type":420,"value":21127},")),",{"type":415,"tag":559,"props":21129,"children":21130},{"style":792},[21131],{"type":420,"value":18888},{"type":415,"tag":559,"props":21133,"children":21134},{"class":561,"line":626},[21135,21139,21143,21148,21152,21156,21160,21164,21168,21172,21176,21180,21184,21188,21192,21196,21200,21204,21208,21213,21217],{"type":415,"tag":559,"props":21136,"children":21137},{"style":583},[21138],{"type":420,"value":8989},{"type":415,"tag":559,"props":21140,"children":21141},{"style":583},[21142],{"type":420,"value":819},{"type":415,"tag":559,"props":21144,"children":21145},{"style":822},[21146],{"type":420,"value":21147},"publishingUserPassword",{"type":415,"tag":559,"props":21149,"children":21150},{"style":583},[21151],{"type":420,"value":819},{"type":415,"tag":559,"props":21153,"children":21154},{"style":583},[21155],{"type":420,"value":14849},{"type":415,"tag":559,"props":21157,"children":21158},{"style":583},[21159],{"type":420,"value":763},{"type":415,"tag":559,"props":21161,"children":21162},{"style":792},[21163],{"type":420,"value":16679},{"type":415,"tag":559,"props":21165,"children":21166},{"style":583},[21167],{"type":420,"value":542},{"type":415,"tag":559,"props":21169,"children":21170},{"style":883},[21171],{"type":420,"value":21080},{"type":415,"tag":559,"props":21173,"children":21174},{"style":583},[21175],{"type":420,"value":814},{"type":415,"tag":559,"props":21177,"children":21178},{"style":792},[21179],{"type":420,"value":21089},{"type":415,"tag":559,"props":21181,"children":21182},{"style":583},[21183],{"type":420,"value":542},{"type":415,"tag":559,"props":21185,"children":21186},{"style":883},[21187],{"type":420,"value":15884},{"type":415,"tag":559,"props":21189,"children":21190},{"style":583},[21191],{"type":420,"value":814},{"type":415,"tag":559,"props":21193,"children":21194},{"style":572},[21195],{"type":420,"value":15893},{"type":415,"tag":559,"props":21197,"children":21198},{"style":583},[21199],{"type":420,"value":1861},{"type":415,"tag":559,"props":21201,"children":21202},{"style":792},[21203],{"type":420,"value":15902},{"type":415,"tag":559,"props":21205,"children":21206},{"style":583},[21207],{"type":420,"value":542},{"type":415,"tag":559,"props":21209,"children":21210},{"style":792},[21211],{"type":420,"value":21212},"PublishingPassword",{"type":415,"tag":559,"props":21214,"children":21215},{"style":583},[21216],{"type":420,"value":21127},{"type":415,"tag":559,"props":21218,"children":21219},{"style":792},[21220],{"type":420,"value":18888},{"type":415,"tag":559,"props":21222,"children":21223},{"class":561,"line":643},[21224,21228,21232,21237,21241,21245,21249,21253,21257],{"type":415,"tag":559,"props":21225,"children":21226},{"style":583},[21227],{"type":420,"value":8989},{"type":415,"tag":559,"props":21229,"children":21230},{"style":583},[21231],{"type":420,"value":819},{"type":415,"tag":559,"props":21233,"children":21234},{"style":822},[21235],{"type":420,"value":21236},"appServiceName",{"type":415,"tag":559,"props":21238,"children":21239},{"style":583},[21240],{"type":420,"value":819},{"type":415,"tag":559,"props":21242,"children":21243},{"style":583},[21244],{"type":420,"value":14849},{"type":415,"tag":559,"props":21246,"children":21247},{"style":583},[21248],{"type":420,"value":763},{"type":415,"tag":559,"props":21250,"children":21251},{"style":792},[21252],{"type":420,"value":20607},{"type":415,"tag":559,"props":21254,"children":21255},{"style":583},[21256],{"type":420,"value":542},{"type":415,"tag":559,"props":21258,"children":21259},{"style":792},[21260],{"type":420,"value":20947},{"type":415,"tag":559,"props":21262,"children":21263},{"class":561,"line":660},[21264],{"type":415,"tag":559,"props":21265,"children":21266},{"style":583},[21267],{"type":420,"value":841},{"type":415,"tag":416,"props":21269,"children":21270},{},[21271,21273,21279],{"type":420,"value":21272},"You might notice that we use the ",{"type":415,"tag":555,"props":21274,"children":21276},{"className":21275},[],[21277],{"type":420,"value":21278},"Output.CreateSecret",{"type":420,"value":21280}," method to create outputs for our publishing credentials. The aim is to tell Pulumi to treat these values as secrets, and that's what it will do by encrypting them in the state file for extra protection (that is not something Terraform does by the way).",{"type":415,"tag":14340,"props":21282,"children":21284},{"id":21283},"implementing-the-provision-infrastructure-step",[21285],{"type":420,"value":21286},"Implementing the Provision Infrastructure step",{"type":415,"tag":416,"props":21288,"children":21289},{},[21290,21292,21297],{"type":420,"value":21291},"To deploy the infrastructure, we can use the ",{"type":415,"tag":555,"props":21293,"children":21295},{"className":21294},[],[21296],{"type":420,"value":18235},{"type":420,"value":21298}," command. We will write the code in a fluent way as we did with the dotnet CLI:",{"type":415,"tag":549,"props":21300,"children":21302},{"className":551,"code":21301,"language":326,"meta":401,"style":401},"AbsolutePath InfrastructureDirectory => RootDirectory / \"infra\";\n\nTarget ProvisionInfra => _ => _  \n    .Description(\"Provision the infrastructure on Azure\")  \n    .Executes(() =>  \n    {  \n        PulumiTasks.PulumiUp(_ => _  \n            .SetCwd(InfrastructureDirectory)  \n            .SetStack(\"dev\")  \n            .EnableSkipPreview());  \n    });\n",[21303],{"type":415,"tag":555,"props":21304,"children":21305},{"__ignoreMap":401},[21306,21345,21352,21380,21417,21440,21451,21484,21512,21548,21568],{"type":415,"tag":559,"props":21307,"children":21308},{"class":561,"line":562},[21309,21313,21317,21321,21325,21329,21333,21337,21341],{"type":415,"tag":559,"props":21310,"children":21311},{"style":792},[21312],{"type":420,"value":19055},{"type":415,"tag":559,"props":21314,"children":21315},{"style":572},[21316],{"type":420,"value":19113},{"type":415,"tag":559,"props":21318,"children":21319},{"style":583},[21320],{"type":420,"value":1861},{"type":415,"tag":559,"props":21322,"children":21323},{"style":792},[21324],{"type":420,"value":19069},{"type":415,"tag":559,"props":21326,"children":21327},{"style":583},[21328],{"type":420,"value":12238},{"type":415,"tag":559,"props":21330,"children":21331},{"style":583},[21332],{"type":420,"value":1434},{"type":415,"tag":559,"props":21334,"children":21335},{"style":822},[21336],{"type":420,"value":14129},{"type":415,"tag":559,"props":21338,"children":21339},{"style":583},[21340],{"type":420,"value":819},{"type":415,"tag":559,"props":21342,"children":21343},{"style":583},[21344],{"type":420,"value":1509},{"type":415,"tag":559,"props":21346,"children":21347},{"class":561,"line":589},[21348],{"type":415,"tag":559,"props":21349,"children":21350},{"emptyLinePlaceholder":847},[21351],{"type":420,"value":850},{"type":415,"tag":559,"props":21353,"children":21354},{"class":561,"line":608},[21355,21359,21364,21368,21372,21376],{"type":415,"tag":559,"props":21356,"children":21357},{"style":792},[21358],{"type":420,"value":18837},{"type":415,"tag":559,"props":21360,"children":21361},{"style":572},[21362],{"type":420,"value":21363},"ProvisionInfra",{"type":415,"tag":559,"props":21365,"children":21366},{"style":583},[21367],{"type":420,"value":1861},{"type":415,"tag":559,"props":21369,"children":21370},{"style":572},[21371],{"type":420,"value":8126},{"type":415,"tag":559,"props":21373,"children":21374},{"style":583},[21375],{"type":420,"value":1861},{"type":415,"tag":559,"props":21377,"children":21378},{"style":792},[21379],{"type":420,"value":18858},{"type":415,"tag":559,"props":21381,"children":21382},{"class":561,"line":626},[21383,21387,21392,21396,21400,21405,21409,21413],{"type":415,"tag":559,"props":21384,"children":21385},{"style":583},[21386],{"type":420,"value":1842},{"type":415,"tag":559,"props":21388,"children":21389},{"style":883},[21390],{"type":420,"value":21391},"Description",{"type":415,"tag":559,"props":21393,"children":21394},{"style":583},[21395],{"type":420,"value":814},{"type":415,"tag":559,"props":21397,"children":21398},{"style":583},[21399],{"type":420,"value":819},{"type":415,"tag":559,"props":21401,"children":21402},{"style":822},[21403],{"type":420,"value":21404},"Provision the infrastructure on Azure",{"type":415,"tag":559,"props":21406,"children":21407},{"style":583},[21408],{"type":420,"value":819},{"type":415,"tag":559,"props":21410,"children":21411},{"style":583},[21412],{"type":420,"value":1468},{"type":415,"tag":559,"props":21414,"children":21415},{"style":792},[21416],{"type":420,"value":18888},{"type":415,"tag":559,"props":21418,"children":21419},{"class":561,"line":643},[21420,21424,21428,21432,21436],{"type":415,"tag":559,"props":21421,"children":21422},{"style":583},[21423],{"type":420,"value":1842},{"type":415,"tag":559,"props":21425,"children":21426},{"style":883},[21427],{"type":420,"value":18900},{"type":415,"tag":559,"props":21429,"children":21430},{"style":583},[21431],{"type":420,"value":18905},{"type":415,"tag":559,"props":21433,"children":21434},{"style":583},[21435],{"type":420,"value":1861},{"type":415,"tag":559,"props":21437,"children":21438},{"style":792},[21439],{"type":420,"value":18888},{"type":415,"tag":559,"props":21441,"children":21442},{"class":561,"line":660},[21443,21447],{"type":415,"tag":559,"props":21444,"children":21445},{"style":583},[21446],{"type":420,"value":18921},{"type":415,"tag":559,"props":21448,"children":21449},{"style":792},[21450],{"type":420,"value":18888},{"type":415,"tag":559,"props":21452,"children":21453},{"class":561,"line":677},[21454,21459,21463,21468,21472,21476,21480],{"type":415,"tag":559,"props":21455,"children":21456},{"style":792},[21457],{"type":420,"value":21458},"        PulumiTasks",{"type":415,"tag":559,"props":21460,"children":21461},{"style":583},[21462],{"type":420,"value":542},{"type":415,"tag":559,"props":21464,"children":21465},{"style":883},[21466],{"type":420,"value":21467},"PulumiUp",{"type":415,"tag":559,"props":21469,"children":21470},{"style":583},[21471],{"type":420,"value":814},{"type":415,"tag":559,"props":21473,"children":21474},{"style":572},[21475],{"type":420,"value":8117},{"type":415,"tag":559,"props":21477,"children":21478},{"style":583},[21479],{"type":420,"value":1861},{"type":415,"tag":559,"props":21481,"children":21482},{"style":792},[21483],{"type":420,"value":18858},{"type":415,"tag":559,"props":21485,"children":21486},{"class":561,"line":690},[21487,21491,21496,21500,21504,21508],{"type":415,"tag":559,"props":21488,"children":21489},{"style":583},[21490],{"type":420,"value":8274},{"type":415,"tag":559,"props":21492,"children":21493},{"style":883},[21494],{"type":420,"value":21495},"SetCwd",{"type":415,"tag":559,"props":21497,"children":21498},{"style":583},[21499],{"type":420,"value":814},{"type":415,"tag":559,"props":21501,"children":21502},{"style":792},[21503],{"type":420,"value":19113},{"type":415,"tag":559,"props":21505,"children":21506},{"style":583},[21507],{"type":420,"value":1468},{"type":415,"tag":559,"props":21509,"children":21510},{"style":792},[21511],{"type":420,"value":18888},{"type":415,"tag":559,"props":21513,"children":21514},{"class":561,"line":1089},[21515,21519,21524,21528,21532,21536,21540,21544],{"type":415,"tag":559,"props":21516,"children":21517},{"style":583},[21518],{"type":420,"value":8274},{"type":415,"tag":559,"props":21520,"children":21521},{"style":883},[21522],{"type":420,"value":21523},"SetStack",{"type":415,"tag":559,"props":21525,"children":21526},{"style":583},[21527],{"type":420,"value":814},{"type":415,"tag":559,"props":21529,"children":21530},{"style":583},[21531],{"type":420,"value":819},{"type":415,"tag":559,"props":21533,"children":21534},{"style":822},[21535],{"type":420,"value":14476},{"type":415,"tag":559,"props":21537,"children":21538},{"style":583},[21539],{"type":420,"value":819},{"type":415,"tag":559,"props":21541,"children":21542},{"style":583},[21543],{"type":420,"value":1468},{"type":415,"tag":559,"props":21545,"children":21546},{"style":792},[21547],{"type":420,"value":18888},{"type":415,"tag":559,"props":21549,"children":21550},{"class":561,"line":1102},[21551,21555,21560,21564],{"type":415,"tag":559,"props":21552,"children":21553},{"style":583},[21554],{"type":420,"value":8274},{"type":415,"tag":559,"props":21556,"children":21557},{"style":883},[21558],{"type":420,"value":21559},"EnableSkipPreview",{"type":415,"tag":559,"props":21561,"children":21562},{"style":583},[21563],{"type":420,"value":19572},{"type":415,"tag":559,"props":21565,"children":21566},{"style":792},[21567],{"type":420,"value":18888},{"type":415,"tag":559,"props":21569,"children":21570},{"class":561,"line":1110},[21571],{"type":415,"tag":559,"props":21572,"children":21573},{"style":583},[21574],{"type":420,"value":7416},{"type":415,"tag":422,"props":21576,"children":21578},{"id":21577},"deploying-the-aspnet-core-api-to-azure-app-service",[21579],{"type":420,"value":21580},"Deploying the ASP.NET Core API to Azure App Service",{"type":415,"tag":416,"props":21582,"children":21583},{},[21584,21586,21592],{"type":420,"value":21585},"I previously said we were going to use the Kudu API to deploy our application. You can check the ",{"type":415,"tag":434,"props":21587,"children":21590},{"href":21588,"rel":21589},"https://github.com/projectkudu/kudu/wiki/Deploying-from-a-zip-file-or-url",[438],[21591],{"type":420,"value":5512},{"type":420,"value":21593}," about that but concretely we will do a POST request to the zipdeploy endpoint using Basic authentication.",{"type":415,"tag":416,"props":21595,"children":21596},{},[21597,21599,21605],{"type":420,"value":21598},"To retrieve a stack output, we can use the ",{"type":415,"tag":555,"props":21600,"children":21602},{"className":21601},[],[21603],{"type":420,"value":21604},"pulumi stack output",{"type":420,"value":21606}," command. To avoid duplicating the code I wrote a short method:",{"type":415,"tag":549,"props":21608,"children":21610},{"className":551,"code":21609,"language":326,"meta":401,"style":401},"string GetPulumiOutput(string outputName)  \n{  \n    return PulumiTasks.PulumiStackOutput(_ => _  \n            .SetCwd(InfrastructureDirectory)  \n            .SetPropertyName(outputName)  \n            .EnableShowSecrets()\n            .DisableProcessLogOutput())  \n        .StdToText();  \n}\n",[21611],{"type":415,"tag":555,"props":21612,"children":21613},{"__ignoreMap":401},[21614,21647,21658,21695,21722,21751,21767,21788,21809],{"type":415,"tag":559,"props":21615,"children":21616},{"class":561,"line":562},[21617,21621,21626,21630,21634,21639,21643],{"type":415,"tag":559,"props":21618,"children":21619},{"style":583},[21620],{"type":420,"value":2015},{"type":415,"tag":559,"props":21622,"children":21623},{"style":883},[21624],{"type":420,"value":21625}," GetPulumiOutput",{"type":415,"tag":559,"props":21627,"children":21628},{"style":583},[21629],{"type":420,"value":814},{"type":415,"tag":559,"props":21631,"children":21632},{"style":583},[21633],{"type":420,"value":2015},{"type":415,"tag":559,"props":21635,"children":21636},{"style":572},[21637],{"type":420,"value":21638}," outputName",{"type":415,"tag":559,"props":21640,"children":21641},{"style":583},[21642],{"type":420,"value":1468},{"type":415,"tag":559,"props":21644,"children":21645},{"style":792},[21646],{"type":420,"value":18888},{"type":415,"tag":559,"props":21648,"children":21649},{"class":561,"line":589},[21650,21654],{"type":415,"tag":559,"props":21651,"children":21652},{"style":583},[21653],{"type":420,"value":2397},{"type":415,"tag":559,"props":21655,"children":21656},{"style":792},[21657],{"type":420,"value":18888},{"type":415,"tag":559,"props":21659,"children":21660},{"class":561,"line":608},[21661,21665,21670,21674,21679,21683,21687,21691],{"type":415,"tag":559,"props":21662,"children":21663},{"style":745},[21664],{"type":420,"value":1517},{"type":415,"tag":559,"props":21666,"children":21667},{"style":792},[21668],{"type":420,"value":21669}," PulumiTasks",{"type":415,"tag":559,"props":21671,"children":21672},{"style":583},[21673],{"type":420,"value":542},{"type":415,"tag":559,"props":21675,"children":21676},{"style":883},[21677],{"type":420,"value":21678},"PulumiStackOutput",{"type":415,"tag":559,"props":21680,"children":21681},{"style":583},[21682],{"type":420,"value":814},{"type":415,"tag":559,"props":21684,"children":21685},{"style":572},[21686],{"type":420,"value":8117},{"type":415,"tag":559,"props":21688,"children":21689},{"style":583},[21690],{"type":420,"value":1861},{"type":415,"tag":559,"props":21692,"children":21693},{"style":792},[21694],{"type":420,"value":18858},{"type":415,"tag":559,"props":21696,"children":21697},{"class":561,"line":626},[21698,21702,21706,21710,21714,21718],{"type":415,"tag":559,"props":21699,"children":21700},{"style":583},[21701],{"type":420,"value":8274},{"type":415,"tag":559,"props":21703,"children":21704},{"style":883},[21705],{"type":420,"value":21495},{"type":415,"tag":559,"props":21707,"children":21708},{"style":583},[21709],{"type":420,"value":814},{"type":415,"tag":559,"props":21711,"children":21712},{"style":792},[21713],{"type":420,"value":19113},{"type":415,"tag":559,"props":21715,"children":21716},{"style":583},[21717],{"type":420,"value":1468},{"type":415,"tag":559,"props":21719,"children":21720},{"style":792},[21721],{"type":420,"value":18888},{"type":415,"tag":559,"props":21723,"children":21724},{"class":561,"line":643},[21725,21729,21734,21738,21743,21747],{"type":415,"tag":559,"props":21726,"children":21727},{"style":583},[21728],{"type":420,"value":8274},{"type":415,"tag":559,"props":21730,"children":21731},{"style":883},[21732],{"type":420,"value":21733},"SetPropertyName",{"type":415,"tag":559,"props":21735,"children":21736},{"style":583},[21737],{"type":420,"value":814},{"type":415,"tag":559,"props":21739,"children":21740},{"style":792},[21741],{"type":420,"value":21742},"outputName",{"type":415,"tag":559,"props":21744,"children":21745},{"style":583},[21746],{"type":420,"value":1468},{"type":415,"tag":559,"props":21748,"children":21749},{"style":792},[21750],{"type":420,"value":18888},{"type":415,"tag":559,"props":21752,"children":21753},{"class":561,"line":660},[21754,21758,21763],{"type":415,"tag":559,"props":21755,"children":21756},{"style":583},[21757],{"type":420,"value":8274},{"type":415,"tag":559,"props":21759,"children":21760},{"style":883},[21761],{"type":420,"value":21762},"EnableShowSecrets",{"type":415,"tag":559,"props":21764,"children":21765},{"style":583},[21766],{"type":420,"value":778},{"type":415,"tag":559,"props":21768,"children":21769},{"class":561,"line":677},[21770,21774,21779,21784],{"type":415,"tag":559,"props":21771,"children":21772},{"style":583},[21773],{"type":420,"value":8274},{"type":415,"tag":559,"props":21775,"children":21776},{"style":883},[21777],{"type":420,"value":21778},"DisableProcessLogOutput",{"type":415,"tag":559,"props":21780,"children":21781},{"style":583},[21782],{"type":420,"value":21783},"())",{"type":415,"tag":559,"props":21785,"children":21786},{"style":792},[21787],{"type":420,"value":18888},{"type":415,"tag":559,"props":21789,"children":21790},{"class":561,"line":690},[21791,21795,21800,21805],{"type":415,"tag":559,"props":21792,"children":21793},{"style":583},[21794],{"type":420,"value":6482},{"type":415,"tag":559,"props":21796,"children":21797},{"style":883},[21798],{"type":420,"value":21799},"StdToText",{"type":415,"tag":559,"props":21801,"children":21802},{"style":583},[21803],{"type":420,"value":21804},"();",{"type":415,"tag":559,"props":21806,"children":21807},{"style":792},[21808],{"type":420,"value":18888},{"type":415,"tag":559,"props":21810,"children":21811},{"class":561,"line":1089},[21812],{"type":415,"tag":559,"props":21813,"children":21814},{"style":583},[21815],{"type":420,"value":1801},{"type":415,"tag":416,"props":21817,"children":21818},{},[21819],{"type":420,"value":21820},"The step itself is not very complicated, just standard C# code using an HttpClient to send a POST request (with our application package as the content) to the Kudu API.",{"type":415,"tag":549,"props":21822,"children":21824},{"className":551,"code":21823,"language":326,"meta":401,"style":401},"Target Deploy => _ => _  \n    .DependsOn(Publish)  \n    .After(ProvisionInfra)  \n    .Executes(async () =>  \n    {  \n        var publishingUsername = GetPulumiOutput(\"publishingUsername\");  \n        var publishingUserPassword = GetPulumiOutput(\"publishingUserPassword\");  \n        var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($\"{publishingUsername}:{publishingUserPassword}\"));  \n  \n        await using var package = File.OpenRead(ArtifactsDirectory / \"api.zip\");  \n        using var httpClient = new HttpClient();  \n        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"Basic\", base64Auth);  \n        await httpClient.PostAsync($\"https://{GetPulumiOutput(\"appServiceName\")}.scm.azurewebsites.net/api/zipdeploy\",  \n            new StreamContent(package));  \n    });\n",[21825],{"type":415,"tag":555,"props":21826,"children":21827},{"__ignoreMap":401},[21828,21856,21883,21911,21942,21953,21997,22041,22136,22143,22214,22250,22321,22394,22424],{"type":415,"tag":559,"props":21829,"children":21830},{"class":561,"line":562},[21831,21835,21840,21844,21848,21852],{"type":415,"tag":559,"props":21832,"children":21833},{"style":792},[21834],{"type":420,"value":18837},{"type":415,"tag":559,"props":21836,"children":21837},{"style":572},[21838],{"type":420,"value":21839},"Deploy",{"type":415,"tag":559,"props":21841,"children":21842},{"style":583},[21843],{"type":420,"value":1861},{"type":415,"tag":559,"props":21845,"children":21846},{"style":572},[21847],{"type":420,"value":8126},{"type":415,"tag":559,"props":21849,"children":21850},{"style":583},[21851],{"type":420,"value":1861},{"type":415,"tag":559,"props":21853,"children":21854},{"style":792},[21855],{"type":420,"value":18858},{"type":415,"tag":559,"props":21857,"children":21858},{"class":561,"line":589},[21859,21863,21867,21871,21875,21879],{"type":415,"tag":559,"props":21860,"children":21861},{"style":583},[21862],{"type":420,"value":1842},{"type":415,"tag":559,"props":21864,"children":21865},{"style":883},[21866],{"type":420,"value":19427},{"type":415,"tag":559,"props":21868,"children":21869},{"style":583},[21870],{"type":420,"value":814},{"type":415,"tag":559,"props":21872,"children":21873},{"style":792},[21874],{"type":420,"value":19628},{"type":415,"tag":559,"props":21876,"children":21877},{"style":583},[21878],{"type":420,"value":1468},{"type":415,"tag":559,"props":21880,"children":21881},{"style":792},[21882],{"type":420,"value":18888},{"type":415,"tag":559,"props":21884,"children":21885},{"class":561,"line":608},[21886,21890,21895,21899,21903,21907],{"type":415,"tag":559,"props":21887,"children":21888},{"style":583},[21889],{"type":420,"value":1842},{"type":415,"tag":559,"props":21891,"children":21892},{"style":883},[21893],{"type":420,"value":21894},"After",{"type":415,"tag":559,"props":21896,"children":21897},{"style":583},[21898],{"type":420,"value":814},{"type":415,"tag":559,"props":21900,"children":21901},{"style":792},[21902],{"type":420,"value":21363},{"type":415,"tag":559,"props":21904,"children":21905},{"style":583},[21906],{"type":420,"value":1468},{"type":415,"tag":559,"props":21908,"children":21909},{"style":792},[21910],{"type":420,"value":18888},{"type":415,"tag":559,"props":21912,"children":21913},{"class":561,"line":626},[21914,21918,21922,21926,21930,21934,21938],{"type":415,"tag":559,"props":21915,"children":21916},{"style":583},[21917],{"type":420,"value":1842},{"type":415,"tag":559,"props":21919,"children":21920},{"style":883},[21921],{"type":420,"value":18900},{"type":415,"tag":559,"props":21923,"children":21924},{"style":583},[21925],{"type":420,"value":814},{"type":415,"tag":559,"props":21927,"children":21928},{"style":566},[21929],{"type":420,"value":2001},{"type":415,"tag":559,"props":21931,"children":21932},{"style":583},[21933],{"type":420,"value":8288},{"type":415,"tag":559,"props":21935,"children":21936},{"style":583},[21937],{"type":420,"value":1861},{"type":415,"tag":559,"props":21939,"children":21940},{"style":792},[21941],{"type":420,"value":18888},{"type":415,"tag":559,"props":21943,"children":21944},{"class":561,"line":643},[21945,21949],{"type":415,"tag":559,"props":21946,"children":21947},{"style":583},[21948],{"type":420,"value":18921},{"type":415,"tag":559,"props":21950,"children":21951},{"style":792},[21952],{"type":420,"value":18888},{"type":415,"tag":559,"props":21954,"children":21955},{"class":561,"line":660},[21956,21960,21965,21969,21973,21977,21981,21985,21989,21993],{"type":415,"tag":559,"props":21957,"children":21958},{"style":572},[21959],{"type":420,"value":2745},{"type":415,"tag":559,"props":21961,"children":21962},{"style":572},[21963],{"type":420,"value":21964}," publishingUsername",{"type":415,"tag":559,"props":21966,"children":21967},{"style":583},[21968],{"type":420,"value":763},{"type":415,"tag":559,"props":21970,"children":21971},{"style":883},[21972],{"type":420,"value":21625},{"type":415,"tag":559,"props":21974,"children":21975},{"style":583},[21976],{"type":420,"value":814},{"type":415,"tag":559,"props":21978,"children":21979},{"style":583},[21980],{"type":420,"value":819},{"type":415,"tag":559,"props":21982,"children":21983},{"style":822},[21984],{"type":420,"value":21055},{"type":415,"tag":559,"props":21986,"children":21987},{"style":583},[21988],{"type":420,"value":819},{"type":415,"tag":559,"props":21990,"children":21991},{"style":583},[21992],{"type":420,"value":18999},{"type":415,"tag":559,"props":21994,"children":21995},{"style":792},[21996],{"type":420,"value":18888},{"type":415,"tag":559,"props":21998,"children":21999},{"class":561,"line":677},[22000,22004,22009,22013,22017,22021,22025,22029,22033,22037],{"type":415,"tag":559,"props":22001,"children":22002},{"style":572},[22003],{"type":420,"value":2745},{"type":415,"tag":559,"props":22005,"children":22006},{"style":572},[22007],{"type":420,"value":22008}," publishingUserPassword",{"type":415,"tag":559,"props":22010,"children":22011},{"style":583},[22012],{"type":420,"value":763},{"type":415,"tag":559,"props":22014,"children":22015},{"style":883},[22016],{"type":420,"value":21625},{"type":415,"tag":559,"props":22018,"children":22019},{"style":583},[22020],{"type":420,"value":814},{"type":415,"tag":559,"props":22022,"children":22023},{"style":583},[22024],{"type":420,"value":819},{"type":415,"tag":559,"props":22026,"children":22027},{"style":822},[22028],{"type":420,"value":21147},{"type":415,"tag":559,"props":22030,"children":22031},{"style":583},[22032],{"type":420,"value":819},{"type":415,"tag":559,"props":22034,"children":22035},{"style":583},[22036],{"type":420,"value":18999},{"type":415,"tag":559,"props":22038,"children":22039},{"style":792},[22040],{"type":420,"value":18888},{"type":415,"tag":559,"props":22042,"children":22043},{"class":561,"line":690},[22044,22048,22053,22057,22061,22065,22070,22074,22079,22083,22087,22091,22096,22100,22104,22108,22112,22116,22120,22124,22128,22132],{"type":415,"tag":559,"props":22045,"children":22046},{"style":572},[22047],{"type":420,"value":2745},{"type":415,"tag":559,"props":22049,"children":22050},{"style":572},[22051],{"type":420,"value":22052}," base64Auth",{"type":415,"tag":559,"props":22054,"children":22055},{"style":583},[22056],{"type":420,"value":763},{"type":415,"tag":559,"props":22058,"children":22059},{"style":792},[22060],{"type":420,"value":10386},{"type":415,"tag":559,"props":22062,"children":22063},{"style":583},[22064],{"type":420,"value":542},{"type":415,"tag":559,"props":22066,"children":22067},{"style":883},[22068],{"type":420,"value":22069},"ToBase64String",{"type":415,"tag":559,"props":22071,"children":22072},{"style":583},[22073],{"type":420,"value":814},{"type":415,"tag":559,"props":22075,"children":22076},{"style":792},[22077],{"type":420,"value":22078},"Encoding",{"type":415,"tag":559,"props":22080,"children":22081},{"style":583},[22082],{"type":420,"value":542},{"type":415,"tag":559,"props":22084,"children":22085},{"style":792},[22086],{"type":420,"value":2096},{"type":415,"tag":559,"props":22088,"children":22089},{"style":583},[22090],{"type":420,"value":542},{"type":415,"tag":559,"props":22092,"children":22093},{"style":883},[22094],{"type":420,"value":22095},"GetBytes",{"type":415,"tag":559,"props":22097,"children":22098},{"style":583},[22099],{"type":420,"value":814},{"type":415,"tag":559,"props":22101,"children":22102},{"style":583},[22103],{"type":420,"value":18162},{"type":415,"tag":559,"props":22105,"children":22106},{"style":792},[22107],{"type":420,"value":21055},{"type":415,"tag":559,"props":22109,"children":22110},{"style":583},[22111],{"type":420,"value":1580},{"type":415,"tag":559,"props":22113,"children":22114},{"style":822},[22115],{"type":420,"value":1206},{"type":415,"tag":559,"props":22117,"children":22118},{"style":583},[22119],{"type":420,"value":2397},{"type":415,"tag":559,"props":22121,"children":22122},{"style":792},[22123],{"type":420,"value":21147},{"type":415,"tag":559,"props":22125,"children":22126},{"style":583},[22127],{"type":420,"value":1602},{"type":415,"tag":559,"props":22129,"children":22130},{"style":583},[22131],{"type":420,"value":19334},{"type":415,"tag":559,"props":22133,"children":22134},{"style":792},[22135],{"type":420,"value":18888},{"type":415,"tag":559,"props":22137,"children":22138},{"class":561,"line":1089},[22139],{"type":415,"tag":559,"props":22140,"children":22141},{"style":792},[22142],{"type":420,"value":18888},{"type":415,"tag":559,"props":22144,"children":22145},{"class":561,"line":1102},[22146,22150,22155,22159,22164,22168,22172,22176,22181,22185,22190,22194,22198,22202,22206,22210],{"type":415,"tag":559,"props":22147,"children":22148},{"style":583},[22149],{"type":420,"value":6201},{"type":415,"tag":559,"props":22151,"children":22152},{"style":745},[22153],{"type":420,"value":22154}," using",{"type":415,"tag":559,"props":22156,"children":22157},{"style":572},[22158],{"type":420,"value":753},{"type":415,"tag":559,"props":22160,"children":22161},{"style":572},[22162],{"type":420,"value":22163}," package",{"type":415,"tag":559,"props":22165,"children":22166},{"style":583},[22167],{"type":420,"value":763},{"type":415,"tag":559,"props":22169,"children":22170},{"style":792},[22171],{"type":420,"value":17533},{"type":415,"tag":559,"props":22173,"children":22174},{"style":583},[22175],{"type":420,"value":542},{"type":415,"tag":559,"props":22177,"children":22178},{"style":883},[22179],{"type":420,"value":22180},"OpenRead",{"type":415,"tag":559,"props":22182,"children":22183},{"style":583},[22184],{"type":420,"value":814},{"type":415,"tag":559,"props":22186,"children":22187},{"style":792},[22188],{"type":420,"value":22189},"ArtifactsDirectory ",{"type":415,"tag":559,"props":22191,"children":22192},{"style":583},[22193],{"type":420,"value":12238},{"type":415,"tag":559,"props":22195,"children":22196},{"style":583},[22197],{"type":420,"value":1434},{"type":415,"tag":559,"props":22199,"children":22200},{"style":822},[22201],{"type":420,"value":19607},{"type":415,"tag":559,"props":22203,"children":22204},{"style":583},[22205],{"type":420,"value":819},{"type":415,"tag":559,"props":22207,"children":22208},{"style":583},[22209],{"type":420,"value":18999},{"type":415,"tag":559,"props":22211,"children":22212},{"style":792},[22213],{"type":420,"value":18888},{"type":415,"tag":559,"props":22215,"children":22216},{"class":561,"line":1110},[22217,22222,22226,22230,22234,22238,22242,22246],{"type":415,"tag":559,"props":22218,"children":22219},{"style":745},[22220],{"type":420,"value":22221},"        using",{"type":415,"tag":559,"props":22223,"children":22224},{"style":572},[22225],{"type":420,"value":753},{"type":415,"tag":559,"props":22227,"children":22228},{"style":572},[22229],{"type":420,"value":758},{"type":415,"tag":559,"props":22231,"children":22232},{"style":583},[22233],{"type":420,"value":763},{"type":415,"tag":559,"props":22235,"children":22236},{"style":583},[22237],{"type":420,"value":768},{"type":415,"tag":559,"props":22239,"children":22240},{"style":572},[22241],{"type":420,"value":773},{"type":415,"tag":559,"props":22243,"children":22244},{"style":583},[22245],{"type":420,"value":21804},{"type":415,"tag":559,"props":22247,"children":22248},{"style":792},[22249],{"type":420,"value":18888},{"type":415,"tag":559,"props":22251,"children":22252},{"class":561,"line":1118},[22253,22258,22262,22267,22271,22276,22280,22284,22289,22293,22297,22301,22305,22309,22313,22317],{"type":415,"tag":559,"props":22254,"children":22255},{"style":792},[22256],{"type":420,"value":22257},"        httpClient",{"type":415,"tag":559,"props":22259,"children":22260},{"style":583},[22261],{"type":420,"value":542},{"type":415,"tag":559,"props":22263,"children":22264},{"style":792},[22265],{"type":420,"value":22266},"DefaultRequestHeaders",{"type":415,"tag":559,"props":22268,"children":22269},{"style":583},[22270],{"type":420,"value":542},{"type":415,"tag":559,"props":22272,"children":22273},{"style":792},[22274],{"type":420,"value":22275},"Authorization ",{"type":415,"tag":559,"props":22277,"children":22278},{"style":583},[22279],{"type":420,"value":800},{"type":415,"tag":559,"props":22281,"children":22282},{"style":583},[22283],{"type":420,"value":768},{"type":415,"tag":559,"props":22285,"children":22286},{"style":572},[22287],{"type":420,"value":22288}," AuthenticationHeaderValue",{"type":415,"tag":559,"props":22290,"children":22291},{"style":583},[22292],{"type":420,"value":814},{"type":415,"tag":559,"props":22294,"children":22295},{"style":583},[22296],{"type":420,"value":819},{"type":415,"tag":559,"props":22298,"children":22299},{"style":822},[22300],{"type":420,"value":20519},{"type":415,"tag":559,"props":22302,"children":22303},{"style":583},[22304],{"type":420,"value":819},{"type":415,"tag":559,"props":22306,"children":22307},{"style":583},[22308],{"type":420,"value":2312},{"type":415,"tag":559,"props":22310,"children":22311},{"style":792},[22312],{"type":420,"value":22052},{"type":415,"tag":559,"props":22314,"children":22315},{"style":583},[22316],{"type":420,"value":18999},{"type":415,"tag":559,"props":22318,"children":22319},{"style":792},[22320],{"type":420,"value":18888},{"type":415,"tag":559,"props":22322,"children":22323},{"class":561,"line":1171},[22324,22328,22332,22336,22341,22345,22349,22354,22358,22363,22368,22372,22377,22382,22386,22390],{"type":415,"tag":559,"props":22325,"children":22326},{"style":583},[22327],{"type":420,"value":6201},{"type":415,"tag":559,"props":22329,"children":22330},{"style":792},[22331],{"type":420,"value":758},{"type":415,"tag":559,"props":22333,"children":22334},{"style":583},[22335],{"type":420,"value":542},{"type":415,"tag":559,"props":22337,"children":22338},{"style":883},[22339],{"type":420,"value":22340},"PostAsync",{"type":415,"tag":559,"props":22342,"children":22343},{"style":583},[22344],{"type":420,"value":814},{"type":415,"tag":559,"props":22346,"children":22347},{"style":583},[22348],{"type":420,"value":16136},{"type":415,"tag":559,"props":22350,"children":22351},{"style":822},[22352],{"type":420,"value":22353},"https://",{"type":415,"tag":559,"props":22355,"children":22356},{"style":583},[22357],{"type":420,"value":2397},{"type":415,"tag":559,"props":22359,"children":22360},{"style":883},[22361],{"type":420,"value":22362},"GetPulumiOutput",{"type":415,"tag":559,"props":22364,"children":22365},{"style":583},[22366],{"type":420,"value":22367},"(\"",{"type":415,"tag":559,"props":22369,"children":22370},{"style":822},[22371],{"type":420,"value":21236},{"type":415,"tag":559,"props":22373,"children":22374},{"style":583},[22375],{"type":420,"value":22376},"\")}",{"type":415,"tag":559,"props":22378,"children":22379},{"style":822},[22380],{"type":420,"value":22381},".scm.azurewebsites.net/api/zipdeploy",{"type":415,"tag":559,"props":22383,"children":22384},{"style":583},[22385],{"type":420,"value":819},{"type":415,"tag":559,"props":22387,"children":22388},{"style":583},[22389],{"type":420,"value":2312},{"type":415,"tag":559,"props":22391,"children":22392},{"style":792},[22393],{"type":420,"value":18888},{"type":415,"tag":559,"props":22395,"children":22396},{"class":561,"line":1748},[22397,22402,22407,22411,22416,22420],{"type":415,"tag":559,"props":22398,"children":22399},{"style":583},[22400],{"type":420,"value":22401},"            new",{"type":415,"tag":559,"props":22403,"children":22404},{"style":572},[22405],{"type":420,"value":22406}," StreamContent",{"type":415,"tag":559,"props":22408,"children":22409},{"style":583},[22410],{"type":420,"value":814},{"type":415,"tag":559,"props":22412,"children":22413},{"style":792},[22414],{"type":420,"value":22415},"package",{"type":415,"tag":559,"props":22417,"children":22418},{"style":583},[22419],{"type":420,"value":19334},{"type":415,"tag":559,"props":22421,"children":22422},{"style":792},[22423],{"type":420,"value":18888},{"type":415,"tag":559,"props":22425,"children":22426},{"class":561,"line":1769},[22427],{"type":415,"tag":559,"props":22428,"children":22429},{"style":583},[22430],{"type":420,"value":7416},{"type":415,"tag":1178,"props":22432,"children":22433},{"icon":5363},[22434],{"type":415,"tag":416,"props":22435,"children":22436},{},[22437,22439,22446],{"type":420,"value":22438},"George Dangl already wrote a nice ",{"type":415,"tag":434,"props":22440,"children":22443},{"href":22441,"rel":22442},"https://blog.dangl.me/archive/lets-use-nuke-to-quickly-deploy-an-app-to-azure-via-zip-deployment/",[438],[22444],{"type":420,"value":22445},"article",{"type":420,"value":22447}," about using Nuke to deploy an application to Azure App Service using the Kudu API, so you can have a look at it. The code in the article is similar to the one we have here except that the credentials don't come from Pulumi outputs but from an Azure Key Vault.",{"type":415,"tag":416,"props":22449,"children":22450},{},[22451],{"type":420,"value":22452},"What I like about this approach is that you know exactly what you are doing, and the deployment logic is not hidden from you in an obscure YAML task whose code you will never read (yes I am talking to you Azure Pipelines and GitHub Actions 😃).",{"type":415,"tag":416,"props":22454,"children":22455},{},[22456],{"type":420,"value":22457},"But the awesome part in Nuke is that you can put a breakpoint in the code and debug it locally. If you need to modify your pipeline, you don't need to write YAML code modifications without knowing if it would work or not 🤞, commit and push your modifications, wait for an agent to run the changed pipeline in the cloud, wait for it to fail, browse the logs to try to understand the problem, and try again until it works.",{"type":415,"tag":422,"props":22459,"children":22461},{"id":22460},"final-pipeline",[22462],{"type":420,"value":22463},"Final pipeline",{"type":415,"tag":416,"props":22465,"children":22466},{},[22467],{"type":420,"value":22468},"If I fold everything, the pipeline code we created looks like that:",{"type":415,"tag":416,"props":22470,"children":22471},{},[22472],{"type":415,"tag":934,"props":22473,"children":22477},{"alt":22474,"className":22475,"src":22476},"Complete Nuke pipeline in the Build.cs file.",[938,8504],"/posts/images/pulumi_met_nuke_11.png",[],{"type":415,"tag":416,"props":22479,"children":22480},{},[22481,22483,22489],{"type":420,"value":22482},"I think it is quite clear with the different steps/targets defined with their dependencies/order. Yet if this is not clear enough for you, you can use the ",{"type":415,"tag":555,"props":22484,"children":22486},{"className":22485},[],[22487],{"type":420,"value":22488},"nuke --plan",{"type":420,"value":22490}," command to display a visual representation of the pipeline (how cool is that !?)",{"type":415,"tag":416,"props":22492,"children":22493},{},[22494],{"type":415,"tag":934,"props":22495,"children":22499},{"alt":22496,"className":22497,"src":22498},"Nuke execution plan displayed as a graph.",[938,8504],"/posts/images/pulumi_met_nuke_12.png",[],{"type":415,"tag":1178,"props":22501,"children":22502},{"icon":1180},[22503],{"type":415,"tag":416,"props":22504,"children":22505},{},[22506],{"type":420,"value":22507},"You can see that the execution plan is almost identical to the pipelines steps we talked about in the beginning of the article. The only difference is that we added to the Publish step a dependence on Clean.",{"type":415,"tag":416,"props":22509,"children":22510},{},[22511],{"type":420,"value":22512},"Let's execute the complete pipeline:",{"type":415,"tag":416,"props":22514,"children":22515},{},[22516],{"type":415,"tag":934,"props":22517,"children":22521},{"alt":22518,"className":22519,"src":22520,"width":18444},"Pipeline output in terminal showing the different steps and their status.",[938,8504],"/posts/images/pulumi_met_nuke_13.png",[],{"type":415,"tag":416,"props":22523,"children":22524},{},[22525],{"type":420,"value":22526},"If I go to my Azure portal I can see the new Azure resources, among them an App Service where my Weather API is deployed.",{"type":415,"tag":416,"props":22528,"children":22529},{},[22530],{"type":415,"tag":934,"props":22531,"children":22535},{"alt":22532,"className":22533,"src":22534,"width":14331},"Weather API weather forecast endpoint response opened in a browser.",[938,8504],"/posts/images/pulumi_met_nuke_14.png",[],{"type":415,"tag":422,"props":22537,"children":22539},{"id":22538},"conclusion",[22540],{"type":420,"value":22541},"Conclusion",{"type":415,"tag":14340,"props":22543,"children":22545},{"id":22544},"improvements-to-the-example-pipeline",[22546],{"type":420,"value":22547},"Improvements to the example pipeline",{"type":415,"tag":416,"props":22549,"children":22550},{},[22551],{"type":420,"value":22552},"The pipeline I have shown in this article is just a simple sample. They are lots of things that could be done to improve it. Beyond obvious ones like adding a Test target or using GitVersion to version the package, I want to talk about some choices I made in the pipeline implementation that may not be the best ones.",{"type":415,"tag":416,"props":22554,"children":22555},{},[22556,22558,22565,22567,22574,22576,22583],{"type":420,"value":22557},"As I said there are many ways to deploy a package to an App Service. While using the Kudu API is fine and allowed me to show you how we can use Pulumi stack outputs to retrieve publishing credentials, it might be a bit limited in some cases and involves a bit of manual code to make the HTTP request. A good alternative would be to use the Azure CLI that has ",{"type":415,"tag":434,"props":22559,"children":22562},{"href":22560,"rel":22561},"https://learn.microsoft.com/en-us/cli/azure/webapp/deployment/source?view=azure-cli-latest#az-webapp-deployment-source-config-zip",[438],[22563],{"type":420,"value":22564},"a command",{"type":420,"value":22566}," for that. But my preferred option would be to use the ",{"type":415,"tag":434,"props":22568,"children":22571},{"href":22569,"rel":22570},"https://learn.microsoft.com/en-us/dotnet/api/overview/azure/resource-manager?view=azure-dotnet",[438],[22572],{"type":420,"value":22573},"Azure Resource Manager libraries for .NET",{"type":420,"value":22575},". Unfortunately this SDK is quite new and miss ",{"type":415,"tag":434,"props":22577,"children":22580},{"href":22578,"rel":22579},"https://github.com/Azure/azure-sdk-for-net/issues/30577",[438],[22581],{"type":420,"value":22582},"samples",{"type":420,"value":22584}," on how to do that.",{"type":415,"tag":416,"props":22586,"children":22587},{},[22588,22590,22597],{"type":420,"value":22589},"Speaking of SDK, Pulumi has an API called the ",{"type":415,"tag":434,"props":22591,"children":22594},{"href":22592,"rel":22593},"https://www.pulumi.com/automation/",[438],[22595],{"type":420,"value":22596},"Automation API",{"type":420,"value":22598}," to use the Pulumi engine as an SDK. I think it would be a better option than using the Pulumi CLI. Generally speaking, I think using SDK instead of CLIs to write the targets of a pipeline brings more power, more flexibility, and a better developer experience.",{"type":415,"tag":14340,"props":22600,"children":22602},{"id":22601},"about-nuke-and-cicd",[22603],{"type":420,"value":22604},"About Nuke and CI/CD",{"type":415,"tag":416,"props":22606,"children":22607},{},[22608],{"type":420,"value":22609},"Nuke has many features I did not show in this small example. If we add some attributes to the pipeline code, Nuke can generate YAML workflow files to execute the Nuke pipeline. When executing the pipeline locally everything works fine because I am logged in to Pulumi CLI and Azure CLI in my terminal but I have to add secret parameters to my Nuke pipeline (a Pulumi token and an Azure Service Principal identifier/password) to make the authentication works when the pipeline is run from a CI/CD platform runner/agent.",{"type":415,"tag":416,"props":22611,"children":22612},{},[22613,22615,22621,22622,22629],{"type":420,"value":22614},"Moreover, there are many things I don't know yet about Nuke because I am just starting to use it. That is why I advise you to have a look at its ",{"type":415,"tag":434,"props":22616,"children":22619},{"href":22617,"rel":22618},"https://nuke.build/docs/introduction/",[438],[22620],{"type":420,"value":5512},{"type":420,"value":14095},{"type":415,"tag":434,"props":22623,"children":22626},{"href":22624,"rel":22625},"https://nuke.build/resources/",[438],[22627],{"type":420,"value":22628},"at some resources",{"type":420,"value":22630}," and start playing with it by yourself.",{"type":415,"tag":416,"props":22632,"children":22633},{},[22634],{"type":420,"value":22635},"In the future, I see myself using Nuke for most of my CI pipelines, and not only for .NET projects (because I can run any CLI tools from Nuke, it also works for front projects where I would use the pnpm CLI for instance). I am not saying that because I am afraid of YAML or because I'm not familiar with ready-made tasks like Azure Pipelines tasks or GitHub Actions. I have been using Azure Pipelines for several years now and I have also played a bit with GitHub Actions. They are good platforms but lack local debugging and the great developer experience provided by a tool like Nuke. So I will continue using them but to run my Nuke pipelines 😉.",{"type":415,"tag":416,"props":22637,"children":22638},{},[22639],{"type":420,"value":22640},"Concerning the CD pipelines, I don't know yet if I can use Nuke for all my use cases. They are real benefits to using Nuke for deployments but I still have to investigate how some things can be done like deploying to multiple environments, and handling approvals between environments.",{"type":415,"tag":14340,"props":22642,"children":22644},{"id":22643},"pulumi-nuke-the-perfect-combo",[22645],{"type":420,"value":22646},"Pulumi & Nuke, the perfect combo?",{"type":415,"tag":416,"props":22648,"children":22649},{},[22650],{"type":420,"value":22651},"I don't know if it's the perfect combo but it's definitively one I love. Having .NET everywhere, from infrastructure code to pipeline code without forgetting the application code is awesome.",{"type":415,"tag":5406,"props":22653,"children":22654},{},[22655],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":22657},[22658,22659,22660,22665,22672,22678,22679,22680],{"id":18406,"depth":589,"text":18409},{"id":18427,"depth":589,"text":18430},{"id":18524,"depth":589,"text":18527,"children":22661},[22662,22663,22664],{"id":18530,"depth":608,"text":18533},{"id":18587,"depth":608,"text":18590},{"id":18707,"depth":608,"text":18710},{"id":18753,"depth":589,"text":18756,"children":22666},[22667,22668,22669,22670,22671],{"id":18759,"depth":608,"text":18762},{"id":18814,"depth":608,"text":18817},{"id":19194,"depth":608,"text":19197},{"id":19348,"depth":608,"text":19351},{"id":19586,"depth":608,"text":19589},{"id":20054,"depth":589,"text":20057,"children":22673},[22674,22675,22676,22677],{"id":20060,"depth":608,"text":20063},{"id":20114,"depth":608,"text":20117},{"id":20801,"depth":608,"text":20804},{"id":21283,"depth":608,"text":21286},{"id":21577,"depth":589,"text":21580},{"id":22460,"depth":589,"text":22463},{"id":22538,"depth":589,"text":22541,"children":22681},[22682,22683,22684],{"id":22544,"depth":608,"text":22547},{"id":22601,"depth":608,"text":22604},{"id":22643,"depth":608,"text":22646},"content:1.posts:45.when-pulumi-met-nuke.md","1.posts/45.when-pulumi-met-nuke.md",{"_path":139,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":138,"description":22688,"lead":22688,"date":22689,"image":22690,"badge":22692,"tags":22694,"body":22695,"_type":5421,"_id":22937,"_source":5423,"_file":22938,"_extension":5425},"Some tips about .NET, pnpm, and Azure DevOps.","2022-11-20T00:00:00.000Z",{"src":22691},"/images/surface_1.jpg",{"label":22693},"Tips",[272,239,293,362,296,208,343,206],{"type":412,"children":22696,"toc":22932},[22697,22703,22717,22737,22759,22765,22796,22801,22810,22824,22833,22841,22846,22855,22863,22876,22882,22887,22896,22914,22923,22928],{"type":415,"tag":422,"props":22698,"children":22700},{"id":22699},"net-tip-of-the-week-install-net-7-using-winget",[22701],{"type":420,"value":22702},".NET tip of the week: install .NET 7 using winget",{"type":415,"tag":416,"props":22704,"children":22705},{},[22706,22708,22715],{"type":420,"value":22707},"This week, I installed .NET 7 on my laptop and I used ",{"type":415,"tag":434,"props":22709,"children":22712},{"href":22710,"rel":22711},"https://learn.microsoft.com/en-us/windows/package-manager/",[438],[22713],{"type":420,"value":22714},"Windows Package Manager",{"type":420,"value":22716}," for that:",{"type":415,"tag":549,"props":22718,"children":22720},{"className":8463,"code":22719,"language":248,"meta":401,"style":401},"winget install Microsoft.DotNet.SDK.7\n",[22721],{"type":415,"tag":555,"props":22722,"children":22723},{"__ignoreMap":401},[22724],{"type":415,"tag":559,"props":22725,"children":22726},{"class":561,"line":562},[22727,22732],{"type":415,"tag":559,"props":22728,"children":22729},{"style":792},[22730],{"type":420,"value":22731},"winget install Microsoft.DotNet.SDK.",{"type":415,"tag":559,"props":22733,"children":22734},{"style":2846},[22735],{"type":420,"value":22736},"7\n",{"type":415,"tag":416,"props":22738,"children":22739},{},[22740,22742,22748,22750,22757],{"type":420,"value":22741},"I like winget, I have already written a few articles about it (you can find them ",{"type":415,"tag":434,"props":22743,"children":22746},{"href":22744,"rel":22745},"https://www.techwatching.dev/tags/winget/",[438],[22747],{"type":420,"value":540},{"type":420,"value":22749},") 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":415,"tag":434,"props":22751,"children":22754},{"href":22752,"rel":22753},"https://devblogs.microsoft.com/dotnet/dotnet-now-on-windows-package-manager/",[438],[22755],{"type":420,"value":22756},"Microsoft's article",{"type":420,"value":22758}," announcing it for more information.",{"type":415,"tag":422,"props":22760,"children":22762},{"id":22761},"tool-of-the-week-pnpm",[22763],{"type":420,"value":22764},"Tool of the week: pnpm",{"type":415,"tag":416,"props":22766,"children":22767},{},[22768,22770,22776,22778,22785,22787,22794],{"type":420,"value":22769},"I don't know which JavaScript package manager you are using but since I tried ",{"type":415,"tag":434,"props":22771,"children":22774},{"href":22772,"rel":22773},"https://pnpm.io/",[438],[22775],{"type":420,"value":362},{"type":420,"value":22777}," 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":415,"tag":434,"props":22779,"children":22782},{"href":22780,"rel":22781},"https://viteconf.org/2022/replay/pnpm",[438],[22783],{"type":420,"value":22784},"\"What makes pnpm performant\"",{"type":420,"value":22786}," that Zoltan Kochan gave at Vite Conf. Many ",{"type":415,"tag":434,"props":22788,"children":22791},{"href":22789,"rel":22790},"https://pnpm.io/workspaces#usage-examples",[438],[22792],{"type":420,"value":22793},"popular open-source projects",{"type":420,"value":22795}," like Vite and Vue are using pnpm.",{"type":415,"tag":416,"props":22797,"children":22798},{},[22799],{"type":420,"value":22800},"Here are some tips about pnpm:",{"type":415,"tag":22802,"props":22803,"children":22804},"ol",{},[22805],{"type":415,"tag":5380,"props":22806,"children":22807},{},[22808],{"type":420,"value":22809},"You can use pnpm to manage Node.js versions on your machine",{"type":415,"tag":416,"props":22811,"children":22812},{},[22813,22815,22822],{"type":420,"value":22814},"Previously, I was using ",{"type":415,"tag":434,"props":22816,"children":22819},{"href":22817,"rel":22818},"https://github.com/coreybutler/nvm-windows",[438],[22820],{"type":420,"value":22821},"nvm-windows",{"type":420,"value":22823}," 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":415,"tag":416,"props":22825,"children":22826},{},[22827],{"type":415,"tag":934,"props":22828,"children":22832},{"alt":22829,"className":22830,"src":22831},"Output of the pnpm env command in a terminal.",[938,8504],"/posts/images/w462022tips_pnpm_env.png",[],{"type":415,"tag":22802,"props":22834,"children":22835},{"start":589},[22836],{"type":415,"tag":5380,"props":22837,"children":22838},{},[22839],{"type":420,"value":22840},"You can configure vscode to run npm scripts using pnpm",{"type":415,"tag":416,"props":22842,"children":22843},{},[22844],{"type":420,"value":22845},"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":415,"tag":416,"props":22847,"children":22848},{},[22849],{"type":415,"tag":934,"props":22850,"children":22854},{"alt":22851,"className":22852,"src":22853,"width":18444},"Npm scripts view in vscode editor.",[938,8504],"/posts/images/w462022tips_pnpm_scripts.png",[],{"type":415,"tag":22802,"props":22856,"children":22857},{"start":608},[22858],{"type":415,"tag":5380,"props":22859,"children":22860},{},[22861],{"type":420,"value":22862},"With pnpm, you can use aliases for packages you install",{"type":415,"tag":416,"props":22864,"children":22865},{},[22866,22868,22874],{"type":420,"value":22867},"Check the ",{"type":415,"tag":434,"props":22869,"children":22872},{"href":22870,"rel":22871},"https://pnpm.io/aliases",[438],[22873],{"type":420,"value":5512},{"type":420,"value":22875}," to see why and how to use this feature.",{"type":415,"tag":422,"props":22877,"children":22879},{"id":22878},"the-gitlensazure-devops-tip-you-did-not-know-about-autolinks",[22880],{"type":420,"value":22881},"The GitLens/Azure DevOps tip you did not know about: autolinks",{"type":415,"tag":416,"props":22883,"children":22884},{},[22885],{"type":420,"value":22886},"GitLens, the awesome extension for vscode has a nice feature called \"autolinks\" that can make external references in your commit messages clickable links.",{"type":415,"tag":416,"props":22888,"children":22889},{},[22890],{"type":415,"tag":934,"props":22891,"children":22895},{"alt":22892,"className":22893,"src":22894,"width":14331},"Autolinks GitLens settings view in vscode.",[938,8504],"/posts/images/w462022tips_gitlens_autolink_1.png",[],{"type":415,"tag":416,"props":22897,"children":22898},{},[22899,22901,22908],{"type":420,"value":22900},"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":415,"tag":434,"props":22902,"children":22905},{"href":22903,"rel":22904},"https://dev.azure.com/%7BorganizationName%7D/%7BprojectName%7D/_workitems/edit/",[438],[22906],{"type":420,"value":22907},"https://dev.azure.com/{organizationName}/{projectName}/_workitems/edit/",{"type":415,"tag":22909,"props":22910,"children":22911},"num",{},[22912],{"type":420,"value":22913}," as the URL) to make it work.",{"type":415,"tag":416,"props":22915,"children":22916},{},[22917],{"type":415,"tag":934,"props":22918,"children":22922},{"alt":22919,"className":22920,"src":22921,"width":14331},"A commit GitLens popin in vscode with an Azure DevOps link.",[938,8504],"/posts/images/w462022tips_gitlens_autolink_2.png",[],{"type":415,"tag":416,"props":22924,"children":22925},{},[22926],{"type":420,"value":22927},"And that's it for this week, happy learning!",{"type":415,"tag":5406,"props":22929,"children":22930},{},[22931],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":22933},[22934,22935,22936],{"id":22699,"depth":589,"text":22702},{"id":22761,"depth":589,"text":22764},{"id":22878,"depth":589,"text":22881},"content:1.posts:44.w46-2022-tips-learned-this-week.md","1.posts/44.w46-2022-tips-learned-this-week.md",{"_path":112,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":111,"description":22940,"lead":22941,"date":22942,"image":22943,"badge":22945,"tags":22946,"body":22947,"_type":5421,"_id":25812,"_source":5423,"_file":25813,"_extension":5425},"In this article, we will talk about how to provision an Azure SQL Database with authentication restricted to Active Directory users/groups/applications. We will use Pulumi to do that.","Using Pulumi and its command provider to grant database permissions","2022-02-22T00:00:00.000Z",{"src":22944},"/images/lockers_1.jpg",{"label":266},[252,299,228,239,312,315],{"type":412,"children":22948,"toc":25794},[22949,22953,22959,22981,22995,23003,23008,23014,23019,23294,23324,23330,23335,23633,23645,23833,23839,23844,23857,23958,23978,23983,23988,24014,24019,24025,24039,24048,24080,24089,24105,24117,24123,24151,24156,24168,24285,24297,24329,24341,24380,24389,24416,24469,24475,24494,24500,24513,24588,24619,24624,24791,24797,24802,24979,24984,25002,25008,25027,25116,25127,25281,25301,25306,25688,25693,25726,25732,25750,25759,25763,25775,25780,25785,25790],{"type":415,"tag":416,"props":22950,"children":22951},{},[22952],{"type":420,"value":22940},{"type":415,"tag":422,"props":22954,"children":22956},{"id":22955},"why-this-article",[22957],{"type":420,"value":22958},"Why this article?",{"type":415,"tag":416,"props":22960,"children":22961},{},[22962,22964,22971,22973,22979],{"type":420,"value":22963},"In ",{"type":415,"tag":434,"props":22965,"children":22968},{"href":22966,"rel":22967},"https://www.techwatching.dev/posts/sqlclient-active-directory-authent",[438],[22969],{"type":420,"value":22970},"a previous article",{"type":420,"value":22972},", I already talked about connecting to an Azure SQL Database using Azure Active Directory authentication. However, my focus was on querying an Azure SQL Database from C# code (from an ASP.NET 6 Minimal API that was using ",{"type":415,"tag":555,"props":22974,"children":22976},{"className":22975},[],[22977],{"type":420,"value":22978},"Microsoft.Data.SqlClient",{"type":420,"value":22980}," 'Active Directory Default' authentication mode to be more precise), and not on the configuration of the Azure AD authentication itself.",{"type":415,"tag":416,"props":22982,"children":22983},{},[22984,22986,22993],{"type":420,"value":22985},"Still, in that article, I wrote an Azure CLI script that showed how to provision and configure the database with Azure AD authentication enabled. So why write another article about that? First because I did not show how to give an Azure AD entity (user, group, or managed identity) permission to access the database. (In my samples, to simplify things I was using the SQL server Azure AD administrator account to make my queries 🤫). Yet, it is something you will probably have to do if you want your App Service or Function App to query your database. Second because even if Azure CLI is great to handle Azure resources (if you are a reader of my blog, you probably know that I ",{"type":415,"tag":434,"props":22987,"children":22990},{"href":22988,"rel":22989},"https://www.techwatching.dev/posts/welcome-azure-cli",[438],[22991],{"type":420,"value":22992},"enjoy very much Azure CLI",{"type":420,"value":22994},"), in a real project I would probably use a more advanced Infrastructure as Code solution like Pulumi. And that is what we will show here.",{"type":415,"tag":1178,"props":22996,"children":22997},{"icon":1180},[22998],{"type":415,"tag":416,"props":22999,"children":23000},{},[23001],{"type":420,"value":23002},"If you are not familiar with Pulumi, it is an IaC solution similar to Terraform but using programming languages like C#. Speaking of C#, that is what I will use to write my infrastructure code but you can easily do the same in another language supported by Pulumi (TypeScript, Go, Python,... choose the one you are used to), the concepts stay relevant and the code will be similar.",{"type":415,"tag":416,"props":23004,"children":23005},{},[23006],{"type":420,"value":23007},"Now, let's get to the heart of the matter.",{"type":415,"tag":422,"props":23009,"children":23011},{"id":23010},"an-azure-ad-user-as-our-sql-server-administrator",[23012],{"type":420,"value":23013},"An Azure AD user as our SQL Server administrator",{"type":415,"tag":416,"props":23015,"children":23016},{},[23017],{"type":420,"value":23018},"Usually, when you create an Azure SQL Server, you have to provide an administrator login and an administrator password. But I said I wanted to limit the authentication to Azure Active Directory authentication only. So we will only need an Azure AD account to set as the administrator of our SQL Server. We could use an existing Azure AD account, but let's create a new Azure AD user just for that:",{"type":415,"tag":549,"props":23020,"children":23022},{"className":551,"code":23021,"language":326,"meta":401,"style":401},"var config = new Config();\nvar sqlAdAdminLogin = config.Require(\"sqlAdAdmin\");\nvar sqlAdAdminPassword = config.RequireSecret(\"sqlAdPassword\");\n\nvar sqlAdAdmin = new User(\"sqlAdmin\", new UserArgs\n{\n    UserPrincipalName = sqlAdAdminLogin,\n    Password = sqlAdAdminPassword,\n    DisplayName = \"Global SQL Admin\"\n});\n",[23023],{"type":415,"tag":555,"props":23024,"children":23025},{"__ignoreMap":401},[23026,23054,23104,23154,23161,23216,23223,23243,23263,23287],{"type":415,"tag":559,"props":23027,"children":23028},{"class":561,"line":562},[23029,23033,23037,23041,23045,23050],{"type":415,"tag":559,"props":23030,"children":23031},{"style":572},[23032],{"type":420,"value":858},{"type":415,"tag":559,"props":23034,"children":23035},{"style":572},[23036],{"type":420,"value":14608},{"type":415,"tag":559,"props":23038,"children":23039},{"style":583},[23040],{"type":420,"value":763},{"type":415,"tag":559,"props":23042,"children":23043},{"style":583},[23044],{"type":420,"value":768},{"type":415,"tag":559,"props":23046,"children":23047},{"style":572},[23048],{"type":420,"value":23049}," Config",{"type":415,"tag":559,"props":23051,"children":23052},{"style":583},[23053],{"type":420,"value":1962},{"type":415,"tag":559,"props":23055,"children":23056},{"class":561,"line":589},[23057,23061,23066,23070,23074,23078,23083,23087,23091,23096,23100],{"type":415,"tag":559,"props":23058,"children":23059},{"style":572},[23060],{"type":420,"value":858},{"type":415,"tag":559,"props":23062,"children":23063},{"style":572},[23064],{"type":420,"value":23065}," sqlAdAdminLogin",{"type":415,"tag":559,"props":23067,"children":23068},{"style":583},[23069],{"type":420,"value":763},{"type":415,"tag":559,"props":23071,"children":23072},{"style":792},[23073],{"type":420,"value":14608},{"type":415,"tag":559,"props":23075,"children":23076},{"style":583},[23077],{"type":420,"value":542},{"type":415,"tag":559,"props":23079,"children":23080},{"style":883},[23081],{"type":420,"value":23082},"Require",{"type":415,"tag":559,"props":23084,"children":23085},{"style":583},[23086],{"type":420,"value":814},{"type":415,"tag":559,"props":23088,"children":23089},{"style":583},[23090],{"type":420,"value":819},{"type":415,"tag":559,"props":23092,"children":23093},{"style":822},[23094],{"type":420,"value":23095},"sqlAdAdmin",{"type":415,"tag":559,"props":23097,"children":23098},{"style":583},[23099],{"type":420,"value":819},{"type":415,"tag":559,"props":23101,"children":23102},{"style":583},[23103],{"type":420,"value":696},{"type":415,"tag":559,"props":23105,"children":23106},{"class":561,"line":608},[23107,23111,23116,23120,23124,23128,23133,23137,23141,23146,23150],{"type":415,"tag":559,"props":23108,"children":23109},{"style":572},[23110],{"type":420,"value":858},{"type":415,"tag":559,"props":23112,"children":23113},{"style":572},[23114],{"type":420,"value":23115}," sqlAdAdminPassword",{"type":415,"tag":559,"props":23117,"children":23118},{"style":583},[23119],{"type":420,"value":763},{"type":415,"tag":559,"props":23121,"children":23122},{"style":792},[23123],{"type":420,"value":14608},{"type":415,"tag":559,"props":23125,"children":23126},{"style":583},[23127],{"type":420,"value":542},{"type":415,"tag":559,"props":23129,"children":23130},{"style":883},[23131],{"type":420,"value":23132},"RequireSecret",{"type":415,"tag":559,"props":23134,"children":23135},{"style":583},[23136],{"type":420,"value":814},{"type":415,"tag":559,"props":23138,"children":23139},{"style":583},[23140],{"type":420,"value":819},{"type":415,"tag":559,"props":23142,"children":23143},{"style":822},[23144],{"type":420,"value":23145},"sqlAdPassword",{"type":415,"tag":559,"props":23147,"children":23148},{"style":583},[23149],{"type":420,"value":819},{"type":415,"tag":559,"props":23151,"children":23152},{"style":583},[23153],{"type":420,"value":696},{"type":415,"tag":559,"props":23155,"children":23156},{"class":561,"line":626},[23157],{"type":415,"tag":559,"props":23158,"children":23159},{"emptyLinePlaceholder":847},[23160],{"type":420,"value":850},{"type":415,"tag":559,"props":23162,"children":23163},{"class":561,"line":643},[23164,23168,23173,23177,23181,23186,23190,23194,23199,23203,23207,23211],{"type":415,"tag":559,"props":23165,"children":23166},{"style":572},[23167],{"type":420,"value":858},{"type":415,"tag":559,"props":23169,"children":23170},{"style":572},[23171],{"type":420,"value":23172}," sqlAdAdmin",{"type":415,"tag":559,"props":23174,"children":23175},{"style":583},[23176],{"type":420,"value":763},{"type":415,"tag":559,"props":23178,"children":23179},{"style":583},[23180],{"type":420,"value":768},{"type":415,"tag":559,"props":23182,"children":23183},{"style":572},[23184],{"type":420,"value":23185}," User",{"type":415,"tag":559,"props":23187,"children":23188},{"style":583},[23189],{"type":420,"value":814},{"type":415,"tag":559,"props":23191,"children":23192},{"style":583},[23193],{"type":420,"value":819},{"type":415,"tag":559,"props":23195,"children":23196},{"style":822},[23197],{"type":420,"value":23198},"sqlAdmin",{"type":415,"tag":559,"props":23200,"children":23201},{"style":583},[23202],{"type":420,"value":819},{"type":415,"tag":559,"props":23204,"children":23205},{"style":583},[23206],{"type":420,"value":2312},{"type":415,"tag":559,"props":23208,"children":23209},{"style":583},[23210],{"type":420,"value":768},{"type":415,"tag":559,"props":23212,"children":23213},{"style":572},[23214],{"type":420,"value":23215}," UserArgs\n",{"type":415,"tag":559,"props":23217,"children":23218},{"class":561,"line":660},[23219],{"type":415,"tag":559,"props":23220,"children":23221},{"style":583},[23222],{"type":420,"value":786},{"type":415,"tag":559,"props":23224,"children":23225},{"class":561,"line":677},[23226,23231,23235,23239],{"type":415,"tag":559,"props":23227,"children":23228},{"style":792},[23229],{"type":420,"value":23230},"    UserPrincipalName ",{"type":415,"tag":559,"props":23232,"children":23233},{"style":583},[23234],{"type":420,"value":800},{"type":415,"tag":559,"props":23236,"children":23237},{"style":792},[23238],{"type":420,"value":23065},{"type":415,"tag":559,"props":23240,"children":23241},{"style":583},[23242],{"type":420,"value":605},{"type":415,"tag":559,"props":23244,"children":23245},{"class":561,"line":690},[23246,23251,23255,23259],{"type":415,"tag":559,"props":23247,"children":23248},{"style":792},[23249],{"type":420,"value":23250},"    Password ",{"type":415,"tag":559,"props":23252,"children":23253},{"style":583},[23254],{"type":420,"value":800},{"type":415,"tag":559,"props":23256,"children":23257},{"style":792},[23258],{"type":420,"value":23115},{"type":415,"tag":559,"props":23260,"children":23261},{"style":583},[23262],{"type":420,"value":605},{"type":415,"tag":559,"props":23264,"children":23265},{"class":561,"line":1089},[23266,23270,23274,23278,23283],{"type":415,"tag":559,"props":23267,"children":23268},{"style":792},[23269],{"type":420,"value":16351},{"type":415,"tag":559,"props":23271,"children":23272},{"style":583},[23273],{"type":420,"value":800},{"type":415,"tag":559,"props":23275,"children":23276},{"style":583},[23277],{"type":420,"value":1434},{"type":415,"tag":559,"props":23279,"children":23280},{"style":822},[23281],{"type":420,"value":23282},"Global SQL Admin",{"type":415,"tag":559,"props":23284,"children":23285},{"style":583},[23286],{"type":420,"value":10222},{"type":415,"tag":559,"props":23288,"children":23289},{"class":561,"line":1102},[23290],{"type":415,"tag":559,"props":23291,"children":23292},{"style":583},[23293],{"type":420,"value":5833},{"type":415,"tag":416,"props":23295,"children":23296},{},[23297,23299,23305,23307,23313,23315,23322],{"type":420,"value":23298},"To create a new Azure AD user we need a login (it will be the email of the new user in our tenant) and a password. In this example, we retrieve these values from the ",{"type":415,"tag":434,"props":23300,"children":23303},{"href":23301,"rel":23302},"https://www.pulumi.com/docs/intro/concepts/config/",[438],[23304],{"type":420,"value":262},{"type":420,"value":23306}," which is stored in the YAML settings file. You can notice there that we retrieve a secret (the password) from the configuration thanks to the ",{"type":415,"tag":555,"props":23308,"children":23310},{"className":23309},[],[23311],{"type":420,"value":23312},"config.RequireSecret",{"type":420,"value":23314}," method. Indeed to avoid exposing a secret in the configuration file or the state file, Pulumi has ",{"type":415,"tag":434,"props":23316,"children":23319},{"href":23317,"rel":23318},"https://www.pulumi.com/docs/intro/concepts/secrets/",[438],[23320],{"type":420,"value":23321},"built-in support for secret encryption and decryption",{"type":420,"value":23323}," (not sure Terraform folks can say the same thing 😉).",{"type":415,"tag":422,"props":23325,"children":23327},{"id":23326},"create-the-azure-sql-server-and-its-database",[23328],{"type":420,"value":23329},"Create the Azure SQL Server and its database.",{"type":415,"tag":416,"props":23331,"children":23332},{},[23333],{"type":420,"value":23334},"Now that we have our administrator account, we can create the Azure SQL Server:",{"type":415,"tag":549,"props":23336,"children":23338},{"className":551,"code":23337,"language":326,"meta":401,"style":401},"var sqlServer = new Server($\"sql-sqlDbWithAzureAd-{Deployment.Instance.StackName}\", new ServerArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    Administrators = new ServerExternalAdministratorArgs\n    {\n        Login = sqlAdAdmin.UserPrincipalName,\n        Sid = sqlAdAdmin.Id,\n        AzureADOnlyAuthentication = true,\n        AdministratorType = AdministratorType.ActiveDirectory,\n        PrincipalType = PrincipalType.User,\n    },\n});\n",[23339],{"type":415,"tag":555,"props":23340,"children":23341},{"__ignoreMap":401},[23342,23421,23428,23455,23476,23483,23512,23540,23560,23590,23619,23626],{"type":415,"tag":559,"props":23343,"children":23344},{"class":561,"line":562},[23345,23349,23354,23358,23362,23367,23371,23375,23380,23384,23388,23392,23396,23400,23404,23408,23412,23416],{"type":415,"tag":559,"props":23346,"children":23347},{"style":572},[23348],{"type":420,"value":858},{"type":415,"tag":559,"props":23350,"children":23351},{"style":572},[23352],{"type":420,"value":23353}," sqlServer",{"type":415,"tag":559,"props":23355,"children":23356},{"style":583},[23357],{"type":420,"value":763},{"type":415,"tag":559,"props":23359,"children":23360},{"style":583},[23361],{"type":420,"value":768},{"type":415,"tag":559,"props":23363,"children":23364},{"style":572},[23365],{"type":420,"value":23366}," Server",{"type":415,"tag":559,"props":23368,"children":23369},{"style":583},[23370],{"type":420,"value":814},{"type":415,"tag":559,"props":23372,"children":23373},{"style":583},[23374],{"type":420,"value":16136},{"type":415,"tag":559,"props":23376,"children":23377},{"style":822},[23378],{"type":420,"value":23379},"sql-sqlDbWithAzureAd-",{"type":415,"tag":559,"props":23381,"children":23382},{"style":583},[23383],{"type":420,"value":2397},{"type":415,"tag":559,"props":23385,"children":23386},{"style":792},[23387],{"type":420,"value":20201},{"type":415,"tag":559,"props":23389,"children":23390},{"style":583},[23391],{"type":420,"value":542},{"type":415,"tag":559,"props":23393,"children":23394},{"style":792},[23395],{"type":420,"value":20210},{"type":415,"tag":559,"props":23397,"children":23398},{"style":583},[23399],{"type":420,"value":542},{"type":415,"tag":559,"props":23401,"children":23402},{"style":792},[23403],{"type":420,"value":20252},{"type":415,"tag":559,"props":23405,"children":23406},{"style":583},[23407],{"type":420,"value":1602},{"type":415,"tag":559,"props":23409,"children":23410},{"style":583},[23411],{"type":420,"value":2312},{"type":415,"tag":559,"props":23413,"children":23414},{"style":583},[23415],{"type":420,"value":768},{"type":415,"tag":559,"props":23417,"children":23418},{"style":572},[23419],{"type":420,"value":23420}," ServerArgs\n",{"type":415,"tag":559,"props":23422,"children":23423},{"class":561,"line":589},[23424],{"type":415,"tag":559,"props":23425,"children":23426},{"style":583},[23427],{"type":420,"value":786},{"type":415,"tag":559,"props":23429,"children":23430},{"class":561,"line":608},[23431,23435,23439,23443,23447,23451],{"type":415,"tag":559,"props":23432,"children":23433},{"style":792},[23434],{"type":420,"value":20405},{"type":415,"tag":559,"props":23436,"children":23437},{"style":583},[23438],{"type":420,"value":800},{"type":415,"tag":559,"props":23440,"children":23441},{"style":792},[23442],{"type":420,"value":20166},{"type":415,"tag":559,"props":23444,"children":23445},{"style":583},[23446],{"type":420,"value":542},{"type":415,"tag":559,"props":23448,"children":23449},{"style":792},[23450],{"type":420,"value":1412},{"type":415,"tag":559,"props":23452,"children":23453},{"style":583},[23454],{"type":420,"value":605},{"type":415,"tag":559,"props":23456,"children":23457},{"class":561,"line":626},[23458,23463,23467,23471],{"type":415,"tag":559,"props":23459,"children":23460},{"style":792},[23461],{"type":420,"value":23462},"    Administrators ",{"type":415,"tag":559,"props":23464,"children":23465},{"style":583},[23466],{"type":420,"value":800},{"type":415,"tag":559,"props":23468,"children":23469},{"style":583},[23470],{"type":420,"value":768},{"type":415,"tag":559,"props":23472,"children":23473},{"style":572},[23474],{"type":420,"value":23475}," ServerExternalAdministratorArgs\n",{"type":415,"tag":559,"props":23477,"children":23478},{"class":561,"line":643},[23479],{"type":415,"tag":559,"props":23480,"children":23481},{"style":583},[23482],{"type":420,"value":2737},{"type":415,"tag":559,"props":23484,"children":23485},{"class":561,"line":660},[23486,23491,23495,23499,23503,23508],{"type":415,"tag":559,"props":23487,"children":23488},{"style":792},[23489],{"type":420,"value":23490},"        Login ",{"type":415,"tag":559,"props":23492,"children":23493},{"style":583},[23494],{"type":420,"value":800},{"type":415,"tag":559,"props":23496,"children":23497},{"style":792},[23498],{"type":420,"value":23172},{"type":415,"tag":559,"props":23500,"children":23501},{"style":583},[23502],{"type":420,"value":542},{"type":415,"tag":559,"props":23504,"children":23505},{"style":792},[23506],{"type":420,"value":23507},"UserPrincipalName",{"type":415,"tag":559,"props":23509,"children":23510},{"style":583},[23511],{"type":420,"value":605},{"type":415,"tag":559,"props":23513,"children":23514},{"class":561,"line":677},[23515,23520,23524,23528,23532,23536],{"type":415,"tag":559,"props":23516,"children":23517},{"style":792},[23518],{"type":420,"value":23519},"        Sid ",{"type":415,"tag":559,"props":23521,"children":23522},{"style":583},[23523],{"type":420,"value":800},{"type":415,"tag":559,"props":23525,"children":23526},{"style":792},[23527],{"type":420,"value":23172},{"type":415,"tag":559,"props":23529,"children":23530},{"style":583},[23531],{"type":420,"value":542},{"type":415,"tag":559,"props":23533,"children":23534},{"style":792},[23535],{"type":420,"value":15150},{"type":415,"tag":559,"props":23537,"children":23538},{"style":583},[23539],{"type":420,"value":605},{"type":415,"tag":559,"props":23541,"children":23542},{"class":561,"line":690},[23543,23548,23552,23556],{"type":415,"tag":559,"props":23544,"children":23545},{"style":792},[23546],{"type":420,"value":23547},"        AzureADOnlyAuthentication ",{"type":415,"tag":559,"props":23549,"children":23550},{"style":583},[23551],{"type":420,"value":800},{"type":415,"tag":559,"props":23553,"children":23554},{"style":6887},[23555],{"type":420,"value":6890},{"type":415,"tag":559,"props":23557,"children":23558},{"style":583},[23559],{"type":420,"value":605},{"type":415,"tag":559,"props":23561,"children":23562},{"class":561,"line":1089},[23563,23568,23572,23577,23581,23586],{"type":415,"tag":559,"props":23564,"children":23565},{"style":792},[23566],{"type":420,"value":23567},"        AdministratorType ",{"type":415,"tag":559,"props":23569,"children":23570},{"style":583},[23571],{"type":420,"value":800},{"type":415,"tag":559,"props":23573,"children":23574},{"style":792},[23575],{"type":420,"value":23576}," AdministratorType",{"type":415,"tag":559,"props":23578,"children":23579},{"style":583},[23580],{"type":420,"value":542},{"type":415,"tag":559,"props":23582,"children":23583},{"style":792},[23584],{"type":420,"value":23585},"ActiveDirectory",{"type":415,"tag":559,"props":23587,"children":23588},{"style":583},[23589],{"type":420,"value":605},{"type":415,"tag":559,"props":23591,"children":23592},{"class":561,"line":1102},[23593,23598,23602,23606,23610,23615],{"type":415,"tag":559,"props":23594,"children":23595},{"style":792},[23596],{"type":420,"value":23597},"        PrincipalType ",{"type":415,"tag":559,"props":23599,"children":23600},{"style":583},[23601],{"type":420,"value":800},{"type":415,"tag":559,"props":23603,"children":23604},{"style":792},[23605],{"type":420,"value":16619},{"type":415,"tag":559,"props":23607,"children":23608},{"style":583},[23609],{"type":420,"value":542},{"type":415,"tag":559,"props":23611,"children":23612},{"style":792},[23613],{"type":420,"value":23614},"User",{"type":415,"tag":559,"props":23616,"children":23617},{"style":583},[23618],{"type":420,"value":605},{"type":415,"tag":559,"props":23620,"children":23621},{"class":561,"line":1110},[23622],{"type":415,"tag":559,"props":23623,"children":23624},{"style":583},[23625],{"type":420,"value":15050},{"type":415,"tag":559,"props":23627,"children":23628},{"class":561,"line":1118},[23629],{"type":415,"tag":559,"props":23630,"children":23631},{"style":583},[23632],{"type":420,"value":5833},{"type":415,"tag":416,"props":23634,"children":23635},{},[23636,23638,23643],{"type":420,"value":23637},"Nothing special here: we are using the variable ",{"type":415,"tag":555,"props":23639,"children":23641},{"className":23640},[],[23642],{"type":420,"value":23198},{"type":420,"value":23644}," that is our newly created user to set the administrator of the SQL Server and we set the authentication to Azure AD only. We can then create the database:",{"type":415,"tag":549,"props":23646,"children":23648},{"className":551,"code":23647,"language":326,"meta":401,"style":401},"var database = new Database(\"sqldb-sqlDbWithAzureAd-Main\", new DatabaseArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    ServerName = sqlServer.Name,\n    Sku = new SkuArgs\n    {\n        Name = \"Basic\"\n    }\n});\n",[23649],{"type":415,"tag":555,"props":23650,"children":23651},{"__ignoreMap":401},[23652,23707,23714,23741,23769,23789,23796,23819,23826],{"type":415,"tag":559,"props":23653,"children":23654},{"class":561,"line":562},[23655,23659,23664,23668,23672,23677,23681,23685,23690,23694,23698,23702],{"type":415,"tag":559,"props":23656,"children":23657},{"style":572},[23658],{"type":420,"value":858},{"type":415,"tag":559,"props":23660,"children":23661},{"style":572},[23662],{"type":420,"value":23663}," database",{"type":415,"tag":559,"props":23665,"children":23666},{"style":583},[23667],{"type":420,"value":763},{"type":415,"tag":559,"props":23669,"children":23670},{"style":583},[23671],{"type":420,"value":768},{"type":415,"tag":559,"props":23673,"children":23674},{"style":572},[23675],{"type":420,"value":23676}," Database",{"type":415,"tag":559,"props":23678,"children":23679},{"style":583},[23680],{"type":420,"value":814},{"type":415,"tag":559,"props":23682,"children":23683},{"style":583},[23684],{"type":420,"value":819},{"type":415,"tag":559,"props":23686,"children":23687},{"style":822},[23688],{"type":420,"value":23689},"sqldb-sqlDbWithAzureAd-Main",{"type":415,"tag":559,"props":23691,"children":23692},{"style":583},[23693],{"type":420,"value":819},{"type":415,"tag":559,"props":23695,"children":23696},{"style":583},[23697],{"type":420,"value":2312},{"type":415,"tag":559,"props":23699,"children":23700},{"style":583},[23701],{"type":420,"value":768},{"type":415,"tag":559,"props":23703,"children":23704},{"style":572},[23705],{"type":420,"value":23706}," DatabaseArgs\n",{"type":415,"tag":559,"props":23708,"children":23709},{"class":561,"line":589},[23710],{"type":415,"tag":559,"props":23711,"children":23712},{"style":583},[23713],{"type":420,"value":786},{"type":415,"tag":559,"props":23715,"children":23716},{"class":561,"line":608},[23717,23721,23725,23729,23733,23737],{"type":415,"tag":559,"props":23718,"children":23719},{"style":792},[23720],{"type":420,"value":20405},{"type":415,"tag":559,"props":23722,"children":23723},{"style":583},[23724],{"type":420,"value":800},{"type":415,"tag":559,"props":23726,"children":23727},{"style":792},[23728],{"type":420,"value":20166},{"type":415,"tag":559,"props":23730,"children":23731},{"style":583},[23732],{"type":420,"value":542},{"type":415,"tag":559,"props":23734,"children":23735},{"style":792},[23736],{"type":420,"value":1412},{"type":415,"tag":559,"props":23738,"children":23739},{"style":583},[23740],{"type":420,"value":605},{"type":415,"tag":559,"props":23742,"children":23743},{"class":561,"line":626},[23744,23749,23753,23757,23761,23765],{"type":415,"tag":559,"props":23745,"children":23746},{"style":792},[23747],{"type":420,"value":23748},"    ServerName ",{"type":415,"tag":559,"props":23750,"children":23751},{"style":583},[23752],{"type":420,"value":800},{"type":415,"tag":559,"props":23754,"children":23755},{"style":792},[23756],{"type":420,"value":23353},{"type":415,"tag":559,"props":23758,"children":23759},{"style":583},[23760],{"type":420,"value":542},{"type":415,"tag":559,"props":23762,"children":23763},{"style":792},[23764],{"type":420,"value":1412},{"type":415,"tag":559,"props":23766,"children":23767},{"style":583},[23768],{"type":420,"value":605},{"type":415,"tag":559,"props":23770,"children":23771},{"class":561,"line":643},[23772,23776,23780,23784],{"type":415,"tag":559,"props":23773,"children":23774},{"style":792},[23775],{"type":420,"value":20470},{"type":415,"tag":559,"props":23777,"children":23778},{"style":583},[23779],{"type":420,"value":800},{"type":415,"tag":559,"props":23781,"children":23782},{"style":583},[23783],{"type":420,"value":768},{"type":415,"tag":559,"props":23785,"children":23786},{"style":572},[23787],{"type":420,"value":23788}," SkuArgs\n",{"type":415,"tag":559,"props":23790,"children":23791},{"class":561,"line":660},[23792],{"type":415,"tag":559,"props":23793,"children":23794},{"style":583},[23795],{"type":420,"value":2737},{"type":415,"tag":559,"props":23797,"children":23798},{"class":561,"line":677},[23799,23803,23807,23811,23815],{"type":415,"tag":559,"props":23800,"children":23801},{"style":792},[23802],{"type":420,"value":20539},{"type":415,"tag":559,"props":23804,"children":23805},{"style":583},[23806],{"type":420,"value":800},{"type":415,"tag":559,"props":23808,"children":23809},{"style":583},[23810],{"type":420,"value":1434},{"type":415,"tag":559,"props":23812,"children":23813},{"style":822},[23814],{"type":420,"value":20519},{"type":415,"tag":559,"props":23816,"children":23817},{"style":583},[23818],{"type":420,"value":10222},{"type":415,"tag":559,"props":23820,"children":23821},{"class":561,"line":690},[23822],{"type":415,"tag":559,"props":23823,"children":23824},{"style":583},[23825],{"type":420,"value":2792},{"type":415,"tag":559,"props":23827,"children":23828},{"class":561,"line":1089},[23829],{"type":415,"tag":559,"props":23830,"children":23831},{"style":583},[23832],{"type":420,"value":5833},{"type":415,"tag":422,"props":23834,"children":23836},{"id":23835},"grant-sql-database-access-permissions-to-azure-ad-entities",[23837],{"type":420,"value":23838},"Grant SQL Database access permissions to Azure AD entities",{"type":415,"tag":416,"props":23840,"children":23841},{},[23842],{"type":420,"value":23843},"Once we have provisioned the Azure SQL Server and its database, here comes the tough part: we need to configure who can access the database. In a project, you will probably have to give access to some users and to the Azure resources that need to query the database (you will have to assign these resources a managed identity before that). But to keep things simple, we will just consider we need to grant SQL Database access to an Azure AD group. That could be a good way to do things by the way: create an Azure AD group, grant permissions to this group and add users and managed identities that need access to the database.",{"type":415,"tag":416,"props":23845,"children":23846},{},[23847,23849,23856],{"type":420,"value":23848},"Why did I say that this part was tough? It's because to grant SQL database permissions, we need to execute an SQL command on the Server as you can read ",{"type":415,"tag":434,"props":23850,"children":23853},{"href":23851,"rel":23852},"https://docs.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database?tabs=windowsclient%2Cef%2Cdotnet#grant-permissions-to-managed-identity",[438],[23854],{"type":420,"value":23855},"in the documentation",{"type":420,"value":542},{"type":415,"tag":549,"props":23858,"children":23862},{"className":23859,"code":23860,"language":23861,"meta":401,"style":401},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","CREATE USER [\u003Cidentity-name>] FROM EXTERNAL PROVIDER;\nALTER ROLE db_datareader ADD MEMBER [\u003Cidentity-name>];\nALTER ROLE db_datawriter ADD MEMBER [\u003Cidentity-name>];\nGO\n","sql",[23863],{"type":415,"tag":555,"props":23864,"children":23865},{"__ignoreMap":401},[23866,23898,23926,23950],{"type":415,"tag":559,"props":23867,"children":23868},{"class":561,"line":562},[23869,23874,23879,23884,23889,23894],{"type":415,"tag":559,"props":23870,"children":23871},{"style":2846},[23872],{"type":420,"value":23873},"CREATE",{"type":415,"tag":559,"props":23875,"children":23876},{"style":792},[23877],{"type":420,"value":23878}," USER [\u003Cidentity-name>] ",{"type":415,"tag":559,"props":23880,"children":23881},{"style":2846},[23882],{"type":420,"value":23883},"FROM",{"type":415,"tag":559,"props":23885,"children":23886},{"style":2846},[23887],{"type":420,"value":23888}," EXTERNAL",{"type":415,"tag":559,"props":23890,"children":23891},{"style":2846},[23892],{"type":420,"value":23893}," PROVIDER",{"type":415,"tag":559,"props":23895,"children":23896},{"style":792},[23897],{"type":420,"value":1509},{"type":415,"tag":559,"props":23899,"children":23900},{"class":561,"line":589},[23901,23906,23911,23916,23921],{"type":415,"tag":559,"props":23902,"children":23903},{"style":2846},[23904],{"type":420,"value":23905},"ALTER",{"type":415,"tag":559,"props":23907,"children":23908},{"style":2846},[23909],{"type":420,"value":23910}," ROLE",{"type":415,"tag":559,"props":23912,"children":23913},{"style":792},[23914],{"type":420,"value":23915}," db_datareader ",{"type":415,"tag":559,"props":23917,"children":23918},{"style":2846},[23919],{"type":420,"value":23920},"ADD",{"type":415,"tag":559,"props":23922,"children":23923},{"style":792},[23924],{"type":420,"value":23925}," MEMBER [\u003Cidentity-name>];\n",{"type":415,"tag":559,"props":23927,"children":23928},{"class":561,"line":608},[23929,23933,23937,23942,23946],{"type":415,"tag":559,"props":23930,"children":23931},{"style":2846},[23932],{"type":420,"value":23905},{"type":415,"tag":559,"props":23934,"children":23935},{"style":2846},[23936],{"type":420,"value":23910},{"type":415,"tag":559,"props":23938,"children":23939},{"style":792},[23940],{"type":420,"value":23941}," db_datawriter ",{"type":415,"tag":559,"props":23943,"children":23944},{"style":2846},[23945],{"type":420,"value":23920},{"type":415,"tag":559,"props":23947,"children":23948},{"style":792},[23949],{"type":420,"value":23925},{"type":415,"tag":559,"props":23951,"children":23952},{"class":561,"line":626},[23953],{"type":415,"tag":559,"props":23954,"children":23955},{"style":2846},[23956],{"type":420,"value":23957},"GO\n",{"type":415,"tag":416,"props":23959,"children":23960},{},[23961,23963,23969,23970,23976],{"type":420,"value":23962},"With this command, we are creating a user and giving ",{"type":415,"tag":555,"props":23964,"children":23966},{"className":23965},[],[23967],{"type":420,"value":23968},"db_datareader",{"type":420,"value":15479},{"type":415,"tag":555,"props":23971,"children":23973},{"className":23972},[],[23974],{"type":420,"value":23975},"db_datawriter",{"type":420,"value":23977}," roles. However it is not a classical user, it's a user that is \"external\" to the database: in our case, it corresponds to an Azure AD entity (a user, group, or application).",{"type":415,"tag":416,"props":23979,"children":23980},{},[23981],{"type":420,"value":23982},"So it's not just about setting a property to properly configure an Azure resource, it's a bit more complicated.",{"type":415,"tag":416,"props":23984,"children":23985},{},[23986],{"type":420,"value":23987},"I see multiple ways of doing that:",{"type":415,"tag":5376,"props":23989,"children":23990},{},[23991,23996,24001],{"type":415,"tag":5380,"props":23992,"children":23993},{},[23994],{"type":420,"value":23995},"Create a new Pulumi provider \"SQL Server provider\" that is to able manage users in an SQL Server database",{"type":415,"tag":5380,"props":23997,"children":23998},{},[23999],{"type":420,"value":24000},"Write custom C# code that executes the SQL command once the database is created",{"type":415,"tag":5380,"props":24002,"children":24003},{},[24004,24006,24012],{"type":420,"value":24005},"Use the Pulumi Command provider to execute the SQL command using the ",{"type":415,"tag":555,"props":24007,"children":24009},{"className":24008},[],[24010],{"type":420,"value":24011},"sqlcmd",{"type":420,"value":24013}," utility",{"type":415,"tag":416,"props":24015,"children":24016},{},[24017],{"type":420,"value":24018},"Let's review these solutions.",{"type":415,"tag":14340,"props":24020,"children":24022},{"id":24021},"new-sql-server-provider",[24023],{"type":420,"value":24024},"New \"SQL Server Provider\"",{"type":415,"tag":416,"props":24026,"children":24027},{},[24028,24030,24037],{"type":420,"value":24029},"To manage SQL Server resources like users and roles, we can create a complete provider. We could create it from scratch of course or use this ",{"type":415,"tag":434,"props":24031,"children":24034},{"href":24032,"rel":24033},"https://github.com/pulumi/pulumi-provider-boilerplate",[438],[24035],{"type":420,"value":24036},"Pulumi GitHub repository",{"type":420,"value":24038}," that provides some boilerplate code to create a Pulumi provider. Usually, Pulumi providers are written in Go (like the Terraform providers by the way) and generate SDKs for all programming languages supported by Pulumi.",{"type":415,"tag":416,"props":24040,"children":24041},{},[24042],{"type":415,"tag":934,"props":24043,"children":24047},{"alt":24044,"className":24045,"src":24046},"xyz Pulumi Provider boilerplate code repository on GitHub.",[938,8504],"/posts/images/sqldatabase_ad_provider_1.png",[],{"type":415,"tag":416,"props":24049,"children":24050},{},[24051,24053,24060,24062,24069,24071,24078],{"type":420,"value":24052},"Another way would be to adapt the existing ",{"type":415,"tag":434,"props":24054,"children":24057},{"href":24055,"rel":24056},"https://registry.terraform.io/providers/betr-io/mssql/latest/docs",[438],[24058],{"type":420,"value":24059},"Microsoft SQL Server Provider",{"type":420,"value":24061}," for Terraform. This Terraform provider made by the community enables you to create and manage logins and users on a SQL Server. I talked about \"adapting\" this provider because you can create a Pulumi provider out of a Terraform provider by using the ",{"type":415,"tag":434,"props":24063,"children":24066},{"href":24064,"rel":24065},"https://github.com/pulumi/pulumi-terraform-bridge",[438],[24067],{"type":420,"value":24068},"Pulumi Terraform Bridge",{"type":420,"value":24070},". That's great because instead of reinventing the wheel you can benefit from Terraform ecosystem by creating a Pulumi provider that wraps an existing Terraform provider. This ",{"type":415,"tag":434,"props":24072,"children":24075},{"href":24073,"rel":24074},"https://github.com/pulumi/pulumi-tf-provider-boilerplate",[438],[24076],{"type":420,"value":24077},"GitHub repository",{"type":420,"value":24079}," contains boilerplate code to do exactly that.",{"type":415,"tag":416,"props":24081,"children":24082},{},[24083],{"type":415,"tag":934,"props":24084,"children":24088},{"alt":24085,"className":24086,"src":24087},"Pulumi Terraform Bridge repository on GitHub.",[938,8504],"/posts/images/sqldatabase_ad_provider_2.png",[],{"type":415,"tag":1178,"props":24090,"children":24091},{"icon":1180},[24092],{"type":415,"tag":416,"props":24093,"children":24094},{},[24095,24097,24103],{"type":420,"value":24096},"You might have noticed that I sometimes criticize Terraform in my articles. That's not because I think Terraform is a bad infrastructure as code solution, in fact, I think it is a great solution with a rich ecosystem. However, I am critical of Terraform because I believe Infrastructure as Code should be done with programming languages instead of Domain-Specific Languages. Moreover, there are some areas (API coverage of major cloud providers, security, IDE support, ...) where I found Terraform is not good enough, especially compared to other platforms like Pulumi. So I am always a bit disappointed when I see that many people choose by default Terraform as their infrastructure as code platform without considering alternatives (and I am not only talking about Pulumi, there are also Farmer and Bicep for instance), even when these alternatives would be better suited to their use cases. That being said, Terraform has also advantages like its great community that creates and contributes to many providers like the ",{"type":415,"tag":555,"props":24098,"children":24100},{"className":24099},[],[24101],{"type":420,"value":24102},"mssql",{"type":420,"value":24104}," one.",{"type":415,"tag":416,"props":24106,"children":24107},{},[24108,24110,24115],{"type":420,"value":24109},"This first solution of creating a new \"SQL Server Provider\" (whether it be from scratch, from boilerplate code, or from the ",{"type":415,"tag":555,"props":24111,"children":24113},{"className":24112},[],[24114],{"type":420,"value":24102},{"type":420,"value":24116}," Terraform provider) is interesting but could be time-consuming because there are some things to set up and some amount of code to write.",{"type":415,"tag":14340,"props":24118,"children":24120},{"id":24119},"custom-c-code",[24121],{"type":420,"value":24122},"Custom C# code",{"type":415,"tag":416,"props":24124,"children":24125},{},[24126,24128,24140,24142,24149],{"type":420,"value":24127},"When you need to do something specific and there is no existing provider that can help you with it, you can just write the code to do it yourself without creating a complete provider. It's one of the reasons why I like Pulumi, even if you are doing Infrastructure as Code, at the end of the day you are just developing software so you can code what you need in the language you are familiar with. For instance, as I am developing in .NET, I can use the ",{"type":415,"tag":434,"props":24129,"children":24132},{"href":24130,"rel":24131},"https://docs.microsoft.com/en-us/sql/connect/ado-net/overview-sqlclient-driver",[438],[24133,24138],{"type":415,"tag":555,"props":24134,"children":24136},{"className":24135},[],[24137],{"type":420,"value":22978},{"type":420,"value":24139}," library",{"type":420,"value":24141}," (which is a data provider for Azure SQL Database) to connect and send commands to the database. And if I want to use ",{"type":415,"tag":434,"props":24143,"children":24146},{"href":24144,"rel":24145},"https://github.com/DapperLib/Dapper",[438],[24147],{"type":420,"value":24148},"Dapper",{"type":420,"value":24150}," on top of it because that's the library I am used to for querying a database I can. Hence writing the code that executes on the database the SQL command we have previously seen should not be very difficult.",{"type":415,"tag":416,"props":24152,"children":24153},{},[24154],{"type":420,"value":24155},"Now, even if we are using imperative language in Pulumi to write the infrastructure code it's still declarative infrastructure as code with a state. Therefore, we have to be careful about how and when this custom code should be executed.",{"type":415,"tag":416,"props":24157,"children":24158},{},[24159,24161,24166],{"type":420,"value":24160},"The easiest way is to use an ",{"type":415,"tag":555,"props":24162,"children":24164},{"className":24163},[],[24165],{"type":420,"value":15884},{"type":420,"value":24167}," method on an output of the database like this:",{"type":415,"tag":549,"props":24169,"children":24171},{"className":551,"code":24170,"language":326,"meta":401,"style":401},"database.Name.Apply(name =>\n{\n    /*** \n     * Indempotent code using Microsoft.Data.SqlClient library\n     * to execute the SQL command that assigns the correct roles\n     * to the Azure AD group we want to have access to the database.\n    ***/ \n    return true;\n});\n",[24172],{"type":415,"tag":555,"props":24173,"children":24174},{"__ignoreMap":401},[24175,24212,24219,24227,24235,24243,24251,24263,24278],{"type":415,"tag":559,"props":24176,"children":24177},{"class":561,"line":562},[24178,24183,24187,24191,24195,24199,24203,24208],{"type":415,"tag":559,"props":24179,"children":24180},{"style":792},[24181],{"type":420,"value":24182},"database",{"type":415,"tag":559,"props":24184,"children":24185},{"style":583},[24186],{"type":420,"value":542},{"type":415,"tag":559,"props":24188,"children":24189},{"style":792},[24190],{"type":420,"value":1412},{"type":415,"tag":559,"props":24192,"children":24193},{"style":583},[24194],{"type":420,"value":542},{"type":415,"tag":559,"props":24196,"children":24197},{"style":883},[24198],{"type":420,"value":15884},{"type":415,"tag":559,"props":24200,"children":24201},{"style":583},[24202],{"type":420,"value":814},{"type":415,"tag":559,"props":24204,"children":24205},{"style":572},[24206],{"type":420,"value":24207},"name",{"type":415,"tag":559,"props":24209,"children":24210},{"style":583},[24211],{"type":420,"value":5741},{"type":415,"tag":559,"props":24213,"children":24214},{"class":561,"line":589},[24215],{"type":415,"tag":559,"props":24216,"children":24217},{"style":583},[24218],{"type":420,"value":786},{"type":415,"tag":559,"props":24220,"children":24221},{"class":561,"line":608},[24222],{"type":415,"tag":559,"props":24223,"children":24224},{"style":2358},[24225],{"type":420,"value":24226},"    /*** \n",{"type":415,"tag":559,"props":24228,"children":24229},{"class":561,"line":626},[24230],{"type":415,"tag":559,"props":24231,"children":24232},{"style":2358},[24233],{"type":420,"value":24234},"     * Indempotent code using Microsoft.Data.SqlClient library\n",{"type":415,"tag":559,"props":24236,"children":24237},{"class":561,"line":643},[24238],{"type":415,"tag":559,"props":24239,"children":24240},{"style":2358},[24241],{"type":420,"value":24242},"     * to execute the SQL command that assigns the correct roles\n",{"type":415,"tag":559,"props":24244,"children":24245},{"class":561,"line":660},[24246],{"type":415,"tag":559,"props":24247,"children":24248},{"style":2358},[24249],{"type":420,"value":24250},"     * to the Azure AD group we want to have access to the database.\n",{"type":415,"tag":559,"props":24252,"children":24253},{"class":561,"line":677},[24254,24259],{"type":415,"tag":559,"props":24255,"children":24256},{"style":2358},[24257],{"type":420,"value":24258},"    ***/",{"type":415,"tag":559,"props":24260,"children":24261},{"style":792},[24262],{"type":420,"value":1473},{"type":415,"tag":559,"props":24264,"children":24265},{"class":561,"line":690},[24266,24270,24274],{"type":415,"tag":559,"props":24267,"children":24268},{"style":745},[24269],{"type":420,"value":1517},{"type":415,"tag":559,"props":24271,"children":24272},{"style":6887},[24273],{"type":420,"value":6890},{"type":415,"tag":559,"props":24275,"children":24276},{"style":583},[24277],{"type":420,"value":1509},{"type":415,"tag":559,"props":24279,"children":24280},{"class":561,"line":1089},[24281],{"type":415,"tag":559,"props":24282,"children":24283},{"style":583},[24284],{"type":420,"value":5833},{"type":415,"tag":416,"props":24286,"children":24287},{},[24288,24290,24295],{"type":420,"value":24289},"The code in the ",{"type":415,"tag":555,"props":24291,"children":24293},{"className":24292},[],[24294],{"type":420,"value":15884},{"type":420,"value":24296}," will execute on every run after the resource is created, that is why it needs to be idempotent. Having to make the code idempotent is a constraint that I would prefer to avoid but at least it gives us a simple way to execute the code that grants access to the database.",{"type":415,"tag":416,"props":24298,"children":24299},{},[24300,24302,24309,24311,24318,24320,24327],{"type":420,"value":24301},"Another way would be to use ",{"type":415,"tag":434,"props":24303,"children":24306},{"href":24304,"rel":24305},"https://www.pulumi.com/docs/intro/concepts/resources/dynamic-providers/",[438],[24307],{"type":420,"value":24308},"Dynamic Providers",{"type":420,"value":24310}," whose purpose is exactly that: do an infrastructure task that no existing provider can help you deliver. You can see some use cases of dynamic providers in ",{"type":415,"tag":434,"props":24312,"children":24315},{"href":24313,"rel":24314},"https://www.pulumi.com/blog/dynamic-providers/#sample-use-cases",[438],[24316],{"type":420,"value":24317},"this Pulumi article",{"type":420,"value":24319},". In our use case, we could imagine writing a dynamic resource provider for an Azure AD entity user in an Azure SQL Database.  We would have to implement the different CRUD operations to handle the different use cases properly (a user is added, a user is removed, user roles are updated, ...). Unfortunately, as you can see in ",{"type":415,"tag":434,"props":24321,"children":24324},{"href":24322,"rel":24323},"https://github.com/pulumi/pulumi/issues/3638",[438],[24325],{"type":420,"value":24326},"this GitHub issue",{"type":420,"value":24328},", .NET Dynamic Providers are not yet supported (only TypesScript, JavaScript and Python are for the moment). It's a shame because Dynamic Providers provide an easy and efficient way of supporting custom resource types.",{"type":415,"tag":14340,"props":24330,"children":24332},{"id":24331},"command-provider-with-the-sqlcmd-utility",[24333,24335,24340],{"type":420,"value":24334},"Command provider with the ",{"type":415,"tag":555,"props":24336,"children":24338},{"className":24337},[],[24339],{"type":420,"value":24011},{"type":420,"value":24013},{"type":415,"tag":416,"props":24342,"children":24343},{},[24344,24350,24352,24363,24365,24370,24372,24379],{"type":415,"tag":434,"props":24345,"children":24347},{"href":23851,"rel":24346},[438],[24348],{"type":420,"value":24349},"The Microsoft tutorial",{"type":420,"value":24351},", that shows how to grant database permissions to an Azure AD entity, explains how the necessary SQL commands can be run using the ",{"type":415,"tag":434,"props":24353,"children":24356},{"href":24354,"rel":24355},"https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility",[438],[24357,24362],{"type":415,"tag":555,"props":24358,"children":24360},{"className":24359},[],[24361],{"type":420,"value":24011},{"type":420,"value":24013},{"type":420,"value":24364},". So instead of writing some C# code to do the same, an interesting idea would be to directly run the ",{"type":415,"tag":555,"props":24366,"children":24368},{"className":24367},[],[24369],{"type":420,"value":24011},{"type":420,"value":24371}," utility. And you know what? There is a Pulumi provider for executing commands and scripts: ",{"type":415,"tag":434,"props":24373,"children":24376},{"href":24374,"rel":24375},"https://www.pulumi.com/registry/packages/command/api-docs/",[438],[24377],{"type":420,"value":24378},"the Command Provider",{"type":420,"value":542},{"type":415,"tag":416,"props":24381,"children":24382},{},[24383],{"type":415,"tag":934,"props":24384,"children":24388},{"alt":24385,"className":24386,"src":24387},"Pulumi Command Provider on GitHub.",[938,8504],"/posts/images/sqldatabase_ad_pulumi_1.png",[],{"type":415,"tag":416,"props":24390,"children":24391},{},[24392,24394,24399,24401,24407,24409,24414],{"type":420,"value":24393},"Because it's a Pulumi provider, the ",{"type":415,"tag":555,"props":24395,"children":24397},{"className":24396},[],[24398],{"type":420,"value":24011},{"type":420,"value":24400}," command would be executed \"as part of the Pulumi resource model\" which means the scripts would be executed at the corresponding time of the resource life-cycle (the ",{"type":415,"tag":555,"props":24402,"children":24404},{"className":24403},[],[24405],{"type":420,"value":24406},"create",{"type":420,"value":24408}," script when the resource is created and so on). So it's very nice and not the same as executing the ",{"type":415,"tag":555,"props":24410,"children":24412},{"className":24411},[],[24413],{"type":420,"value":24011},{"type":420,"value":24415}," outside of a Pulumi program, without access to all the variables and where you would have to make your script idempotent. Moreover, the ability to execute commands remotely can bring interesting use cases, just not for our current concern here.",{"type":415,"tag":1178,"props":24417,"children":24418},{"icon":5363},[24419],{"type":415,"tag":416,"props":24420,"children":24421},{},[24422,24424,24429,24430,24436,24438,24444,24445,24451,24452,24458,24460,24467],{"type":420,"value":24423},"Pulumi Command Provider is currently in preview and only supports running scripts on ",{"type":415,"tag":555,"props":24425,"children":24427},{"className":24426},[],[24428],{"type":420,"value":24406},{"type":420,"value":15479},{"type":415,"tag":555,"props":24431,"children":24433},{"className":24432},[],[24434],{"type":420,"value":24435},"destroy",{"type":420,"value":24437}," operations (support for ",{"type":415,"tag":555,"props":24439,"children":24441},{"className":24440},[],[24442],{"type":420,"value":24443},"diff",{"type":420,"value":14095},{"type":415,"tag":555,"props":24446,"children":24448},{"className":24447},[],[24449],{"type":420,"value":24450},"update",{"type":420,"value":15479},{"type":415,"tag":555,"props":24453,"children":24455},{"className":24454},[],[24456],{"type":420,"value":24457},"read",{"type":420,"value":24459}," operations ",{"type":415,"tag":434,"props":24461,"children":24464},{"href":24462,"rel":24463},"https://github.com/pulumi/pulumi-command/issues/20",[438],[24465],{"type":420,"value":24466},"will probably be added later",{"type":420,"value":24468},"). It works fine but does not log details about the error when a script fails, which makes debugging difficult. That should not prevent you from using it but as with any components in preview, use it with caution knowing everything is not perfect yet.",{"type":415,"tag":422,"props":24470,"children":24472},{"id":24471},"implement-the-database-permissions-for-an-azure-ad-group",[24473],{"type":420,"value":24474},"Implement the database permissions for an Azure AD Group",{"type":415,"tag":416,"props":24476,"children":24477},{},[24478,24480,24485,24487,24492],{"type":420,"value":24479},"Of the 3 possible solutions let's take the 3rd one with the Command provider and the ",{"type":415,"tag":555,"props":24481,"children":24483},{"className":24482},[],[24484],{"type":420,"value":24011},{"type":420,"value":24486}," utility. It is probably not the \"best\" solution but I thought it would be simpler to use the ",{"type":415,"tag":555,"props":24488,"children":24490},{"className":24489},[],[24491],{"type":420,"value":24011},{"type":420,"value":24493}," utility than writing a complete provider or even custom C# code to do the same. Furthermore, it's the opportunity to test the Command provider which is fairly new.",{"type":415,"tag":14340,"props":24495,"children":24497},{"id":24496},"allow-the-machine-running-the-pulumi-program-to-connect-to-the-sql-server",[24498],{"type":420,"value":24499},"Allow the machine running the Pulumi program to connect to the SQL Server",{"type":415,"tag":416,"props":24501,"children":24502},{},[24503,24505,24511],{"type":420,"value":24504},"To run a SQL command in the database, the machine that executes the Pulumi program needs to have its public IP authorized. To programmatically retrieve the public IP address from where the Pulumi program is running we can use ",{"type":415,"tag":555,"props":24506,"children":24508},{"className":24507},[],[24509],{"type":420,"value":24510},"ipify API",{"type":420,"value":24512},". It's a simple open source HTTP API that returns the public IP address of the caller.",{"type":415,"tag":549,"props":24514,"children":24516},{"className":551,"code":24515,"language":326,"meta":401,"style":401},"var publicIp = Output.Create(new HttpClient().GetStringAsync(\"https://api.ipify.org\"));\n",[24517],{"type":415,"tag":555,"props":24518,"children":24519},{"__ignoreMap":401},[24520],{"type":415,"tag":559,"props":24521,"children":24522},{"class":561,"line":562},[24523,24527,24532,24536,24540,24544,24549,24553,24557,24562,24567,24571,24575,24580,24584],{"type":415,"tag":559,"props":24524,"children":24525},{"style":572},[24526],{"type":420,"value":858},{"type":415,"tag":559,"props":24528,"children":24529},{"style":572},[24530],{"type":420,"value":24531}," publicIp",{"type":415,"tag":559,"props":24533,"children":24534},{"style":583},[24535],{"type":420,"value":763},{"type":415,"tag":559,"props":24537,"children":24538},{"style":792},[24539],{"type":420,"value":16679},{"type":415,"tag":559,"props":24541,"children":24542},{"style":583},[24543],{"type":420,"value":542},{"type":415,"tag":559,"props":24545,"children":24546},{"style":883},[24547],{"type":420,"value":24548},"Create",{"type":415,"tag":559,"props":24550,"children":24551},{"style":583},[24552],{"type":420,"value":5770},{"type":415,"tag":559,"props":24554,"children":24555},{"style":572},[24556],{"type":420,"value":773},{"type":415,"tag":559,"props":24558,"children":24559},{"style":583},[24560],{"type":420,"value":24561},"().",{"type":415,"tag":559,"props":24563,"children":24564},{"style":883},[24565],{"type":420,"value":24566},"GetStringAsync",{"type":415,"tag":559,"props":24568,"children":24569},{"style":583},[24570],{"type":420,"value":814},{"type":415,"tag":559,"props":24572,"children":24573},{"style":583},[24574],{"type":420,"value":819},{"type":415,"tag":559,"props":24576,"children":24577},{"style":822},[24578],{"type":420,"value":24579},"https://api.ipify.org",{"type":415,"tag":559,"props":24581,"children":24582},{"style":583},[24583],{"type":420,"value":819},{"type":415,"tag":559,"props":24585,"children":24586},{"style":583},[24587],{"type":420,"value":5796},{"type":415,"tag":1178,"props":24589,"children":24590},{"icon":1180},[24591],{"type":415,"tag":416,"props":24592,"children":24593},{},[24594,24596,24601,24603,24608,24610,24617],{"type":420,"value":24595},"You can note here that we are just using standard C# code with an ",{"type":415,"tag":555,"props":24597,"children":24599},{"className":24598},[],[24600],{"type":420,"value":707},{"type":420,"value":24602}," that makes a ",{"type":415,"tag":555,"props":24604,"children":24606},{"className":24605},[],[24607],{"type":420,"value":723},{"type":420,"value":24609}," to the API and returns asynchronously a string. I like the fact that with Pulumi we can reuse our existing C# skills, and the libraries we are used to. If we were to do that in Terraform we would have to look in the documentation how to do HTTP calls, discover that there is an ",{"type":415,"tag":434,"props":24611,"children":24614},{"href":24612,"rel":24613},"https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http",[438],[24615],{"type":420,"value":24616},"http data source",{"type":420,"value":24618}," that can be used, understand how it works (to be honest it seems quite simple but still that is not natural) and use it.",{"type":415,"tag":416,"props":24620,"children":24621},{},[24622],{"type":420,"value":24623},"Now we can enable this public IP by creating a firewall rule in the SQL Server.",{"type":415,"tag":549,"props":24625,"children":24627},{"className":551,"code":24626,"language":326,"meta":401,"style":401},"var enableLocalMachine = new FirewallRule(\"AllowLocalMachine\", new FirewallRuleArgs\n{\n    ResourceGroupName = resourceGroup.Name,\n    ServerName = sqlServer.Name,\n    StartIpAddress = publicIp,\n    EndIpAddress = publicIp\n});\n",[24628],{"type":415,"tag":555,"props":24629,"children":24630},{"__ignoreMap":401},[24631,24686,24693,24720,24747,24767,24784],{"type":415,"tag":559,"props":24632,"children":24633},{"class":561,"line":562},[24634,24638,24643,24647,24651,24656,24660,24664,24669,24673,24677,24681],{"type":415,"tag":559,"props":24635,"children":24636},{"style":572},[24637],{"type":420,"value":858},{"type":415,"tag":559,"props":24639,"children":24640},{"style":572},[24641],{"type":420,"value":24642}," enableLocalMachine",{"type":415,"tag":559,"props":24644,"children":24645},{"style":583},[24646],{"type":420,"value":763},{"type":415,"tag":559,"props":24648,"children":24649},{"style":583},[24650],{"type":420,"value":768},{"type":415,"tag":559,"props":24652,"children":24653},{"style":572},[24654],{"type":420,"value":24655}," FirewallRule",{"type":415,"tag":559,"props":24657,"children":24658},{"style":583},[24659],{"type":420,"value":814},{"type":415,"tag":559,"props":24661,"children":24662},{"style":583},[24663],{"type":420,"value":819},{"type":415,"tag":559,"props":24665,"children":24666},{"style":822},[24667],{"type":420,"value":24668},"AllowLocalMachine",{"type":415,"tag":559,"props":24670,"children":24671},{"style":583},[24672],{"type":420,"value":819},{"type":415,"tag":559,"props":24674,"children":24675},{"style":583},[24676],{"type":420,"value":2312},{"type":415,"tag":559,"props":24678,"children":24679},{"style":583},[24680],{"type":420,"value":768},{"type":415,"tag":559,"props":24682,"children":24683},{"style":572},[24684],{"type":420,"value":24685}," FirewallRuleArgs\n",{"type":415,"tag":559,"props":24687,"children":24688},{"class":561,"line":589},[24689],{"type":415,"tag":559,"props":24690,"children":24691},{"style":583},[24692],{"type":420,"value":786},{"type":415,"tag":559,"props":24694,"children":24695},{"class":561,"line":608},[24696,24700,24704,24708,24712,24716],{"type":415,"tag":559,"props":24697,"children":24698},{"style":792},[24699],{"type":420,"value":20405},{"type":415,"tag":559,"props":24701,"children":24702},{"style":583},[24703],{"type":420,"value":800},{"type":415,"tag":559,"props":24705,"children":24706},{"style":792},[24707],{"type":420,"value":20166},{"type":415,"tag":559,"props":24709,"children":24710},{"style":583},[24711],{"type":420,"value":542},{"type":415,"tag":559,"props":24713,"children":24714},{"style":792},[24715],{"type":420,"value":1412},{"type":415,"tag":559,"props":24717,"children":24718},{"style":583},[24719],{"type":420,"value":605},{"type":415,"tag":559,"props":24721,"children":24722},{"class":561,"line":626},[24723,24727,24731,24735,24739,24743],{"type":415,"tag":559,"props":24724,"children":24725},{"style":792},[24726],{"type":420,"value":23748},{"type":415,"tag":559,"props":24728,"children":24729},{"style":583},[24730],{"type":420,"value":800},{"type":415,"tag":559,"props":24732,"children":24733},{"style":792},[24734],{"type":420,"value":23353},{"type":415,"tag":559,"props":24736,"children":24737},{"style":583},[24738],{"type":420,"value":542},{"type":415,"tag":559,"props":24740,"children":24741},{"style":792},[24742],{"type":420,"value":1412},{"type":415,"tag":559,"props":24744,"children":24745},{"style":583},[24746],{"type":420,"value":605},{"type":415,"tag":559,"props":24748,"children":24749},{"class":561,"line":643},[24750,24755,24759,24763],{"type":415,"tag":559,"props":24751,"children":24752},{"style":792},[24753],{"type":420,"value":24754},"    StartIpAddress ",{"type":415,"tag":559,"props":24756,"children":24757},{"style":583},[24758],{"type":420,"value":800},{"type":415,"tag":559,"props":24760,"children":24761},{"style":792},[24762],{"type":420,"value":24531},{"type":415,"tag":559,"props":24764,"children":24765},{"style":583},[24766],{"type":420,"value":605},{"type":415,"tag":559,"props":24768,"children":24769},{"class":561,"line":660},[24770,24775,24779],{"type":415,"tag":559,"props":24771,"children":24772},{"style":792},[24773],{"type":420,"value":24774},"    EndIpAddress ",{"type":415,"tag":559,"props":24776,"children":24777},{"style":583},[24778],{"type":420,"value":800},{"type":415,"tag":559,"props":24780,"children":24781},{"style":792},[24782],{"type":420,"value":24783}," publicIp\n",{"type":415,"tag":559,"props":24785,"children":24786},{"class":561,"line":677},[24787],{"type":415,"tag":559,"props":24788,"children":24789},{"style":583},[24790],{"type":420,"value":5833},{"type":415,"tag":14340,"props":24792,"children":24794},{"id":24793},"create-the-azure-ad-group-that-will-be-given-access-to-the-database",[24795],{"type":420,"value":24796},"Create the Azure AD group that will be given access to the database",{"type":415,"tag":416,"props":24798,"children":24799},{},[24800],{"type":420,"value":24801},"We said we wanted to grant SQL Database access to an Azure AD group that will contain in the future users and application managed identities that need access to the database. So let's create that:",{"type":415,"tag":549,"props":24803,"children":24805},{"className":551,"code":24804,"language":326,"meta":401,"style":401},"var sqlDatabaseAuthorizedGroup = new Group(\"SqlDbUsersGroup\", new GroupArgs\n{\n    DisplayName = \"SqlDbUsersGroup\",\n    SecurityEnabled = true,\n    Owners = new InputList\u003Cstring> { sqlAdAdmin.Id }\n});\n",[24806],{"type":415,"tag":555,"props":24807,"children":24808},{"__ignoreMap":401},[24809,24864,24871,24898,24918,24972],{"type":415,"tag":559,"props":24810,"children":24811},{"class":561,"line":562},[24812,24816,24821,24825,24829,24834,24838,24842,24847,24851,24855,24859],{"type":415,"tag":559,"props":24813,"children":24814},{"style":572},[24815],{"type":420,"value":858},{"type":415,"tag":559,"props":24817,"children":24818},{"style":572},[24819],{"type":420,"value":24820}," sqlDatabaseAuthorizedGroup",{"type":415,"tag":559,"props":24822,"children":24823},{"style":583},[24824],{"type":420,"value":763},{"type":415,"tag":559,"props":24826,"children":24827},{"style":583},[24828],{"type":420,"value":768},{"type":415,"tag":559,"props":24830,"children":24831},{"style":572},[24832],{"type":420,"value":24833}," Group",{"type":415,"tag":559,"props":24835,"children":24836},{"style":583},[24837],{"type":420,"value":814},{"type":415,"tag":559,"props":24839,"children":24840},{"style":583},[24841],{"type":420,"value":819},{"type":415,"tag":559,"props":24843,"children":24844},{"style":822},[24845],{"type":420,"value":24846},"SqlDbUsersGroup",{"type":415,"tag":559,"props":24848,"children":24849},{"style":583},[24850],{"type":420,"value":819},{"type":415,"tag":559,"props":24852,"children":24853},{"style":583},[24854],{"type":420,"value":2312},{"type":415,"tag":559,"props":24856,"children":24857},{"style":583},[24858],{"type":420,"value":768},{"type":415,"tag":559,"props":24860,"children":24861},{"style":572},[24862],{"type":420,"value":24863}," GroupArgs\n",{"type":415,"tag":559,"props":24865,"children":24866},{"class":561,"line":589},[24867],{"type":415,"tag":559,"props":24868,"children":24869},{"style":583},[24870],{"type":420,"value":786},{"type":415,"tag":559,"props":24872,"children":24873},{"class":561,"line":608},[24874,24878,24882,24886,24890,24894],{"type":415,"tag":559,"props":24875,"children":24876},{"style":792},[24877],{"type":420,"value":16351},{"type":415,"tag":559,"props":24879,"children":24880},{"style":583},[24881],{"type":420,"value":800},{"type":415,"tag":559,"props":24883,"children":24884},{"style":583},[24885],{"type":420,"value":1434},{"type":415,"tag":559,"props":24887,"children":24888},{"style":822},[24889],{"type":420,"value":24846},{"type":415,"tag":559,"props":24891,"children":24892},{"style":583},[24893],{"type":420,"value":819},{"type":415,"tag":559,"props":24895,"children":24896},{"style":583},[24897],{"type":420,"value":605},{"type":415,"tag":559,"props":24899,"children":24900},{"class":561,"line":626},[24901,24906,24910,24914],{"type":415,"tag":559,"props":24902,"children":24903},{"style":792},[24904],{"type":420,"value":24905},"    SecurityEnabled ",{"type":415,"tag":559,"props":24907,"children":24908},{"style":583},[24909],{"type":420,"value":800},{"type":415,"tag":559,"props":24911,"children":24912},{"style":6887},[24913],{"type":420,"value":6890},{"type":415,"tag":559,"props":24915,"children":24916},{"style":583},[24917],{"type":420,"value":605},{"type":415,"tag":559,"props":24919,"children":24920},{"class":561,"line":643},[24921,24926,24930,24934,24939,24943,24947,24951,24955,24959,24963,24968],{"type":415,"tag":559,"props":24922,"children":24923},{"style":792},[24924],{"type":420,"value":24925},"    Owners ",{"type":415,"tag":559,"props":24927,"children":24928},{"style":583},[24929],{"type":420,"value":800},{"type":415,"tag":559,"props":24931,"children":24932},{"style":583},[24933],{"type":420,"value":768},{"type":415,"tag":559,"props":24935,"children":24936},{"style":572},[24937],{"type":420,"value":24938}," InputList",{"type":415,"tag":559,"props":24940,"children":24941},{"style":583},[24942],{"type":420,"value":891},{"type":415,"tag":559,"props":24944,"children":24945},{"style":583},[24946],{"type":420,"value":2015},{"type":415,"tag":559,"props":24948,"children":24949},{"style":583},[24950],{"type":420,"value":5985},{"type":415,"tag":559,"props":24952,"children":24953},{"style":583},[24954],{"type":420,"value":1144},{"type":415,"tag":559,"props":24956,"children":24957},{"style":792},[24958],{"type":420,"value":23172},{"type":415,"tag":559,"props":24960,"children":24961},{"style":583},[24962],{"type":420,"value":542},{"type":415,"tag":559,"props":24964,"children":24965},{"style":792},[24966],{"type":420,"value":24967},"Id ",{"type":415,"tag":559,"props":24969,"children":24970},{"style":583},[24971],{"type":420,"value":1801},{"type":415,"tag":559,"props":24973,"children":24974},{"class":561,"line":660},[24975],{"type":415,"tag":559,"props":24976,"children":24977},{"style":583},[24978],{"type":420,"value":5833},{"type":415,"tag":416,"props":24980,"children":24981},{},[24982],{"type":420,"value":24983},"We set the Azure SQL Server admin as the owner of the group. This way, the admin of the database can add Azure AD users to the group and they directly have the permissions configured for this group. I like authorizing an Azure AD group instead of each Azure AD user because:",{"type":415,"tag":5376,"props":24985,"children":24986},{},[24987,24992,24997],{"type":415,"tag":5380,"props":24988,"children":24989},{},[24990],{"type":420,"value":24991},"it is easier to manage a group than individual users (adding a user to a group is less work than using SQL commands to assign the correct role for each user)",{"type":415,"tag":5380,"props":24993,"children":24994},{},[24995],{"type":420,"value":24996},"you don't lose granularity of access control (you can always create several groups with different permissions if you need to)",{"type":415,"tag":5380,"props":24998,"children":24999},{},[25000],{"type":420,"value":25001},"you can ensure that your application runs with the same permissions locally (the code you debug uses your user account identity) and on Azure (the code uses the managed identity of the App Service where it is hosted) by putting users and managed identities in the same group",{"type":415,"tag":14340,"props":25003,"children":25005},{"id":25004},"assign-the-roles-to-the-azure-ad-group-using-the-command-provider",[25006],{"type":420,"value":25007},"Assign the roles to the Azure AD group using the Command provider",{"type":415,"tag":416,"props":25009,"children":25010},{},[25011,25013,25018,25020,25025],{"type":420,"value":25012},"As we already talked about, we can specify a script to run on the ",{"type":415,"tag":555,"props":25014,"children":25016},{"className":25015},[],[25017],{"type":420,"value":24406},{"type":420,"value":25019}," operation and another on the ",{"type":415,"tag":555,"props":25021,"children":25023},{"className":25022},[],[25024],{"type":420,"value":24435},{"type":420,"value":25026}," operations. To keep things simple for this sample, we will only handle the creation scenario where we will add our Azure AD group as a user of the database and give it the expected roles. We already showed the SQL Command to execute, with our new group name it becomes:",{"type":415,"tag":549,"props":25028,"children":25030},{"className":23859,"code":25029,"language":23861,"meta":401,"style":401},"CREATE USER {sqlDatabaseAuthorizedGroup.DisplayName} FROM EXTERNAL PROVIDER;\nALTER ROLE db_datareader ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};\nALTER ROLE db_datawriter ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};\nGO\n",[25031],{"type":415,"tag":555,"props":25032,"children":25033},{"__ignoreMap":401},[25034,25062,25086,25109],{"type":415,"tag":559,"props":25035,"children":25036},{"class":561,"line":562},[25037,25041,25046,25050,25054,25058],{"type":415,"tag":559,"props":25038,"children":25039},{"style":2846},[25040],{"type":420,"value":23873},{"type":415,"tag":559,"props":25042,"children":25043},{"style":792},[25044],{"type":420,"value":25045}," USER {sqlDatabaseAuthorizedGroup.DisplayName} ",{"type":415,"tag":559,"props":25047,"children":25048},{"style":2846},[25049],{"type":420,"value":23883},{"type":415,"tag":559,"props":25051,"children":25052},{"style":2846},[25053],{"type":420,"value":23888},{"type":415,"tag":559,"props":25055,"children":25056},{"style":2846},[25057],{"type":420,"value":23893},{"type":415,"tag":559,"props":25059,"children":25060},{"style":792},[25061],{"type":420,"value":1509},{"type":415,"tag":559,"props":25063,"children":25064},{"class":561,"line":589},[25065,25069,25073,25077,25081],{"type":415,"tag":559,"props":25066,"children":25067},{"style":2846},[25068],{"type":420,"value":23905},{"type":415,"tag":559,"props":25070,"children":25071},{"style":2846},[25072],{"type":420,"value":23910},{"type":415,"tag":559,"props":25074,"children":25075},{"style":792},[25076],{"type":420,"value":23915},{"type":415,"tag":559,"props":25078,"children":25079},{"style":2846},[25080],{"type":420,"value":23920},{"type":415,"tag":559,"props":25082,"children":25083},{"style":792},[25084],{"type":420,"value":25085}," MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};\n",{"type":415,"tag":559,"props":25087,"children":25088},{"class":561,"line":608},[25089,25093,25097,25101,25105],{"type":415,"tag":559,"props":25090,"children":25091},{"style":2846},[25092],{"type":420,"value":23905},{"type":415,"tag":559,"props":25094,"children":25095},{"style":2846},[25096],{"type":420,"value":23910},{"type":415,"tag":559,"props":25098,"children":25099},{"style":792},[25100],{"type":420,"value":23941},{"type":415,"tag":559,"props":25102,"children":25103},{"style":2846},[25104],{"type":420,"value":23920},{"type":415,"tag":559,"props":25106,"children":25107},{"style":792},[25108],{"type":420,"value":25085},{"type":415,"tag":559,"props":25110,"children":25111},{"class":561,"line":626},[25112],{"type":415,"tag":559,"props":25113,"children":25114},{"style":2846},[25115],{"type":420,"value":23957},{"type":415,"tag":416,"props":25117,"children":25118},{},[25119,25120,25125],{"type":420,"value":8781},{"type":415,"tag":555,"props":25121,"children":25123},{"className":25122},[],[25124],{"type":420,"value":24011},{"type":420,"value":25126}," utility can be used like this to send a command on the database:",{"type":415,"tag":549,"props":25128,"children":25130},{"className":8463,"code":25129,"language":248,"meta":401,"style":401},"sqlcmd -S {sqlServer.Name}.database.windows.net -d {database.Name} -U {sqlAdAdmin.UserPrincipalName} -P {sqlAdAdmin.Password} -G -l 30 -Q '___SQL Command___'\n",[25131],{"type":415,"tag":555,"props":25132,"children":25133},{"__ignoreMap":401},[25134],{"type":415,"tag":559,"props":25135,"children":25136},{"class":561,"line":562},[25137,25142,25146,25151,25155,25160,25164,25169,25173,25178,25182,25187,25191,25195,25200,25204,25209,25213,25217,25222,25226,25231,25235,25239,25244,25248,25253,25258,25262,25267,25272,25277],{"type":415,"tag":559,"props":25138,"children":25139},{"style":792},[25140],{"type":420,"value":25141},"sqlcmd ",{"type":415,"tag":559,"props":25143,"children":25144},{"style":583},[25145],{"type":420,"value":17172},{"type":415,"tag":559,"props":25147,"children":25148},{"style":792},[25149],{"type":420,"value":25150},"S ",{"type":415,"tag":559,"props":25152,"children":25153},{"style":583},[25154],{"type":420,"value":2397},{"type":415,"tag":559,"props":25156,"children":25157},{"style":792},[25158],{"type":420,"value":25159},"sqlServer.Name",{"type":415,"tag":559,"props":25161,"children":25162},{"style":583},[25163],{"type":420,"value":1580},{"type":415,"tag":559,"props":25165,"children":25166},{"style":792},[25167],{"type":420,"value":25168},".database.windows.net ",{"type":415,"tag":559,"props":25170,"children":25171},{"style":583},[25172],{"type":420,"value":17172},{"type":415,"tag":559,"props":25174,"children":25175},{"style":792},[25176],{"type":420,"value":25177},"d ",{"type":415,"tag":559,"props":25179,"children":25180},{"style":583},[25181],{"type":420,"value":2397},{"type":415,"tag":559,"props":25183,"children":25184},{"style":792},[25185],{"type":420,"value":25186},"database.Name",{"type":415,"tag":559,"props":25188,"children":25189},{"style":583},[25190],{"type":420,"value":1580},{"type":415,"tag":559,"props":25192,"children":25193},{"style":583},[25194],{"type":420,"value":8540},{"type":415,"tag":559,"props":25196,"children":25197},{"style":792},[25198],{"type":420,"value":25199},"U ",{"type":415,"tag":559,"props":25201,"children":25202},{"style":583},[25203],{"type":420,"value":2397},{"type":415,"tag":559,"props":25205,"children":25206},{"style":792},[25207],{"type":420,"value":25208},"sqlAdAdmin.UserPrincipalName",{"type":415,"tag":559,"props":25210,"children":25211},{"style":583},[25212],{"type":420,"value":1580},{"type":415,"tag":559,"props":25214,"children":25215},{"style":583},[25216],{"type":420,"value":8540},{"type":415,"tag":559,"props":25218,"children":25219},{"style":792},[25220],{"type":420,"value":25221},"P ",{"type":415,"tag":559,"props":25223,"children":25224},{"style":583},[25225],{"type":420,"value":2397},{"type":415,"tag":559,"props":25227,"children":25228},{"style":792},[25229],{"type":420,"value":25230},"sqlAdAdmin.Password",{"type":415,"tag":559,"props":25232,"children":25233},{"style":583},[25234],{"type":420,"value":1580},{"type":415,"tag":559,"props":25236,"children":25237},{"style":583},[25238],{"type":420,"value":8540},{"type":415,"tag":559,"props":25240,"children":25241},{"style":792},[25242],{"type":420,"value":25243},"G ",{"type":415,"tag":559,"props":25245,"children":25246},{"style":583},[25247],{"type":420,"value":17172},{"type":415,"tag":559,"props":25249,"children":25250},{"style":792},[25251],{"type":420,"value":25252},"l ",{"type":415,"tag":559,"props":25254,"children":25255},{"style":2846},[25256],{"type":420,"value":25257},"30",{"type":415,"tag":559,"props":25259,"children":25260},{"style":583},[25261],{"type":420,"value":8540},{"type":415,"tag":559,"props":25263,"children":25264},{"style":792},[25265],{"type":420,"value":25266},"Q ",{"type":415,"tag":559,"props":25268,"children":25269},{"style":583},[25270],{"type":420,"value":25271},"'",{"type":415,"tag":559,"props":25273,"children":25274},{"style":822},[25275],{"type":420,"value":25276},"___SQL Command___",{"type":415,"tag":559,"props":25278,"children":25279},{"style":583},[25280],{"type":420,"value":17260},{"type":415,"tag":416,"props":25282,"children":25283},{},[25284,25286,25292,25294,25299],{"type":420,"value":25285},"You can check the ",{"type":415,"tag":434,"props":25287,"children":25290},{"href":25288,"rel":25289},"https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility?view=sql-server-ver15#sqlcmd-commands",[438],[25291],{"type":420,"value":5512},{"type":420,"value":25293}," to learn more about how to use ",{"type":415,"tag":555,"props":25295,"children":25297},{"className":25296},[],[25298],{"type":420,"value":24011},{"type":420,"value":25300}," but that is quite simple: we are just specifying to send a command line query on our database using Azure Active Directory to authenticate.",{"type":415,"tag":416,"props":25302,"children":25303},{},[25304],{"type":420,"value":25305},"If we use all that with our Command provider, we get the following C# code.",{"type":415,"tag":549,"props":25307,"children":25309},{"className":551,"code":25308,"language":326,"meta":401,"style":401},"var authorizeAdGroup = new Command(\"AuthorizeAdGroup\", new CommandArgs\n{\n    Create = Output.Format($\"sqlcmd -S {sqlServer.Name}.database.windows.net -d {database.Name} -U {sqlAdAdmin.UserPrincipalName} -P {sqlAdAdmin.Password} -G -l 30 -Q 'CREATE USER {sqlDatabaseAuthorizedGroup.DisplayName} FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName}; ALTER ROLE db_datawriter ADD MEMBER {sqlDatabaseAuthorizedGroup.DisplayName};'\"),\n    Interpreter = new InputList\u003Cstring>\n    {\n        \"pwsh\",\n        \"-c\"\n    }\n});\n",[25310],{"type":415,"tag":555,"props":25311,"children":25312},{"__ignoreMap":401},[25313,25368,25375,25598,25630,25637,25658,25674,25681],{"type":415,"tag":559,"props":25314,"children":25315},{"class":561,"line":562},[25316,25320,25325,25329,25333,25338,25342,25346,25351,25355,25359,25363],{"type":415,"tag":559,"props":25317,"children":25318},{"style":572},[25319],{"type":420,"value":858},{"type":415,"tag":559,"props":25321,"children":25322},{"style":572},[25323],{"type":420,"value":25324}," authorizeAdGroup",{"type":415,"tag":559,"props":25326,"children":25327},{"style":583},[25328],{"type":420,"value":763},{"type":415,"tag":559,"props":25330,"children":25331},{"style":583},[25332],{"type":420,"value":768},{"type":415,"tag":559,"props":25334,"children":25335},{"style":572},[25336],{"type":420,"value":25337}," Command",{"type":415,"tag":559,"props":25339,"children":25340},{"style":583},[25341],{"type":420,"value":814},{"type":415,"tag":559,"props":25343,"children":25344},{"style":583},[25345],{"type":420,"value":819},{"type":415,"tag":559,"props":25347,"children":25348},{"style":822},[25349],{"type":420,"value":25350},"AuthorizeAdGroup",{"type":415,"tag":559,"props":25352,"children":25353},{"style":583},[25354],{"type":420,"value":819},{"type":415,"tag":559,"props":25356,"children":25357},{"style":583},[25358],{"type":420,"value":2312},{"type":415,"tag":559,"props":25360,"children":25361},{"style":583},[25362],{"type":420,"value":768},{"type":415,"tag":559,"props":25364,"children":25365},{"style":572},[25366],{"type":420,"value":25367}," CommandArgs\n",{"type":415,"tag":559,"props":25369,"children":25370},{"class":561,"line":589},[25371],{"type":415,"tag":559,"props":25372,"children":25373},{"style":583},[25374],{"type":420,"value":786},{"type":415,"tag":559,"props":25376,"children":25377},{"class":561,"line":608},[25378,25383,25387,25391,25395,25399,25403,25407,25412,25416,25421,25425,25429,25433,25438,25442,25446,25450,25454,25458,25463,25467,25471,25475,25479,25483,25488,25492,25496,25500,25505,25509,25514,25518,25523,25527,25531,25535,25540,25544,25548,25552,25556,25560,25565,25569,25573,25577,25581,25585,25590,25594],{"type":415,"tag":559,"props":25379,"children":25380},{"style":792},[25381],{"type":420,"value":25382},"    Create ",{"type":415,"tag":559,"props":25384,"children":25385},{"style":583},[25386],{"type":420,"value":800},{"type":415,"tag":559,"props":25388,"children":25389},{"style":792},[25390],{"type":420,"value":16679},{"type":415,"tag":559,"props":25392,"children":25393},{"style":583},[25394],{"type":420,"value":542},{"type":415,"tag":559,"props":25396,"children":25397},{"style":883},[25398],{"type":420,"value":16688},{"type":415,"tag":559,"props":25400,"children":25401},{"style":583},[25402],{"type":420,"value":814},{"type":415,"tag":559,"props":25404,"children":25405},{"style":583},[25406],{"type":420,"value":16136},{"type":415,"tag":559,"props":25408,"children":25409},{"style":822},[25410],{"type":420,"value":25411},"sqlcmd -S ",{"type":415,"tag":559,"props":25413,"children":25414},{"style":583},[25415],{"type":420,"value":2397},{"type":415,"tag":559,"props":25417,"children":25418},{"style":792},[25419],{"type":420,"value":25420},"sqlServer",{"type":415,"tag":559,"props":25422,"children":25423},{"style":583},[25424],{"type":420,"value":542},{"type":415,"tag":559,"props":25426,"children":25427},{"style":792},[25428],{"type":420,"value":1412},{"type":415,"tag":559,"props":25430,"children":25431},{"style":583},[25432],{"type":420,"value":1580},{"type":415,"tag":559,"props":25434,"children":25435},{"style":822},[25436],{"type":420,"value":25437},".database.windows.net -d ",{"type":415,"tag":559,"props":25439,"children":25440},{"style":583},[25441],{"type":420,"value":2397},{"type":415,"tag":559,"props":25443,"children":25444},{"style":792},[25445],{"type":420,"value":24182},{"type":415,"tag":559,"props":25447,"children":25448},{"style":583},[25449],{"type":420,"value":542},{"type":415,"tag":559,"props":25451,"children":25452},{"style":792},[25453],{"type":420,"value":1412},{"type":415,"tag":559,"props":25455,"children":25456},{"style":583},[25457],{"type":420,"value":1580},{"type":415,"tag":559,"props":25459,"children":25460},{"style":822},[25461],{"type":420,"value":25462}," -U ",{"type":415,"tag":559,"props":25464,"children":25465},{"style":583},[25466],{"type":420,"value":2397},{"type":415,"tag":559,"props":25468,"children":25469},{"style":792},[25470],{"type":420,"value":23095},{"type":415,"tag":559,"props":25472,"children":25473},{"style":583},[25474],{"type":420,"value":542},{"type":415,"tag":559,"props":25476,"children":25477},{"style":792},[25478],{"type":420,"value":23507},{"type":415,"tag":559,"props":25480,"children":25481},{"style":583},[25482],{"type":420,"value":1580},{"type":415,"tag":559,"props":25484,"children":25485},{"style":822},[25486],{"type":420,"value":25487}," -P ",{"type":415,"tag":559,"props":25489,"children":25490},{"style":583},[25491],{"type":420,"value":2397},{"type":415,"tag":559,"props":25493,"children":25494},{"style":792},[25495],{"type":420,"value":23095},{"type":415,"tag":559,"props":25497,"children":25498},{"style":583},[25499],{"type":420,"value":542},{"type":415,"tag":559,"props":25501,"children":25502},{"style":792},[25503],{"type":420,"value":25504},"Password",{"type":415,"tag":559,"props":25506,"children":25507},{"style":583},[25508],{"type":420,"value":1580},{"type":415,"tag":559,"props":25510,"children":25511},{"style":822},[25512],{"type":420,"value":25513}," -G -l 30 -Q 'CREATE USER ",{"type":415,"tag":559,"props":25515,"children":25516},{"style":583},[25517],{"type":420,"value":2397},{"type":415,"tag":559,"props":25519,"children":25520},{"style":792},[25521],{"type":420,"value":25522},"sqlDatabaseAuthorizedGroup",{"type":415,"tag":559,"props":25524,"children":25525},{"style":583},[25526],{"type":420,"value":542},{"type":415,"tag":559,"props":25528,"children":25529},{"style":792},[25530],{"type":420,"value":16203},{"type":415,"tag":559,"props":25532,"children":25533},{"style":583},[25534],{"type":420,"value":1580},{"type":415,"tag":559,"props":25536,"children":25537},{"style":822},[25538],{"type":420,"value":25539}," FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER ",{"type":415,"tag":559,"props":25541,"children":25542},{"style":583},[25543],{"type":420,"value":2397},{"type":415,"tag":559,"props":25545,"children":25546},{"style":792},[25547],{"type":420,"value":25522},{"type":415,"tag":559,"props":25549,"children":25550},{"style":583},[25551],{"type":420,"value":542},{"type":415,"tag":559,"props":25553,"children":25554},{"style":792},[25555],{"type":420,"value":16203},{"type":415,"tag":559,"props":25557,"children":25558},{"style":583},[25559],{"type":420,"value":1580},{"type":415,"tag":559,"props":25561,"children":25562},{"style":822},[25563],{"type":420,"value":25564},"; ALTER ROLE db_datawriter ADD MEMBER ",{"type":415,"tag":559,"props":25566,"children":25567},{"style":583},[25568],{"type":420,"value":2397},{"type":415,"tag":559,"props":25570,"children":25571},{"style":792},[25572],{"type":420,"value":25522},{"type":415,"tag":559,"props":25574,"children":25575},{"style":583},[25576],{"type":420,"value":542},{"type":415,"tag":559,"props":25578,"children":25579},{"style":792},[25580],{"type":420,"value":16203},{"type":415,"tag":559,"props":25582,"children":25583},{"style":583},[25584],{"type":420,"value":1580},{"type":415,"tag":559,"props":25586,"children":25587},{"style":822},[25588],{"type":420,"value":25589},";'",{"type":415,"tag":559,"props":25591,"children":25592},{"style":583},[25593],{"type":420,"value":819},{"type":415,"tag":559,"props":25595,"children":25596},{"style":583},[25597],{"type":420,"value":10369},{"type":415,"tag":559,"props":25599,"children":25600},{"class":561,"line":626},[25601,25606,25610,25614,25618,25622,25626],{"type":415,"tag":559,"props":25602,"children":25603},{"style":792},[25604],{"type":420,"value":25605},"    Interpreter ",{"type":415,"tag":559,"props":25607,"children":25608},{"style":583},[25609],{"type":420,"value":800},{"type":415,"tag":559,"props":25611,"children":25612},{"style":583},[25613],{"type":420,"value":768},{"type":415,"tag":559,"props":25615,"children":25616},{"style":572},[25617],{"type":420,"value":24938},{"type":415,"tag":559,"props":25619,"children":25620},{"style":583},[25621],{"type":420,"value":891},{"type":415,"tag":559,"props":25623,"children":25624},{"style":583},[25625],{"type":420,"value":2015},{"type":415,"tag":559,"props":25627,"children":25628},{"style":583},[25629],{"type":420,"value":13470},{"type":415,"tag":559,"props":25631,"children":25632},{"class":561,"line":643},[25633],{"type":415,"tag":559,"props":25634,"children":25635},{"style":583},[25636],{"type":420,"value":2737},{"type":415,"tag":559,"props":25638,"children":25639},{"class":561,"line":660},[25640,25645,25650,25654],{"type":415,"tag":559,"props":25641,"children":25642},{"style":583},[25643],{"type":420,"value":25644},"        \"",{"type":415,"tag":559,"props":25646,"children":25647},{"style":822},[25648],{"type":420,"value":25649},"pwsh",{"type":415,"tag":559,"props":25651,"children":25652},{"style":583},[25653],{"type":420,"value":819},{"type":415,"tag":559,"props":25655,"children":25656},{"style":583},[25657],{"type":420,"value":605},{"type":415,"tag":559,"props":25659,"children":25660},{"class":561,"line":677},[25661,25665,25670],{"type":415,"tag":559,"props":25662,"children":25663},{"style":583},[25664],{"type":420,"value":25644},{"type":415,"tag":559,"props":25666,"children":25667},{"style":822},[25668],{"type":420,"value":25669},"-c",{"type":415,"tag":559,"props":25671,"children":25672},{"style":583},[25673],{"type":420,"value":10222},{"type":415,"tag":559,"props":25675,"children":25676},{"class":561,"line":690},[25677],{"type":415,"tag":559,"props":25678,"children":25679},{"style":583},[25680],{"type":420,"value":2792},{"type":415,"tag":559,"props":25682,"children":25683},{"class":561,"line":1089},[25684],{"type":415,"tag":559,"props":25685,"children":25686},{"style":583},[25687],{"type":420,"value":5833},{"type":415,"tag":416,"props":25689,"children":25690},{},[25691],{"type":420,"value":25692},"As you can see, we can specify a specific interpreter to use (PowerShell here).",{"type":415,"tag":1178,"props":25694,"children":25695},{"icon":1180},[25696],{"type":415,"tag":416,"props":25697,"children":25698},{},[25699,25701,25708,25710,25716,25718,25724],{"type":420,"value":25700},"Don't do like me and forget that our variables are ",{"type":415,"tag":434,"props":25702,"children":25705},{"href":25703,"rel":25704},"https://www.pulumi.com/docs/intro/concepts/inputs-outputs/#inputs-and-outputs",[438],[25706],{"type":420,"value":25707},"outputs",{"type":420,"value":25709}," (only fully known when the infrastructure resource is completely provisioned). Because of that it is necessary to use the ",{"type":415,"tag":555,"props":25711,"children":25713},{"className":25712},[],[25714],{"type":420,"value":25715},"Output.Format",{"type":420,"value":25717}," method for string interpolation instead of using the C# operator ",{"type":415,"tag":555,"props":25719,"children":25721},{"className":25720},[],[25722],{"type":420,"value":25723},"$",{"type":420,"value":25725},". Thanks to the community on Slack for helping me on that one because with the Command provider not logging the errors details I had a hard time on this.",{"type":415,"tag":14340,"props":25727,"children":25729},{"id":25728},"results",[25730],{"type":420,"value":25731},"Results",{"type":415,"tag":416,"props":25733,"children":25734},{},[25735,25737,25742,25743,25748],{"type":420,"value":25736},"And that's it! We now have created the Azure AD group as an external user in the database and assigned it the ",{"type":415,"tag":555,"props":25738,"children":25740},{"className":25739},[],[25741],{"type":420,"value":23968},{"type":420,"value":15479},{"type":415,"tag":555,"props":25744,"children":25746},{"className":25745},[],[25747],{"type":420,"value":23975},{"type":420,"value":25749}," roles.\nHere is what it looks like in Azure Data Studio:",{"type":415,"tag":416,"props":25751,"children":25752},{},[25753],{"type":415,"tag":934,"props":25754,"children":25758},{"alt":25755,"className":25756,"src":25757},"SQL query listing database members and roles in Azure Data Studio.",[938,8504],"/posts/images/sqldatabase_ad_azuredatastudio.png",[],{"type":415,"tag":422,"props":25760,"children":25761},{"id":22538},[25762],{"type":420,"value":22541},{"type":415,"tag":416,"props":25764,"children":25765},{},[25766,25768,25774],{"type":420,"value":25767},"This article is a bit long because I explain all the steps and possibilities but the complete code is not very big or complex. You can find it in this ",{"type":415,"tag":434,"props":25769,"children":25772},{"href":25770,"rel":25771},"https://github.com/TechWatching/SqlDatabaseWithAzureAd",[438],[25773],{"type":420,"value":24077},{"type":420,"value":542},{"type":415,"tag":416,"props":25776,"children":25777},{},[25778],{"type":420,"value":25779},"I did not see that many articles on the web that talk about using Azure Active Directory authentication for an Azure SQL Database, and even less that showed how to properly configure it using Infrastructure as Code. Yet, I think it's an important thing to do to properly secure your Azure SQL database. So I hope you enjoyed it and learn something. Whether you use Azure CLI, Bicep, ARM Templates, Terraform, or Pulumi, don't hesitate to use Azure AD authentication on your Azure SQL Database, for me that is the right and secure way to go.",{"type":415,"tag":416,"props":25781,"children":25782},{},[25783],{"type":420,"value":25784},"As you have seen in this article, even when there is no provider for your custom resource or task, there are always several solutions to do what you want with Pulumi. Some are more elegant, some are more complex than others but you will always find a way and you will not be limited by the platform.",{"type":415,"tag":416,"props":25786,"children":25787},{},[25788],{"type":420,"value":25789},"A big thank you to the Pulumi community that gave me some insights on how to configure Azure AD authentication on a database properly using Pulumi. Without the help of some people in the Pulumi Slack or the GitHub Issues/Discussions I would not have been able to write this article. Indeed some ideas and solutions are directly inspired by people's answers to my questions. This article is my way of contributing back and helping others that would have similar questions.",{"type":415,"tag":5406,"props":25791,"children":25792},{},[25793],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":25795},[25796,25797,25798,25799,25805,25811],{"id":22955,"depth":589,"text":22958},{"id":23010,"depth":589,"text":23013},{"id":23326,"depth":589,"text":23329},{"id":23835,"depth":589,"text":23838,"children":25800},[25801,25802,25803],{"id":24021,"depth":608,"text":24024},{"id":24119,"depth":608,"text":24122},{"id":24331,"depth":608,"text":25804},"Command provider with the sqlcmd utility",{"id":24471,"depth":589,"text":24474,"children":25806},[25807,25808,25809,25810],{"id":24496,"depth":608,"text":24499},{"id":24793,"depth":608,"text":24796},{"id":25004,"depth":608,"text":25007},{"id":25728,"depth":608,"text":25731},{"id":22538,"depth":589,"text":22541},"content:1.posts:35.sqldatabase-active-directory-authent.md","1.posts/35.sqldatabase-active-directory-authent.md",{"_path":109,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":108,"description":25815,"lead":25816,"date":25817,"image":25818,"badge":25819,"tags":25820,"body":25821,"_type":5421,"_id":26116,"_source":5423,"_file":26117,"_extension":5425},"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":22691},{"label":22693},[272,239,349,343,352,208,206],{"type":412,"children":25822,"toc":26110},[25823,25827,25833,25879,25891,25900,25913,25922,25934,25943,25956,25962,25975,25984,25997,26003,26008,26051,26056,26065,26071,26083,26092,26106],{"type":415,"tag":416,"props":25824,"children":25825},{},[25826],{"type":420,"value":25815},{"type":415,"tag":422,"props":25828,"children":25830},{"id":25829},"net-tip-of-the-week-configuring-code-analysis-on-your-project",[25831],{"type":420,"value":25832},".NET tip of the week: configuring code analysis on your project",{"type":415,"tag":416,"props":25834,"children":25835},{},[25836,25838,25844,25846,25852,25854,25861,25863,25869,25871,25877],{"type":420,"value":25837},"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":415,"tag":555,"props":25839,"children":25841},{"className":25840},[],[25842],{"type":420,"value":25843},".editorconfig",{"type":420,"value":25845}," file. However, until I read this ",{"type":415,"tag":434,"props":25847,"children":25850},{"href":25848,"rel":25849},"https://endjin.com/blog/2022/01/raising-coding-standard-dotnet-analyzers.html",[438],[25851],{"type":420,"value":22445},{"type":420,"value":25853}," a few days ago, I did not know that you could set a ",{"type":415,"tag":434,"props":25855,"children":25858},{"href":25856,"rel":25857},"https://docs.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysismode",[438],[25859],{"type":420,"value":25860},"predefined code analysis configuration",{"type":420,"value":25862}," just by setting an ",{"type":415,"tag":555,"props":25864,"children":25866},{"className":25865},[],[25867],{"type":420,"value":25868},"AnalysisMode",{"type":420,"value":25870}," 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":415,"tag":555,"props":25872,"children":25874},{"className":25873},[],[25875],{"type":420,"value":25876},"editorconfig",{"type":420,"value":25878}," file. You can just choose the analysis mode you feel more appropriate and eventually disable a few rules that you don't want.",{"type":415,"tag":416,"props":25880,"children":25881},{},[25882,25884,25889],{"type":420,"value":25883},"For instance, in this ASP.NET Core 6 project I created from the built-in template, I added an empty interface in the ",{"type":415,"tag":555,"props":25885,"children":25887},{"className":25886},[],[25888],{"type":420,"value":2831},{"type":420,"value":25890}," file.\nBy default I see a message indicating that I should declare my interface in a namespace.",{"type":415,"tag":416,"props":25892,"children":25893},{},[25894],{"type":415,"tag":934,"props":25895,"children":25899},{"alt":25896,"className":25897,"src":25898},"Program in vscode with default analysis mode.",[938,8504],"/posts/images/w052022tips_analysismode_1.png",[],{"type":415,"tag":416,"props":25901,"children":25902},{},[25903,25905,25911],{"type":420,"value":25904},"If I set the analysis mode to ",{"type":415,"tag":555,"props":25906,"children":25908},{"className":25907},[],[25909],{"type":420,"value":25910},"Recommended",{"type":420,"value":25912},", the code analysis indicates to me the same thing but this time as a warning.",{"type":415,"tag":416,"props":25914,"children":25915},{},[25916],{"type":415,"tag":934,"props":25917,"children":25921},{"alt":25918,"className":25919,"src":25920},"Program in vscode with 'Recommended' analysis mode.",[938,8504],"/posts/images/w052022tips_analysismode_2.png",[],{"type":415,"tag":416,"props":25923,"children":25924},{},[25925,25926,25932],{"type":420,"value":25904},{"type":415,"tag":555,"props":25927,"children":25929},{"className":25928},[],[25930],{"type":420,"value":25931},"All",{"type":420,"value":25933},", 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":415,"tag":416,"props":25935,"children":25936},{},[25937],{"type":415,"tag":934,"props":25938,"children":25942},{"alt":25939,"className":25940,"src":25941},"Program in vscode with 'All' analysis mode.",[938,8504],"/posts/images/w052022tips_analysismode_3.png",[],{"type":415,"tag":416,"props":25944,"children":25945},{},[25946,25948,25954],{"type":420,"value":25947},"There are also properties to only apply rules specific to a category (security for instance). You can check the ",{"type":415,"tag":434,"props":25949,"children":25952},{"href":25950,"rel":25951},"https://docs.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysismodecategory",[438],[25953],{"type":420,"value":5512},{"type":420,"value":25955}," to learn more about these.",{"type":415,"tag":422,"props":25957,"children":25959},{"id":25958},"tool-of-the-week-crontab-guru",[25960],{"type":420,"value":25961},"Tool of the week: crontab guru",{"type":415,"tag":416,"props":25963,"children":25964},{},[25965,25967,25973],{"type":420,"value":25966},"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":415,"tag":555,"props":25968,"children":25970},{"className":25969},[],[25971],{"type":420,"value":25972},"crontab guru",{"type":420,"value":25974}," is a tool that helps you create cron schedule expressions or understand what existing cron expressions mean.",{"type":415,"tag":416,"props":25976,"children":25977},{},[25978],{"type":415,"tag":934,"props":25979,"children":25983},{"alt":25980,"className":25981,"src":25982},"Crontab Guru website.",[938,8504],"/posts/images/w052022tips_crontab_guru.png",[],{"type":415,"tag":416,"props":25985,"children":25986},{},[25987,25989,25996],{"type":420,"value":25988},"It's really helpful, so add it to your ",{"type":415,"tag":434,"props":25990,"children":25993},{"href":25991,"rel":25992},"https://crontab.guru/",[438],[25994],{"type":420,"value":25995},"bookmarks",{"type":420,"value":542},{"type":415,"tag":422,"props":25998,"children":26000},{"id":25999},"the-azure-devops-tip-you-did-not-know-about-creating-diagrams-in-markdown-with-mermaidjs",[26001],{"type":420,"value":26002},"The Azure DevOps tip you did not know about: creating diagrams in markdown with Mermaid.js",{"type":415,"tag":416,"props":26004,"children":26005},{},[26006],{"type":420,"value":26007},"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":415,"tag":416,"props":26009,"children":26010},{},[26011,26013,26019,26021,26027,26029,26034,26036,26041,26043,26050],{"type":420,"value":26012},"And guess what, that's possible thanks to ",{"type":415,"tag":555,"props":26014,"children":26016},{"className":26015},[],[26017],{"type":420,"value":26018},"Mermaid.js",{"type":420,"value":26020},". As you can read on its website, ",{"type":415,"tag":434,"props":26022,"children":26025},{"href":26023,"rel":26024},"https://mermaid-js.github.io/",[438],[26026],{"type":420,"value":26018},{"type":420,"value":26028}," 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":415,"tag":555,"props":26030,"children":26032},{"className":26031},[],[26033],{"type":420,"value":26018},{"type":420,"value":26035},". There are a lot of types of diagrams that you can create using ",{"type":415,"tag":555,"props":26037,"children":26039},{"className":26038},[],[26040],{"type":420,"value":26018},{"type":420,"value":26042}," but Azure DevOps only ",{"type":415,"tag":434,"props":26044,"children":26047},{"href":26045,"rel":26046},"https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page",[438],[26048],{"type":420,"value":26049},"supports Sequence diagrams, Gantt Charts, and Flowcharts",{"type":420,"value":542},{"type":415,"tag":416,"props":26052,"children":26053},{},[26054],{"type":420,"value":26055},"Here is an example of a diagram I created in an Azure DevOps wiki:",{"type":415,"tag":416,"props":26057,"children":26058},{},[26059],{"type":415,"tag":934,"props":26060,"children":26064},{"alt":26061,"className":26062,"src":26063},"Mermaid.js diagram in Azure DevOps wiki.",[938,8504],"/posts/images/w052022tips_mermaid_1.png",[],{"type":415,"tag":422,"props":26066,"children":26068},{"id":26067},"the-vs-code-extension-you-should-try-rest-client",[26069],{"type":420,"value":26070},"The VS Code extension you should try: Rest Client",{"type":415,"tag":416,"props":26072,"children":26073},{},[26074,26081],{"type":415,"tag":434,"props":26075,"children":26078},{"href":26076,"rel":26077},"https://github.com/Huachao/vscode-restclient",[438],[26079],{"type":420,"value":26080},"REST Client",{"type":420,"value":26082}," 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":415,"tag":416,"props":26084,"children":26085},{},[26086],{"type":415,"tag":934,"props":26087,"children":26091},{"alt":26088,"className":26089,"src":26090},"REST Client vscode extension.",[938,8504],"/posts/images/w052022tips_restclient.png",[],{"type":415,"tag":416,"props":26093,"children":26094},{},[26095,26097,26104],{"type":420,"value":26096},"In fact, it's quite funny because the ",{"type":415,"tag":434,"props":26098,"children":26101},{"href":26099,"rel":26100},"https://www.techwatching.dev/posts/testing-your-api-with-rest-client",[438],[26102],{"type":420,"value":26103},"first article",{"type":420,"value":26105}," 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":415,"tag":416,"props":26107,"children":26108},{},[26109],{"type":420,"value":22927},{"title":401,"searchDepth":589,"depth":589,"links":26111},[26112,26113,26114,26115],{"id":25829,"depth":589,"text":25832},{"id":25958,"depth":589,"text":25961},{"id":25999,"depth":589,"text":26002},{"id":26067,"depth":589,"text":26070},"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":26119,"lead":26120,"date":26121,"image":26122,"badge":26123,"tags":26124,"body":26125,"_type":5421,"_id":26544,"_source":5423,"_file":26545,"_extension":5425},".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":22691},{"label":22693},[272,239,263,343,208,346,241,206],{"type":412,"children":26126,"toc":26538},[26127,26133,26183,26192,26205,26294,26316,26322,26345,26350,26359,26365,26370,26384,26397,26410,26415,26424,26429,26434,26439,26448,26463,26469,26474,26509,26518,26530,26534],{"type":415,"tag":422,"props":26128,"children":26130},{"id":26129},"net-tip-of-the-week-the-new-way-to-add-a-configuration-source",[26131],{"type":420,"value":26132},".NET tip of the week: the new way to add a configuration source",{"type":415,"tag":416,"props":26134,"children":26135},{},[26136,26138,26144,26145,26151,26153,26159,26161,26166,26168,26173,26175,26182],{"type":420,"value":26137},".NET 6 introduced a new way to build a .NET application using the new ",{"type":415,"tag":555,"props":26139,"children":26141},{"className":26140},[],[26142],{"type":420,"value":26143},"WebApplication",{"type":420,"value":15479},{"type":415,"tag":555,"props":26146,"children":26148},{"className":26147},[],[26149],{"type":420,"value":26150},"WebApplicationBuilder",{"type":420,"value":26152}," classes. One thing I like about it is how configuration is handled. Instead of using the ",{"type":415,"tag":555,"props":26154,"children":26156},{"className":26155},[],[26157],{"type":420,"value":26158},"ConfigureAppConfiguration",{"type":420,"value":26160}," method to add a new configuration source, you can directly use the ",{"type":415,"tag":555,"props":26162,"children":26164},{"className":26163},[],[26165],{"type":420,"value":263},{"type":420,"value":26167}," property on the ",{"type":415,"tag":555,"props":26169,"children":26171},{"className":26170},[],[26172],{"type":420,"value":26150},{"type":420,"value":26174}," instance. You can see an example of this change on this screenshot of the ",{"type":415,"tag":434,"props":26176,"children":26179},{"href":26177,"rel":26178},"https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-6.0#add-configuration-providers",[438],[26180],{"type":420,"value":26181},"ASP.NET Core documentation",{"type":420,"value":1206},{"type":415,"tag":416,"props":26184,"children":26185},{},[26186],{"type":415,"tag":934,"props":26187,"children":26191},{"alt":26188,"className":26189,"src":26190},"Using configuration provider in ASP.NET 5 versus ASP.NET 6.",[938,8504],"/posts/images/w032022tips_net_configuration_1.png",[],{"type":415,"tag":416,"props":26193,"children":26194},{},[26195,26197,26203],{"type":420,"value":26196},"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":415,"tag":555,"props":26198,"children":26200},{"className":26199},[],[26201],{"type":420,"value":26202},"appsettings.Development.json",{"type":420,"value":26204}," file). Before you would have to partially build your configuration to get the value of a setting, now you can just access it.",{"type":415,"tag":549,"props":26206,"children":26208},{"className":551,"code":26207,"language":326,"meta":401,"style":401},"builder.Configuration.AddAzureKeyVault(new Uri(builder.Configuration[\"KeyVault:VaultUri\"]), new DefaultAzureCredential());\n",[26209],{"type":415,"tag":555,"props":26210,"children":26211},{"__ignoreMap":401},[26212],{"type":415,"tag":559,"props":26213,"children":26214},{"class":561,"line":562},[26215,26219,26223,26227,26231,26236,26240,26244,26248,26252,26256,26260,26264,26268,26273,26277,26282,26286,26290],{"type":415,"tag":559,"props":26216,"children":26217},{"style":792},[26218],{"type":420,"value":5671},{"type":415,"tag":559,"props":26220,"children":26221},{"style":583},[26222],{"type":420,"value":542},{"type":415,"tag":559,"props":26224,"children":26225},{"style":792},[26226],{"type":420,"value":263},{"type":415,"tag":559,"props":26228,"children":26229},{"style":583},[26230],{"type":420,"value":542},{"type":415,"tag":559,"props":26232,"children":26233},{"style":883},[26234],{"type":420,"value":26235},"AddAzureKeyVault",{"type":415,"tag":559,"props":26237,"children":26238},{"style":583},[26239],{"type":420,"value":5770},{"type":415,"tag":559,"props":26241,"children":26242},{"style":572},[26243],{"type":420,"value":809},{"type":415,"tag":559,"props":26245,"children":26246},{"style":583},[26247],{"type":420,"value":814},{"type":415,"tag":559,"props":26249,"children":26250},{"style":792},[26251],{"type":420,"value":5671},{"type":415,"tag":559,"props":26253,"children":26254},{"style":583},[26255],{"type":420,"value":542},{"type":415,"tag":559,"props":26257,"children":26258},{"style":792},[26259],{"type":420,"value":263},{"type":415,"tag":559,"props":26261,"children":26262},{"style":583},[26263],{"type":420,"value":8804},{"type":415,"tag":559,"props":26265,"children":26266},{"style":583},[26267],{"type":420,"value":819},{"type":415,"tag":559,"props":26269,"children":26270},{"style":822},[26271],{"type":420,"value":26272},"KeyVault:VaultUri",{"type":415,"tag":559,"props":26274,"children":26275},{"style":583},[26276],{"type":420,"value":819},{"type":415,"tag":559,"props":26278,"children":26279},{"style":583},[26280],{"type":420,"value":26281},"]),",{"type":415,"tag":559,"props":26283,"children":26284},{"style":583},[26285],{"type":420,"value":768},{"type":415,"tag":559,"props":26287,"children":26288},{"style":572},[26289],{"type":420,"value":5821},{"type":415,"tag":559,"props":26291,"children":26292},{"style":583},[26293],{"type":420,"value":1312},{"type":415,"tag":416,"props":26295,"children":26296},{},[26297,26299,26306,26308,26314],{"type":420,"value":26298},"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":415,"tag":434,"props":26300,"children":26303},{"href":26301,"rel":26302},"https://andrewlock.net/exploring-dotnet-6-part-1-looking-inside-configurationmanager-in-dotnet-6/",[438],[26304],{"type":420,"value":26305},"very interesting article",{"type":420,"value":26307}," about ",{"type":415,"tag":555,"props":26309,"children":26311},{"className":26310},[],[26312],{"type":420,"value":26313},"ConfigurationManager",{"type":420,"value":26315}," that I suggest you read.",{"type":415,"tag":422,"props":26317,"children":26319},{"id":26318},"the-vs-code-extension-you-should-try-vite",[26320],{"type":420,"value":26321},"The VS Code extension you should try: Vite",{"type":415,"tag":416,"props":26323,"children":26324},{},[26325,26327,26334,26336,26343],{"type":420,"value":26326},"If you are developing a front-end using Vite (and there are ",{"type":415,"tag":434,"props":26328,"children":26331},{"href":26329,"rel":26330},"https://vitejs.dev/guide/why.html",[438],[26332],{"type":420,"value":26333},"good reasons",{"type":420,"value":26335}," why you should), there is a ",{"type":415,"tag":434,"props":26337,"children":26340},{"href":26338,"rel":26339},"https://marketplace.visualstudio.com/items?itemName=antfu.vite",[438],[26341],{"type":420,"value":26342},"Vite extension for VS Code",{"type":420,"value":26344}," currently in preview.",{"type":415,"tag":416,"props":26346,"children":26347},{},[26348],{"type":420,"value":26349},"You can see the main features of this extension below: little things that make you always more productive.",{"type":415,"tag":416,"props":26351,"children":26352},{},[26353],{"type":415,"tag":934,"props":26354,"children":26358},{"alt":26355,"className":26356,"src":26357},"Vs code vite exension.",[938,8504],"/posts/images/w032022tips_vscode_vite_1.png",[],{"type":415,"tag":422,"props":26360,"children":26362},{"id":26361},"the-azure-devops-tip-you-did-not-know-about-creating-pull-requests-templates",[26363],{"type":420,"value":26364},"The Azure DevOps tip you did not know about: creating pull requests templates",{"type":415,"tag":416,"props":26366,"children":26367},{},[26368],{"type":420,"value":26369},"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":415,"tag":416,"props":26371,"children":26372},{},[26373,26375,26382],{"type":420,"value":26374},"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":415,"tag":434,"props":26376,"children":26379},{"href":26377,"rel":26378},"https://docs.microsoft.com/en-us/azure/devops/repos/git/pull-request-templates?view=azure-devops",[438],[26380],{"type":420,"value":26381},"official documentation",{"type":420,"value":26383}," but let me show you quickly how it works:",{"type":415,"tag":416,"props":26385,"children":26386},{},[26387,26389,26395],{"type":420,"value":26388},"1- You create a ",{"type":415,"tag":555,"props":26390,"children":26392},{"className":26391},[],[26393],{"type":420,"value":26394},".azuredevops",{"type":420,"value":26396}," folder in the root of your git repository",{"type":415,"tag":416,"props":26398,"children":26399},{},[26400,26402,26408],{"type":420,"value":26401},"2- You create a markdown file ",{"type":415,"tag":555,"props":26403,"children":26405},{"className":26404},[],[26406],{"type":420,"value":26407},"pull_request_template.md",{"type":420,"value":26409}," containing the description you want",{"type":415,"tag":416,"props":26411,"children":26412},{},[26413],{"type":420,"value":26414},"You can see below an example of a template I created:",{"type":415,"tag":416,"props":26416,"children":26417},{},[26418],{"type":415,"tag":934,"props":26419,"children":26423},{"alt":26420,"className":26421,"src":26422},"Pull request markdown template file.",[938,8504],"/posts/images/w032022tips_pr_template_1.png",[],{"type":415,"tag":416,"props":26425,"children":26426},{},[26427],{"type":420,"value":26428},"3- You commit this file and push it in your main branch",{"type":415,"tag":416,"props":26430,"children":26431},{},[26432],{"type":420,"value":26433},"4- Now when someone creates a pull request, he will have a pre-filled description to complete before submitting his pull request",{"type":415,"tag":416,"props":26435,"children":26436},{},[26437],{"type":420,"value":26438},"This is what it looks like for my template:",{"type":415,"tag":416,"props":26440,"children":26441},{},[26442],{"type":415,"tag":934,"props":26443,"children":26447},{"alt":26444,"className":26445,"src":26446},"Pull request template in Azure DevOps.",[938,8504],"/posts/images/w032022tips_pr_template_2.png",[],{"type":415,"tag":1178,"props":26449,"children":26450},{"icon":1180},[26451],{"type":415,"tag":416,"props":26452,"children":26453},{},[26454,26456,26462],{"type":420,"value":26455},"If you are using GitHub and not Azure DevOps, just know that there are also pull requests templates in ",{"type":415,"tag":434,"props":26457,"children":26460},{"href":26458,"rel":26459},"https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository",[438],[26461],{"type":420,"value":233},{"type":420,"value":542},{"type":415,"tag":422,"props":26464,"children":26466},{"id":26465},"tool-of-the-week-degit",[26467],{"type":420,"value":26468},"Tool of the week: degit",{"type":415,"tag":416,"props":26470,"children":26471},{},[26472],{"type":420,"value":26473},"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":415,"tag":416,"props":26475,"children":26476},{},[26477,26484,26486,26492,26494,26500,26502,26508],{"type":415,"tag":434,"props":26478,"children":26481},{"href":26479,"rel":26480},"https://github.com/Rich-Harris/degit",[438],[26482],{"type":420,"value":26483},"degit",{"type":420,"value":26485}," 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":415,"tag":555,"props":26487,"children":26489},{"className":26488},[],[26490],{"type":420,"value":26491},"npm",{"type":420,"value":26493}," tool so you can install it globally with ",{"type":415,"tag":555,"props":26495,"children":26497},{"className":26496},[],[26498],{"type":420,"value":26499},"npm install -g degit",{"type":420,"value":26501}," or directly run it using ",{"type":415,"tag":555,"props":26503,"children":26505},{"className":26504},[],[26506],{"type":420,"value":26507},"npx",{"type":420,"value":542},{"type":415,"tag":416,"props":26510,"children":26511},{},[26512],{"type":415,"tag":934,"props":26513,"children":26517},{"alt":26514,"className":26515,"src":26516},"Ouput when using degit package on a repository.",[938,8504],"/posts/images/w032022tips_degit_1.png",[],{"type":415,"tag":416,"props":26519,"children":26520},{},[26521,26523,26528],{"type":420,"value":26522},"Don't hesitate to give the project a star on ",{"type":415,"tag":434,"props":26524,"children":26526},{"href":26479,"rel":26525},[438],[26527],{"type":420,"value":233},{"type":420,"value":26529}," if you find it useful.",{"type":415,"tag":416,"props":26531,"children":26532},{},[26533],{"type":420,"value":22927},{"type":415,"tag":5406,"props":26535,"children":26536},{},[26537],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":26539},[26540,26541,26542,26543],{"id":26129,"depth":589,"text":26132},{"id":26318,"depth":589,"text":26321},{"id":26361,"depth":589,"text":26364},{"id":26465,"depth":589,"text":26468},"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":26547,"lead":26548,"date":26549,"image":26550,"badge":26551,"tags":26552,"body":26553,"_type":5421,"_id":26786,"_source":5423,"_file":26787,"_extension":5425},"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":22691},{"label":22693},[272,239,225,233,208,206],{"type":412,"children":26554,"toc":26779},[26555,26569,26575,26588,26597,26602,26614,26626,26656,26665,26671,26685,26698,26711,26720,26733,26739,26753,26762,26775],{"type":415,"tag":416,"props":26556,"children":26557},{},[26558,26560,26567],{"type":420,"value":26559},"This is my first article of the series ",{"type":415,"tag":434,"props":26561,"children":26564},{"href":26562,"rel":26563},"https://www.techwatching.dev/tags/tips-learned-this-week/",[438],[26565],{"type":420,"value":26566},"Tips I learned this week",{"type":420,"value":26568}," for 2022 🚀! And today we are going to see some tips about .NET, Azure, GitHub, and VS Code.",{"type":415,"tag":422,"props":26570,"children":26572},{"id":26571},"net-tip-of-the-week-changing-the-net-cli-language",[26573],{"type":420,"value":26574},".NET tip of the week: changing the .NET CLI language",{"type":415,"tag":416,"props":26576,"children":26577},{},[26578,26580,26586],{"type":420,"value":26579},"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":415,"tag":555,"props":26581,"children":26583},{"className":26582},[],[26584],{"type":420,"value":26585},"en",{"type":420,"value":26587}," for instance I can change it to English.",{"type":415,"tag":416,"props":26589,"children":26590},{},[26591],{"type":415,"tag":934,"props":26592,"children":26596},{"alt":26593,"className":26594,"src":26595},".NET CLI language change in terminal.",[938,8504],"/posts/images/w022022tips_dotnet_cli.png",[],{"type":415,"tag":416,"props":26598,"children":26599},{},[26600],{"type":420,"value":26601},"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":415,"tag":422,"props":26603,"children":26605},{"id":26604},"the-azure-tip-you-did-not-know-about-simplify-your-azure-cli-configuration-with-azure-init",[26606,26608],{"type":420,"value":26607},"The Azure tip you did not know about: simplify your Azure CLI configuration with ",{"type":415,"tag":555,"props":26609,"children":26611},{"className":26610},[],[26612],{"type":420,"value":26613},"azure init",{"type":415,"tag":416,"props":26615,"children":26616},{},[26617,26619,26624],{"type":420,"value":26618},"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":415,"tag":434,"props":26620,"children":26622},{"href":22988,"rel":26621},[438],[26623],{"type":420,"value":15},{"type":420,"value":26625},"\".",{"type":415,"tag":416,"props":26627,"children":26628},{},[26629,26631,26637,26639,26646,26648,26654],{"type":420,"value":26630},"However, if you want to configure your Azure CLI, it can be sometimes a bit boring and slow to configure it using the ",{"type":415,"tag":555,"props":26632,"children":26634},{"className":26633},[],[26635],{"type":420,"value":26636},"az config",{"type":420,"value":26638}," command. That is why Microsoft has ",{"type":415,"tag":434,"props":26640,"children":26643},{"href":26641,"rel":26642},"https://techcommunity.microsoft.com/t5/azure-tools-blog/streamline-configuring-azure-cli-with-az-init/ba-p/3051810",[438],[26644],{"type":420,"value":26645},"released in preview",{"type":420,"value":26647}," an Azure CLI extension called ",{"type":415,"tag":555,"props":26649,"children":26651},{"className":26650},[],[26652],{"type":420,"value":26653},"az init",{"type":420,"value":26655}," to simplify this configuration. For example you can quickly configure the output of the commands or the syntax highlighting, things like that.",{"type":415,"tag":416,"props":26657,"children":26658},{},[26659],{"type":415,"tag":934,"props":26660,"children":26664},{"alt":26661,"className":26662,"src":26663},"azure init command output.",[938,8504],"/posts/images/w022022tips_az_init.png",[],{"type":415,"tag":422,"props":26666,"children":26668},{"id":26667},"tool-of-the-week-github-code-search",[26669],{"type":420,"value":26670},"Tool of the week: GitHub Code Search",{"type":415,"tag":416,"props":26672,"children":26673},{},[26674,26676,26683],{"type":420,"value":26675},"Have you ever wished you could easily search code on GitHub in multiple repositories without cloning anything? That is now possible with ",{"type":415,"tag":434,"props":26677,"children":26680},{"href":26678,"rel":26679},"https://cs.github.com/",[438],[26681],{"type":420,"value":26682},"GitHub Code Search",{"type":420,"value":26684},". 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":415,"tag":416,"props":26686,"children":26687},{},[26688,26690,26696],{"type":420,"value":26689},"For a long time, I have kept a bookmark to the \"",{"type":415,"tag":434,"props":26691,"children":26694},{"href":26692,"rel":26693},"https://source.dot.net/",[438],[26695],{"type":420,"value":26692},{"type":420,"value":26697},"\" 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":415,"tag":416,"props":26699,"children":26700},{},[26701,26703,26709],{"type":420,"value":26702},"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":415,"tag":555,"props":26704,"children":26706},{"className":26705},[],[26707],{"type":420,"value":26708},"Host.CreateDefaultBuilder",{"type":420,"value":26710}," 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":415,"tag":416,"props":26712,"children":26713},{},[26714],{"type":415,"tag":934,"props":26715,"children":26719},{"alt":26716,"className":26717,"src":26718},"GitHub search usage.",[938,8504],"/posts/images/w022022tips_githu_cs.gif",[],{"type":415,"tag":416,"props":26721,"children":26722},{},[26723,26725,26732],{"type":420,"value":26724},"You can read more about GitHub Code Search on ",{"type":415,"tag":434,"props":26726,"children":26729},{"href":26727,"rel":26728},"https://github.blog/2021-12-08-improving-github-code-search/",[438],[26730],{"type":420,"value":26731},"GitHub's blog",{"type":420,"value":542},{"type":415,"tag":422,"props":26734,"children":26736},{"id":26735},"the-vs-code-extension-you-should-try-i18n-ally",[26737],{"type":420,"value":26738},"The VS Code extension you should try: i18n ally",{"type":415,"tag":416,"props":26740,"children":26741},{},[26742,26744,26751],{"type":420,"value":26743},"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":415,"tag":434,"props":26745,"children":26748},{"href":26746,"rel":26747},"https://github.com/lokalise/i18n-ally",[438],[26749],{"type":420,"value":26750},"i18n ally",{"type":420,"value":26752}," because it will save you a lot of time.",{"type":415,"tag":416,"props":26754,"children":26755},{},[26756],{"type":415,"tag":934,"props":26757,"children":26761},{"alt":26758,"className":26759,"src":26760},"i18n ally extension in vscode.",[938,8504],"/posts/images/w222021tips_i18n_ally.png",[],{"type":415,"tag":416,"props":26763,"children":26764},{},[26765,26767,26773],{"type":420,"value":26766},"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":415,"tag":434,"props":26768,"children":26771},{"href":26769,"rel":26770},"https://github.com/lokalise/i18n-ally/wiki/Supported-Frameworks",[438],[26772],{"type":420,"value":540},{"type":420,"value":26774},"). My only regret with this extension is not to have heard about it sooner.",{"type":415,"tag":416,"props":26776,"children":26777},{},[26778],{"type":420,"value":22927},{"title":401,"searchDepth":589,"depth":589,"links":26780},[26781,26782,26784,26785],{"id":26571,"depth":589,"text":26574},{"id":26604,"depth":589,"text":26783},"The Azure tip you did not know about: simplify your Azure CLI configuration with azure init",{"id":26667,"depth":589,"text":26670},{"id":26735,"depth":589,"text":26738},"content:1.posts:32.w02-2022-tips-learned-this-week.md","1.posts/32.w02-2022-tips-learned-this-week.md",{"_path":88,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":87,"description":26789,"lead":26790,"date":26791,"badge":26792,"image":26794,"tags":26796,"body":26797,"_type":5421,"_id":27977,"_source":5423,"_file":27978,"_extension":5425},"Today I talk to you about the recent changes I made to my blog when I migrated it to Statiq and open-sourced it.","What changed on my blog - Statiq, GitHub, giscus, and much more.","2021-11-07T00:00:00.000Z",{"label":26793},"Tooling",{"src":26795},"/images/migration_1.jpg",[331,239,233,307,334],{"type":412,"children":26798,"toc":27960},[26799,26812,26816,26821,26883,26888,26894,26900,26905,26927,26939,27016,27022,27036,27041,27047,27061,27074,27079,27088,27102,27108,27128,27141,27147,27152,27158,27163,27172,27177,27185,27199,27208,27220,27250,27256,27261,27636,27641,27647,27652,27661,27667,27679,27707,27720,27770,27779,27791,27824,27830,27844,27853,27859,27864,27934,27939,27956],{"type":415,"tag":416,"props":26800,"children":26801},{},[26802,26804,26810],{"type":420,"value":26803},"Today I talk to you about the recent changes I made to my blog when I migrated it to ",{"type":415,"tag":434,"props":26805,"children":26808},{"href":26806,"rel":26807},"https://statiq.dev/",[438],[26809],{"type":420,"value":331},{"type":420,"value":26811}," and open-sourced it.",{"type":415,"tag":422,"props":26813,"children":26814},{"id":424},[26815],{"type":420,"value":427},{"type":415,"tag":416,"props":26817,"children":26818},{},[26819],{"type":420,"value":26820},"I initially created my blog in March 2019 using:",{"type":415,"tag":5376,"props":26822,"children":26823},{},[26824,26836,26848,26859,26871],{"type":415,"tag":5380,"props":26825,"children":26826},{},[26827,26834],{"type":415,"tag":434,"props":26828,"children":26831},{"href":26829,"rel":26830},"https://github.com/Wyamio/Wyam",[438],[26832],{"type":420,"value":26833},"Wyam",{"type":420,"value":26835}," (a .NET static website generator) to generate the website",{"type":415,"tag":5380,"props":26837,"children":26838},{},[26839,26846],{"type":415,"tag":434,"props":26840,"children":26843},{"href":26841,"rel":26842},"https://azure.microsoft.com/en-us/services/devops/repos/",[438],[26844],{"type":420,"value":26845},"Azure Repos",{"type":420,"value":26847}," to store the source code on a private git repository",{"type":415,"tag":5380,"props":26849,"children":26850},{},[26851,26857],{"type":415,"tag":434,"props":26852,"children":26855},{"href":26853,"rel":26854},"https://azure.microsoft.com/en-us/services/devops/pipelines/",[438],[26856],{"type":420,"value":278},{"type":420,"value":26858}," to build and deploy the website",{"type":415,"tag":5380,"props":26860,"children":26861},{},[26862,26869],{"type":415,"tag":434,"props":26863,"children":26866},{"href":26864,"rel":26865},"https://www.netlify.com/",[438],[26867],{"type":420,"value":26868},"Netlify",{"type":420,"value":26870}," to host the website",{"type":415,"tag":5380,"props":26872,"children":26873},{},[26874,26881],{"type":415,"tag":434,"props":26875,"children":26878},{"href":26876,"rel":26877},"https://disqus.com/",[438],[26879],{"type":420,"value":26880},"Disqus",{"type":420,"value":26882}," to allow visitors to comment on my articles",{"type":415,"tag":416,"props":26884,"children":26885},{},[26886],{"type":420,"value":26887},"A little bit more than 2 years later in October 2021, everything was still working perfectly fine and I could have let everything that way. Yet, I thought some things could be improved and I wanted to change some parts of this stack.",{"type":415,"tag":422,"props":26889,"children":26891},{"id":26890},"migrating-from-wyam-to-statiq",[26892],{"type":420,"value":26893},"Migrating from Wyam to Statiq",{"type":415,"tag":14340,"props":26895,"children":26897},{"id":26896},"why",[26898],{"type":420,"value":26899},"Why?",{"type":415,"tag":416,"props":26901,"children":26902},{},[26903],{"type":420,"value":26904},"I am convinced that static website generators have a great future and are one of the best solutions for blogs #ThisIsTheWay.",{"type":415,"tag":416,"props":26906,"children":26907},{},[26908,26910,26916,26918,26925],{"type":420,"value":26909},"Although Wyam was working fine for my blog, it has been \"rebranded and rebooted as ",{"type":415,"tag":434,"props":26911,"children":26914},{"href":26912,"rel":26913},"https://www.statiq.dev/",[438],[26915],{"type":420,"value":331},{"type":420,"value":26917}," with a ton of improvements\" (as you can read on ",{"type":415,"tag":434,"props":26919,"children":26922},{"href":26920,"rel":26921},"https://wyam.io/",[438],[26923],{"type":420,"value":26924},"Wyam website",{"type":420,"value":26926},") so it made sense to migrate to use an actively maintained tool.",{"type":415,"tag":416,"props":26928,"children":26929},{},[26930,26932,26937],{"type":420,"value":26931},"I could have migrated to another static website generator (there are so many of them!) but I like using one written in .NET. If I want to customize how my website is generated, I can easily modify the code as it's .NET code. So ",{"type":415,"tag":555,"props":26933,"children":26935},{"className":26934},[],[26936],{"type":420,"value":331},{"type":420,"value":26938}," is a good choice for me.",{"type":415,"tag":1178,"props":26940,"children":26941},{"icon":1180},[26942,26961],{"type":415,"tag":416,"props":26943,"children":26944},{},[26945,26947,26952,26954,26959],{"type":420,"value":26946},"By the way, in this article when I am talking about ",{"type":415,"tag":555,"props":26948,"children":26950},{"className":26949},[],[26951],{"type":420,"value":331},{"type":420,"value":26953}," I am talking about the static site generator but technically ",{"type":415,"tag":555,"props":26955,"children":26957},{"className":26956},[],[26958],{"type":420,"value":331},{"type":420,"value":26960}," is more than that. It is a static generation platform that is divided into 3 parts:",{"type":415,"tag":5376,"props":26962,"children":26963},{},[26964,26975,26991],{"type":415,"tag":5380,"props":26965,"children":26966},{},[26967,26973],{"type":415,"tag":555,"props":26968,"children":26970},{"className":26969},[],[26971],{"type":420,"value":26972},"Statiq Framework",{"type":420,"value":26974}," ➡ a framework to build a custom static generator application",{"type":415,"tag":5380,"props":26976,"children":26977},{},[26978,26984,26986],{"type":415,"tag":555,"props":26979,"children":26981},{"className":26980},[],[26982],{"type":420,"value":26983},"Statiq Web",{"type":420,"value":26985}," ➡ a static website generation toolkit built on top of ",{"type":415,"tag":555,"props":26987,"children":26989},{"className":26988},[],[26990],{"type":420,"value":26972},{"type":415,"tag":5380,"props":26992,"children":26993},{},[26994,27000,27002,27007,27009,27015],{"type":415,"tag":555,"props":26995,"children":26997},{"className":26996},[],[26998],{"type":420,"value":26999},"Statiq Docs",{"type":420,"value":27001}," ➡ a toolkit built on top of ",{"type":415,"tag":555,"props":27003,"children":27005},{"className":27004},[],[27006],{"type":420,"value":26983},{"type":420,"value":27008}," to generate a site with .NET API documentation\nYou may not know, but the .NET Foundation website is generated using ",{"type":415,"tag":555,"props":27010,"children":27012},{"className":27011},[],[27013],{"type":420,"value":27014},"Statiq.Web",{"type":420,"value":542},{"type":415,"tag":14340,"props":27017,"children":27019},{"id":27018},"how",[27020],{"type":420,"value":27021},"How?",{"type":415,"tag":416,"props":27023,"children":27024},{},[27025,27027,27034],{"type":420,"value":27026},"Migration was quite easy (some CSS classes to replace and some configuration to change and that was it!). Statiq has a ",{"type":415,"tag":434,"props":27028,"children":27031},{"href":27029,"rel":27030},"https://www.statiq.dev/web/porting-from-wyam",[438],[27032],{"type":420,"value":27033},"page",{"type":420,"value":27035}," in its documentation to explain how to do that.",{"type":415,"tag":416,"props":27037,"children":27038},{},[27039],{"type":420,"value":27040},"The main difference is that instead of using the Wyam CLI to generate my blog from my articles in markdown and a config file, I now have a .NET console application that I run to do the same.",{"type":415,"tag":14340,"props":27042,"children":27044},{"id":27043},"what-changed",[27045],{"type":420,"value":27046},"What changed?",{"type":415,"tag":416,"props":27048,"children":27049},{},[27050,27052,27059],{"type":420,"value":27051},"Although Statiq is a reboot of Wyam, and a lot has changed internally, my blog is pretty much the same as before. Statiq comes with the theme ",{"type":415,"tag":434,"props":27053,"children":27056},{"href":27054,"rel":27055},"https://github.com/statiqdev/CleanBlog",[438],[27057],{"type":420,"value":27058},"CleanBlog",{"type":420,"value":27060}," that I was using before with Wyam so the UI looks the same. However as it uses a more recent version of the theme, the migration brought a few improvements to my blog:",{"type":415,"tag":5376,"props":27062,"children":27063},{},[27064,27069],{"type":415,"tag":5380,"props":27065,"children":27066},{},[27067],{"type":420,"value":27068},"there is now a search box to search my blog (everything is indexed so finding an article that might interest you is easier than ever)",{"type":415,"tag":5380,"props":27070,"children":27071},{},[27072],{"type":420,"value":27073},"the code highlighting is prettier than before",{"type":415,"tag":416,"props":27075,"children":27076},{},[27077],{"type":420,"value":27078},"You can see below an example of that:",{"type":415,"tag":416,"props":27080,"children":27081},{},[27082],{"type":415,"tag":934,"props":27083,"children":27087},{"alt":27084,"className":27085,"src":27086},"Screenshot of the techwatching.dev blog.",[938,8504],"/posts/images/migrating_blog_1.png",[],{"type":415,"tag":416,"props":27089,"children":27090},{},[27091,27093,27100],{"type":420,"value":27092},"I also took the opportunity of migrating my blog to correct a lot of grammar and spelling mistakes there were on my articles. To find the mistakes and correct them I used the free version of ",{"type":415,"tag":434,"props":27094,"children":27097},{"href":27095,"rel":27096},"https://www.grammarly.com/",[438],[27098],{"type":420,"value":27099},"Grammarly",{"type":420,"value":27101}," and I was surprised by how good it was. I intend to use it to write my future articles and I strongly recommend it to you. It is especially useful to me as I am not an English native speaker. Of course, I am not saying there will be no mistake in my articles but I should catch most of them with Grammarly.",{"type":415,"tag":422,"props":27103,"children":27105},{"id":27104},"open-sourcing-my-blog",[27106],{"type":420,"value":27107},"Open-sourcing my blog",{"type":415,"tag":416,"props":27109,"children":27110},{},[27111,27113,27119,27121,27127],{"type":420,"value":27112},"People interested in creating their blog sometimes ask me what stack I used to build my blog. So I thought open-sourcing my blog would be a great way to answer this question and show exactly how this blog is built. If you are a .NET developer and want to create your blog, I strongly recommend you to use ",{"type":415,"tag":434,"props":27114,"children":27117},{"href":27115,"rel":27116},"https://www.statiq.dev/web/",[438],[27118],{"type":420,"value":26983},{"type":420,"value":27120},". You can get started by following the documentation, it is very easy. And now, you have an example of a blog using Statiq that you can look at ",{"type":415,"tag":434,"props":27122,"children":27125},{"href":27123,"rel":27124},"https://github.com/techwatching/techwatching.dev",[438],[27126],{"type":420,"value":540},{"type":420,"value":542},{"type":415,"tag":416,"props":27129,"children":27130},{},[27131,27133,27139],{"type":420,"value":27132},"I am often a consumer of open source code (as we all are these days) so it feels great to be a contributor this time by sharing the source code of my blog (even if there is currently not much customization). I don't expect many people to look at it but at least it's ",{"type":415,"tag":434,"props":27134,"children":27136},{"href":27123,"rel":27135},[438],[27137],{"type":420,"value":27138},"there",{"type":420,"value":27140}," if you care.",{"type":415,"tag":422,"props":27142,"children":27144},{"id":27143},"all-in-on-github",[27145],{"type":420,"value":27146},"All-in on GitHub",{"type":415,"tag":416,"props":27148,"children":27149},{},[27150],{"type":420,"value":27151},"GitHub is one of the best platforms for open source projects. But whether it be for open source or proprietary software, GitHub is above all a great development platform to build, ship, and maintain software. I am more familiar with Azure DevOps which is a great platform too and that I use at work but using GitHub was the opportunity to learn new things. Therefore, I decided to migrate to GitHub for my blog and not only for hosting the code.",{"type":415,"tag":14340,"props":27153,"children":27155},{"id":27154},"hosting-the-source-code-of-my-blog",[27156],{"type":420,"value":27157},"Hosting the source code of my blog",{"type":415,"tag":416,"props":27159,"children":27160},{},[27161],{"type":420,"value":27162},"Speaking of hosting the code, here is my new git repository on GitHub:",{"type":415,"tag":416,"props":27164,"children":27165},{},[27166],{"type":415,"tag":934,"props":27167,"children":27171},{"alt":27168,"className":27169,"src":27170},"Techwatching.dev GitHub repository.",[938,8504],"/posts/images/migrating_blog_2.png",[],{"type":415,"tag":416,"props":27173,"children":27174},{},[27175],{"type":420,"value":27176},"To move my code to GitHub, I just created a new git repository in GitHub and copy-pasted my code there. Adding GitHub as a new remote of my repository could have been a better way to migrate my code to GitHub while preserving the commit history. However, I did not care about history and took the opportunity to reorganize my code.",{"type":415,"tag":1178,"props":27178,"children":27179},{"icon":1180},[27180],{"type":415,"tag":416,"props":27181,"children":27182},{},[27183],{"type":420,"value":27184},"I know that it is possible to have public projects/git repositories in Azure DevOps so I could have kept my code there, but as I said, moving to GitHub to store my code was a choice.",{"type":415,"tag":416,"props":27186,"children":27187},{},[27188,27190,27197],{"type":420,"value":27189},"And now that my git repository is on GitHub, I can use the ",{"type":415,"tag":434,"props":27191,"children":27194},{"href":27192,"rel":27193},"https://docs.github.com/en/codespaces/the-githubdev-web-based-editor",[438],[27195],{"type":420,"value":27196},"github.dev",{"type":420,"value":27198}," web-based editor to modify my repository directly in the browser. How cool is that?",{"type":415,"tag":416,"props":27200,"children":27201},{},[27202],{"type":415,"tag":934,"props":27203,"children":27207},{"alt":27204,"className":27205,"src":27206},"Blog in github.dev editor.",[938,8504],"/posts/images/migrating_blog_3.png",[],{"type":415,"tag":416,"props":27209,"children":27210},{},[27211,27213,27218],{"type":420,"value":27212},"I don't know if I will use ",{"type":415,"tag":555,"props":27214,"children":27216},{"className":27215},[],[27217],{"type":420,"value":27196},{"type":420,"value":27219}," a lot but I like the fact of being able to work on my blog from any computer without having to install anything.",{"type":415,"tag":1178,"props":27221,"children":27222},{"icon":5363},[27223],{"type":415,"tag":416,"props":27224,"children":27225},{},[27226,27228,27233,27235,27241,27243,27248],{"type":420,"value":27227},"If you never heard of github.dev, simply go to any GitHub repository in your favorite web browser and press ",{"type":415,"tag":555,"props":27229,"children":27231},{"className":27230},[],[27232],{"type":420,"value":542},{"type":420,"value":27234}," to open this repository in a vscode-like editor that runs entirely in your browser. You can also replace ",{"type":415,"tag":555,"props":27236,"children":27238},{"className":27237},[],[27239],{"type":420,"value":27240},"github.com",{"type":420,"value":27242}," with ",{"type":415,"tag":555,"props":27244,"children":27246},{"className":27245},[],[27247],{"type":420,"value":27196},{"type":420,"value":27249}," in the URL to open it. It even works on your mobile although I don't find it very convenient.",{"type":415,"tag":14340,"props":27251,"children":27253},{"id":27252},"building-and-deploying-my-blog",[27254],{"type":420,"value":27255},"Building and deploying my blog",{"type":415,"tag":416,"props":27257,"children":27258},{},[27259],{"type":420,"value":27260},"Coming from Azure DevOps, moving from Azure Pipelines to GitHub Actions was not a big deal. What changed however is that my pipeline doesn't need to install any specific CLI to build and deploy my blog. Indeed, with Statiq my blog is a .NET console application, so my site can be generated directly with the .NET CLI. Statiq as built-in support for deploying a website on different platforms including Netlify thus my pipeline to generate and deploy my site is quite simple:",{"type":415,"tag":549,"props":27262,"children":27266},{"className":27263,"code":27264,"language":27265,"meta":401,"style":401},"language-yml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","name: Deploy Blog to Netlify\n\non:\n  push:\n    branches: \n      - main\n  schedule:\n  - cron: \"0 5 * * *\"\n\njobs:\n  build:\n    runs-on: windows-latest\n    steps:\n    - uses: actions/checkout@v2\n      with:\n        ref: main\n        submodules: recursive\n    - uses: actions/setup-dotnet@v1\n      with:\n        dotnet-version: '5.0.x'\n    - run: dotnet run -c Release -- deploy\n      env:\n        NetlifySiteId: ${{ secrets.NetlifySiteId }}\n        NetlifyAccessToken: ${{ secrets.NetlifyAccessToken }}\n","yml",[27267],{"type":415,"tag":555,"props":27268,"children":27269},{"__ignoreMap":401},[27270,27286,27293,27305,27317,27333,27345,27357,27386,27393,27405,27417,27434,27446,27468,27480,27496,27513,27533,27544,27569,27590,27602,27619],{"type":415,"tag":559,"props":27271,"children":27272},{"class":561,"line":562},[27273,27277,27281],{"type":415,"tag":559,"props":27274,"children":27275},{"style":8631},[27276],{"type":420,"value":24207},{"type":415,"tag":559,"props":27278,"children":27279},{"style":583},[27280],{"type":420,"value":1206},{"type":415,"tag":559,"props":27282,"children":27283},{"style":822},[27284],{"type":420,"value":27285}," Deploy Blog to Netlify\n",{"type":415,"tag":559,"props":27287,"children":27288},{"class":561,"line":589},[27289],{"type":415,"tag":559,"props":27290,"children":27291},{"emptyLinePlaceholder":847},[27292],{"type":420,"value":850},{"type":415,"tag":559,"props":27294,"children":27295},{"class":561,"line":608},[27296,27301],{"type":415,"tag":559,"props":27297,"children":27298},{"style":6887},[27299],{"type":420,"value":27300},"on",{"type":415,"tag":559,"props":27302,"children":27303},{"style":583},[27304],{"type":420,"value":17118},{"type":415,"tag":559,"props":27306,"children":27307},{"class":561,"line":626},[27308,27313],{"type":415,"tag":559,"props":27309,"children":27310},{"style":8631},[27311],{"type":420,"value":27312},"  push",{"type":415,"tag":559,"props":27314,"children":27315},{"style":583},[27316],{"type":420,"value":17118},{"type":415,"tag":559,"props":27318,"children":27319},{"class":561,"line":643},[27320,27325,27329],{"type":415,"tag":559,"props":27321,"children":27322},{"style":8631},[27323],{"type":420,"value":27324},"    branches",{"type":415,"tag":559,"props":27326,"children":27327},{"style":583},[27328],{"type":420,"value":1206},{"type":415,"tag":559,"props":27330,"children":27331},{"style":792},[27332],{"type":420,"value":1473},{"type":415,"tag":559,"props":27334,"children":27335},{"class":561,"line":660},[27336,27341],{"type":415,"tag":559,"props":27337,"children":27338},{"style":583},[27339],{"type":420,"value":27340},"      -",{"type":415,"tag":559,"props":27342,"children":27343},{"style":822},[27344],{"type":420,"value":17131},{"type":415,"tag":559,"props":27346,"children":27347},{"class":561,"line":677},[27348,27353],{"type":415,"tag":559,"props":27349,"children":27350},{"style":8631},[27351],{"type":420,"value":27352},"  schedule",{"type":415,"tag":559,"props":27354,"children":27355},{"style":583},[27356],{"type":420,"value":17118},{"type":415,"tag":559,"props":27358,"children":27359},{"class":561,"line":690},[27360,27364,27369,27373,27377,27382],{"type":415,"tag":559,"props":27361,"children":27362},{"style":583},[27363],{"type":420,"value":17126},{"type":415,"tag":559,"props":27365,"children":27366},{"style":8631},[27367],{"type":420,"value":27368}," cron",{"type":415,"tag":559,"props":27370,"children":27371},{"style":583},[27372],{"type":420,"value":1206},{"type":415,"tag":559,"props":27374,"children":27375},{"style":583},[27376],{"type":420,"value":1434},{"type":415,"tag":559,"props":27378,"children":27379},{"style":822},[27380],{"type":420,"value":27381},"0 5 * * *",{"type":415,"tag":559,"props":27383,"children":27384},{"style":583},[27385],{"type":420,"value":10222},{"type":415,"tag":559,"props":27387,"children":27388},{"class":561,"line":1089},[27389],{"type":415,"tag":559,"props":27390,"children":27391},{"emptyLinePlaceholder":847},[27392],{"type":420,"value":850},{"type":415,"tag":559,"props":27394,"children":27395},{"class":561,"line":1102},[27396,27401],{"type":415,"tag":559,"props":27397,"children":27398},{"style":8631},[27399],{"type":420,"value":27400},"jobs",{"type":415,"tag":559,"props":27402,"children":27403},{"style":583},[27404],{"type":420,"value":17118},{"type":415,"tag":559,"props":27406,"children":27407},{"class":561,"line":1110},[27408,27413],{"type":415,"tag":559,"props":27409,"children":27410},{"style":8631},[27411],{"type":420,"value":27412},"  build",{"type":415,"tag":559,"props":27414,"children":27415},{"style":583},[27416],{"type":420,"value":17118},{"type":415,"tag":559,"props":27418,"children":27419},{"class":561,"line":1118},[27420,27425,27429],{"type":415,"tag":559,"props":27421,"children":27422},{"style":8631},[27423],{"type":420,"value":27424},"    runs-on",{"type":415,"tag":559,"props":27426,"children":27427},{"style":583},[27428],{"type":420,"value":1206},{"type":415,"tag":559,"props":27430,"children":27431},{"style":822},[27432],{"type":420,"value":27433}," windows-latest\n",{"type":415,"tag":559,"props":27435,"children":27436},{"class":561,"line":1171},[27437,27442],{"type":415,"tag":559,"props":27438,"children":27439},{"style":8631},[27440],{"type":420,"value":27441},"    steps",{"type":415,"tag":559,"props":27443,"children":27444},{"style":583},[27445],{"type":420,"value":17118},{"type":415,"tag":559,"props":27447,"children":27448},{"class":561,"line":1748},[27449,27454,27459,27463],{"type":415,"tag":559,"props":27450,"children":27451},{"style":583},[27452],{"type":420,"value":27453},"    -",{"type":415,"tag":559,"props":27455,"children":27456},{"style":8631},[27457],{"type":420,"value":27458}," uses",{"type":415,"tag":559,"props":27460,"children":27461},{"style":583},[27462],{"type":420,"value":1206},{"type":415,"tag":559,"props":27464,"children":27465},{"style":822},[27466],{"type":420,"value":27467}," actions/checkout@v2\n",{"type":415,"tag":559,"props":27469,"children":27470},{"class":561,"line":1769},[27471,27476],{"type":415,"tag":559,"props":27472,"children":27473},{"style":8631},[27474],{"type":420,"value":27475},"      with",{"type":415,"tag":559,"props":27477,"children":27478},{"style":583},[27479],{"type":420,"value":17118},{"type":415,"tag":559,"props":27481,"children":27482},{"class":561,"line":1786},[27483,27488,27492],{"type":415,"tag":559,"props":27484,"children":27485},{"style":8631},[27486],{"type":420,"value":27487},"        ref",{"type":415,"tag":559,"props":27489,"children":27490},{"style":583},[27491],{"type":420,"value":1206},{"type":415,"tag":559,"props":27493,"children":27494},{"style":822},[27495],{"type":420,"value":17131},{"type":415,"tag":559,"props":27497,"children":27498},{"class":561,"line":1795},[27499,27504,27508],{"type":415,"tag":559,"props":27500,"children":27501},{"style":8631},[27502],{"type":420,"value":27503},"        submodules",{"type":415,"tag":559,"props":27505,"children":27506},{"style":583},[27507],{"type":420,"value":1206},{"type":415,"tag":559,"props":27509,"children":27510},{"style":822},[27511],{"type":420,"value":27512}," recursive\n",{"type":415,"tag":559,"props":27514,"children":27515},{"class":561,"line":3289},[27516,27520,27524,27528],{"type":415,"tag":559,"props":27517,"children":27518},{"style":583},[27519],{"type":420,"value":27453},{"type":415,"tag":559,"props":27521,"children":27522},{"style":8631},[27523],{"type":420,"value":27458},{"type":415,"tag":559,"props":27525,"children":27526},{"style":583},[27527],{"type":420,"value":1206},{"type":415,"tag":559,"props":27529,"children":27530},{"style":822},[27531],{"type":420,"value":27532}," actions/setup-dotnet@v1\n",{"type":415,"tag":559,"props":27534,"children":27535},{"class":561,"line":3297},[27536,27540],{"type":415,"tag":559,"props":27537,"children":27538},{"style":8631},[27539],{"type":420,"value":27475},{"type":415,"tag":559,"props":27541,"children":27542},{"style":583},[27543],{"type":420,"value":17118},{"type":415,"tag":559,"props":27545,"children":27546},{"class":561,"line":3349},[27547,27552,27556,27560,27565],{"type":415,"tag":559,"props":27548,"children":27549},{"style":8631},[27550],{"type":420,"value":27551},"        dotnet-version",{"type":415,"tag":559,"props":27553,"children":27554},{"style":583},[27555],{"type":420,"value":1206},{"type":415,"tag":559,"props":27557,"children":27558},{"style":583},[27559],{"type":420,"value":17251},{"type":415,"tag":559,"props":27561,"children":27562},{"style":822},[27563],{"type":420,"value":27564},"5.0.x",{"type":415,"tag":559,"props":27566,"children":27567},{"style":583},[27568],{"type":420,"value":17260},{"type":415,"tag":559,"props":27570,"children":27571},{"class":561,"line":3374},[27572,27576,27581,27585],{"type":415,"tag":559,"props":27573,"children":27574},{"style":583},[27575],{"type":420,"value":27453},{"type":415,"tag":559,"props":27577,"children":27578},{"style":8631},[27579],{"type":420,"value":27580}," run",{"type":415,"tag":559,"props":27582,"children":27583},{"style":583},[27584],{"type":420,"value":1206},{"type":415,"tag":559,"props":27586,"children":27587},{"style":822},[27588],{"type":420,"value":27589}," dotnet run -c Release -- deploy\n",{"type":415,"tag":559,"props":27591,"children":27592},{"class":561,"line":3382},[27593,27598],{"type":415,"tag":559,"props":27594,"children":27595},{"style":8631},[27596],{"type":420,"value":27597},"      env",{"type":415,"tag":559,"props":27599,"children":27600},{"style":583},[27601],{"type":420,"value":17118},{"type":415,"tag":559,"props":27603,"children":27604},{"class":561,"line":3390},[27605,27610,27614],{"type":415,"tag":559,"props":27606,"children":27607},{"style":8631},[27608],{"type":420,"value":27609},"        NetlifySiteId",{"type":415,"tag":559,"props":27611,"children":27612},{"style":583},[27613],{"type":420,"value":1206},{"type":415,"tag":559,"props":27615,"children":27616},{"style":822},[27617],{"type":420,"value":27618}," ${{ secrets.NetlifySiteId }}\n",{"type":415,"tag":559,"props":27620,"children":27621},{"class":561,"line":3434},[27622,27627,27631],{"type":415,"tag":559,"props":27623,"children":27624},{"style":8631},[27625],{"type":420,"value":27626},"        NetlifyAccessToken",{"type":415,"tag":559,"props":27628,"children":27629},{"style":583},[27630],{"type":420,"value":1206},{"type":415,"tag":559,"props":27632,"children":27633},{"style":822},[27634],{"type":420,"value":27635}," ${{ secrets.NetlifyAccessToken }}\n",{"type":415,"tag":416,"props":27637,"children":27638},{},[27639],{"type":420,"value":27640},"This pipeline runs every day and each time something is merged on my main branch. This way my website is redeployed when I publish a new article (which generally corresponds to a commit being made on the main branch through the merge of the branch where I was writing the article). This also allows me to finalize an article but publish it at a future date without having to take care of it.",{"type":415,"tag":14340,"props":27642,"children":27644},{"id":27643},"hosting-my-website",[27645],{"type":420,"value":27646},"Hosting my website",{"type":415,"tag":416,"props":27648,"children":27649},{},[27650],{"type":420,"value":27651},"This is the only part where I did not really go all-in on GitHub as I did not use GitHub Pages to host my blog, I kept Netlify. I am happy with it, it does the job, costs me nothing, and allows me to have previews of my blog if I want to so there was no reason to change.",{"type":415,"tag":416,"props":27653,"children":27654},{},[27655],{"type":415,"tag":934,"props":27656,"children":27660},{"alt":27657,"className":27658,"src":27659},"Netlify dashboard the blog.",[938,8504],"/posts/images/migrating_blog_4.png",[],{"type":415,"tag":14340,"props":27662,"children":27664},{"id":27663},"providing-a-comments-system",[27665],{"type":420,"value":27666},"Providing a comments system",{"type":415,"tag":416,"props":27668,"children":27669},{},[27670,27672,27677],{"type":420,"value":27671},"I was previously using the well-known comments system ",{"type":415,"tag":434,"props":27673,"children":27675},{"href":26876,"rel":27674},[438],[27676],{"type":420,"value":26880},{"type":420,"value":27678}," to let readers of my blog comment on the articles. To be honest, it works well, has a lot of features (moderation, monitoring...), and is used on many blogs. However, I have always found it a bit complex for my needs and was annoyed to \"force\" my readers to create a Disqus account to write comments. So when I read articles of people complaining about Disqus ads, tracking and performance issues I knew it was time to find an alternative.",{"type":415,"tag":416,"props":27680,"children":27681},{},[27682,27684,27691,27693,27699,27700,27705],{"type":420,"value":27683},"And there are many alternatives to Disqus! But one I found very interesting was ",{"type":415,"tag":434,"props":27685,"children":27688},{"href":27686,"rel":27687},"https://utteranc.es/",[438],[27689],{"type":420,"value":27690},"utterances",{"type":420,"value":27692},", a GitHub application that relies on GitHub issues to store blog comments. As the creator of this library explains ",{"type":415,"tag":434,"props":27694,"children":27697},{"href":27695,"rel":27696},"https://danyow.net/using-github-issues-for-blog-comments/",[438],[27698],{"type":420,"value":540},{"type":420,"value":14095},{"type":415,"tag":555,"props":27701,"children":27703},{"className":27702},[],[27704],{"type":420,"value":27690},{"type":420,"value":27706}," served as a POC for the GitHub-based feedback system in Microsoft Docs. I thought using GitHub issues for the comments of my blog was awesome because:",{"type":415,"tag":5376,"props":27708,"children":27709},{},[27710,27715],{"type":415,"tag":5380,"props":27711,"children":27712},{},[27713],{"type":420,"value":27714},"my readers will not have to create an account to write comments, my readers are developers so they probably already have a GitHub account",{"type":415,"tag":5380,"props":27716,"children":27717},{},[27718],{"type":420,"value":27719},"with comments stored as GitHub issues on my GitHub repository, I have everything at the same place (code, pipelines, and comments)",{"type":415,"tag":416,"props":27721,"children":27722},{},[27723,27725,27730,27732,27739,27741,27746,27748,27755,27757,27762,27764,27769],{"type":420,"value":27724},"But you know what? I finally did not choose ",{"type":415,"tag":555,"props":27726,"children":27728},{"className":27727},[],[27729],{"type":420,"value":27690},{"type":420,"value":27731}," as the comments system for my blog 😀. Instead, I chose to use ",{"type":415,"tag":434,"props":27733,"children":27736},{"href":27734,"rel":27735},"https://giscus.app/",[438],[27737],{"type":420,"value":27738},"giscus",{"type":420,"value":27740}," which is similar to ",{"type":415,"tag":555,"props":27742,"children":27744},{"className":27743},[],[27745],{"type":420,"value":27690},{"type":420,"value":27747}," (in fact it is heavily based on it) but stores comments in ",{"type":415,"tag":434,"props":27749,"children":27752},{"href":27750,"rel":27751},"https://docs.github.com/en/discussions",[438],[27753],{"type":420,"value":27754},"GitHub Discussions",{"type":420,"value":27756},". GitHub Discussions did not exist when ",{"type":415,"tag":555,"props":27758,"children":27760},{"className":27759},[],[27761],{"type":420,"value":27690},{"type":420,"value":27763}," was created but I think discussions are a much more appropriate place than GitHub issues to store comments, that's why I chose it. Apart from that, advantages are the same as ",{"type":415,"tag":555,"props":27765,"children":27767},{"className":27766},[],[27768],{"type":420,"value":27690},{"type":420,"value":542},{"type":415,"tag":416,"props":27771,"children":27772},{},[27773],{"type":415,"tag":934,"props":27774,"children":27778},{"alt":27775,"className":27776,"src":27777},"Comment on the blog using discuss.",[938,8504],"/posts/images/migrating_blog_5.png",[],{"type":415,"tag":416,"props":27780,"children":27781},{},[27782,27784,27789],{"type":420,"value":27783},"If you don't have a comments system on your blog yet or that your current one does not satisfy you, you should check ",{"type":415,"tag":434,"props":27785,"children":27787},{"href":27734,"rel":27786},[438],[27788],{"type":420,"value":27738},{"type":420,"value":27790},", I am very happy with it.",{"type":415,"tag":1178,"props":27792,"children":27793},{"icon":1180},[27794],{"type":415,"tag":416,"props":27795,"children":27796},{},[27797,27799,27804,27806,27813,27815,27822],{"type":420,"value":27798},"If you are currently using Disqus and want to migrate to ",{"type":415,"tag":555,"props":27800,"children":27802},{"className":27801},[],[27803],{"type":420,"value":27738},{"type":420,"value":27805}," (while preserving your existing comments), the easiest way I found was to export the Disqus comments in a file, use this ",{"type":415,"tag":434,"props":27807,"children":27810},{"href":27808,"rel":27809},"https://github.com/JuergenGutsch/disqus-to-github-issues",[438],[27811],{"type":420,"value":27812},"tool",{"type":420,"value":27814}," on GitHub to convert them into issues, and manually convert existing issues to discussions on each issue page. You can read this ",{"type":415,"tag":434,"props":27816,"children":27819},{"href":27817,"rel":27818},"https://ljvmiranda921.github.io/notebook/2021/03/26/migrating-from-disqus-to-utterances/",[438],[27820],{"type":420,"value":27821},"blog post",{"type":420,"value":27823}," that partially explains how to do that.",{"type":415,"tag":14340,"props":27825,"children":27827},{"id":27826},"managing-my-blog-as-a-project",[27828],{"type":420,"value":27829},"Managing my blog as a project",{"type":415,"tag":416,"props":27831,"children":27832},{},[27833,27835,27842],{"type":420,"value":27834},"My blog is not very hard to manage but there are always things to do or think about: improvements to do, articles to write, ideas to find. Instead of writing that down on my ToDo app or my OneNote as I used to do, I decided to use the ",{"type":415,"tag":434,"props":27836,"children":27839},{"href":27837,"rel":27838},"https://github.com/features/issues/",[438],[27840],{"type":420,"value":27841},"GitHub Issues beta",{"type":420,"value":27843}," that allows you to create a \"project\" with a backlog, boards, and issues that can be categorized with custom fields.",{"type":415,"tag":416,"props":27845,"children":27846},{},[27847],{"type":415,"tag":934,"props":27848,"children":27852},{"alt":27849,"className":27850,"src":27851},"Github project for the blog.",[938,8504],"/posts/images/migrating_blog_6.png",[],{"type":415,"tag":422,"props":27854,"children":27856},{"id":27855},"summary",[27857],{"type":420,"value":27858},"Summary",{"type":415,"tag":416,"props":27860,"children":27861},{},[27862],{"type":420,"value":27863},"In this article, I talked to you about what changed on my blog, and what my new stack is:",{"type":415,"tag":5376,"props":27865,"children":27866},{},[27867,27877,27888,27898,27909,27925],{"type":415,"tag":5380,"props":27868,"children":27869},{},[27870,27875],{"type":415,"tag":434,"props":27871,"children":27873},{"href":27115,"rel":27872},[438],[27874],{"type":420,"value":331},{"type":420,"value":27876}," a .NET static website generator to generate the website",{"type":415,"tag":5380,"props":27878,"children":27879},{},[27880,27886],{"type":415,"tag":434,"props":27881,"children":27884},{"href":27882,"rel":27883},"https://github.com/",[438],[27885],{"type":420,"value":233},{"type":420,"value":27887}," to store the source code on a public (open source) git repository",{"type":415,"tag":5380,"props":27889,"children":27890},{},[27891,27897],{"type":415,"tag":434,"props":27892,"children":27895},{"href":27893,"rel":27894},"https://github.com/features/actions",[438],[27896],{"type":420,"value":307},{"type":420,"value":26858},{"type":415,"tag":5380,"props":27899,"children":27900},{},[27901,27907],{"type":415,"tag":434,"props":27902,"children":27904},{"href":27837,"rel":27903},[438],[27905],{"type":420,"value":27906},"GitHub Issues (beta)",{"type":420,"value":27908}," to manage my ideas for the blog",{"type":415,"tag":5380,"props":27910,"children":27911},{},[27912,27917,27918,27923],{"type":415,"tag":434,"props":27913,"children":27915},{"href":27750,"rel":27914},[438],[27916],{"type":420,"value":27754},{"type":420,"value":27242},{"type":415,"tag":434,"props":27919,"children":27921},{"href":27734,"rel":27920},[438],[27922],{"type":420,"value":27738},{"type":420,"value":27924}," to allow visitors to comment my articles",{"type":415,"tag":5380,"props":27926,"children":27927},{},[27928,27933],{"type":415,"tag":434,"props":27929,"children":27931},{"href":26864,"rel":27930},[438],[27932],{"type":420,"value":26868},{"type":420,"value":26870},{"type":415,"tag":416,"props":27935,"children":27936},{},[27937],{"type":420,"value":27938},"I like this new stack where most things are centralized in one place: GitHub. I own the content of this blog, but I love that code to generate this blog is open source. There is still plenty of room for improvement on my blog, but I am confident Statiq will help me to continue customizing my blog easily. I hope you liked this article, do not hesitate to comment (you now know how comments work behind the scenes 😀).",{"type":415,"tag":1178,"props":27940,"children":27941},{"icon":1180},[27942],{"type":415,"tag":416,"props":27943,"children":27944},{},[27945,27947,27954],{"type":420,"value":27946},"If you are reading this article from hashnode or dev.to and not directly on my ",{"type":415,"tag":434,"props":27948,"children":27951},{"href":27949,"rel":27950},"https://techwatching.dev",[438],[27952],{"type":420,"value":27953},"blog",{"type":420,"value":27955},", these changes do not apply to you. But do not worry, I will continue to cross-post my articles on these platforms too which have great communities.",{"type":415,"tag":5406,"props":27957,"children":27958},{},[27959],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":27961},[27962,27963,27968,27969,27976],{"id":424,"depth":589,"text":427},{"id":26890,"depth":589,"text":26893,"children":27964},[27965,27966,27967],{"id":26896,"depth":608,"text":26899},{"id":27018,"depth":608,"text":27021},{"id":27043,"depth":608,"text":27046},{"id":27104,"depth":589,"text":27107},{"id":27143,"depth":589,"text":27146,"children":27970},[27971,27972,27973,27974,27975],{"id":27154,"depth":608,"text":27157},{"id":27252,"depth":608,"text":27255},{"id":27643,"depth":608,"text":27646},{"id":27663,"depth":608,"text":27666},{"id":27826,"depth":608,"text":27829},{"id":27855,"depth":589,"text":27858},"content:1.posts:27.migrating-blog.md","1.posts/27.migrating-blog.md",{"_path":22,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":21,"description":27980,"lead":27981,"date":27982,"image":27983,"badge":27985,"tags":27986,"body":27987,"_type":5421,"_id":31813,"_source":5423,"_file":31814,"_extension":5425},"In our daily job, we often have to query secure REST APIs that require our HTTP requests to have a valid access token in their Authorization header.\nOf course, many APIs come with an SDK that makes the job easier for us as it directly takes care of retrieving a token and sending the authenticated HTTP requests.\nHowever, it is not always the case and knowing how to implement that using HttpClient, IMemoryCache, and DelegatingHandler can become pretty useful.","Using a DelegatingHandler","2020-01-29T00:00:00.000Z",{"src":27984},"/images/keyboard_1.jpg",{"label":408},[213,210,236,239],{"type":412,"children":27988,"toc":31806},[27989,27993,27999,28004,28013,28047,28052,28090,28194,28206,28211,28441,28459,28578,28590,28596,28622,29723,29728,29763,29769,29810,30460,30480,30486,30525,30558,30570,30938,30943,31467,31480,31793,31797,31802],{"type":415,"tag":416,"props":27990,"children":27991},{},[27992],{"type":420,"value":27980},{"type":415,"tag":422,"props":27994,"children":27996},{"id":27995},"context",[27997],{"type":420,"value":27998},"Context",{"type":415,"tag":416,"props":28000,"children":28001},{},[28002],{"type":420,"value":28003},"Let's imagine we have a very simple API that contains the following routes :",{"type":415,"tag":416,"props":28005,"children":28006},{},[28007],{"type":415,"tag":934,"props":28008,"children":28012},{"alt":28009,"className":28010,"src":28011},"Open API specifications of the Users API",[938,8504],"/posts/images/delegatinghandler_api_1.png",[],{"type":415,"tag":416,"props":28014,"children":28015},{},[28016,28017,28023,28025,28031,28033,28039,28040,28046],{"type":420,"value":8781},{"type":415,"tag":555,"props":28018,"children":28020},{"className":28019},[],[28021],{"type":420,"value":28022},"POST /login",{"type":420,"value":28024}," route returns an ",{"type":415,"tag":555,"props":28026,"children":28028},{"className":28027},[],[28029],{"type":420,"value":28030},"AuthResponse",{"type":420,"value":28032}," that contains the necessary Bearer token to call the 2 protected routes ",{"type":415,"tag":555,"props":28034,"children":28036},{"className":28035},[],[28037],{"type":420,"value":28038},"GET /users",{"type":420,"value":15479},{"type":415,"tag":555,"props":28041,"children":28043},{"className":28042},[],[28044],{"type":420,"value":28045},"PUT /users/{username}",{"type":420,"value":542},{"type":415,"tag":416,"props":28048,"children":28049},{},[28050],{"type":420,"value":28051},"We want to implement an IUserService that has 2 methods:",{"type":415,"tag":5376,"props":28053,"children":28054},{},[28055,28073],{"type":415,"tag":5380,"props":28056,"children":28057},{},[28058,28064,28066,28071],{"type":415,"tag":555,"props":28059,"children":28061},{"className":28060},[],[28062],{"type":420,"value":28063},"GetAllUsers",{"type":420,"value":28065}," to retrieve the list of users that will use the ",{"type":415,"tag":555,"props":28067,"children":28069},{"className":28068},[],[28070],{"type":420,"value":28038},{"type":420,"value":28072}," route",{"type":415,"tag":5380,"props":28074,"children":28075},{},[28076,28082,28084,28089],{"type":415,"tag":555,"props":28077,"children":28079},{"className":28078},[],[28080],{"type":420,"value":28081},"UpdateUser",{"type":420,"value":28083}," to update a user that will use the ",{"type":415,"tag":555,"props":28085,"children":28087},{"className":28086},[],[28088],{"type":420,"value":28045},{"type":420,"value":28072},{"type":415,"tag":549,"props":28091,"children":28093},{"className":551,"code":28092,"language":326,"meta":401,"style":401},"public interface IUserService\n{\n    Task\u003CIReadOnlyCollection\u003CUser>> GetAllUsers();\n    Task UpdateUser(User userToUpdate);\n}\n",[28094],{"type":415,"tag":555,"props":28095,"children":28096},{"__ignoreMap":401},[28097,28113,28120,28158,28187],{"type":415,"tag":559,"props":28098,"children":28099},{"class":561,"line":562},[28100,28104,28108],{"type":415,"tag":559,"props":28101,"children":28102},{"style":566},[28103],{"type":420,"value":569},{"type":415,"tag":559,"props":28105,"children":28106},{"style":572},[28107],{"type":420,"value":12900},{"type":415,"tag":559,"props":28109,"children":28110},{"style":572},[28111],{"type":420,"value":28112}," IUserService\n",{"type":415,"tag":559,"props":28114,"children":28115},{"class":561,"line":589},[28116],{"type":415,"tag":559,"props":28117,"children":28118},{"style":583},[28119],{"type":420,"value":786},{"type":415,"tag":559,"props":28121,"children":28122},{"class":561,"line":608},[28123,28127,28131,28136,28140,28144,28149,28154],{"type":415,"tag":559,"props":28124,"children":28125},{"style":572},[28126],{"type":420,"value":12953},{"type":415,"tag":559,"props":28128,"children":28129},{"style":583},[28130],{"type":420,"value":891},{"type":415,"tag":559,"props":28132,"children":28133},{"style":572},[28134],{"type":420,"value":28135},"IReadOnlyCollection",{"type":415,"tag":559,"props":28137,"children":28138},{"style":583},[28139],{"type":420,"value":891},{"type":415,"tag":559,"props":28141,"children":28142},{"style":572},[28143],{"type":420,"value":23614},{"type":415,"tag":559,"props":28145,"children":28146},{"style":583},[28147],{"type":420,"value":28148},">>",{"type":415,"tag":559,"props":28150,"children":28151},{"style":883},[28152],{"type":420,"value":28153}," GetAllUsers",{"type":415,"tag":559,"props":28155,"children":28156},{"style":583},[28157],{"type":420,"value":1962},{"type":415,"tag":559,"props":28159,"children":28160},{"class":561,"line":626},[28161,28165,28170,28174,28178,28183],{"type":415,"tag":559,"props":28162,"children":28163},{"style":572},[28164],{"type":420,"value":12953},{"type":415,"tag":559,"props":28166,"children":28167},{"style":883},[28168],{"type":420,"value":28169}," UpdateUser",{"type":415,"tag":559,"props":28171,"children":28172},{"style":583},[28173],{"type":420,"value":814},{"type":415,"tag":559,"props":28175,"children":28176},{"style":572},[28177],{"type":420,"value":23614},{"type":415,"tag":559,"props":28179,"children":28180},{"style":572},[28181],{"type":420,"value":28182}," userToUpdate",{"type":415,"tag":559,"props":28184,"children":28185},{"style":583},[28186],{"type":420,"value":696},{"type":415,"tag":559,"props":28188,"children":28189},{"class":561,"line":643},[28190],{"type":415,"tag":559,"props":28191,"children":28192},{"style":583},[28193],{"type":420,"value":1801},{"type":415,"tag":416,"props":28195,"children":28196},{},[28197,28199,28204],{"type":420,"value":28198},"Each of these methods needs to retrieve a valid token from the ",{"type":415,"tag":555,"props":28200,"children":28202},{"className":28201},[],[28203],{"type":420,"value":28022},{"type":420,"value":28205}," route and set the Authorization header with this token in the HTTP request to each of the protected routes.",{"type":415,"tag":416,"props":28207,"children":28208},{},[28209],{"type":420,"value":28210},"The following code shows how to retrieve the token:",{"type":415,"tag":549,"props":28212,"children":28214},{"className":551,"code":28213,"language":326,"meta":401,"style":401},"var body = new { login = \"login\", password = \"password\" };\nvar response = await _httpClient.PostAsync(\"login\", new StringContent(JsonConvert.SerializeObject(body)));\nvar authResponse = await response.Content.ReadAsAsync\u003CAuthResponse>();\n",[28215],{"type":415,"tag":555,"props":28216,"children":28217},{"__ignoreMap":401},[28218,28294,28387],{"type":415,"tag":559,"props":28219,"children":28220},{"class":561,"line":562},[28221,28225,28230,28234,28238,28242,28247,28251,28255,28260,28264,28268,28273,28277,28281,28286,28290],{"type":415,"tag":559,"props":28222,"children":28223},{"style":572},[28224],{"type":420,"value":858},{"type":415,"tag":559,"props":28226,"children":28227},{"style":572},[28228],{"type":420,"value":28229}," body",{"type":415,"tag":559,"props":28231,"children":28232},{"style":583},[28233],{"type":420,"value":763},{"type":415,"tag":559,"props":28235,"children":28236},{"style":583},[28237],{"type":420,"value":768},{"type":415,"tag":559,"props":28239,"children":28240},{"style":583},[28241],{"type":420,"value":1144},{"type":415,"tag":559,"props":28243,"children":28244},{"style":792},[28245],{"type":420,"value":28246}," login ",{"type":415,"tag":559,"props":28248,"children":28249},{"style":583},[28250],{"type":420,"value":800},{"type":415,"tag":559,"props":28252,"children":28253},{"style":583},[28254],{"type":420,"value":1434},{"type":415,"tag":559,"props":28256,"children":28257},{"style":822},[28258],{"type":420,"value":28259},"login",{"type":415,"tag":559,"props":28261,"children":28262},{"style":583},[28263],{"type":420,"value":819},{"type":415,"tag":559,"props":28265,"children":28266},{"style":583},[28267],{"type":420,"value":2312},{"type":415,"tag":559,"props":28269,"children":28270},{"style":792},[28271],{"type":420,"value":28272}," password ",{"type":415,"tag":559,"props":28274,"children":28275},{"style":583},[28276],{"type":420,"value":800},{"type":415,"tag":559,"props":28278,"children":28279},{"style":583},[28280],{"type":420,"value":1434},{"type":415,"tag":559,"props":28282,"children":28283},{"style":822},[28284],{"type":420,"value":28285},"password",{"type":415,"tag":559,"props":28287,"children":28288},{"style":583},[28289],{"type":420,"value":819},{"type":415,"tag":559,"props":28291,"children":28292},{"style":583},[28293],{"type":420,"value":11432},{"type":415,"tag":559,"props":28295,"children":28296},{"class":561,"line":589},[28297,28301,28305,28309,28313,28318,28322,28326,28330,28334,28338,28342,28346,28350,28355,28359,28364,28368,28373,28377,28382],{"type":415,"tag":559,"props":28298,"children":28299},{"style":572},[28300],{"type":420,"value":858},{"type":415,"tag":559,"props":28302,"children":28303},{"style":572},[28304],{"type":420,"value":2750},{"type":415,"tag":559,"props":28306,"children":28307},{"style":583},[28308],{"type":420,"value":763},{"type":415,"tag":559,"props":28310,"children":28311},{"style":583},[28312],{"type":420,"value":872},{"type":415,"tag":559,"props":28314,"children":28315},{"style":792},[28316],{"type":420,"value":28317}," _httpClient",{"type":415,"tag":559,"props":28319,"children":28320},{"style":583},[28321],{"type":420,"value":542},{"type":415,"tag":559,"props":28323,"children":28324},{"style":883},[28325],{"type":420,"value":22340},{"type":415,"tag":559,"props":28327,"children":28328},{"style":583},[28329],{"type":420,"value":814},{"type":415,"tag":559,"props":28331,"children":28332},{"style":583},[28333],{"type":420,"value":819},{"type":415,"tag":559,"props":28335,"children":28336},{"style":822},[28337],{"type":420,"value":28259},{"type":415,"tag":559,"props":28339,"children":28340},{"style":583},[28341],{"type":420,"value":819},{"type":415,"tag":559,"props":28343,"children":28344},{"style":583},[28345],{"type":420,"value":2312},{"type":415,"tag":559,"props":28347,"children":28348},{"style":583},[28349],{"type":420,"value":768},{"type":415,"tag":559,"props":28351,"children":28352},{"style":572},[28353],{"type":420,"value":28354}," StringContent",{"type":415,"tag":559,"props":28356,"children":28357},{"style":583},[28358],{"type":420,"value":814},{"type":415,"tag":559,"props":28360,"children":28361},{"style":792},[28362],{"type":420,"value":28363},"JsonConvert",{"type":415,"tag":559,"props":28365,"children":28366},{"style":583},[28367],{"type":420,"value":542},{"type":415,"tag":559,"props":28369,"children":28370},{"style":883},[28371],{"type":420,"value":28372},"SerializeObject",{"type":415,"tag":559,"props":28374,"children":28375},{"style":583},[28376],{"type":420,"value":814},{"type":415,"tag":559,"props":28378,"children":28379},{"style":792},[28380],{"type":420,"value":28381},"body",{"type":415,"tag":559,"props":28383,"children":28384},{"style":583},[28385],{"type":420,"value":28386},")));\n",{"type":415,"tag":559,"props":28388,"children":28389},{"class":561,"line":608},[28390,28394,28399,28403,28407,28411,28415,28420,28424,28429,28433,28437],{"type":415,"tag":559,"props":28391,"children":28392},{"style":572},[28393],{"type":420,"value":858},{"type":415,"tag":559,"props":28395,"children":28396},{"style":572},[28397],{"type":420,"value":28398}," authResponse",{"type":415,"tag":559,"props":28400,"children":28401},{"style":583},[28402],{"type":420,"value":763},{"type":415,"tag":559,"props":28404,"children":28405},{"style":583},[28406],{"type":420,"value":872},{"type":415,"tag":559,"props":28408,"children":28409},{"style":792},[28410],{"type":420,"value":2750},{"type":415,"tag":559,"props":28412,"children":28413},{"style":583},[28414],{"type":420,"value":542},{"type":415,"tag":559,"props":28416,"children":28417},{"style":792},[28418],{"type":420,"value":28419},"Content",{"type":415,"tag":559,"props":28421,"children":28422},{"style":583},[28423],{"type":420,"value":542},{"type":415,"tag":559,"props":28425,"children":28426},{"style":883},[28427],{"type":420,"value":28428},"ReadAsAsync",{"type":415,"tag":559,"props":28430,"children":28431},{"style":583},[28432],{"type":420,"value":891},{"type":415,"tag":559,"props":28434,"children":28435},{"style":572},[28436],{"type":420,"value":28030},{"type":415,"tag":559,"props":28438,"children":28439},{"style":583},[28440],{"type":420,"value":5703},{"type":415,"tag":416,"props":28442,"children":28443},{},[28444,28446,28451,28453,28458],{"type":420,"value":28445},"where ",{"type":415,"tag":555,"props":28447,"children":28449},{"className":28448},[],[28450],{"type":420,"value":28030},{"type":420,"value":28452}," is a class we defined to map the response of the ",{"type":415,"tag":555,"props":28454,"children":28456},{"className":28455},[],[28457],{"type":420,"value":28022},{"type":420,"value":28072},{"type":415,"tag":549,"props":28460,"children":28462},{"className":551,"code":28461,"language":326,"meta":401,"style":401},"public class AuthResponse\n{\n  public string Token { get; set; }\n  public DateTime Expiration { get; set; }\n}\n",[28463],{"type":415,"tag":555,"props":28464,"children":28465},{"__ignoreMap":401},[28466,28482,28489,28530,28571],{"type":415,"tag":559,"props":28467,"children":28468},{"class":561,"line":562},[28469,28473,28477],{"type":415,"tag":559,"props":28470,"children":28471},{"style":566},[28472],{"type":420,"value":569},{"type":415,"tag":559,"props":28474,"children":28475},{"style":572},[28476],{"type":420,"value":5933},{"type":415,"tag":559,"props":28478,"children":28479},{"style":572},[28480],{"type":420,"value":28481}," AuthResponse\n",{"type":415,"tag":559,"props":28483,"children":28484},{"class":561,"line":589},[28485],{"type":415,"tag":559,"props":28486,"children":28487},{"style":583},[28488],{"type":420,"value":786},{"type":415,"tag":559,"props":28490,"children":28491},{"class":561,"line":608},[28492,28497,28501,28506,28510,28514,28518,28522,28526],{"type":415,"tag":559,"props":28493,"children":28494},{"style":566},[28495],{"type":420,"value":28496},"  public",{"type":415,"tag":559,"props":28498,"children":28499},{"style":583},[28500],{"type":420,"value":1129},{"type":415,"tag":559,"props":28502,"children":28503},{"style":572},[28504],{"type":420,"value":28505}," Token",{"type":415,"tag":559,"props":28507,"children":28508},{"style":583},[28509],{"type":420,"value":1144},{"type":415,"tag":559,"props":28511,"children":28512},{"style":572},[28513],{"type":420,"value":1149},{"type":415,"tag":559,"props":28515,"children":28516},{"style":583},[28517],{"type":420,"value":1154},{"type":415,"tag":559,"props":28519,"children":28520},{"style":572},[28521],{"type":420,"value":1159},{"type":415,"tag":559,"props":28523,"children":28524},{"style":583},[28525],{"type":420,"value":1154},{"type":415,"tag":559,"props":28527,"children":28528},{"style":583},[28529],{"type":420,"value":1168},{"type":415,"tag":559,"props":28531,"children":28532},{"class":561,"line":626},[28533,28537,28542,28547,28551,28555,28559,28563,28567],{"type":415,"tag":559,"props":28534,"children":28535},{"style":566},[28536],{"type":420,"value":28496},{"type":415,"tag":559,"props":28538,"children":28539},{"style":572},[28540],{"type":420,"value":28541}," DateTime",{"type":415,"tag":559,"props":28543,"children":28544},{"style":572},[28545],{"type":420,"value":28546}," Expiration",{"type":415,"tag":559,"props":28548,"children":28549},{"style":583},[28550],{"type":420,"value":1144},{"type":415,"tag":559,"props":28552,"children":28553},{"style":572},[28554],{"type":420,"value":1149},{"type":415,"tag":559,"props":28556,"children":28557},{"style":583},[28558],{"type":420,"value":1154},{"type":415,"tag":559,"props":28560,"children":28561},{"style":572},[28562],{"type":420,"value":1159},{"type":415,"tag":559,"props":28564,"children":28565},{"style":583},[28566],{"type":420,"value":1154},{"type":415,"tag":559,"props":28568,"children":28569},{"style":583},[28570],{"type":420,"value":1168},{"type":415,"tag":559,"props":28572,"children":28573},{"class":561,"line":643},[28574],{"type":415,"tag":559,"props":28575,"children":28576},{"style":583},[28577],{"type":420,"value":1801},{"type":415,"tag":416,"props":28579,"children":28580},{},[28581,28583,28589],{"type":420,"value":28582},"So now we have the code to retrieve the token, how do we use it to implement our ",{"type":415,"tag":555,"props":28584,"children":28586},{"className":28585},[],[28587],{"type":420,"value":28588},"IUserService",{"type":420,"value":1134},{"type":415,"tag":422,"props":28591,"children":28593},{"id":28592},"retrieve-the-token-from-a-private-method",[28594],{"type":420,"value":28595},"Retrieve the token from a private method",{"type":415,"tag":416,"props":28597,"children":28598},{},[28599,28601,28607,28609,28614,28615,28620],{"type":420,"value":28600},"The easiest way to do that is to create a private method in ",{"type":415,"tag":555,"props":28602,"children":28604},{"className":28603},[],[28605],{"type":420,"value":28606},"UserService",{"type":420,"value":28608}," that returns this token and to call it from ",{"type":415,"tag":555,"props":28610,"children":28612},{"className":28611},[],[28613],{"type":420,"value":28063},{"type":420,"value":15479},{"type":415,"tag":555,"props":28616,"children":28618},{"className":28617},[],[28619],{"type":420,"value":28081},{"type":420,"value":28621},". That would give us something like that :",{"type":415,"tag":549,"props":28623,"children":28625},{"className":551,"code":28624,"language":326,"meta":401,"style":401},"public class UserService : IUserService\n{\n    private readonly HttpClient _httpClient;\n    public UserService(HttpClient httpClient)\n    {\n        _httpClient = httpClient;\n    }\n\n    public async Task\u003CIReadOnlyCollection\u003CUser>> GetAllUsers()\n    {\n        var token = await RetrieveToken();\n        var request = new HttpRequestMessage(HttpMethod.Get, \"user\");\n        request.Headers.Authorization = new AuthenticationHeaderValue(\"Bearer\", token);\n        var response = await _httpClient.SendAsync(request);\n        response.EnsureSuccessStatusCode();\n        return await response.Content.ReadAsAsync\u003CIReadOnlyCollection\u003CUser>>();\n    }\n\n    public async Task UpdateUser(User userToUpdate)\n    {\n        var token = await RetrieveToken();\n        var request = new HttpRequestMessage(HttpMethod.Put, $\"user/{userToUpdate.Name}\");\n        request.Headers.Authorization = new AuthenticationHeaderValue(\"Bearer\", token);\n        request.Content = new StringContent(JsonConvert.SerializeObject(userToUpdate));\n        var response = await _httpClient.SendAsync(request);\n        response.EnsureSuccessStatusCode();\n    }\n\n    private async Task\u003Cstring> RetrieveToken()\n    {\n        var body = new { login = \"login\", password = \"password\" };\n        var response = await _httpClient.PostAsync(\"login\", new StringContent(JsonConvert.SerializeObject(body)));\n        var authResponse = await response.Content.ReadAsAsync\u003CAuthResponse>();\n        return authResponse.Token;\n    }\n}\n",[28626],{"type":415,"tag":555,"props":28627,"children":28628},{"__ignoreMap":401},[28629,28653,28660,28683,28710,28717,28737,28744,28751,28794,28801,28830,28893,28959,29004,29025,29077,29084,29091,29126,29133,29160,29239,29302,29358,29401,29420,29427,29434,29469,29476,29547,29634,29685,29709,29716],{"type":415,"tag":559,"props":28630,"children":28631},{"class":561,"line":562},[28632,28636,28640,28645,28649],{"type":415,"tag":559,"props":28633,"children":28634},{"style":566},[28635],{"type":420,"value":569},{"type":415,"tag":559,"props":28637,"children":28638},{"style":572},[28639],{"type":420,"value":5933},{"type":415,"tag":559,"props":28641,"children":28642},{"style":572},[28643],{"type":420,"value":28644}," UserService",{"type":415,"tag":559,"props":28646,"children":28647},{"style":583},[28648],{"type":420,"value":2437},{"type":415,"tag":559,"props":28650,"children":28651},{"style":572},[28652],{"type":420,"value":28112},{"type":415,"tag":559,"props":28654,"children":28655},{"class":561,"line":589},[28656],{"type":415,"tag":559,"props":28657,"children":28658},{"style":583},[28659],{"type":420,"value":786},{"type":415,"tag":559,"props":28661,"children":28662},{"class":561,"line":608},[28663,28667,28671,28675,28679],{"type":415,"tag":559,"props":28664,"children":28665},{"style":566},[28666],{"type":420,"value":5962},{"type":415,"tag":559,"props":28668,"children":28669},{"style":566},[28670],{"type":420,"value":5967},{"type":415,"tag":559,"props":28672,"children":28673},{"style":572},[28674],{"type":420,"value":773},{"type":415,"tag":559,"props":28676,"children":28677},{"style":572},[28678],{"type":420,"value":28317},{"type":415,"tag":559,"props":28680,"children":28681},{"style":583},[28682],{"type":420,"value":1509},{"type":415,"tag":559,"props":28684,"children":28685},{"class":561,"line":626},[28686,28690,28694,28698,28702,28706],{"type":415,"tag":559,"props":28687,"children":28688},{"style":566},[28689],{"type":420,"value":1124},{"type":415,"tag":559,"props":28691,"children":28692},{"style":883},[28693],{"type":420,"value":28644},{"type":415,"tag":559,"props":28695,"children":28696},{"style":583},[28697],{"type":420,"value":814},{"type":415,"tag":559,"props":28699,"children":28700},{"style":572},[28701],{"type":420,"value":707},{"type":415,"tag":559,"props":28703,"children":28704},{"style":572},[28705],{"type":420,"value":758},{"type":415,"tag":559,"props":28707,"children":28708},{"style":583},[28709],{"type":420,"value":833},{"type":415,"tag":559,"props":28711,"children":28712},{"class":561,"line":643},[28713],{"type":415,"tag":559,"props":28714,"children":28715},{"style":583},[28716],{"type":420,"value":2737},{"type":415,"tag":559,"props":28718,"children":28719},{"class":561,"line":660},[28720,28725,28729,28733],{"type":415,"tag":559,"props":28721,"children":28722},{"style":792},[28723],{"type":420,"value":28724},"        _httpClient ",{"type":415,"tag":559,"props":28726,"children":28727},{"style":583},[28728],{"type":420,"value":800},{"type":415,"tag":559,"props":28730,"children":28731},{"style":792},[28732],{"type":420,"value":758},{"type":415,"tag":559,"props":28734,"children":28735},{"style":583},[28736],{"type":420,"value":1509},{"type":415,"tag":559,"props":28738,"children":28739},{"class":561,"line":677},[28740],{"type":415,"tag":559,"props":28741,"children":28742},{"style":583},[28743],{"type":420,"value":2792},{"type":415,"tag":559,"props":28745,"children":28746},{"class":561,"line":690},[28747],{"type":415,"tag":559,"props":28748,"children":28749},{"emptyLinePlaceholder":847},[28750],{"type":420,"value":850},{"type":415,"tag":559,"props":28752,"children":28753},{"class":561,"line":1089},[28754,28758,28762,28766,28770,28774,28778,28782,28786,28790],{"type":415,"tag":559,"props":28755,"children":28756},{"style":566},[28757],{"type":420,"value":1124},{"type":415,"tag":559,"props":28759,"children":28760},{"style":566},[28761],{"type":420,"value":6159},{"type":415,"tag":559,"props":28763,"children":28764},{"style":572},[28765],{"type":420,"value":2006},{"type":415,"tag":559,"props":28767,"children":28768},{"style":583},[28769],{"type":420,"value":891},{"type":415,"tag":559,"props":28771,"children":28772},{"style":572},[28773],{"type":420,"value":28135},{"type":415,"tag":559,"props":28775,"children":28776},{"style":583},[28777],{"type":420,"value":891},{"type":415,"tag":559,"props":28779,"children":28780},{"style":572},[28781],{"type":420,"value":23614},{"type":415,"tag":559,"props":28783,"children":28784},{"style":583},[28785],{"type":420,"value":28148},{"type":415,"tag":559,"props":28787,"children":28788},{"style":883},[28789],{"type":420,"value":28153},{"type":415,"tag":559,"props":28791,"children":28792},{"style":583},[28793],{"type":420,"value":778},{"type":415,"tag":559,"props":28795,"children":28796},{"class":561,"line":1102},[28797],{"type":415,"tag":559,"props":28798,"children":28799},{"style":583},[28800],{"type":420,"value":2737},{"type":415,"tag":559,"props":28802,"children":28803},{"class":561,"line":1110},[28804,28808,28813,28817,28821,28826],{"type":415,"tag":559,"props":28805,"children":28806},{"style":572},[28807],{"type":420,"value":2745},{"type":415,"tag":559,"props":28809,"children":28810},{"style":572},[28811],{"type":420,"value":28812}," token",{"type":415,"tag":559,"props":28814,"children":28815},{"style":583},[28816],{"type":420,"value":763},{"type":415,"tag":559,"props":28818,"children":28819},{"style":583},[28820],{"type":420,"value":872},{"type":415,"tag":559,"props":28822,"children":28823},{"style":883},[28824],{"type":420,"value":28825}," RetrieveToken",{"type":415,"tag":559,"props":28827,"children":28828},{"style":583},[28829],{"type":420,"value":1962},{"type":415,"tag":559,"props":28831,"children":28832},{"class":561,"line":1118},[28833,28837,28842,28846,28850,28855,28859,28864,28868,28872,28876,28880,28885,28889],{"type":415,"tag":559,"props":28834,"children":28835},{"style":572},[28836],{"type":420,"value":2745},{"type":415,"tag":559,"props":28838,"children":28839},{"style":572},[28840],{"type":420,"value":28841}," request",{"type":415,"tag":559,"props":28843,"children":28844},{"style":583},[28845],{"type":420,"value":763},{"type":415,"tag":559,"props":28847,"children":28848},{"style":583},[28849],{"type":420,"value":768},{"type":415,"tag":559,"props":28851,"children":28852},{"style":572},[28853],{"type":420,"value":28854}," HttpRequestMessage",{"type":415,"tag":559,"props":28856,"children":28857},{"style":583},[28858],{"type":420,"value":814},{"type":415,"tag":559,"props":28860,"children":28861},{"style":792},[28862],{"type":420,"value":28863},"HttpMethod",{"type":415,"tag":559,"props":28865,"children":28866},{"style":583},[28867],{"type":420,"value":542},{"type":415,"tag":559,"props":28869,"children":28870},{"style":792},[28871],{"type":420,"value":12924},{"type":415,"tag":559,"props":28873,"children":28874},{"style":583},[28875],{"type":420,"value":2312},{"type":415,"tag":559,"props":28877,"children":28878},{"style":583},[28879],{"type":420,"value":1434},{"type":415,"tag":559,"props":28881,"children":28882},{"style":822},[28883],{"type":420,"value":28884},"user",{"type":415,"tag":559,"props":28886,"children":28887},{"style":583},[28888],{"type":420,"value":819},{"type":415,"tag":559,"props":28890,"children":28891},{"style":583},[28892],{"type":420,"value":696},{"type":415,"tag":559,"props":28894,"children":28895},{"class":561,"line":1171},[28896,28901,28905,28910,28914,28918,28922,28926,28930,28934,28938,28943,28947,28951,28955],{"type":415,"tag":559,"props":28897,"children":28898},{"style":792},[28899],{"type":420,"value":28900},"        request",{"type":415,"tag":559,"props":28902,"children":28903},{"style":583},[28904],{"type":420,"value":542},{"type":415,"tag":559,"props":28906,"children":28907},{"style":792},[28908],{"type":420,"value":28909},"Headers",{"type":415,"tag":559,"props":28911,"children":28912},{"style":583},[28913],{"type":420,"value":542},{"type":415,"tag":559,"props":28915,"children":28916},{"style":792},[28917],{"type":420,"value":22275},{"type":415,"tag":559,"props":28919,"children":28920},{"style":583},[28921],{"type":420,"value":800},{"type":415,"tag":559,"props":28923,"children":28924},{"style":583},[28925],{"type":420,"value":768},{"type":415,"tag":559,"props":28927,"children":28928},{"style":572},[28929],{"type":420,"value":22288},{"type":415,"tag":559,"props":28931,"children":28932},{"style":583},[28933],{"type":420,"value":814},{"type":415,"tag":559,"props":28935,"children":28936},{"style":583},[28937],{"type":420,"value":819},{"type":415,"tag":559,"props":28939,"children":28940},{"style":822},[28941],{"type":420,"value":28942},"Bearer",{"type":415,"tag":559,"props":28944,"children":28945},{"style":583},[28946],{"type":420,"value":819},{"type":415,"tag":559,"props":28948,"children":28949},{"style":583},[28950],{"type":420,"value":2312},{"type":415,"tag":559,"props":28952,"children":28953},{"style":792},[28954],{"type":420,"value":28812},{"type":415,"tag":559,"props":28956,"children":28957},{"style":583},[28958],{"type":420,"value":696},{"type":415,"tag":559,"props":28960,"children":28961},{"class":561,"line":1748},[28962,28966,28970,28974,28978,28982,28986,28991,28995,29000],{"type":415,"tag":559,"props":28963,"children":28964},{"style":572},[28965],{"type":420,"value":2745},{"type":415,"tag":559,"props":28967,"children":28968},{"style":572},[28969],{"type":420,"value":2750},{"type":415,"tag":559,"props":28971,"children":28972},{"style":583},[28973],{"type":420,"value":763},{"type":415,"tag":559,"props":28975,"children":28976},{"style":583},[28977],{"type":420,"value":872},{"type":415,"tag":559,"props":28979,"children":28980},{"style":792},[28981],{"type":420,"value":28317},{"type":415,"tag":559,"props":28983,"children":28984},{"style":583},[28985],{"type":420,"value":542},{"type":415,"tag":559,"props":28987,"children":28988},{"style":883},[28989],{"type":420,"value":28990},"SendAsync",{"type":415,"tag":559,"props":28992,"children":28993},{"style":583},[28994],{"type":420,"value":814},{"type":415,"tag":559,"props":28996,"children":28997},{"style":792},[28998],{"type":420,"value":28999},"request",{"type":415,"tag":559,"props":29001,"children":29002},{"style":583},[29003],{"type":420,"value":696},{"type":415,"tag":559,"props":29005,"children":29006},{"class":561,"line":1769},[29007,29012,29016,29021],{"type":415,"tag":559,"props":29008,"children":29009},{"style":792},[29010],{"type":420,"value":29011},"        response",{"type":415,"tag":559,"props":29013,"children":29014},{"style":583},[29015],{"type":420,"value":542},{"type":415,"tag":559,"props":29017,"children":29018},{"style":883},[29019],{"type":420,"value":29020},"EnsureSuccessStatusCode",{"type":415,"tag":559,"props":29022,"children":29023},{"style":583},[29024],{"type":420,"value":1962},{"type":415,"tag":559,"props":29026,"children":29027},{"class":561,"line":1786},[29028,29032,29036,29040,29044,29048,29052,29056,29060,29064,29068,29072],{"type":415,"tag":559,"props":29029,"children":29030},{"style":745},[29031],{"type":420,"value":8218},{"type":415,"tag":559,"props":29033,"children":29034},{"style":583},[29035],{"type":420,"value":872},{"type":415,"tag":559,"props":29037,"children":29038},{"style":792},[29039],{"type":420,"value":2750},{"type":415,"tag":559,"props":29041,"children":29042},{"style":583},[29043],{"type":420,"value":542},{"type":415,"tag":559,"props":29045,"children":29046},{"style":792},[29047],{"type":420,"value":28419},{"type":415,"tag":559,"props":29049,"children":29050},{"style":583},[29051],{"type":420,"value":542},{"type":415,"tag":559,"props":29053,"children":29054},{"style":883},[29055],{"type":420,"value":28428},{"type":415,"tag":559,"props":29057,"children":29058},{"style":583},[29059],{"type":420,"value":891},{"type":415,"tag":559,"props":29061,"children":29062},{"style":572},[29063],{"type":420,"value":28135},{"type":415,"tag":559,"props":29065,"children":29066},{"style":583},[29067],{"type":420,"value":891},{"type":415,"tag":559,"props":29069,"children":29070},{"style":572},[29071],{"type":420,"value":23614},{"type":415,"tag":559,"props":29073,"children":29074},{"style":583},[29075],{"type":420,"value":29076},">>();\n",{"type":415,"tag":559,"props":29078,"children":29079},{"class":561,"line":1795},[29080],{"type":415,"tag":559,"props":29081,"children":29082},{"style":583},[29083],{"type":420,"value":2792},{"type":415,"tag":559,"props":29085,"children":29086},{"class":561,"line":3289},[29087],{"type":415,"tag":559,"props":29088,"children":29089},{"emptyLinePlaceholder":847},[29090],{"type":420,"value":850},{"type":415,"tag":559,"props":29092,"children":29093},{"class":561,"line":3297},[29094,29098,29102,29106,29110,29114,29118,29122],{"type":415,"tag":559,"props":29095,"children":29096},{"style":566},[29097],{"type":420,"value":1124},{"type":415,"tag":559,"props":29099,"children":29100},{"style":566},[29101],{"type":420,"value":6159},{"type":415,"tag":559,"props":29103,"children":29104},{"style":572},[29105],{"type":420,"value":2006},{"type":415,"tag":559,"props":29107,"children":29108},{"style":883},[29109],{"type":420,"value":28169},{"type":415,"tag":559,"props":29111,"children":29112},{"style":583},[29113],{"type":420,"value":814},{"type":415,"tag":559,"props":29115,"children":29116},{"style":572},[29117],{"type":420,"value":23614},{"type":415,"tag":559,"props":29119,"children":29120},{"style":572},[29121],{"type":420,"value":28182},{"type":415,"tag":559,"props":29123,"children":29124},{"style":583},[29125],{"type":420,"value":833},{"type":415,"tag":559,"props":29127,"children":29128},{"class":561,"line":3349},[29129],{"type":415,"tag":559,"props":29130,"children":29131},{"style":583},[29132],{"type":420,"value":2737},{"type":415,"tag":559,"props":29134,"children":29135},{"class":561,"line":3374},[29136,29140,29144,29148,29152,29156],{"type":415,"tag":559,"props":29137,"children":29138},{"style":572},[29139],{"type":420,"value":2745},{"type":415,"tag":559,"props":29141,"children":29142},{"style":572},[29143],{"type":420,"value":28812},{"type":415,"tag":559,"props":29145,"children":29146},{"style":583},[29147],{"type":420,"value":763},{"type":415,"tag":559,"props":29149,"children":29150},{"style":583},[29151],{"type":420,"value":872},{"type":415,"tag":559,"props":29153,"children":29154},{"style":883},[29155],{"type":420,"value":28825},{"type":415,"tag":559,"props":29157,"children":29158},{"style":583},[29159],{"type":420,"value":1962},{"type":415,"tag":559,"props":29161,"children":29162},{"class":561,"line":3382},[29163,29167,29171,29175,29179,29183,29187,29191,29195,29200,29204,29209,29214,29218,29223,29227,29231,29235],{"type":415,"tag":559,"props":29164,"children":29165},{"style":572},[29166],{"type":420,"value":2745},{"type":415,"tag":559,"props":29168,"children":29169},{"style":572},[29170],{"type":420,"value":28841},{"type":415,"tag":559,"props":29172,"children":29173},{"style":583},[29174],{"type":420,"value":763},{"type":415,"tag":559,"props":29176,"children":29177},{"style":583},[29178],{"type":420,"value":768},{"type":415,"tag":559,"props":29180,"children":29181},{"style":572},[29182],{"type":420,"value":28854},{"type":415,"tag":559,"props":29184,"children":29185},{"style":583},[29186],{"type":420,"value":814},{"type":415,"tag":559,"props":29188,"children":29189},{"style":792},[29190],{"type":420,"value":28863},{"type":415,"tag":559,"props":29192,"children":29193},{"style":583},[29194],{"type":420,"value":542},{"type":415,"tag":559,"props":29196,"children":29197},{"style":792},[29198],{"type":420,"value":29199},"Put",{"type":415,"tag":559,"props":29201,"children":29202},{"style":583},[29203],{"type":420,"value":2312},{"type":415,"tag":559,"props":29205,"children":29206},{"style":583},[29207],{"type":420,"value":29208}," $\"",{"type":415,"tag":559,"props":29210,"children":29211},{"style":822},[29212],{"type":420,"value":29213},"user/",{"type":415,"tag":559,"props":29215,"children":29216},{"style":583},[29217],{"type":420,"value":2397},{"type":415,"tag":559,"props":29219,"children":29220},{"style":792},[29221],{"type":420,"value":29222},"userToUpdate",{"type":415,"tag":559,"props":29224,"children":29225},{"style":583},[29226],{"type":420,"value":542},{"type":415,"tag":559,"props":29228,"children":29229},{"style":792},[29230],{"type":420,"value":1412},{"type":415,"tag":559,"props":29232,"children":29233},{"style":583},[29234],{"type":420,"value":1602},{"type":415,"tag":559,"props":29236,"children":29237},{"style":583},[29238],{"type":420,"value":696},{"type":415,"tag":559,"props":29240,"children":29241},{"class":561,"line":3390},[29242,29246,29250,29254,29258,29262,29266,29270,29274,29278,29282,29286,29290,29294,29298],{"type":415,"tag":559,"props":29243,"children":29244},{"style":792},[29245],{"type":420,"value":28900},{"type":415,"tag":559,"props":29247,"children":29248},{"style":583},[29249],{"type":420,"value":542},{"type":415,"tag":559,"props":29251,"children":29252},{"style":792},[29253],{"type":420,"value":28909},{"type":415,"tag":559,"props":29255,"children":29256},{"style":583},[29257],{"type":420,"value":542},{"type":415,"tag":559,"props":29259,"children":29260},{"style":792},[29261],{"type":420,"value":22275},{"type":415,"tag":559,"props":29263,"children":29264},{"style":583},[29265],{"type":420,"value":800},{"type":415,"tag":559,"props":29267,"children":29268},{"style":583},[29269],{"type":420,"value":768},{"type":415,"tag":559,"props":29271,"children":29272},{"style":572},[29273],{"type":420,"value":22288},{"type":415,"tag":559,"props":29275,"children":29276},{"style":583},[29277],{"type":420,"value":814},{"type":415,"tag":559,"props":29279,"children":29280},{"style":583},[29281],{"type":420,"value":819},{"type":415,"tag":559,"props":29283,"children":29284},{"style":822},[29285],{"type":420,"value":28942},{"type":415,"tag":559,"props":29287,"children":29288},{"style":583},[29289],{"type":420,"value":819},{"type":415,"tag":559,"props":29291,"children":29292},{"style":583},[29293],{"type":420,"value":2312},{"type":415,"tag":559,"props":29295,"children":29296},{"style":792},[29297],{"type":420,"value":28812},{"type":415,"tag":559,"props":29299,"children":29300},{"style":583},[29301],{"type":420,"value":696},{"type":415,"tag":559,"props":29303,"children":29304},{"class":561,"line":3434},[29305,29309,29313,29318,29322,29326,29330,29334,29338,29342,29346,29350,29354],{"type":415,"tag":559,"props":29306,"children":29307},{"style":792},[29308],{"type":420,"value":28900},{"type":415,"tag":559,"props":29310,"children":29311},{"style":583},[29312],{"type":420,"value":542},{"type":415,"tag":559,"props":29314,"children":29315},{"style":792},[29316],{"type":420,"value":29317},"Content ",{"type":415,"tag":559,"props":29319,"children":29320},{"style":583},[29321],{"type":420,"value":800},{"type":415,"tag":559,"props":29323,"children":29324},{"style":583},[29325],{"type":420,"value":768},{"type":415,"tag":559,"props":29327,"children":29328},{"style":572},[29329],{"type":420,"value":28354},{"type":415,"tag":559,"props":29331,"children":29332},{"style":583},[29333],{"type":420,"value":814},{"type":415,"tag":559,"props":29335,"children":29336},{"style":792},[29337],{"type":420,"value":28363},{"type":415,"tag":559,"props":29339,"children":29340},{"style":583},[29341],{"type":420,"value":542},{"type":415,"tag":559,"props":29343,"children":29344},{"style":883},[29345],{"type":420,"value":28372},{"type":415,"tag":559,"props":29347,"children":29348},{"style":583},[29349],{"type":420,"value":814},{"type":415,"tag":559,"props":29351,"children":29352},{"style":792},[29353],{"type":420,"value":29222},{"type":415,"tag":559,"props":29355,"children":29356},{"style":583},[29357],{"type":420,"value":5796},{"type":415,"tag":559,"props":29359,"children":29360},{"class":561,"line":3442},[29361,29365,29369,29373,29377,29381,29385,29389,29393,29397],{"type":415,"tag":559,"props":29362,"children":29363},{"style":572},[29364],{"type":420,"value":2745},{"type":415,"tag":559,"props":29366,"children":29367},{"style":572},[29368],{"type":420,"value":2750},{"type":415,"tag":559,"props":29370,"children":29371},{"style":583},[29372],{"type":420,"value":763},{"type":415,"tag":559,"props":29374,"children":29375},{"style":583},[29376],{"type":420,"value":872},{"type":415,"tag":559,"props":29378,"children":29379},{"style":792},[29380],{"type":420,"value":28317},{"type":415,"tag":559,"props":29382,"children":29383},{"style":583},[29384],{"type":420,"value":542},{"type":415,"tag":559,"props":29386,"children":29387},{"style":883},[29388],{"type":420,"value":28990},{"type":415,"tag":559,"props":29390,"children":29391},{"style":583},[29392],{"type":420,"value":814},{"type":415,"tag":559,"props":29394,"children":29395},{"style":792},[29396],{"type":420,"value":28999},{"type":415,"tag":559,"props":29398,"children":29399},{"style":583},[29400],{"type":420,"value":696},{"type":415,"tag":559,"props":29402,"children":29403},{"class":561,"line":3498},[29404,29408,29412,29416],{"type":415,"tag":559,"props":29405,"children":29406},{"style":792},[29407],{"type":420,"value":29011},{"type":415,"tag":559,"props":29409,"children":29410},{"style":583},[29411],{"type":420,"value":542},{"type":415,"tag":559,"props":29413,"children":29414},{"style":883},[29415],{"type":420,"value":29020},{"type":415,"tag":559,"props":29417,"children":29418},{"style":583},[29419],{"type":420,"value":1962},{"type":415,"tag":559,"props":29421,"children":29422},{"class":561,"line":3542},[29423],{"type":415,"tag":559,"props":29424,"children":29425},{"style":583},[29426],{"type":420,"value":2792},{"type":415,"tag":559,"props":29428,"children":29429},{"class":561,"line":3550},[29430],{"type":415,"tag":559,"props":29431,"children":29432},{"emptyLinePlaceholder":847},[29433],{"type":420,"value":850},{"type":415,"tag":559,"props":29435,"children":29436},{"class":561,"line":3582},[29437,29441,29445,29449,29453,29457,29461,29465],{"type":415,"tag":559,"props":29438,"children":29439},{"style":566},[29440],{"type":420,"value":5962},{"type":415,"tag":559,"props":29442,"children":29443},{"style":566},[29444],{"type":420,"value":6159},{"type":415,"tag":559,"props":29446,"children":29447},{"style":572},[29448],{"type":420,"value":2006},{"type":415,"tag":559,"props":29450,"children":29451},{"style":583},[29452],{"type":420,"value":891},{"type":415,"tag":559,"props":29454,"children":29455},{"style":583},[29456],{"type":420,"value":2015},{"type":415,"tag":559,"props":29458,"children":29459},{"style":583},[29460],{"type":420,"value":5985},{"type":415,"tag":559,"props":29462,"children":29463},{"style":883},[29464],{"type":420,"value":28825},{"type":415,"tag":559,"props":29466,"children":29467},{"style":583},[29468],{"type":420,"value":778},{"type":415,"tag":559,"props":29470,"children":29471},{"class":561,"line":3622},[29472],{"type":415,"tag":559,"props":29473,"children":29474},{"style":583},[29475],{"type":420,"value":2737},{"type":415,"tag":559,"props":29477,"children":29478},{"class":561,"line":3654},[29479,29483,29487,29491,29495,29499,29503,29507,29511,29515,29519,29523,29527,29531,29535,29539,29543],{"type":415,"tag":559,"props":29480,"children":29481},{"style":572},[29482],{"type":420,"value":2745},{"type":415,"tag":559,"props":29484,"children":29485},{"style":572},[29486],{"type":420,"value":28229},{"type":415,"tag":559,"props":29488,"children":29489},{"style":583},[29490],{"type":420,"value":763},{"type":415,"tag":559,"props":29492,"children":29493},{"style":583},[29494],{"type":420,"value":768},{"type":415,"tag":559,"props":29496,"children":29497},{"style":583},[29498],{"type":420,"value":1144},{"type":415,"tag":559,"props":29500,"children":29501},{"style":792},[29502],{"type":420,"value":28246},{"type":415,"tag":559,"props":29504,"children":29505},{"style":583},[29506],{"type":420,"value":800},{"type":415,"tag":559,"props":29508,"children":29509},{"style":583},[29510],{"type":420,"value":1434},{"type":415,"tag":559,"props":29512,"children":29513},{"style":822},[29514],{"type":420,"value":28259},{"type":415,"tag":559,"props":29516,"children":29517},{"style":583},[29518],{"type":420,"value":819},{"type":415,"tag":559,"props":29520,"children":29521},{"style":583},[29522],{"type":420,"value":2312},{"type":415,"tag":559,"props":29524,"children":29525},{"style":792},[29526],{"type":420,"value":28272},{"type":415,"tag":559,"props":29528,"children":29529},{"style":583},[29530],{"type":420,"value":800},{"type":415,"tag":559,"props":29532,"children":29533},{"style":583},[29534],{"type":420,"value":1434},{"type":415,"tag":559,"props":29536,"children":29537},{"style":822},[29538],{"type":420,"value":28285},{"type":415,"tag":559,"props":29540,"children":29541},{"style":583},[29542],{"type":420,"value":819},{"type":415,"tag":559,"props":29544,"children":29545},{"style":583},[29546],{"type":420,"value":11432},{"type":415,"tag":559,"props":29548,"children":29549},{"class":561,"line":3662},[29550,29554,29558,29562,29566,29570,29574,29578,29582,29586,29590,29594,29598,29602,29606,29610,29614,29618,29622,29626,29630],{"type":415,"tag":559,"props":29551,"children":29552},{"style":572},[29553],{"type":420,"value":2745},{"type":415,"tag":559,"props":29555,"children":29556},{"style":572},[29557],{"type":420,"value":2750},{"type":415,"tag":559,"props":29559,"children":29560},{"style":583},[29561],{"type":420,"value":763},{"type":415,"tag":559,"props":29563,"children":29564},{"style":583},[29565],{"type":420,"value":872},{"type":415,"tag":559,"props":29567,"children":29568},{"style":792},[29569],{"type":420,"value":28317},{"type":415,"tag":559,"props":29571,"children":29572},{"style":583},[29573],{"type":420,"value":542},{"type":415,"tag":559,"props":29575,"children":29576},{"style":883},[29577],{"type":420,"value":22340},{"type":415,"tag":559,"props":29579,"children":29580},{"style":583},[29581],{"type":420,"value":814},{"type":415,"tag":559,"props":29583,"children":29584},{"style":583},[29585],{"type":420,"value":819},{"type":415,"tag":559,"props":29587,"children":29588},{"style":822},[29589],{"type":420,"value":28259},{"type":415,"tag":559,"props":29591,"children":29592},{"style":583},[29593],{"type":420,"value":819},{"type":415,"tag":559,"props":29595,"children":29596},{"style":583},[29597],{"type":420,"value":2312},{"type":415,"tag":559,"props":29599,"children":29600},{"style":583},[29601],{"type":420,"value":768},{"type":415,"tag":559,"props":29603,"children":29604},{"style":572},[29605],{"type":420,"value":28354},{"type":415,"tag":559,"props":29607,"children":29608},{"style":583},[29609],{"type":420,"value":814},{"type":415,"tag":559,"props":29611,"children":29612},{"style":792},[29613],{"type":420,"value":28363},{"type":415,"tag":559,"props":29615,"children":29616},{"style":583},[29617],{"type":420,"value":542},{"type":415,"tag":559,"props":29619,"children":29620},{"style":883},[29621],{"type":420,"value":28372},{"type":415,"tag":559,"props":29623,"children":29624},{"style":583},[29625],{"type":420,"value":814},{"type":415,"tag":559,"props":29627,"children":29628},{"style":792},[29629],{"type":420,"value":28381},{"type":415,"tag":559,"props":29631,"children":29632},{"style":583},[29633],{"type":420,"value":28386},{"type":415,"tag":559,"props":29635,"children":29636},{"class":561,"line":3730},[29637,29641,29645,29649,29653,29657,29661,29665,29669,29673,29677,29681],{"type":415,"tag":559,"props":29638,"children":29639},{"style":572},[29640],{"type":420,"value":2745},{"type":415,"tag":559,"props":29642,"children":29643},{"style":572},[29644],{"type":420,"value":28398},{"type":415,"tag":559,"props":29646,"children":29647},{"style":583},[29648],{"type":420,"value":763},{"type":415,"tag":559,"props":29650,"children":29651},{"style":583},[29652],{"type":420,"value":872},{"type":415,"tag":559,"props":29654,"children":29655},{"style":792},[29656],{"type":420,"value":2750},{"type":415,"tag":559,"props":29658,"children":29659},{"style":583},[29660],{"type":420,"value":542},{"type":415,"tag":559,"props":29662,"children":29663},{"style":792},[29664],{"type":420,"value":28419},{"type":415,"tag":559,"props":29666,"children":29667},{"style":583},[29668],{"type":420,"value":542},{"type":415,"tag":559,"props":29670,"children":29671},{"style":883},[29672],{"type":420,"value":28428},{"type":415,"tag":559,"props":29674,"children":29675},{"style":583},[29676],{"type":420,"value":891},{"type":415,"tag":559,"props":29678,"children":29679},{"style":572},[29680],{"type":420,"value":28030},{"type":415,"tag":559,"props":29682,"children":29683},{"style":583},[29684],{"type":420,"value":5703},{"type":415,"tag":559,"props":29686,"children":29687},{"class":561,"line":3738},[29688,29692,29696,29700,29705],{"type":415,"tag":559,"props":29689,"children":29690},{"style":745},[29691],{"type":420,"value":8218},{"type":415,"tag":559,"props":29693,"children":29694},{"style":792},[29695],{"type":420,"value":28398},{"type":415,"tag":559,"props":29697,"children":29698},{"style":583},[29699],{"type":420,"value":542},{"type":415,"tag":559,"props":29701,"children":29702},{"style":792},[29703],{"type":420,"value":29704},"Token",{"type":415,"tag":559,"props":29706,"children":29707},{"style":583},[29708],{"type":420,"value":1509},{"type":415,"tag":559,"props":29710,"children":29711},{"class":561,"line":3810},[29712],{"type":415,"tag":559,"props":29713,"children":29714},{"style":583},[29715],{"type":420,"value":2792},{"type":415,"tag":559,"props":29717,"children":29718},{"class":561,"line":3818},[29719],{"type":415,"tag":559,"props":29720,"children":29721},{"style":583},[29722],{"type":420,"value":1801},{"type":415,"tag":416,"props":29724,"children":29725},{},[29726],{"type":420,"value":29727},"There are two main problems with this way of doing things:",{"type":415,"tag":5376,"props":29729,"children":29730},{},[29731,29751],{"type":415,"tag":5380,"props":29732,"children":29733},{},[29734,29736,29742,29744,29749],{"type":420,"value":29735},"We have some code duplication as we are calling the ",{"type":415,"tag":555,"props":29737,"children":29739},{"className":29738},[],[29740],{"type":420,"value":29741},"RetrieveToken",{"type":420,"value":29743}," in each of our methods calling the API. That could be okay here as we only have 2 methods calling the API but that can quickly be problematic if we start to have more methods and repeat the call to ",{"type":415,"tag":555,"props":29745,"children":29747},{"className":29746},[],[29748],{"type":420,"value":29741},{"type":420,"value":29750},"in each method.",{"type":415,"tag":5380,"props":29752,"children":29753},{},[29754,29756,29761],{"type":420,"value":29755},"For each call to an authenticated route of the API, we are making a call to the ",{"type":415,"tag":555,"props":29757,"children":29759},{"className":29758},[],[29760],{"type":420,"value":28259},{"type":420,"value":29762}," route even if our token from a previous call is probably still valid.",{"type":415,"tag":422,"props":29764,"children":29766},{"id":29765},"use-a-dedicated-service-to-retrieve-the-token-and-save-it-for-future-calls",[29767],{"type":420,"value":29768},"Use a dedicated service to retrieve the token and save it for future calls",{"type":415,"tag":416,"props":29770,"children":29771},{},[29772,29774,29779,29781,29787,29789,29794,29796,29801,29803,29808],{"type":420,"value":29773},"Although it's not necessary at this point, it can be interesting to move the code of our private method ",{"type":415,"tag":555,"props":29775,"children":29777},{"className":29776},[],[29778],{"type":420,"value":29741},{"type":420,"value":29780}," into a separate service ",{"type":415,"tag":555,"props":29782,"children":29784},{"className":29783},[],[29785],{"type":420,"value":29786},"UserApiAuthenticationService",{"type":420,"value":29788}," that will be injected in ",{"type":415,"tag":555,"props":29790,"children":29792},{"className":29791},[],[29793],{"type":420,"value":28606},{"type":420,"value":29795},". That way, if the authentication method changes someday, ",{"type":415,"tag":555,"props":29797,"children":29799},{"className":29798},[],[29800],{"type":420,"value":28606},{"type":420,"value":29802}," implementation won't change. Moreover, we won't mess with the same ",{"type":415,"tag":555,"props":29804,"children":29806},{"className":29805},[],[29807],{"type":420,"value":707},{"type":420,"value":29809}," for authentication and other calls.",{"type":415,"tag":549,"props":29811,"children":29813},{"className":551,"code":29812,"language":326,"meta":401,"style":401},"public class UserApiAuthenticationService : IUserApiAuthenticationService\n{\n    private readonly IMemoryCache _memoryCache;\n    private readonly HttpClient _httpClient;\n\n    public UserApiAuthenticationService(HttpClient httpClient, IMemoryCache memoryCache)\n    {\n        _httpClient = httpClient;\n        _memoryCache = memoryCache;\n    }\n\n    public async Task\u003Cstring> RetrieveToken()\n    {\n        DateTime expirationDate;\n        if (!_memoryCache.TryGetValue(\"Token\", out string token))\n        {\n            var body = new { login = \"login\", password = \"password\" };\n            var response = await _httpClient.PostAsync(\"login\", new StringContent(JsonConvert.SerializeObject(body)));\n            (token,  expirationDate) = await response.Content.ReadAsAsync\u003CAuthResponse>();\n            _memoryCache.Set(\"Token\", token, new DateTimeOffset(expirationDate));\n        }\n        return token;\n    }\n}\n",[29814],{"type":415,"tag":555,"props":29815,"children":29816},{"__ignoreMap":401},[29817,29842,29849,29874,29897,29904,29944,29951,29970,29990,29997,30004,30039,30046,30063,30126,30133,30205,30292,30358,30424,30431,30446,30453],{"type":415,"tag":559,"props":29818,"children":29819},{"class":561,"line":562},[29820,29824,29828,29833,29837],{"type":415,"tag":559,"props":29821,"children":29822},{"style":566},[29823],{"type":420,"value":569},{"type":415,"tag":559,"props":29825,"children":29826},{"style":572},[29827],{"type":420,"value":5933},{"type":415,"tag":559,"props":29829,"children":29830},{"style":572},[29831],{"type":420,"value":29832}," UserApiAuthenticationService",{"type":415,"tag":559,"props":29834,"children":29835},{"style":583},[29836],{"type":420,"value":2437},{"type":415,"tag":559,"props":29838,"children":29839},{"style":572},[29840],{"type":420,"value":29841}," IUserApiAuthenticationService\n",{"type":415,"tag":559,"props":29843,"children":29844},{"class":561,"line":589},[29845],{"type":415,"tag":559,"props":29846,"children":29847},{"style":583},[29848],{"type":420,"value":786},{"type":415,"tag":559,"props":29850,"children":29851},{"class":561,"line":608},[29852,29856,29860,29865,29870],{"type":415,"tag":559,"props":29853,"children":29854},{"style":566},[29855],{"type":420,"value":5962},{"type":415,"tag":559,"props":29857,"children":29858},{"style":566},[29859],{"type":420,"value":5967},{"type":415,"tag":559,"props":29861,"children":29862},{"style":572},[29863],{"type":420,"value":29864}," IMemoryCache",{"type":415,"tag":559,"props":29866,"children":29867},{"style":572},[29868],{"type":420,"value":29869}," _memoryCache",{"type":415,"tag":559,"props":29871,"children":29872},{"style":583},[29873],{"type":420,"value":1509},{"type":415,"tag":559,"props":29875,"children":29876},{"class":561,"line":626},[29877,29881,29885,29889,29893],{"type":415,"tag":559,"props":29878,"children":29879},{"style":566},[29880],{"type":420,"value":5962},{"type":415,"tag":559,"props":29882,"children":29883},{"style":566},[29884],{"type":420,"value":5967},{"type":415,"tag":559,"props":29886,"children":29887},{"style":572},[29888],{"type":420,"value":773},{"type":415,"tag":559,"props":29890,"children":29891},{"style":572},[29892],{"type":420,"value":28317},{"type":415,"tag":559,"props":29894,"children":29895},{"style":583},[29896],{"type":420,"value":1509},{"type":415,"tag":559,"props":29898,"children":29899},{"class":561,"line":643},[29900],{"type":415,"tag":559,"props":29901,"children":29902},{"emptyLinePlaceholder":847},[29903],{"type":420,"value":850},{"type":415,"tag":559,"props":29905,"children":29906},{"class":561,"line":660},[29907,29911,29915,29919,29923,29927,29931,29935,29940],{"type":415,"tag":559,"props":29908,"children":29909},{"style":566},[29910],{"type":420,"value":1124},{"type":415,"tag":559,"props":29912,"children":29913},{"style":883},[29914],{"type":420,"value":29832},{"type":415,"tag":559,"props":29916,"children":29917},{"style":583},[29918],{"type":420,"value":814},{"type":415,"tag":559,"props":29920,"children":29921},{"style":572},[29922],{"type":420,"value":707},{"type":415,"tag":559,"props":29924,"children":29925},{"style":572},[29926],{"type":420,"value":758},{"type":415,"tag":559,"props":29928,"children":29929},{"style":583},[29930],{"type":420,"value":2312},{"type":415,"tag":559,"props":29932,"children":29933},{"style":572},[29934],{"type":420,"value":29864},{"type":415,"tag":559,"props":29936,"children":29937},{"style":572},[29938],{"type":420,"value":29939}," memoryCache",{"type":415,"tag":559,"props":29941,"children":29942},{"style":583},[29943],{"type":420,"value":833},{"type":415,"tag":559,"props":29945,"children":29946},{"class":561,"line":677},[29947],{"type":415,"tag":559,"props":29948,"children":29949},{"style":583},[29950],{"type":420,"value":2737},{"type":415,"tag":559,"props":29952,"children":29953},{"class":561,"line":690},[29954,29958,29962,29966],{"type":415,"tag":559,"props":29955,"children":29956},{"style":792},[29957],{"type":420,"value":28724},{"type":415,"tag":559,"props":29959,"children":29960},{"style":583},[29961],{"type":420,"value":800},{"type":415,"tag":559,"props":29963,"children":29964},{"style":792},[29965],{"type":420,"value":758},{"type":415,"tag":559,"props":29967,"children":29968},{"style":583},[29969],{"type":420,"value":1509},{"type":415,"tag":559,"props":29971,"children":29972},{"class":561,"line":1089},[29973,29978,29982,29986],{"type":415,"tag":559,"props":29974,"children":29975},{"style":792},[29976],{"type":420,"value":29977},"        _memoryCache ",{"type":415,"tag":559,"props":29979,"children":29980},{"style":583},[29981],{"type":420,"value":800},{"type":415,"tag":559,"props":29983,"children":29984},{"style":792},[29985],{"type":420,"value":29939},{"type":415,"tag":559,"props":29987,"children":29988},{"style":583},[29989],{"type":420,"value":1509},{"type":415,"tag":559,"props":29991,"children":29992},{"class":561,"line":1102},[29993],{"type":415,"tag":559,"props":29994,"children":29995},{"style":583},[29996],{"type":420,"value":2792},{"type":415,"tag":559,"props":29998,"children":29999},{"class":561,"line":1110},[30000],{"type":415,"tag":559,"props":30001,"children":30002},{"emptyLinePlaceholder":847},[30003],{"type":420,"value":850},{"type":415,"tag":559,"props":30005,"children":30006},{"class":561,"line":1118},[30007,30011,30015,30019,30023,30027,30031,30035],{"type":415,"tag":559,"props":30008,"children":30009},{"style":566},[30010],{"type":420,"value":1124},{"type":415,"tag":559,"props":30012,"children":30013},{"style":566},[30014],{"type":420,"value":6159},{"type":415,"tag":559,"props":30016,"children":30017},{"style":572},[30018],{"type":420,"value":2006},{"type":415,"tag":559,"props":30020,"children":30021},{"style":583},[30022],{"type":420,"value":891},{"type":415,"tag":559,"props":30024,"children":30025},{"style":583},[30026],{"type":420,"value":2015},{"type":415,"tag":559,"props":30028,"children":30029},{"style":583},[30030],{"type":420,"value":5985},{"type":415,"tag":559,"props":30032,"children":30033},{"style":883},[30034],{"type":420,"value":28825},{"type":415,"tag":559,"props":30036,"children":30037},{"style":583},[30038],{"type":420,"value":778},{"type":415,"tag":559,"props":30040,"children":30041},{"class":561,"line":1171},[30042],{"type":415,"tag":559,"props":30043,"children":30044},{"style":583},[30045],{"type":420,"value":2737},{"type":415,"tag":559,"props":30047,"children":30048},{"class":561,"line":1748},[30049,30054,30059],{"type":415,"tag":559,"props":30050,"children":30051},{"style":572},[30052],{"type":420,"value":30053},"        DateTime",{"type":415,"tag":559,"props":30055,"children":30056},{"style":572},[30057],{"type":420,"value":30058}," expirationDate",{"type":415,"tag":559,"props":30060,"children":30061},{"style":583},[30062],{"type":420,"value":1509},{"type":415,"tag":559,"props":30064,"children":30065},{"class":561,"line":1769},[30066,30071,30076,30081,30085,30090,30094,30098,30102,30106,30110,30114,30118,30122],{"type":415,"tag":559,"props":30067,"children":30068},{"style":745},[30069],{"type":420,"value":30070},"        if",{"type":415,"tag":559,"props":30072,"children":30073},{"style":583},[30074],{"type":420,"value":30075}," (!",{"type":415,"tag":559,"props":30077,"children":30078},{"style":792},[30079],{"type":420,"value":30080},"_memoryCache",{"type":415,"tag":559,"props":30082,"children":30083},{"style":583},[30084],{"type":420,"value":542},{"type":415,"tag":559,"props":30086,"children":30087},{"style":883},[30088],{"type":420,"value":30089},"TryGetValue",{"type":415,"tag":559,"props":30091,"children":30092},{"style":583},[30093],{"type":420,"value":814},{"type":415,"tag":559,"props":30095,"children":30096},{"style":583},[30097],{"type":420,"value":819},{"type":415,"tag":559,"props":30099,"children":30100},{"style":822},[30101],{"type":420,"value":29704},{"type":415,"tag":559,"props":30103,"children":30104},{"style":583},[30105],{"type":420,"value":819},{"type":415,"tag":559,"props":30107,"children":30108},{"style":583},[30109],{"type":420,"value":2312},{"type":415,"tag":559,"props":30111,"children":30112},{"style":566},[30113],{"type":420,"value":1454},{"type":415,"tag":559,"props":30115,"children":30116},{"style":583},[30117],{"type":420,"value":1129},{"type":415,"tag":559,"props":30119,"children":30120},{"style":572},[30121],{"type":420,"value":28812},{"type":415,"tag":559,"props":30123,"children":30124},{"style":583},[30125],{"type":420,"value":6258},{"type":415,"tag":559,"props":30127,"children":30128},{"class":561,"line":1786},[30129],{"type":415,"tag":559,"props":30130,"children":30131},{"style":583},[30132],{"type":420,"value":6266},{"type":415,"tag":559,"props":30134,"children":30135},{"class":561,"line":1795},[30136,30141,30145,30149,30153,30157,30161,30165,30169,30173,30177,30181,30185,30189,30193,30197,30201],{"type":415,"tag":559,"props":30137,"children":30138},{"style":572},[30139],{"type":420,"value":30140},"            var",{"type":415,"tag":559,"props":30142,"children":30143},{"style":572},[30144],{"type":420,"value":28229},{"type":415,"tag":559,"props":30146,"children":30147},{"style":583},[30148],{"type":420,"value":763},{"type":415,"tag":559,"props":30150,"children":30151},{"style":583},[30152],{"type":420,"value":768},{"type":415,"tag":559,"props":30154,"children":30155},{"style":583},[30156],{"type":420,"value":1144},{"type":415,"tag":559,"props":30158,"children":30159},{"style":792},[30160],{"type":420,"value":28246},{"type":415,"tag":559,"props":30162,"children":30163},{"style":583},[30164],{"type":420,"value":800},{"type":415,"tag":559,"props":30166,"children":30167},{"style":583},[30168],{"type":420,"value":1434},{"type":415,"tag":559,"props":30170,"children":30171},{"style":822},[30172],{"type":420,"value":28259},{"type":415,"tag":559,"props":30174,"children":30175},{"style":583},[30176],{"type":420,"value":819},{"type":415,"tag":559,"props":30178,"children":30179},{"style":583},[30180],{"type":420,"value":2312},{"type":415,"tag":559,"props":30182,"children":30183},{"style":792},[30184],{"type":420,"value":28272},{"type":415,"tag":559,"props":30186,"children":30187},{"style":583},[30188],{"type":420,"value":800},{"type":415,"tag":559,"props":30190,"children":30191},{"style":583},[30192],{"type":420,"value":1434},{"type":415,"tag":559,"props":30194,"children":30195},{"style":822},[30196],{"type":420,"value":28285},{"type":415,"tag":559,"props":30198,"children":30199},{"style":583},[30200],{"type":420,"value":819},{"type":415,"tag":559,"props":30202,"children":30203},{"style":583},[30204],{"type":420,"value":11432},{"type":415,"tag":559,"props":30206,"children":30207},{"class":561,"line":3289},[30208,30212,30216,30220,30224,30228,30232,30236,30240,30244,30248,30252,30256,30260,30264,30268,30272,30276,30280,30284,30288],{"type":415,"tag":559,"props":30209,"children":30210},{"style":572},[30211],{"type":420,"value":30140},{"type":415,"tag":559,"props":30213,"children":30214},{"style":572},[30215],{"type":420,"value":2750},{"type":415,"tag":559,"props":30217,"children":30218},{"style":583},[30219],{"type":420,"value":763},{"type":415,"tag":559,"props":30221,"children":30222},{"style":583},[30223],{"type":420,"value":872},{"type":415,"tag":559,"props":30225,"children":30226},{"style":792},[30227],{"type":420,"value":28317},{"type":415,"tag":559,"props":30229,"children":30230},{"style":583},[30231],{"type":420,"value":542},{"type":415,"tag":559,"props":30233,"children":30234},{"style":883},[30235],{"type":420,"value":22340},{"type":415,"tag":559,"props":30237,"children":30238},{"style":583},[30239],{"type":420,"value":814},{"type":415,"tag":559,"props":30241,"children":30242},{"style":583},[30243],{"type":420,"value":819},{"type":415,"tag":559,"props":30245,"children":30246},{"style":822},[30247],{"type":420,"value":28259},{"type":415,"tag":559,"props":30249,"children":30250},{"style":583},[30251],{"type":420,"value":819},{"type":415,"tag":559,"props":30253,"children":30254},{"style":583},[30255],{"type":420,"value":2312},{"type":415,"tag":559,"props":30257,"children":30258},{"style":583},[30259],{"type":420,"value":768},{"type":415,"tag":559,"props":30261,"children":30262},{"style":572},[30263],{"type":420,"value":28354},{"type":415,"tag":559,"props":30265,"children":30266},{"style":583},[30267],{"type":420,"value":814},{"type":415,"tag":559,"props":30269,"children":30270},{"style":792},[30271],{"type":420,"value":28363},{"type":415,"tag":559,"props":30273,"children":30274},{"style":583},[30275],{"type":420,"value":542},{"type":415,"tag":559,"props":30277,"children":30278},{"style":883},[30279],{"type":420,"value":28372},{"type":415,"tag":559,"props":30281,"children":30282},{"style":583},[30283],{"type":420,"value":814},{"type":415,"tag":559,"props":30285,"children":30286},{"style":792},[30287],{"type":420,"value":28381},{"type":415,"tag":559,"props":30289,"children":30290},{"style":583},[30291],{"type":420,"value":28386},{"type":415,"tag":559,"props":30293,"children":30294},{"class":561,"line":3297},[30295,30300,30305,30309,30314,30318,30322,30326,30330,30334,30338,30342,30346,30350,30354],{"type":415,"tag":559,"props":30296,"children":30297},{"style":583},[30298],{"type":420,"value":30299},"            (",{"type":415,"tag":559,"props":30301,"children":30302},{"style":792},[30303],{"type":420,"value":30304},"token",{"type":415,"tag":559,"props":30306,"children":30307},{"style":583},[30308],{"type":420,"value":2312},{"type":415,"tag":559,"props":30310,"children":30311},{"style":792},[30312],{"type":420,"value":30313},"  expirationDate",{"type":415,"tag":559,"props":30315,"children":30316},{"style":583},[30317],{"type":420,"value":1468},{"type":415,"tag":559,"props":30319,"children":30320},{"style":583},[30321],{"type":420,"value":763},{"type":415,"tag":559,"props":30323,"children":30324},{"style":583},[30325],{"type":420,"value":872},{"type":415,"tag":559,"props":30327,"children":30328},{"style":792},[30329],{"type":420,"value":2750},{"type":415,"tag":559,"props":30331,"children":30332},{"style":583},[30333],{"type":420,"value":542},{"type":415,"tag":559,"props":30335,"children":30336},{"style":792},[30337],{"type":420,"value":28419},{"type":415,"tag":559,"props":30339,"children":30340},{"style":583},[30341],{"type":420,"value":542},{"type":415,"tag":559,"props":30343,"children":30344},{"style":883},[30345],{"type":420,"value":28428},{"type":415,"tag":559,"props":30347,"children":30348},{"style":583},[30349],{"type":420,"value":891},{"type":415,"tag":559,"props":30351,"children":30352},{"style":572},[30353],{"type":420,"value":28030},{"type":415,"tag":559,"props":30355,"children":30356},{"style":583},[30357],{"type":420,"value":5703},{"type":415,"tag":559,"props":30359,"children":30360},{"class":561,"line":3349},[30361,30366,30370,30375,30379,30383,30387,30391,30395,30399,30403,30407,30411,30415,30420],{"type":415,"tag":559,"props":30362,"children":30363},{"style":792},[30364],{"type":420,"value":30365},"            _memoryCache",{"type":415,"tag":559,"props":30367,"children":30368},{"style":583},[30369],{"type":420,"value":542},{"type":415,"tag":559,"props":30371,"children":30372},{"style":883},[30373],{"type":420,"value":30374},"Set",{"type":415,"tag":559,"props":30376,"children":30377},{"style":583},[30378],{"type":420,"value":814},{"type":415,"tag":559,"props":30380,"children":30381},{"style":583},[30382],{"type":420,"value":819},{"type":415,"tag":559,"props":30384,"children":30385},{"style":822},[30386],{"type":420,"value":29704},{"type":415,"tag":559,"props":30388,"children":30389},{"style":583},[30390],{"type":420,"value":819},{"type":415,"tag":559,"props":30392,"children":30393},{"style":583},[30394],{"type":420,"value":2312},{"type":415,"tag":559,"props":30396,"children":30397},{"style":792},[30398],{"type":420,"value":28812},{"type":415,"tag":559,"props":30400,"children":30401},{"style":583},[30402],{"type":420,"value":2312},{"type":415,"tag":559,"props":30404,"children":30405},{"style":583},[30406],{"type":420,"value":768},{"type":415,"tag":559,"props":30408,"children":30409},{"style":572},[30410],{"type":420,"value":1271},{"type":415,"tag":559,"props":30412,"children":30413},{"style":583},[30414],{"type":420,"value":814},{"type":415,"tag":559,"props":30416,"children":30417},{"style":792},[30418],{"type":420,"value":30419},"expirationDate",{"type":415,"tag":559,"props":30421,"children":30422},{"style":583},[30423],{"type":420,"value":5796},{"type":415,"tag":559,"props":30425,"children":30426},{"class":561,"line":3374},[30427],{"type":415,"tag":559,"props":30428,"children":30429},{"style":583},[30430],{"type":420,"value":6316},{"type":415,"tag":559,"props":30432,"children":30433},{"class":561,"line":3382},[30434,30438,30442],{"type":415,"tag":559,"props":30435,"children":30436},{"style":745},[30437],{"type":420,"value":8218},{"type":415,"tag":559,"props":30439,"children":30440},{"style":792},[30441],{"type":420,"value":28812},{"type":415,"tag":559,"props":30443,"children":30444},{"style":583},[30445],{"type":420,"value":1509},{"type":415,"tag":559,"props":30447,"children":30448},{"class":561,"line":3390},[30449],{"type":415,"tag":559,"props":30450,"children":30451},{"style":583},[30452],{"type":420,"value":2792},{"type":415,"tag":559,"props":30454,"children":30455},{"class":561,"line":3434},[30456],{"type":415,"tag":559,"props":30457,"children":30458},{"style":583},[30459],{"type":420,"value":1801},{"type":415,"tag":416,"props":30461,"children":30462},{},[30463,30465,30471,30473,30479],{"type":420,"value":30464},"To avoid requesting always the same token to the API, we added a line to store the token in the memory cache and a line to check if the token is already in the cache before querying the API.\nWe could also have used a class as a singleton to store the token and its expiration date, but the built-in ",{"type":415,"tag":555,"props":30466,"children":30468},{"className":30467},[],[30469],{"type":420,"value":30470},"IMemoryCache",{"type":420,"value":30472}," of ASP.NET Core is more convenient and handle the expiration of the token for us by removing it from the cache when the date is passed. You can find more about cache memory in ASP.NET Core ",{"type":415,"tag":434,"props":30474,"children":30477},{"href":30475,"rel":30476},"https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1",[438],[30478],{"type":420,"value":540},{"type":420,"value":542},{"type":415,"tag":422,"props":30481,"children":30483},{"id":30482},"use-a-delegating-handler-to-directly-set-the-token-in-the-httpclient-request",[30484],{"type":420,"value":30485},"Use a Delegating handler to directly set the token in the HttpClient request",{"type":415,"tag":416,"props":30487,"children":30488},{},[30489,30491,30496,30498,30503,30505,30510,30512,30517,30519,30524],{"type":420,"value":30490},"Handling the token retrieval in a separate service is nice but that does not solve the issue of duplicated code. Even if the ",{"type":415,"tag":555,"props":30492,"children":30494},{"className":30493},[],[30495],{"type":420,"value":29741},{"type":420,"value":30497}," method is now part of ",{"type":415,"tag":555,"props":30499,"children":30501},{"className":30500},[],[30502],{"type":420,"value":29786},{"type":420,"value":30504},", each method of ",{"type":415,"tag":555,"props":30506,"children":30508},{"className":30507},[],[30509],{"type":420,"value":28606},{"type":420,"value":30511}," will still call ",{"type":415,"tag":555,"props":30513,"children":30515},{"className":30514},[],[30516],{"type":420,"value":29741},{"type":420,"value":30518},". Moreover setting the token on each request should not be a concern of ",{"type":415,"tag":555,"props":30520,"children":30522},{"className":30521},[],[30523],{"type":420,"value":28606},{"type":420,"value":542},{"type":415,"tag":416,"props":30526,"children":30527},{},[30528,30530,30535,30537,30542,30544,30548,30550,30556],{"type":420,"value":30529},"That's where come ",{"type":415,"tag":14435,"props":30531,"children":30532},{},[30533],{"type":420,"value":30534},"delegating handlers",{"type":420,"value":30536},". A delegating handler is quite similar to an ASP.NET Core middleware but instead of applying some processing on an incoming request and its response, it does so on an outgoing request and its response. In concrete terms, you use a delegating handler to apply something (logging, authentication, caching ...) to HTTP requests you make to an API using an ",{"type":415,"tag":555,"props":30538,"children":30540},{"className":30539},[],[30541],{"type":420,"value":707},{"type":420,"value":30543},". To learn more about ",{"type":415,"tag":14435,"props":30545,"children":30546},{},[30547],{"type":420,"value":30534},{"type":420,"value":30549}," there is a nice ",{"type":415,"tag":434,"props":30551,"children":30554},{"href":30552,"rel":30553},"https://www.stevejgordon.co.uk/httpclientfactory-aspnetcore-outgoing-request-middleware-pipeline-delegatinghandlers",[438],[30555],{"type":420,"value":22445},{"type":420,"value":30557}," from Steve Gordon on the topic.",{"type":415,"tag":416,"props":30559,"children":30560},{},[30561,30563,30568],{"type":420,"value":30562},"A custom delegating handler is exactly what we need: a piece of code that all our HTTP requests from ",{"type":415,"tag":555,"props":30564,"children":30566},{"className":30565},[],[30567],{"type":420,"value":28606},{"type":420,"value":30569}," will go through and where we will be able to set the token on the authentication header of each request. Here is the code of our custom delegating handler:",{"type":415,"tag":549,"props":30571,"children":30573},{"className":551,"code":30572,"language":326,"meta":401,"style":401},"public class UserApiAuthenticationHandler : DelegatingHandler\n{\n    private readonly IUserApiAuthenticationService _authenticationService;\n\n    public UserApiAuthenticationHandler(IUserApiAuthenticationService authenticationService)\n    {\n        _authenticationService = authenticationService;\n    }\n    \n    protected async override Task\u003CHttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationTokencancellationToken)\n    {\n        var token = await _authenticationService.RetrieveToken();\n        request.Headers.Authorization = new AuthenticationHeaderValue(\"Bearer\", token);\n        return await base.SendAsync(request, cancellationToken);\n    }\n}\n",[30574],{"type":415,"tag":555,"props":30575,"children":30576},{"__ignoreMap":401},[30577,30602,30609,30634,30641,30670,30677,30697,30704,30711,30774,30781,30816,30879,30924,30931],{"type":415,"tag":559,"props":30578,"children":30579},{"class":561,"line":562},[30580,30584,30588,30593,30597],{"type":415,"tag":559,"props":30581,"children":30582},{"style":566},[30583],{"type":420,"value":569},{"type":415,"tag":559,"props":30585,"children":30586},{"style":572},[30587],{"type":420,"value":5933},{"type":415,"tag":559,"props":30589,"children":30590},{"style":572},[30591],{"type":420,"value":30592}," UserApiAuthenticationHandler",{"type":415,"tag":559,"props":30594,"children":30595},{"style":583},[30596],{"type":420,"value":2437},{"type":415,"tag":559,"props":30598,"children":30599},{"style":572},[30600],{"type":420,"value":30601}," DelegatingHandler\n",{"type":415,"tag":559,"props":30603,"children":30604},{"class":561,"line":589},[30605],{"type":415,"tag":559,"props":30606,"children":30607},{"style":583},[30608],{"type":420,"value":786},{"type":415,"tag":559,"props":30610,"children":30611},{"class":561,"line":608},[30612,30616,30620,30625,30630],{"type":415,"tag":559,"props":30613,"children":30614},{"style":566},[30615],{"type":420,"value":5962},{"type":415,"tag":559,"props":30617,"children":30618},{"style":566},[30619],{"type":420,"value":5967},{"type":415,"tag":559,"props":30621,"children":30622},{"style":572},[30623],{"type":420,"value":30624}," IUserApiAuthenticationService",{"type":415,"tag":559,"props":30626,"children":30627},{"style":572},[30628],{"type":420,"value":30629}," _authenticationService",{"type":415,"tag":559,"props":30631,"children":30632},{"style":583},[30633],{"type":420,"value":1509},{"type":415,"tag":559,"props":30635,"children":30636},{"class":561,"line":626},[30637],{"type":415,"tag":559,"props":30638,"children":30639},{"emptyLinePlaceholder":847},[30640],{"type":420,"value":850},{"type":415,"tag":559,"props":30642,"children":30643},{"class":561,"line":643},[30644,30648,30652,30656,30661,30666],{"type":415,"tag":559,"props":30645,"children":30646},{"style":566},[30647],{"type":420,"value":1124},{"type":415,"tag":559,"props":30649,"children":30650},{"style":883},[30651],{"type":420,"value":30592},{"type":415,"tag":559,"props":30653,"children":30654},{"style":583},[30655],{"type":420,"value":814},{"type":415,"tag":559,"props":30657,"children":30658},{"style":572},[30659],{"type":420,"value":30660},"IUserApiAuthenticationService",{"type":415,"tag":559,"props":30662,"children":30663},{"style":572},[30664],{"type":420,"value":30665}," authenticationService",{"type":415,"tag":559,"props":30667,"children":30668},{"style":583},[30669],{"type":420,"value":833},{"type":415,"tag":559,"props":30671,"children":30672},{"class":561,"line":660},[30673],{"type":415,"tag":559,"props":30674,"children":30675},{"style":583},[30676],{"type":420,"value":2737},{"type":415,"tag":559,"props":30678,"children":30679},{"class":561,"line":677},[30680,30685,30689,30693],{"type":415,"tag":559,"props":30681,"children":30682},{"style":792},[30683],{"type":420,"value":30684},"        _authenticationService ",{"type":415,"tag":559,"props":30686,"children":30687},{"style":583},[30688],{"type":420,"value":800},{"type":415,"tag":559,"props":30690,"children":30691},{"style":792},[30692],{"type":420,"value":30665},{"type":415,"tag":559,"props":30694,"children":30695},{"style":583},[30696],{"type":420,"value":1509},{"type":415,"tag":559,"props":30698,"children":30699},{"class":561,"line":690},[30700],{"type":415,"tag":559,"props":30701,"children":30702},{"style":583},[30703],{"type":420,"value":2792},{"type":415,"tag":559,"props":30705,"children":30706},{"class":561,"line":1089},[30707],{"type":415,"tag":559,"props":30708,"children":30709},{"style":792},[30710],{"type":420,"value":6508},{"type":415,"tag":559,"props":30712,"children":30713},{"class":561,"line":1102},[30714,30718,30722,30726,30730,30734,30739,30743,30748,30752,30757,30761,30765,30770],{"type":415,"tag":559,"props":30715,"children":30716},{"style":566},[30717],{"type":420,"value":6149},{"type":415,"tag":559,"props":30719,"children":30720},{"style":566},[30721],{"type":420,"value":6159},{"type":415,"tag":559,"props":30723,"children":30724},{"style":566},[30725],{"type":420,"value":6154},{"type":415,"tag":559,"props":30727,"children":30728},{"style":572},[30729],{"type":420,"value":2006},{"type":415,"tag":559,"props":30731,"children":30732},{"style":583},[30733],{"type":420,"value":891},{"type":415,"tag":559,"props":30735,"children":30736},{"style":572},[30737],{"type":420,"value":30738},"HttpResponseMessage",{"type":415,"tag":559,"props":30740,"children":30741},{"style":583},[30742],{"type":420,"value":5985},{"type":415,"tag":559,"props":30744,"children":30745},{"style":883},[30746],{"type":420,"value":30747}," SendAsync",{"type":415,"tag":559,"props":30749,"children":30750},{"style":583},[30751],{"type":420,"value":814},{"type":415,"tag":559,"props":30753,"children":30754},{"style":572},[30755],{"type":420,"value":30756},"HttpRequestMessage",{"type":415,"tag":559,"props":30758,"children":30759},{"style":572},[30760],{"type":420,"value":28841},{"type":415,"tag":559,"props":30762,"children":30763},{"style":583},[30764],{"type":420,"value":2312},{"type":415,"tag":559,"props":30766,"children":30767},{"style":792},[30768],{"type":420,"value":30769}," CancellationTokencancellationToken",{"type":415,"tag":559,"props":30771,"children":30772},{"style":583},[30773],{"type":420,"value":833},{"type":415,"tag":559,"props":30775,"children":30776},{"class":561,"line":1110},[30777],{"type":415,"tag":559,"props":30778,"children":30779},{"style":583},[30780],{"type":420,"value":2737},{"type":415,"tag":559,"props":30782,"children":30783},{"class":561,"line":1118},[30784,30788,30792,30796,30800,30804,30808,30812],{"type":415,"tag":559,"props":30785,"children":30786},{"style":572},[30787],{"type":420,"value":2745},{"type":415,"tag":559,"props":30789,"children":30790},{"style":572},[30791],{"type":420,"value":28812},{"type":415,"tag":559,"props":30793,"children":30794},{"style":583},[30795],{"type":420,"value":763},{"type":415,"tag":559,"props":30797,"children":30798},{"style":583},[30799],{"type":420,"value":872},{"type":415,"tag":559,"props":30801,"children":30802},{"style":792},[30803],{"type":420,"value":30629},{"type":415,"tag":559,"props":30805,"children":30806},{"style":583},[30807],{"type":420,"value":542},{"type":415,"tag":559,"props":30809,"children":30810},{"style":883},[30811],{"type":420,"value":29741},{"type":415,"tag":559,"props":30813,"children":30814},{"style":583},[30815],{"type":420,"value":1962},{"type":415,"tag":559,"props":30817,"children":30818},{"class":561,"line":1171},[30819,30823,30827,30831,30835,30839,30843,30847,30851,30855,30859,30863,30867,30871,30875],{"type":415,"tag":559,"props":30820,"children":30821},{"style":792},[30822],{"type":420,"value":28900},{"type":415,"tag":559,"props":30824,"children":30825},{"style":583},[30826],{"type":420,"value":542},{"type":415,"tag":559,"props":30828,"children":30829},{"style":792},[30830],{"type":420,"value":28909},{"type":415,"tag":559,"props":30832,"children":30833},{"style":583},[30834],{"type":420,"value":542},{"type":415,"tag":559,"props":30836,"children":30837},{"style":792},[30838],{"type":420,"value":22275},{"type":415,"tag":559,"props":30840,"children":30841},{"style":583},[30842],{"type":420,"value":800},{"type":415,"tag":559,"props":30844,"children":30845},{"style":583},[30846],{"type":420,"value":768},{"type":415,"tag":559,"props":30848,"children":30849},{"style":572},[30850],{"type":420,"value":22288},{"type":415,"tag":559,"props":30852,"children":30853},{"style":583},[30854],{"type":420,"value":814},{"type":415,"tag":559,"props":30856,"children":30857},{"style":583},[30858],{"type":420,"value":819},{"type":415,"tag":559,"props":30860,"children":30861},{"style":822},[30862],{"type":420,"value":28942},{"type":415,"tag":559,"props":30864,"children":30865},{"style":583},[30866],{"type":420,"value":819},{"type":415,"tag":559,"props":30868,"children":30869},{"style":583},[30870],{"type":420,"value":2312},{"type":415,"tag":559,"props":30872,"children":30873},{"style":792},[30874],{"type":420,"value":28812},{"type":415,"tag":559,"props":30876,"children":30877},{"style":583},[30878],{"type":420,"value":696},{"type":415,"tag":559,"props":30880,"children":30881},{"class":561,"line":1748},[30882,30886,30890,30895,30899,30903,30907,30911,30915,30920],{"type":415,"tag":559,"props":30883,"children":30884},{"style":745},[30885],{"type":420,"value":8218},{"type":415,"tag":559,"props":30887,"children":30888},{"style":583},[30889],{"type":420,"value":872},{"type":415,"tag":559,"props":30891,"children":30892},{"style":792},[30893],{"type":420,"value":30894}," base",{"type":415,"tag":559,"props":30896,"children":30897},{"style":583},[30898],{"type":420,"value":542},{"type":415,"tag":559,"props":30900,"children":30901},{"style":883},[30902],{"type":420,"value":28990},{"type":415,"tag":559,"props":30904,"children":30905},{"style":583},[30906],{"type":420,"value":814},{"type":415,"tag":559,"props":30908,"children":30909},{"style":792},[30910],{"type":420,"value":28999},{"type":415,"tag":559,"props":30912,"children":30913},{"style":583},[30914],{"type":420,"value":2312},{"type":415,"tag":559,"props":30916,"children":30917},{"style":792},[30918],{"type":420,"value":30919}," cancellationToken",{"type":415,"tag":559,"props":30921,"children":30922},{"style":583},[30923],{"type":420,"value":696},{"type":415,"tag":559,"props":30925,"children":30926},{"class":561,"line":1769},[30927],{"type":415,"tag":559,"props":30928,"children":30929},{"style":583},[30930],{"type":420,"value":2792},{"type":415,"tag":559,"props":30932,"children":30933},{"class":561,"line":1786},[30934],{"type":415,"tag":559,"props":30935,"children":30936},{"style":583},[30937],{"type":420,"value":1801},{"type":415,"tag":416,"props":30939,"children":30940},{},[30941],{"type":420,"value":30942},"That's it, we don't need anymore to handle token retrieval on UserService which becomes simpler:",{"type":415,"tag":549,"props":30944,"children":30946},{"className":551,"code":30945,"language":326,"meta":401,"style":401},"public class UserService : \n{\n    private readonly HttpClient _httpClient;\n    public UserService(HttpClient httpClient)\n    {\n        _httpClient = httpClient;\n    }\n\n    public async Task\u003CIReadOnlyCollection\u003CUser>> GetAllUsers()\n    {\n        var response = await _httpClient.GetAsync(new Uri(\"user\"));\n        response.EnsureSuccessStatusCode();\n        return await response.Content.ReadAsAsync\u003CIReadOnlyCollection\u003CUser>>();\n    }\n\n    public async Task UpdateUser(User userToUpdate)\n    {\n        var content = new StringContent(JsonConvert.SerializeObject(userToUpdate));\n        var response = await _httpClient.PutAsync($\"user/{userToUpdate.Name}\", content);\n        response.EnsureSuccessStatusCode();\n    }\n}\n",[30947],{"type":415,"tag":555,"props":30948,"children":30949},{"__ignoreMap":401},[30950,30973,30980,31003,31030,31037,31056,31063,31070,31113,31120,31180,31199,31250,31257,31264,31299,31306,31358,31434,31453,31460],{"type":415,"tag":559,"props":30951,"children":30952},{"class":561,"line":562},[30953,30957,30961,30965,30969],{"type":415,"tag":559,"props":30954,"children":30955},{"style":566},[30956],{"type":420,"value":569},{"type":415,"tag":559,"props":30958,"children":30959},{"style":572},[30960],{"type":420,"value":5933},{"type":415,"tag":559,"props":30962,"children":30963},{"style":572},[30964],{"type":420,"value":28644},{"type":415,"tag":559,"props":30966,"children":30967},{"style":583},[30968],{"type":420,"value":2437},{"type":415,"tag":559,"props":30970,"children":30971},{"style":792},[30972],{"type":420,"value":1473},{"type":415,"tag":559,"props":30974,"children":30975},{"class":561,"line":589},[30976],{"type":415,"tag":559,"props":30977,"children":30978},{"style":583},[30979],{"type":420,"value":786},{"type":415,"tag":559,"props":30981,"children":30982},{"class":561,"line":608},[30983,30987,30991,30995,30999],{"type":415,"tag":559,"props":30984,"children":30985},{"style":566},[30986],{"type":420,"value":5962},{"type":415,"tag":559,"props":30988,"children":30989},{"style":566},[30990],{"type":420,"value":5967},{"type":415,"tag":559,"props":30992,"children":30993},{"style":572},[30994],{"type":420,"value":773},{"type":415,"tag":559,"props":30996,"children":30997},{"style":572},[30998],{"type":420,"value":28317},{"type":415,"tag":559,"props":31000,"children":31001},{"style":583},[31002],{"type":420,"value":1509},{"type":415,"tag":559,"props":31004,"children":31005},{"class":561,"line":626},[31006,31010,31014,31018,31022,31026],{"type":415,"tag":559,"props":31007,"children":31008},{"style":566},[31009],{"type":420,"value":1124},{"type":415,"tag":559,"props":31011,"children":31012},{"style":883},[31013],{"type":420,"value":28644},{"type":415,"tag":559,"props":31015,"children":31016},{"style":583},[31017],{"type":420,"value":814},{"type":415,"tag":559,"props":31019,"children":31020},{"style":572},[31021],{"type":420,"value":707},{"type":415,"tag":559,"props":31023,"children":31024},{"style":572},[31025],{"type":420,"value":758},{"type":415,"tag":559,"props":31027,"children":31028},{"style":583},[31029],{"type":420,"value":833},{"type":415,"tag":559,"props":31031,"children":31032},{"class":561,"line":643},[31033],{"type":415,"tag":559,"props":31034,"children":31035},{"style":583},[31036],{"type":420,"value":2737},{"type":415,"tag":559,"props":31038,"children":31039},{"class":561,"line":660},[31040,31044,31048,31052],{"type":415,"tag":559,"props":31041,"children":31042},{"style":792},[31043],{"type":420,"value":28724},{"type":415,"tag":559,"props":31045,"children":31046},{"style":583},[31047],{"type":420,"value":800},{"type":415,"tag":559,"props":31049,"children":31050},{"style":792},[31051],{"type":420,"value":758},{"type":415,"tag":559,"props":31053,"children":31054},{"style":583},[31055],{"type":420,"value":1509},{"type":415,"tag":559,"props":31057,"children":31058},{"class":561,"line":677},[31059],{"type":415,"tag":559,"props":31060,"children":31061},{"style":583},[31062],{"type":420,"value":2792},{"type":415,"tag":559,"props":31064,"children":31065},{"class":561,"line":690},[31066],{"type":415,"tag":559,"props":31067,"children":31068},{"emptyLinePlaceholder":847},[31069],{"type":420,"value":850},{"type":415,"tag":559,"props":31071,"children":31072},{"class":561,"line":1089},[31073,31077,31081,31085,31089,31093,31097,31101,31105,31109],{"type":415,"tag":559,"props":31074,"children":31075},{"style":566},[31076],{"type":420,"value":1124},{"type":415,"tag":559,"props":31078,"children":31079},{"style":566},[31080],{"type":420,"value":6159},{"type":415,"tag":559,"props":31082,"children":31083},{"style":572},[31084],{"type":420,"value":2006},{"type":415,"tag":559,"props":31086,"children":31087},{"style":583},[31088],{"type":420,"value":891},{"type":415,"tag":559,"props":31090,"children":31091},{"style":572},[31092],{"type":420,"value":28135},{"type":415,"tag":559,"props":31094,"children":31095},{"style":583},[31096],{"type":420,"value":891},{"type":415,"tag":559,"props":31098,"children":31099},{"style":572},[31100],{"type":420,"value":23614},{"type":415,"tag":559,"props":31102,"children":31103},{"style":583},[31104],{"type":420,"value":28148},{"type":415,"tag":559,"props":31106,"children":31107},{"style":883},[31108],{"type":420,"value":28153},{"type":415,"tag":559,"props":31110,"children":31111},{"style":583},[31112],{"type":420,"value":778},{"type":415,"tag":559,"props":31114,"children":31115},{"class":561,"line":1102},[31116],{"type":415,"tag":559,"props":31117,"children":31118},{"style":583},[31119],{"type":420,"value":2737},{"type":415,"tag":559,"props":31121,"children":31122},{"class":561,"line":1110},[31123,31127,31131,31135,31139,31143,31147,31152,31156,31160,31164,31168,31172,31176],{"type":415,"tag":559,"props":31124,"children":31125},{"style":572},[31126],{"type":420,"value":2745},{"type":415,"tag":559,"props":31128,"children":31129},{"style":572},[31130],{"type":420,"value":2750},{"type":415,"tag":559,"props":31132,"children":31133},{"style":583},[31134],{"type":420,"value":763},{"type":415,"tag":559,"props":31136,"children":31137},{"style":583},[31138],{"type":420,"value":872},{"type":415,"tag":559,"props":31140,"children":31141},{"style":792},[31142],{"type":420,"value":28317},{"type":415,"tag":559,"props":31144,"children":31145},{"style":583},[31146],{"type":420,"value":542},{"type":415,"tag":559,"props":31148,"children":31149},{"style":883},[31150],{"type":420,"value":31151},"GetAsync",{"type":415,"tag":559,"props":31153,"children":31154},{"style":583},[31155],{"type":420,"value":5770},{"type":415,"tag":559,"props":31157,"children":31158},{"style":572},[31159],{"type":420,"value":809},{"type":415,"tag":559,"props":31161,"children":31162},{"style":583},[31163],{"type":420,"value":814},{"type":415,"tag":559,"props":31165,"children":31166},{"style":583},[31167],{"type":420,"value":819},{"type":415,"tag":559,"props":31169,"children":31170},{"style":822},[31171],{"type":420,"value":28884},{"type":415,"tag":559,"props":31173,"children":31174},{"style":583},[31175],{"type":420,"value":819},{"type":415,"tag":559,"props":31177,"children":31178},{"style":583},[31179],{"type":420,"value":5796},{"type":415,"tag":559,"props":31181,"children":31182},{"class":561,"line":1118},[31183,31187,31191,31195],{"type":415,"tag":559,"props":31184,"children":31185},{"style":792},[31186],{"type":420,"value":29011},{"type":415,"tag":559,"props":31188,"children":31189},{"style":583},[31190],{"type":420,"value":542},{"type":415,"tag":559,"props":31192,"children":31193},{"style":883},[31194],{"type":420,"value":29020},{"type":415,"tag":559,"props":31196,"children":31197},{"style":583},[31198],{"type":420,"value":1962},{"type":415,"tag":559,"props":31200,"children":31201},{"class":561,"line":1171},[31202,31206,31210,31214,31218,31222,31226,31230,31234,31238,31242,31246],{"type":415,"tag":559,"props":31203,"children":31204},{"style":745},[31205],{"type":420,"value":8218},{"type":415,"tag":559,"props":31207,"children":31208},{"style":583},[31209],{"type":420,"value":872},{"type":415,"tag":559,"props":31211,"children":31212},{"style":792},[31213],{"type":420,"value":2750},{"type":415,"tag":559,"props":31215,"children":31216},{"style":583},[31217],{"type":420,"value":542},{"type":415,"tag":559,"props":31219,"children":31220},{"style":792},[31221],{"type":420,"value":28419},{"type":415,"tag":559,"props":31223,"children":31224},{"style":583},[31225],{"type":420,"value":542},{"type":415,"tag":559,"props":31227,"children":31228},{"style":883},[31229],{"type":420,"value":28428},{"type":415,"tag":559,"props":31231,"children":31232},{"style":583},[31233],{"type":420,"value":891},{"type":415,"tag":559,"props":31235,"children":31236},{"style":572},[31237],{"type":420,"value":28135},{"type":415,"tag":559,"props":31239,"children":31240},{"style":583},[31241],{"type":420,"value":891},{"type":415,"tag":559,"props":31243,"children":31244},{"style":572},[31245],{"type":420,"value":23614},{"type":415,"tag":559,"props":31247,"children":31248},{"style":583},[31249],{"type":420,"value":29076},{"type":415,"tag":559,"props":31251,"children":31252},{"class":561,"line":1748},[31253],{"type":415,"tag":559,"props":31254,"children":31255},{"style":583},[31256],{"type":420,"value":2792},{"type":415,"tag":559,"props":31258,"children":31259},{"class":561,"line":1769},[31260],{"type":415,"tag":559,"props":31261,"children":31262},{"emptyLinePlaceholder":847},[31263],{"type":420,"value":850},{"type":415,"tag":559,"props":31265,"children":31266},{"class":561,"line":1786},[31267,31271,31275,31279,31283,31287,31291,31295],{"type":415,"tag":559,"props":31268,"children":31269},{"style":566},[31270],{"type":420,"value":1124},{"type":415,"tag":559,"props":31272,"children":31273},{"style":566},[31274],{"type":420,"value":6159},{"type":415,"tag":559,"props":31276,"children":31277},{"style":572},[31278],{"type":420,"value":2006},{"type":415,"tag":559,"props":31280,"children":31281},{"style":883},[31282],{"type":420,"value":28169},{"type":415,"tag":559,"props":31284,"children":31285},{"style":583},[31286],{"type":420,"value":814},{"type":415,"tag":559,"props":31288,"children":31289},{"style":572},[31290],{"type":420,"value":23614},{"type":415,"tag":559,"props":31292,"children":31293},{"style":572},[31294],{"type":420,"value":28182},{"type":415,"tag":559,"props":31296,"children":31297},{"style":583},[31298],{"type":420,"value":833},{"type":415,"tag":559,"props":31300,"children":31301},{"class":561,"line":1795},[31302],{"type":415,"tag":559,"props":31303,"children":31304},{"style":583},[31305],{"type":420,"value":2737},{"type":415,"tag":559,"props":31307,"children":31308},{"class":561,"line":3289},[31309,31313,31318,31322,31326,31330,31334,31338,31342,31346,31350,31354],{"type":415,"tag":559,"props":31310,"children":31311},{"style":572},[31312],{"type":420,"value":2745},{"type":415,"tag":559,"props":31314,"children":31315},{"style":572},[31316],{"type":420,"value":31317}," content",{"type":415,"tag":559,"props":31319,"children":31320},{"style":583},[31321],{"type":420,"value":763},{"type":415,"tag":559,"props":31323,"children":31324},{"style":583},[31325],{"type":420,"value":768},{"type":415,"tag":559,"props":31327,"children":31328},{"style":572},[31329],{"type":420,"value":28354},{"type":415,"tag":559,"props":31331,"children":31332},{"style":583},[31333],{"type":420,"value":814},{"type":415,"tag":559,"props":31335,"children":31336},{"style":792},[31337],{"type":420,"value":28363},{"type":415,"tag":559,"props":31339,"children":31340},{"style":583},[31341],{"type":420,"value":542},{"type":415,"tag":559,"props":31343,"children":31344},{"style":883},[31345],{"type":420,"value":28372},{"type":415,"tag":559,"props":31347,"children":31348},{"style":583},[31349],{"type":420,"value":814},{"type":415,"tag":559,"props":31351,"children":31352},{"style":792},[31353],{"type":420,"value":29222},{"type":415,"tag":559,"props":31355,"children":31356},{"style":583},[31357],{"type":420,"value":5796},{"type":415,"tag":559,"props":31359,"children":31360},{"class":561,"line":3297},[31361,31365,31369,31373,31377,31381,31385,31390,31394,31398,31402,31406,31410,31414,31418,31422,31426,31430],{"type":415,"tag":559,"props":31362,"children":31363},{"style":572},[31364],{"type":420,"value":2745},{"type":415,"tag":559,"props":31366,"children":31367},{"style":572},[31368],{"type":420,"value":2750},{"type":415,"tag":559,"props":31370,"children":31371},{"style":583},[31372],{"type":420,"value":763},{"type":415,"tag":559,"props":31374,"children":31375},{"style":583},[31376],{"type":420,"value":872},{"type":415,"tag":559,"props":31378,"children":31379},{"style":792},[31380],{"type":420,"value":28317},{"type":415,"tag":559,"props":31382,"children":31383},{"style":583},[31384],{"type":420,"value":542},{"type":415,"tag":559,"props":31386,"children":31387},{"style":883},[31388],{"type":420,"value":31389},"PutAsync",{"type":415,"tag":559,"props":31391,"children":31392},{"style":583},[31393],{"type":420,"value":814},{"type":415,"tag":559,"props":31395,"children":31396},{"style":583},[31397],{"type":420,"value":16136},{"type":415,"tag":559,"props":31399,"children":31400},{"style":822},[31401],{"type":420,"value":29213},{"type":415,"tag":559,"props":31403,"children":31404},{"style":583},[31405],{"type":420,"value":2397},{"type":415,"tag":559,"props":31407,"children":31408},{"style":792},[31409],{"type":420,"value":29222},{"type":415,"tag":559,"props":31411,"children":31412},{"style":583},[31413],{"type":420,"value":542},{"type":415,"tag":559,"props":31415,"children":31416},{"style":792},[31417],{"type":420,"value":1412},{"type":415,"tag":559,"props":31419,"children":31420},{"style":583},[31421],{"type":420,"value":1602},{"type":415,"tag":559,"props":31423,"children":31424},{"style":583},[31425],{"type":420,"value":2312},{"type":415,"tag":559,"props":31427,"children":31428},{"style":792},[31429],{"type":420,"value":31317},{"type":415,"tag":559,"props":31431,"children":31432},{"style":583},[31433],{"type":420,"value":696},{"type":415,"tag":559,"props":31435,"children":31436},{"class":561,"line":3349},[31437,31441,31445,31449],{"type":415,"tag":559,"props":31438,"children":31439},{"style":792},[31440],{"type":420,"value":29011},{"type":415,"tag":559,"props":31442,"children":31443},{"style":583},[31444],{"type":420,"value":542},{"type":415,"tag":559,"props":31446,"children":31447},{"style":883},[31448],{"type":420,"value":29020},{"type":415,"tag":559,"props":31450,"children":31451},{"style":583},[31452],{"type":420,"value":1962},{"type":415,"tag":559,"props":31454,"children":31455},{"class":561,"line":3374},[31456],{"type":415,"tag":559,"props":31457,"children":31458},{"style":583},[31459],{"type":420,"value":2792},{"type":415,"tag":559,"props":31461,"children":31462},{"class":561,"line":3382},[31463],{"type":415,"tag":559,"props":31464,"children":31465},{"style":583},[31466],{"type":420,"value":1801},{"type":415,"tag":416,"props":31468,"children":31469},{},[31470,31472,31478],{"type":420,"value":31471},"To finish we just have to specify in the ",{"type":415,"tag":555,"props":31473,"children":31475},{"className":31474},[],[31476],{"type":420,"value":31477},"Startup.cs",{"type":420,"value":31479}," on which HttpClient to apply the delegating handler we have just created.",{"type":415,"tag":549,"props":31481,"children":31483},{"className":551,"code":31482,"language":326,"meta":401,"style":401},"public void ConfigureServices(IServiceCollectionservices)\n{\n    services.AddMemoryCache();\n    services.AddHttpClient\u003CIUserApiAuthenticationService, UserApiAuthenticationService>()\n            .ConfigureHttpClient(c => c.BaseAddress =\"http://urltotheuserapi.com\");\n    \n    services.AddTransient\u003CUserApiAuthenticationHandler>();\n    services.AddHttpClient\u003CUserService, UserService>()\n            .ConfigureHttpClient(c => c.BaseAddress =\"http://urltotheuserapi.com\")\n            .AddHttpMessageHandler\u003CUserApiAuthenticationHanler>();\n}\n",[31484],{"type":415,"tag":555,"props":31485,"children":31486},{"__ignoreMap":401},[31487,31517,31524,31545,31581,31637,31644,31672,31707,31762,31786],{"type":415,"tag":559,"props":31488,"children":31489},{"class":561,"line":562},[31490,31494,31499,31504,31508,31513],{"type":415,"tag":559,"props":31491,"children":31492},{"style":566},[31493],{"type":420,"value":569},{"type":415,"tag":559,"props":31495,"children":31496},{"style":583},[31497],{"type":420,"value":31498}," void",{"type":415,"tag":559,"props":31500,"children":31501},{"style":883},[31502],{"type":420,"value":31503}," ConfigureServices",{"type":415,"tag":559,"props":31505,"children":31506},{"style":583},[31507],{"type":420,"value":814},{"type":415,"tag":559,"props":31509,"children":31510},{"style":792},[31511],{"type":420,"value":31512},"IServiceCollectionservices",{"type":415,"tag":559,"props":31514,"children":31515},{"style":583},[31516],{"type":420,"value":833},{"type":415,"tag":559,"props":31518,"children":31519},{"class":561,"line":589},[31520],{"type":415,"tag":559,"props":31521,"children":31522},{"style":583},[31523],{"type":420,"value":786},{"type":415,"tag":559,"props":31525,"children":31526},{"class":561,"line":608},[31527,31532,31536,31541],{"type":415,"tag":559,"props":31528,"children":31529},{"style":792},[31530],{"type":420,"value":31531},"    services",{"type":415,"tag":559,"props":31533,"children":31534},{"style":583},[31535],{"type":420,"value":542},{"type":415,"tag":559,"props":31537,"children":31538},{"style":883},[31539],{"type":420,"value":31540},"AddMemoryCache",{"type":415,"tag":559,"props":31542,"children":31543},{"style":583},[31544],{"type":420,"value":1962},{"type":415,"tag":559,"props":31546,"children":31547},{"class":561,"line":626},[31548,31552,31556,31561,31565,31569,31573,31577],{"type":415,"tag":559,"props":31549,"children":31550},{"style":792},[31551],{"type":420,"value":31531},{"type":415,"tag":559,"props":31553,"children":31554},{"style":583},[31555],{"type":420,"value":542},{"type":415,"tag":559,"props":31557,"children":31558},{"style":883},[31559],{"type":420,"value":31560},"AddHttpClient",{"type":415,"tag":559,"props":31562,"children":31563},{"style":583},[31564],{"type":420,"value":891},{"type":415,"tag":559,"props":31566,"children":31567},{"style":572},[31568],{"type":420,"value":30660},{"type":415,"tag":559,"props":31570,"children":31571},{"style":583},[31572],{"type":420,"value":2312},{"type":415,"tag":559,"props":31574,"children":31575},{"style":572},[31576],{"type":420,"value":29832},{"type":415,"tag":559,"props":31578,"children":31579},{"style":583},[31580],{"type":420,"value":13722},{"type":415,"tag":559,"props":31582,"children":31583},{"class":561,"line":643},[31584,31588,31592,31596,31600,31604,31608,31612,31616,31620,31624,31629,31633],{"type":415,"tag":559,"props":31585,"children":31586},{"style":583},[31587],{"type":420,"value":8274},{"type":415,"tag":559,"props":31589,"children":31590},{"style":883},[31591],{"type":420,"value":13734},{"type":415,"tag":559,"props":31593,"children":31594},{"style":583},[31595],{"type":420,"value":814},{"type":415,"tag":559,"props":31597,"children":31598},{"style":572},[31599],{"type":420,"value":15893},{"type":415,"tag":559,"props":31601,"children":31602},{"style":583},[31603],{"type":420,"value":1861},{"type":415,"tag":559,"props":31605,"children":31606},{"style":792},[31607],{"type":420,"value":15902},{"type":415,"tag":559,"props":31609,"children":31610},{"style":583},[31611],{"type":420,"value":542},{"type":415,"tag":559,"props":31613,"children":31614},{"style":792},[31615],{"type":420,"value":13842},{"type":415,"tag":559,"props":31617,"children":31618},{"style":583},[31619],{"type":420,"value":800},{"type":415,"tag":559,"props":31621,"children":31622},{"style":583},[31623],{"type":420,"value":819},{"type":415,"tag":559,"props":31625,"children":31626},{"style":822},[31627],{"type":420,"value":31628},"http://urltotheuserapi.com",{"type":415,"tag":559,"props":31630,"children":31631},{"style":583},[31632],{"type":420,"value":819},{"type":415,"tag":559,"props":31634,"children":31635},{"style":583},[31636],{"type":420,"value":696},{"type":415,"tag":559,"props":31638,"children":31639},{"class":561,"line":660},[31640],{"type":415,"tag":559,"props":31641,"children":31642},{"style":792},[31643],{"type":420,"value":6508},{"type":415,"tag":559,"props":31645,"children":31646},{"class":561,"line":677},[31647,31651,31655,31659,31663,31668],{"type":415,"tag":559,"props":31648,"children":31649},{"style":792},[31650],{"type":420,"value":31531},{"type":415,"tag":559,"props":31652,"children":31653},{"style":583},[31654],{"type":420,"value":542},{"type":415,"tag":559,"props":31656,"children":31657},{"style":883},[31658],{"type":420,"value":13672},{"type":415,"tag":559,"props":31660,"children":31661},{"style":583},[31662],{"type":420,"value":891},{"type":415,"tag":559,"props":31664,"children":31665},{"style":572},[31666],{"type":420,"value":31667},"UserApiAuthenticationHandler",{"type":415,"tag":559,"props":31669,"children":31670},{"style":583},[31671],{"type":420,"value":5703},{"type":415,"tag":559,"props":31673,"children":31674},{"class":561,"line":690},[31675,31679,31683,31687,31691,31695,31699,31703],{"type":415,"tag":559,"props":31676,"children":31677},{"style":792},[31678],{"type":420,"value":31531},{"type":415,"tag":559,"props":31680,"children":31681},{"style":583},[31682],{"type":420,"value":542},{"type":415,"tag":559,"props":31684,"children":31685},{"style":883},[31686],{"type":420,"value":31560},{"type":415,"tag":559,"props":31688,"children":31689},{"style":583},[31690],{"type":420,"value":891},{"type":415,"tag":559,"props":31692,"children":31693},{"style":572},[31694],{"type":420,"value":28606},{"type":415,"tag":559,"props":31696,"children":31697},{"style":583},[31698],{"type":420,"value":2312},{"type":415,"tag":559,"props":31700,"children":31701},{"style":572},[31702],{"type":420,"value":28644},{"type":415,"tag":559,"props":31704,"children":31705},{"style":583},[31706],{"type":420,"value":13722},{"type":415,"tag":559,"props":31708,"children":31709},{"class":561,"line":1089},[31710,31714,31718,31722,31726,31730,31734,31738,31742,31746,31750,31754,31758],{"type":415,"tag":559,"props":31711,"children":31712},{"style":583},[31713],{"type":420,"value":8274},{"type":415,"tag":559,"props":31715,"children":31716},{"style":883},[31717],{"type":420,"value":13734},{"type":415,"tag":559,"props":31719,"children":31720},{"style":583},[31721],{"type":420,"value":814},{"type":415,"tag":559,"props":31723,"children":31724},{"style":572},[31725],{"type":420,"value":15893},{"type":415,"tag":559,"props":31727,"children":31728},{"style":583},[31729],{"type":420,"value":1861},{"type":415,"tag":559,"props":31731,"children":31732},{"style":792},[31733],{"type":420,"value":15902},{"type":415,"tag":559,"props":31735,"children":31736},{"style":583},[31737],{"type":420,"value":542},{"type":415,"tag":559,"props":31739,"children":31740},{"style":792},[31741],{"type":420,"value":13842},{"type":415,"tag":559,"props":31743,"children":31744},{"style":583},[31745],{"type":420,"value":800},{"type":415,"tag":559,"props":31747,"children":31748},{"style":583},[31749],{"type":420,"value":819},{"type":415,"tag":559,"props":31751,"children":31752},{"style":822},[31753],{"type":420,"value":31628},{"type":415,"tag":559,"props":31755,"children":31756},{"style":583},[31757],{"type":420,"value":819},{"type":415,"tag":559,"props":31759,"children":31760},{"style":583},[31761],{"type":420,"value":833},{"type":415,"tag":559,"props":31763,"children":31764},{"class":561,"line":1102},[31765,31769,31773,31777,31782],{"type":415,"tag":559,"props":31766,"children":31767},{"style":583},[31768],{"type":420,"value":8274},{"type":415,"tag":559,"props":31770,"children":31771},{"style":883},[31772],{"type":420,"value":13895},{"type":415,"tag":559,"props":31774,"children":31775},{"style":583},[31776],{"type":420,"value":891},{"type":415,"tag":559,"props":31778,"children":31779},{"style":572},[31780],{"type":420,"value":31781},"UserApiAuthenticationHanler",{"type":415,"tag":559,"props":31783,"children":31784},{"style":583},[31785],{"type":420,"value":5703},{"type":415,"tag":559,"props":31787,"children":31788},{"class":561,"line":1110},[31789],{"type":415,"tag":559,"props":31790,"children":31791},{"style":583},[31792],{"type":420,"value":1801},{"type":415,"tag":422,"props":31794,"children":31795},{"id":18285},[31796],{"type":420,"value":18288},{"type":415,"tag":416,"props":31798,"children":31799},{},[31800],{"type":420,"value":31801},"To summarize, we have put the code that retrieves a token in a separate dedicated service that caches the token until it expires. And we have created a custom delegating handler that calls this service and sets the retrieved token on the authentication header of each HTTP request to the API.",{"type":415,"tag":5406,"props":31803,"children":31804},{},[31805],{"type":420,"value":5410},{"title":401,"searchDepth":589,"depth":589,"links":31807},[31808,31809,31810,31811,31812],{"id":27995,"depth":589,"text":27998},{"id":28592,"depth":589,"text":28595},{"id":29765,"depth":589,"text":29768},{"id":30482,"depth":589,"text":30485},{"id":18285,"depth":589,"text":18288},"content:1.posts:5.delegating-handler.md","1.posts/5.delegating-handler.md",1716749600586]