[{"data":1,"prerenderedAt":14953},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-HTTP":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,1440,7257,7913,8926,10220,14076],{"_path":190,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":189,"description":402,"lead":403,"date":404,"image":405,"badge":407,"tags":409,"ImageAttribution":410,"body":411,"_type":1435,"_id":1436,"_source":1437,"_file":1438,"_extension":1439},"posts",false,"","I have written several blog posts about HTTP clients in the past. I am a big fan of using HTTP text files versioned in a git repository alongside API code and executed by an IDE tooling. However, there was one use case where a GUI tool like Postman or a swagger page was more convenient: retrieving OAuth 2.0 users' tokens. Thanks to the latest OAuth 2.0 feature in JetBrains' IDE built-in HTTP client, this is no longer an issue.","Automatically acquire OAuth 2.0 tokens","2024-03-11T00:00:00.000Z",{"src":406},"/images/access-code-door.webp",{"label":408},"Tooling",[206,213,393,396],"Picture of \u003Ca href=\"https://unsplash.com/fr/@drice22\">Danielle Rice\u003C/a> on \u003Ca href=\"https://unsplash.com/fr/photos/personne-detenant-une-carte-en-noir-et-blanc-7GfRwb78YWs\">Unsplash\u003C/a>",{"type":412,"children":413,"toc":1425},"root",[414,442,449,471,476,481,487,492,521,526,539,558,563,576,582,587,615,622,636,650,655,660,685,690,726,743,756,762,767,772,1273,1281,1289,1302,1308,1313,1318,1330,1343,1383,1388,1394,1399,1419],{"type":415,"tag":416,"props":417,"children":418},"element","p",{},[419,422,431,433,440],{"type":420,"value":421},"text","I have written several ",{"type":415,"tag":423,"props":424,"children":428},"a",{"href":425,"rel":426},"https://www.techwatching.dev/posts/http-clients",[427],"nofollow",[429],{"type":420,"value":430},"blog posts",{"type":420,"value":432}," about HTTP clients in the past. I am a big fan of using HTTP text files versioned in a git repository alongside API code and executed by an IDE tooling. However, there was one use case where a GUI tool like Postman or a swagger page was more convenient: retrieving OAuth 2.0 users' tokens. Thanks to the latest ",{"type":415,"tag":423,"props":434,"children":437},{"href":435,"rel":436},"https://www.jetbrains.com/help/idea/oauth-2-0-authorization.html",[427],[438],{"type":420,"value":439},"OAuth 2.0 feature",{"type":420,"value":441}," in JetBrains' IDE built-in HTTP client, this is no longer an issue.",{"type":415,"tag":443,"props":444,"children":446},"h2",{"id":445},"context",[447],{"type":420,"value":448},"Context",{"type":415,"tag":416,"props":450,"children":451},{},[452,454,460,462,469],{"type":420,"value":453},"I am developing a web application composed of a Vue.js frontend and an ASP.NET Core backend (just describing my use case, technologies don't matter). The end users of this application are authenticated using ",{"type":415,"tag":423,"props":455,"children":458},{"href":456,"rel":457},"https://learn.microsoft.com/en-us/azure/active-directory-b2c/overview",[427],[459],{"type":420,"value":396},{"type":420,"value":461},", which is a ",{"type":415,"tag":423,"props":463,"children":466},{"href":464,"rel":465},"https://en.wikipedia.org/wiki/Customer_identity_access_management",[427],[467],{"type":420,"value":468},"customer identity access management",{"type":420,"value":470}," solution like Auth0 or other competitors.",{"type":415,"tag":416,"props":472,"children":473},{},[474],{"type":420,"value":475},"I often need to manually call the endpoints of the API to verify the code is working properly and that an endpoint is returning the expected result. HTTP files are a convenient way of writing and executing the HTTP requests. Once committed in the Git repository, they can easily be shared with other developers of the team who may not have worked on some endpoints and want to have proper examples with the query parameters and payloads.",{"type":415,"tag":416,"props":477,"children":478},{},[479],{"type":420,"value":480},"As the API is protected by Azure AD B2C, I need to retrieve a valid access token and pass it to my requests.",{"type":415,"tag":443,"props":482,"children":484},{"id":483},"previous-solutions",[485],{"type":420,"value":486},"Previous solutions",{"type":415,"tag":416,"props":488,"children":489},{},[490],{"type":420,"value":491},"Passing a valid access token to my HTTP requests is something I was previously doing by:",{"type":415,"tag":493,"props":494,"children":495},"ul",{},[496,502,507],{"type":415,"tag":497,"props":498,"children":499},"li",{},[500],{"type":420,"value":501},"signing in my frontend",{"type":415,"tag":497,"props":503,"children":504},{},[505],{"type":420,"value":506},"grabbing the token in the web browser dev tools",{"type":415,"tag":497,"props":508,"children":509},{},[510,512,519],{"type":420,"value":511},"copying the token to my ",{"type":415,"tag":423,"props":513,"children":516},{"href":514,"rel":515},"https://www.jetbrains.com/help/idea/exploring-http-syntax.html#environment-variables",[427],[517],{"type":420,"value":518},"HTTP environment variables",{"type":420,"value":520}," (preferably the private environment file to avoid committing a secret in your repository)",{"type":415,"tag":416,"props":522,"children":523},{},[524],{"type":420,"value":525},"That works but:",{"type":415,"tag":493,"props":527,"children":528},{},[529,534],{"type":415,"tag":497,"props":530,"children":531},{},[532],{"type":420,"value":533},"it's cumbersome",{"type":415,"tag":497,"props":535,"children":536},{},[537],{"type":420,"value":538},"you have to do it each time your access token expires",{"type":415,"tag":416,"props":540,"children":541},{},[542,544,556],{"type":420,"value":543},"Another solution is to use a tool that generates app-specific local JWTs and configure your local dev environment to authenticate with these tokens instead of using the Azure AD B2C configuration. In .NET, you can use the ",{"type":415,"tag":423,"props":545,"children":548},{"href":546,"rel":547},"https://learn.microsoft.com/en-us/aspnet/core/security/authentication/jwt-authn",[427],[549],{"type":415,"tag":550,"props":551,"children":553},"code",{"className":552},[],[554],{"type":420,"value":555},"dotnet user-jwts",{"type":420,"value":557}," to do exactly that. It allows you to generate a JWT token with the scopes, roles, and claims you want. So it's a good solution to debug your API locally without having to bypass the authentication and authorization mechanisms.",{"type":415,"tag":416,"props":559,"children":560},{},[561],{"type":420,"value":562},"However, it has some downsides:",{"type":415,"tag":493,"props":564,"children":565},{},[566,571],{"type":415,"tag":497,"props":567,"children":568},{},[569],{"type":420,"value":570},"the tokens are only valid in your local machine so it only works for your local environment",{"type":415,"tag":497,"props":572,"children":573},{},[574],{"type":420,"value":575},"the Azure AD B2C authentication is replaced by this \"local JWT authentication\" so you are not testing your API in real conditions",{"type":415,"tag":443,"props":577,"children":579},{"id":578},"with-the-new-http-client-oauth-20-feature",[580],{"type":420,"value":581},"With the new HTTP Client OAuth 2.0 feature",{"type":415,"tag":416,"props":583,"children":584},{},[585],{"type":420,"value":586},"Starting version 2024.1, HTTP Client in the JetBrains IDEs (in my case Rider 2024.1) support automatically authenticating HTTP requests, provided that you properly configured it.",{"type":415,"tag":588,"props":589,"children":591},"callout",{"icon":590},"i-heroicons-chat-bubble-left-20-solid",[592],{"type":415,"tag":416,"props":593,"children":594},{},[595,597,604,606,613],{"type":420,"value":596},"Support for OAuth 2.0 started in ",{"type":415,"tag":423,"props":598,"children":601},{"href":599,"rel":600},"https://blog.jetbrains.com/idea/2023/10/intellij-idea-2023-3-eap-3/#oauth-2.0-support",[427],[602],{"type":420,"value":603},"version 2023.3",{"type":420,"value":605},", however, Authorization Code Flow with PKCE (PKCE challenge is required in the ",{"type":415,"tag":423,"props":607,"children":610},{"href":608,"rel":609},"https://oauth.net/2.1/",[427],[611],{"type":420,"value":612},"OAuth 2.1 specification",{"type":420,"value":614}," is only supported since 2024.1.",{"type":415,"tag":616,"props":617,"children":619},"h3",{"id":618},"oauth-20-authorization-code-flow-with-pkce",[620],{"type":420,"value":621},"OAuth 2.0 authorization code flow with PKCE",{"type":415,"tag":416,"props":623,"children":624},{},[625,627,634],{"type":420,"value":626},"The OAuth 2.0 flow involved in retrieving a valid access token to make requests to an Azure AD B2C protected API is the authorization code flow with PKCE. There are 2 steps in the ",{"type":415,"tag":423,"props":628,"children":631},{"href":629,"rel":630},"https://learn.microsoft.com/en-us/azure/active-directory-b2c/authorization-code-flow",[427],[632],{"type":420,"value":633},"OAuth 2.0 authorization code flow",{"type":420,"value":635},":",{"type":415,"tag":637,"props":638,"children":639},"ol",{},[640,645],{"type":415,"tag":497,"props":641,"children":642},{},[643],{"type":420,"value":644},"Get an authorization code",{"type":415,"tag":497,"props":646,"children":647},{},[648],{"type":420,"value":649},"Exchange the authorization code for an access token",{"type":415,"tag":416,"props":651,"children":652},{},[653],{"type":420,"value":654},"Step 1 involves the user entering their credentials in the login form (Azure AD B2C login form in this case). At first sight, it might appear not very suitable for using HTTP files but the JetBrains HTTP Client handled it by opening the login form in the IDE embedded browser.",{"type":415,"tag":416,"props":656,"children":657},{},[658],{"type":420,"value":659},"For Azure AD B2C,",{"type":415,"tag":493,"props":661,"children":662},{},[663,674],{"type":415,"tag":497,"props":664,"children":665},{},[666,668],{"type":420,"value":667},"the authorize endpoint is ",{"type":415,"tag":550,"props":669,"children":671},{"className":670},[],[672],{"type":420,"value":673},"https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize",{"type":415,"tag":497,"props":675,"children":676},{},[677,679],{"type":420,"value":678},"the token endpoint is ",{"type":415,"tag":550,"props":680,"children":682},{"className":681},[],[683],{"type":420,"value":684},"https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token",{"type":415,"tag":416,"props":686,"children":687},{},[688],{"type":420,"value":689},"where:",{"type":415,"tag":493,"props":691,"children":692},{},[693,704,715],{"type":415,"tag":497,"props":694,"children":695},{},[696,702],{"type":415,"tag":550,"props":697,"children":699},{"className":698},[],[700],{"type":420,"value":701},"tenant",{"type":420,"value":703}," is the name of the Azure AD B2C tenant",{"type":415,"tag":497,"props":705,"children":706},{},[707,713],{"type":415,"tag":550,"props":708,"children":710},{"className":709},[],[711],{"type":420,"value":712},"clientId",{"type":420,"value":714}," is the application ID of the application registered in Azure AD the B2C tenant",{"type":415,"tag":497,"props":716,"children":717},{},[718,724],{"type":415,"tag":550,"props":719,"children":721},{"className":720},[],[722],{"type":420,"value":723},"policy",{"type":420,"value":725}," is the name of the policy created in the Azure AD B2C tenant",{"type":415,"tag":588,"props":727,"children":729},{"icon":728},"i-heroicons-light-bulb",[730],{"type":415,"tag":416,"props":731,"children":732},{},[733,735,741],{"type":420,"value":734},"When using a custom domain in Azure AD B2C, the endpoints are similar but the ",{"type":415,"tag":550,"props":736,"children":738},{"className":737},[],[739],{"type":420,"value":740},"{tenant}.b2clogin.com",{"type":420,"value":742}," part is replaced by the custom domain.",{"type":415,"tag":416,"props":744,"children":745},{},[746,748,754],{"type":420,"value":747},"If you want to better understand how this flow works, there is a nice diagram in ",{"type":415,"tag":423,"props":749,"children":751},{"href":435,"rel":750},[427],[752],{"type":420,"value":753},"Auth0 documentation",{"type":420,"value":755},".",{"type":415,"tag":616,"props":757,"children":759},{"id":758},"configuration-in-the-jetbrains-http-client",[760],{"type":420,"value":761},"Configuration in the JetBrains HTTP Client",{"type":415,"tag":416,"props":763,"children":764},{},[765],{"type":420,"value":766},"To make the authorization code flow work in the HTTP Client, all I have to do is provide the configuration for the Azure AD B2C tenant in the HTTP environment file.",{"type":415,"tag":416,"props":768,"children":769},{},[770],{"type":420,"value":771},"Here is an example of such configuration:",{"type":415,"tag":773,"props":774,"children":778},"pre",{"className":775,"code":776,"language":777,"meta":401,"style":401},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"apiUrl\": \"https://localhost:5001/api\",\n  \"Security\": {\n    \"Auth\": {\n      \"CIAM\": {\n        \"Type\": \"OAuth2\",\n        \"Grant Type\": \"Authorization Code\",\n        \"PKCE\": true,\n        \"Client ID\": \"3a53c90d-20c4-40e9-b440-4825b70374d7\",\n        \"Scope\": \"openid offline_access profile https://mytenant.onmicrosoft.com/security/user.read\",\n        \"Auth URL\": \"https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/b2c_1_sign_in/oauth2/v2.0/authorize\",\n        \"Token URL\": \"https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/b2c_1_sign_in/oauth2/v2.0/token\",\n        \"Redirect URL\": \"https://localhost:8080/oidc-callback\",\n        \"Acquire Automatically\": true\n      }\n    }\n  }\n}\n","json",[779],{"type":415,"tag":550,"props":780,"children":781},{"__ignoreMap":401},[782,794,838,864,891,918,957,995,1021,1059,1097,1135,1173,1211,1237,1246,1255,1264],{"type":415,"tag":783,"props":784,"children":787},"span",{"class":785,"line":786},"line",1,[788],{"type":415,"tag":783,"props":789,"children":791},{"style":790},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[792],{"type":420,"value":793},"{\n",{"type":415,"tag":783,"props":795,"children":797},{"class":785,"line":796},2,[798,803,809,814,818,823,829,833],{"type":415,"tag":783,"props":799,"children":800},{"style":790},[801],{"type":420,"value":802},"  \"",{"type":415,"tag":783,"props":804,"children":806},{"style":805},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[807],{"type":420,"value":808},"apiUrl",{"type":415,"tag":783,"props":810,"children":811},{"style":790},[812],{"type":420,"value":813},"\"",{"type":415,"tag":783,"props":815,"children":816},{"style":790},[817],{"type":420,"value":635},{"type":415,"tag":783,"props":819,"children":820},{"style":790},[821],{"type":420,"value":822}," \"",{"type":415,"tag":783,"props":824,"children":826},{"style":825},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[827],{"type":420,"value":828},"https://localhost:5001/api",{"type":415,"tag":783,"props":830,"children":831},{"style":790},[832],{"type":420,"value":813},{"type":415,"tag":783,"props":834,"children":835},{"style":790},[836],{"type":420,"value":837},",\n",{"type":415,"tag":783,"props":839,"children":841},{"class":785,"line":840},3,[842,846,851,855,859],{"type":415,"tag":783,"props":843,"children":844},{"style":790},[845],{"type":420,"value":802},{"type":415,"tag":783,"props":847,"children":848},{"style":805},[849],{"type":420,"value":850},"Security",{"type":415,"tag":783,"props":852,"children":853},{"style":790},[854],{"type":420,"value":813},{"type":415,"tag":783,"props":856,"children":857},{"style":790},[858],{"type":420,"value":635},{"type":415,"tag":783,"props":860,"children":861},{"style":790},[862],{"type":420,"value":863}," {\n",{"type":415,"tag":783,"props":865,"children":867},{"class":785,"line":866},4,[868,873,879,883,887],{"type":415,"tag":783,"props":869,"children":870},{"style":790},[871],{"type":420,"value":872},"    \"",{"type":415,"tag":783,"props":874,"children":876},{"style":875},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[877],{"type":420,"value":878},"Auth",{"type":415,"tag":783,"props":880,"children":881},{"style":790},[882],{"type":420,"value":813},{"type":415,"tag":783,"props":884,"children":885},{"style":790},[886],{"type":420,"value":635},{"type":415,"tag":783,"props":888,"children":889},{"style":790},[890],{"type":420,"value":863},{"type":415,"tag":783,"props":892,"children":894},{"class":785,"line":893},5,[895,900,906,910,914],{"type":415,"tag":783,"props":896,"children":897},{"style":790},[898],{"type":420,"value":899},"      \"",{"type":415,"tag":783,"props":901,"children":903},{"style":902},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[904],{"type":420,"value":905},"CIAM",{"type":415,"tag":783,"props":907,"children":908},{"style":790},[909],{"type":420,"value":813},{"type":415,"tag":783,"props":911,"children":912},{"style":790},[913],{"type":420,"value":635},{"type":415,"tag":783,"props":915,"children":916},{"style":790},[917],{"type":420,"value":863},{"type":415,"tag":783,"props":919,"children":921},{"class":785,"line":920},6,[922,927,933,937,941,945,949,953],{"type":415,"tag":783,"props":923,"children":924},{"style":790},[925],{"type":420,"value":926},"        \"",{"type":415,"tag":783,"props":928,"children":930},{"style":929},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[931],{"type":420,"value":932},"Type",{"type":415,"tag":783,"props":934,"children":935},{"style":790},[936],{"type":420,"value":813},{"type":415,"tag":783,"props":938,"children":939},{"style":790},[940],{"type":420,"value":635},{"type":415,"tag":783,"props":942,"children":943},{"style":790},[944],{"type":420,"value":822},{"type":415,"tag":783,"props":946,"children":947},{"style":825},[948],{"type":420,"value":393},{"type":415,"tag":783,"props":950,"children":951},{"style":790},[952],{"type":420,"value":813},{"type":415,"tag":783,"props":954,"children":955},{"style":790},[956],{"type":420,"value":837},{"type":415,"tag":783,"props":958,"children":960},{"class":785,"line":959},7,[961,965,970,974,978,982,987,991],{"type":415,"tag":783,"props":962,"children":963},{"style":790},[964],{"type":420,"value":926},{"type":415,"tag":783,"props":966,"children":967},{"style":929},[968],{"type":420,"value":969},"Grant Type",{"type":415,"tag":783,"props":971,"children":972},{"style":790},[973],{"type":420,"value":813},{"type":415,"tag":783,"props":975,"children":976},{"style":790},[977],{"type":420,"value":635},{"type":415,"tag":783,"props":979,"children":980},{"style":790},[981],{"type":420,"value":822},{"type":415,"tag":783,"props":983,"children":984},{"style":825},[985],{"type":420,"value":986},"Authorization Code",{"type":415,"tag":783,"props":988,"children":989},{"style":790},[990],{"type":420,"value":813},{"type":415,"tag":783,"props":992,"children":993},{"style":790},[994],{"type":420,"value":837},{"type":415,"tag":783,"props":996,"children":998},{"class":785,"line":997},8,[999,1003,1008,1012,1016],{"type":415,"tag":783,"props":1000,"children":1001},{"style":790},[1002],{"type":420,"value":926},{"type":415,"tag":783,"props":1004,"children":1005},{"style":929},[1006],{"type":420,"value":1007},"PKCE",{"type":415,"tag":783,"props":1009,"children":1010},{"style":790},[1011],{"type":420,"value":813},{"type":415,"tag":783,"props":1013,"children":1014},{"style":790},[1015],{"type":420,"value":635},{"type":415,"tag":783,"props":1017,"children":1018},{"style":790},[1019],{"type":420,"value":1020}," true,\n",{"type":415,"tag":783,"props":1022,"children":1024},{"class":785,"line":1023},9,[1025,1029,1034,1038,1042,1046,1051,1055],{"type":415,"tag":783,"props":1026,"children":1027},{"style":790},[1028],{"type":420,"value":926},{"type":415,"tag":783,"props":1030,"children":1031},{"style":929},[1032],{"type":420,"value":1033},"Client ID",{"type":415,"tag":783,"props":1035,"children":1036},{"style":790},[1037],{"type":420,"value":813},{"type":415,"tag":783,"props":1039,"children":1040},{"style":790},[1041],{"type":420,"value":635},{"type":415,"tag":783,"props":1043,"children":1044},{"style":790},[1045],{"type":420,"value":822},{"type":415,"tag":783,"props":1047,"children":1048},{"style":825},[1049],{"type":420,"value":1050},"3a53c90d-20c4-40e9-b440-4825b70374d7",{"type":415,"tag":783,"props":1052,"children":1053},{"style":790},[1054],{"type":420,"value":813},{"type":415,"tag":783,"props":1056,"children":1057},{"style":790},[1058],{"type":420,"value":837},{"type":415,"tag":783,"props":1060,"children":1062},{"class":785,"line":1061},10,[1063,1067,1072,1076,1080,1084,1089,1093],{"type":415,"tag":783,"props":1064,"children":1065},{"style":790},[1066],{"type":420,"value":926},{"type":415,"tag":783,"props":1068,"children":1069},{"style":929},[1070],{"type":420,"value":1071},"Scope",{"type":415,"tag":783,"props":1073,"children":1074},{"style":790},[1075],{"type":420,"value":813},{"type":415,"tag":783,"props":1077,"children":1078},{"style":790},[1079],{"type":420,"value":635},{"type":415,"tag":783,"props":1081,"children":1082},{"style":790},[1083],{"type":420,"value":822},{"type":415,"tag":783,"props":1085,"children":1086},{"style":825},[1087],{"type":420,"value":1088},"openid offline_access profile https://mytenant.onmicrosoft.com/security/user.read",{"type":415,"tag":783,"props":1090,"children":1091},{"style":790},[1092],{"type":420,"value":813},{"type":415,"tag":783,"props":1094,"children":1095},{"style":790},[1096],{"type":420,"value":837},{"type":415,"tag":783,"props":1098,"children":1100},{"class":785,"line":1099},11,[1101,1105,1110,1114,1118,1122,1127,1131],{"type":415,"tag":783,"props":1102,"children":1103},{"style":790},[1104],{"type":420,"value":926},{"type":415,"tag":783,"props":1106,"children":1107},{"style":929},[1108],{"type":420,"value":1109},"Auth URL",{"type":415,"tag":783,"props":1111,"children":1112},{"style":790},[1113],{"type":420,"value":813},{"type":415,"tag":783,"props":1115,"children":1116},{"style":790},[1117],{"type":420,"value":635},{"type":415,"tag":783,"props":1119,"children":1120},{"style":790},[1121],{"type":420,"value":822},{"type":415,"tag":783,"props":1123,"children":1124},{"style":825},[1125],{"type":420,"value":1126},"https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/b2c_1_sign_in/oauth2/v2.0/authorize",{"type":415,"tag":783,"props":1128,"children":1129},{"style":790},[1130],{"type":420,"value":813},{"type":415,"tag":783,"props":1132,"children":1133},{"style":790},[1134],{"type":420,"value":837},{"type":415,"tag":783,"props":1136,"children":1138},{"class":785,"line":1137},12,[1139,1143,1148,1152,1156,1160,1165,1169],{"type":415,"tag":783,"props":1140,"children":1141},{"style":790},[1142],{"type":420,"value":926},{"type":415,"tag":783,"props":1144,"children":1145},{"style":929},[1146],{"type":420,"value":1147},"Token URL",{"type":415,"tag":783,"props":1149,"children":1150},{"style":790},[1151],{"type":420,"value":813},{"type":415,"tag":783,"props":1153,"children":1154},{"style":790},[1155],{"type":420,"value":635},{"type":415,"tag":783,"props":1157,"children":1158},{"style":790},[1159],{"type":420,"value":822},{"type":415,"tag":783,"props":1161,"children":1162},{"style":825},[1163],{"type":420,"value":1164},"https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/b2c_1_sign_in/oauth2/v2.0/token",{"type":415,"tag":783,"props":1166,"children":1167},{"style":790},[1168],{"type":420,"value":813},{"type":415,"tag":783,"props":1170,"children":1171},{"style":790},[1172],{"type":420,"value":837},{"type":415,"tag":783,"props":1174,"children":1176},{"class":785,"line":1175},13,[1177,1181,1186,1190,1194,1198,1203,1207],{"type":415,"tag":783,"props":1178,"children":1179},{"style":790},[1180],{"type":420,"value":926},{"type":415,"tag":783,"props":1182,"children":1183},{"style":929},[1184],{"type":420,"value":1185},"Redirect URL",{"type":415,"tag":783,"props":1187,"children":1188},{"style":790},[1189],{"type":420,"value":813},{"type":415,"tag":783,"props":1191,"children":1192},{"style":790},[1193],{"type":420,"value":635},{"type":415,"tag":783,"props":1195,"children":1196},{"style":790},[1197],{"type":420,"value":822},{"type":415,"tag":783,"props":1199,"children":1200},{"style":825},[1201],{"type":420,"value":1202},"https://localhost:8080/oidc-callback",{"type":415,"tag":783,"props":1204,"children":1205},{"style":790},[1206],{"type":420,"value":813},{"type":415,"tag":783,"props":1208,"children":1209},{"style":790},[1210],{"type":420,"value":837},{"type":415,"tag":783,"props":1212,"children":1214},{"class":785,"line":1213},14,[1215,1219,1224,1228,1232],{"type":415,"tag":783,"props":1216,"children":1217},{"style":790},[1218],{"type":420,"value":926},{"type":415,"tag":783,"props":1220,"children":1221},{"style":929},[1222],{"type":420,"value":1223},"Acquire Automatically",{"type":415,"tag":783,"props":1225,"children":1226},{"style":790},[1227],{"type":420,"value":813},{"type":415,"tag":783,"props":1229,"children":1230},{"style":790},[1231],{"type":420,"value":635},{"type":415,"tag":783,"props":1233,"children":1234},{"style":790},[1235],{"type":420,"value":1236}," true\n",{"type":415,"tag":783,"props":1238,"children":1240},{"class":785,"line":1239},15,[1241],{"type":415,"tag":783,"props":1242,"children":1243},{"style":790},[1244],{"type":420,"value":1245},"      }\n",{"type":415,"tag":783,"props":1247,"children":1249},{"class":785,"line":1248},16,[1250],{"type":415,"tag":783,"props":1251,"children":1252},{"style":790},[1253],{"type":420,"value":1254},"    }\n",{"type":415,"tag":783,"props":1256,"children":1258},{"class":785,"line":1257},17,[1259],{"type":415,"tag":783,"props":1260,"children":1261},{"style":790},[1262],{"type":420,"value":1263},"  }\n",{"type":415,"tag":783,"props":1265,"children":1267},{"class":785,"line":1266},18,[1268],{"type":415,"tag":783,"props":1269,"children":1270},{"style":790},[1271],{"type":420,"value":1272},"}\n",{"type":415,"tag":588,"props":1274,"children":1275},{"icon":728},[1276],{"type":415,"tag":416,"props":1277,"children":1278},{},[1279],{"type":420,"value":1280},"Instead of setting PKCE to true, you can set if to a JSON object with the code challenge method and code verifier to use in it.",{"type":415,"tag":588,"props":1282,"children":1283},{"icon":590},[1284],{"type":415,"tag":416,"props":1285,"children":1286},{},[1287],{"type":420,"value":1288},"In this example, I have set a local Redirect URL as my front was running locally. But I could also have set the Redirect URL to another environment where my web application is running.",{"type":415,"tag":416,"props":1290,"children":1291},{},[1292,1294,1300],{"type":420,"value":1293},"You can check the ",{"type":415,"tag":423,"props":1295,"children":1297},{"href":435,"rel":1296},[427],[1298],{"type":420,"value":1299},"JetBrains documentation",{"type":420,"value":1301}," to have more information about the HTTP Client support for OAuth 2.0 authorization.",{"type":415,"tag":616,"props":1303,"children":1305},{"id":1304},"authenticated-http-requests-in-the-http-file",[1306],{"type":420,"value":1307},"Authenticated HTTP Requests in the HTTP file",{"type":415,"tag":416,"props":1309,"children":1310},{},[1311],{"type":420,"value":1312},"Once the configuration is set, retrieving an access token can be done with a simple click in the configuration file.",{"type":415,"tag":416,"props":1314,"children":1315},{},[1316],{"type":420,"value":1317},"The authentication process is logged so we can check the requests made and identify any mistakes made in the configuration.",{"type":415,"tag":416,"props":1319,"children":1320},{},[1321],{"type":415,"tag":1322,"props":1323,"children":1329},"img",{"alt":1324,"className":1325,"src":1328},"HTTP authentication log",[1326,1327],"rounded-lg","mx-auto","/posts/images/httpclientsoauht2_1.webp",[],{"type":415,"tag":416,"props":1331,"children":1332},{},[1333,1335,1341],{"type":420,"value":1334},"Hopefully, we don't have to manually retrieve an access token each time we need to execute an HTTP request in an HTTP file of our IDE. We can just use the ",{"type":415,"tag":550,"props":1336,"children":1338},{"className":1337},[],[1339],{"type":420,"value":1340},"{{$auth.token()}}",{"type":420,"value":1342}," variable in the Authorization header of our requests, like this:",{"type":415,"tag":773,"props":1344,"children":1347},{"className":1345,"code":1346,"language":212,"meta":401,"style":401},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","GET {{apiUrl}}/products\nAuthorization: Bearer {{$auth.token(\"CIAM\")}}\n",[1348],{"type":415,"tag":550,"props":1349,"children":1350},{"__ignoreMap":401},[1351,1366],{"type":415,"tag":783,"props":1352,"children":1353},{"class":785,"line":786},[1354,1360],{"type":415,"tag":783,"props":1355,"children":1357},{"style":1356},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[1358],{"type":420,"value":1359},"GET",{"type":415,"tag":783,"props":1361,"children":1363},{"style":1362},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1364],{"type":420,"value":1365}," {{apiUrl}}/products\n",{"type":415,"tag":783,"props":1367,"children":1368},{"class":785,"line":796},[1369,1374,1378],{"type":415,"tag":783,"props":1370,"children":1371},{"style":929},[1372],{"type":420,"value":1373},"Authorization",{"type":415,"tag":783,"props":1375,"children":1376},{"style":902},[1377],{"type":420,"value":635},{"type":415,"tag":783,"props":1379,"children":1380},{"style":825},[1381],{"type":420,"value":1382}," Bearer {{$auth.token(\"CIAM\")}}\n",{"type":415,"tag":416,"props":1384,"children":1385},{},[1386],{"type":420,"value":1387},"The IDE will handle the rest for us.",{"type":415,"tag":443,"props":1389,"children":1391},{"id":1390},"wrapping-up",[1392],{"type":420,"value":1393},"Wrapping up",{"type":415,"tag":416,"props":1395,"children":1396},{},[1397],{"type":420,"value":1398},"The HTTP Client OAuth 2.0 feature in JetBrains IDEs has greatly simplified making authenticated HTTP requests to secure APIs. While this article focused on Azure AD B2C, the same principles apply to other Authorization Servers, with only the authorize and token endpoints differing.",{"type":415,"tag":416,"props":1400,"children":1401},{},[1402,1404,1410,1412,1417],{"type":420,"value":1403},"I hope other IDEs will adopt this feature, using the same convention for the ",{"type":415,"tag":550,"props":1405,"children":1407},{"className":1406},[],[1408],{"type":420,"value":1409},"$auth.token()",{"type":420,"value":1411}," variable and its configuration. The only drawback is for developers not using JetBrains IDEs, who will need to adjust requests containing the ",{"type":415,"tag":550,"props":1413,"children":1415},{"className":1414},[],[1416],{"type":420,"value":1409},{"type":420,"value":1418}," variable to run them in their IDEs.",{"type":415,"tag":1420,"props":1421,"children":1422},"style",{},[1423],{"type":420,"value":1424},"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":796,"depth":796,"links":1426},[1427,1428,1429,1434],{"id":445,"depth":796,"text":448},{"id":483,"depth":796,"text":486},{"id":578,"depth":796,"text":581,"children":1430},[1431,1432,1433],{"id":618,"depth":840,"text":621},{"id":758,"depth":840,"text":761},{"id":1304,"depth":840,"text":1307},{"id":1390,"depth":796,"text":1393},"markdown","content:1.posts:61.http-clients-oauth2.md","content","1.posts/61.http-clients-oauth2.md","md",{"_path":175,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":174,"description":1441,"lead":1442,"date":1443,"image":1444,"badge":1446,"tags":1448,"body":1449,"_type":1435,"_id":7255,"_source":1437,"_file":7256,"_extension":1439},"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":1445},"/images/weather_flag.webp",{"label":1447},"Development",[326,239,236,213,384],{"type":412,"children":1450,"toc":7250},[1451,1455,1461,1474,1505,1510,1519,1524,1559,1572,1581,1594,1657,1679,1695,1714,1723,1729,1734,1739,1781,1790,1803,2179,2207,2366,2378,2407,3577,3582,3738,3759,4280,4290,4507,4521,4725,4730,4993,4998,5009,5335,5343,5356,5588,5616,5621,5753,5758,5893,5906,6233,6245,6268,6575,6595,7007,7013,7018,7020,7182,7210,7232,7246],{"type":415,"tag":416,"props":1452,"children":1453},{},[1454],{"type":420,"value":1441},{"type":415,"tag":443,"props":1456,"children":1458},{"id":1457},"getting-started-with-the-aspnet-core-web-api-template",[1459],{"type":420,"value":1460},"Getting started with the ASP.NET Core Web API template",{"type":415,"tag":416,"props":1462,"children":1463},{},[1464,1466,1473],{"type":420,"value":1465},"First, let's install the latest ",{"type":415,"tag":423,"props":1467,"children":1470},{"href":1468,"rel":1469},"https://dotnet.microsoft.com/en-us/download/dotnet/8.0",[427],[1471],{"type":420,"value":1472},".NET 8 SDK",{"type":420,"value":635},{"type":415,"tag":773,"props":1475,"children":1478},{"className":1476,"code":1477,"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",[1479],{"type":415,"tag":550,"props":1480,"children":1481},{"__ignoreMap":401},[1482],{"type":415,"tag":783,"props":1483,"children":1484},{"class":785,"line":786},[1485,1490,1495,1500],{"type":415,"tag":783,"props":1486,"children":1487},{"style":1362},[1488],{"type":420,"value":1489},"winget install ",{"type":415,"tag":783,"props":1491,"children":1492},{"style":790},[1493],{"type":420,"value":1494},"--",{"type":415,"tag":783,"props":1496,"children":1497},{"style":1362},[1498],{"type":420,"value":1499},"id Microsoft.DotNet.SDK.",{"type":415,"tag":783,"props":1501,"children":1502},{"style":902},[1503],{"type":420,"value":1504},"8\n",{"type":415,"tag":416,"props":1506,"children":1507},{},[1508],{"type":420,"value":1509},"We can list the available templates:",{"type":415,"tag":416,"props":1511,"children":1512},{},[1513],{"type":415,"tag":1322,"props":1514,"children":1518},{"alt":1515,"className":1516,"src":1517},"List of the available dotnet templates",[1326,1327],"/posts/images/dontnet8_templates.webp",[],{"type":415,"tag":416,"props":1520,"children":1521},{},[1522],{"type":420,"value":1523},"Let's go for the basic ASP.NET Core Web API template but with the controllers:",{"type":415,"tag":773,"props":1525,"children":1527},{"className":1476,"code":1526,"language":248,"meta":401,"style":401},"dotnet new webapi --use-controllers -n WeatherApi\n",[1528],{"type":415,"tag":550,"props":1529,"children":1530},{"__ignoreMap":401},[1531],{"type":415,"tag":783,"props":1532,"children":1533},{"class":785,"line":786},[1534,1539,1543,1549,1554],{"type":415,"tag":783,"props":1535,"children":1536},{"style":1362},[1537],{"type":420,"value":1538},"dotnet new webapi ",{"type":415,"tag":783,"props":1540,"children":1541},{"style":790},[1542],{"type":420,"value":1494},{"type":415,"tag":783,"props":1544,"children":1546},{"style":1545},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[1547],{"type":420,"value":1548},"use-controllers",{"type":415,"tag":783,"props":1550,"children":1551},{"style":790},[1552],{"type":420,"value":1553}," -",{"type":415,"tag":783,"props":1555,"children":1556},{"style":1362},[1557],{"type":420,"value":1558},"n WeatherApi\n",{"type":415,"tag":588,"props":1560,"children":1561},{"icon":728},[1562],{"type":415,"tag":416,"props":1563,"children":1564},{},[1565,1570],{"type":415,"tag":783,"props":1566,"children":1567},{},[1568],{"type":420,"value":1569},"Minimal APIs",{"type":420,"value":1571}," are great too but having controllers is more suited to what I want to show in this article.",{"type":415,"tag":416,"props":1573,"children":1574},{},[1575],{"type":415,"tag":1322,"props":1576,"children":1580},{"alt":1577,"className":1578,"src":1579},"Screenshot of the generated project in Rider",[1326,1327],"/posts/images/dontnet8_webapi_template.webp",[],{"type":415,"tag":416,"props":1582,"children":1583},{},[1584,1586,1592],{"type":420,"value":1585},"We can run the API and test the ",{"type":415,"tag":550,"props":1587,"children":1589},{"className":1588},[],[1590],{"type":420,"value":1591},"GET /weatherforecast",{"type":420,"value":1593}," endpoint using the generated request file:",{"type":415,"tag":773,"props":1595,"children":1597},{"className":1345,"code":1596,"language":212,"meta":401,"style":401},"@WeatherApi_HostAddress = http://localhost:5103\n\nGET {{WeatherApi_HostAddress}}/weatherforecast/\nAccept: application/json\n",[1598],{"type":415,"tag":550,"props":1599,"children":1600},{"__ignoreMap":401},[1601,1619,1628,1640],{"type":415,"tag":783,"props":1602,"children":1603},{"class":785,"line":786},[1604,1609,1614],{"type":415,"tag":783,"props":1605,"children":1606},{"style":902},[1607],{"type":420,"value":1608},"@",{"type":415,"tag":783,"props":1610,"children":1611},{"style":1362},[1612],{"type":420,"value":1613},"WeatherApi_HostAddress = ",{"type":415,"tag":783,"props":1615,"children":1616},{"style":825},[1617],{"type":420,"value":1618},"http://localhost:5103\n",{"type":415,"tag":783,"props":1620,"children":1621},{"class":785,"line":796},[1622],{"type":415,"tag":783,"props":1623,"children":1625},{"emptyLinePlaceholder":1624},true,[1626],{"type":420,"value":1627},"\n",{"type":415,"tag":783,"props":1629,"children":1630},{"class":785,"line":840},[1631,1635],{"type":415,"tag":783,"props":1632,"children":1633},{"style":1356},[1634],{"type":420,"value":1359},{"type":415,"tag":783,"props":1636,"children":1637},{"style":1362},[1638],{"type":420,"value":1639}," {{WeatherApi_HostAddress}}/weatherforecast/\n",{"type":415,"tag":783,"props":1641,"children":1642},{"class":785,"line":866},[1643,1648,1652],{"type":415,"tag":783,"props":1644,"children":1645},{"style":929},[1646],{"type":420,"value":1647},"Accept",{"type":415,"tag":783,"props":1649,"children":1650},{"style":902},[1651],{"type":420,"value":635},{"type":415,"tag":783,"props":1653,"children":1654},{"style":825},[1655],{"type":420,"value":1656}," application/json\n",{"type":415,"tag":416,"props":1658,"children":1659},{},[1660,1662,1668,1670,1677],{"type":420,"value":1661},"This is included in the dotnet ",{"type":415,"tag":550,"props":1663,"children":1665},{"className":1664},[],[1666],{"type":420,"value":1667},"webapi",{"type":420,"value":1669}," template and is supported by Visual Studio, Rider, and vscode (using the ",{"type":415,"tag":423,"props":1671,"children":1674},{"href":1672,"rel":1673},"https://marketplace.visualstudio.com/items?itemName=humao.rest-client",[427],[1675],{"type":420,"value":1676},"REST Client extension",{"type":420,"value":1678},")",{"type":415,"tag":588,"props":1680,"children":1681},{"icon":728},[1682],{"type":415,"tag":416,"props":1683,"children":1684},{},[1685,1687,1693],{"type":420,"value":1686},"Read my article about ",{"type":415,"tag":423,"props":1688,"children":1690},{"href":425,"rel":1689},[427],[1691],{"type":420,"value":1692},"choosing an API Client",{"type":420,"value":1694}," and why I prefer versioned HTTP files rather than GUI tools like Postman.",{"type":415,"tag":416,"props":1696,"children":1697},{},[1698,1700,1713],{"type":420,"value":1699},"If we put a breakpoint in the controller we can see one small ASP.NET 8 improvement concerning the debugging experience: ",{"type":415,"tag":423,"props":1701,"children":1704},{"href":1702,"rel":1703},"https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0#improved-debugging-experience",[427],[1705,1707],{"type":420,"value":1706},"better debug summaries are displayed for types like ",{"type":415,"tag":550,"props":1708,"children":1710},{"className":1709},[],[1711],{"type":420,"value":1712},"HttpContext",{"type":420,"value":755},{"type":415,"tag":416,"props":1715,"children":1716},{},[1717],{"type":415,"tag":1322,"props":1718,"children":1722},{"alt":1719,"className":1720,"src":1721},"Debugging display of the HTTPContext class",[1326,1327],"/posts/images/dontnet8_httpcontext.webp",[],{"type":415,"tag":443,"props":1724,"children":1726},{"id":1725},"enhancing-the-weather-forecast-api",[1727],{"type":420,"value":1728},"Enhancing the Weather Forecast API",{"type":415,"tag":416,"props":1730,"children":1731},{},[1732],{"type":420,"value":1733},"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":1735,"children":1736},{},[1737],{"type":420,"value":1738},"To do that we can:",{"type":415,"tag":493,"props":1740,"children":1741},{},[1742,1755,1768],{"type":415,"tag":497,"props":1743,"children":1744},{},[1745,1747,1753],{"type":420,"value":1746},"introduce an ",{"type":415,"tag":550,"props":1748,"children":1750},{"className":1749},[],[1751],{"type":420,"value":1752},"IWeatherService",{"type":420,"value":1754}," interface that contains a method to retrieve weather forecasts",{"type":415,"tag":497,"props":1756,"children":1757},{},[1758,1760,1766],{"type":420,"value":1759},"extract the current logic that generates the random weather forecasts in a ",{"type":415,"tag":550,"props":1761,"children":1763},{"className":1762},[],[1764],{"type":420,"value":1765},"RandomWeatherService.cs",{"type":420,"value":1767}," that implements this interface",{"type":415,"tag":497,"props":1769,"children":1770},{},[1771,1773,1779],{"type":420,"value":1772},"creates a new implementation ",{"type":415,"tag":550,"props":1774,"children":1776},{"className":1775},[],[1777],{"type":420,"value":1778},"OpenWeatherService",{"type":420,"value":1780}," of this interface that retrieves the weather data from the Open Weather Map API",{"type":415,"tag":416,"props":1782,"children":1783},{},[1784],{"type":415,"tag":1322,"props":1785,"children":1789},{"alt":1786,"className":1787,"src":1788},"A diagram of the ASP.NETCore Weather API",[1326,1327],"/posts/images/dontnet8_webapi_diagram.webp",[],{"type":415,"tag":416,"props":1791,"children":1792},{},[1793,1795,1801],{"type":420,"value":1794},"The ",{"type":415,"tag":550,"props":1796,"children":1798},{"className":1797},[],[1799],{"type":420,"value":1800},"WeatherForecastController",{"type":420,"value":1802}," becomes:",{"type":415,"tag":773,"props":1804,"children":1807},{"className":1805,"code":1806,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[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",[1808],{"type":415,"tag":550,"props":1809,"children":1810},{"__ignoreMap":401},[1811,1829,1864,1892,1899,1927,1934,1964,1972,1993,2000,2007,2051,2096,2132,2139,2165,2172],{"type":415,"tag":783,"props":1812,"children":1813},{"class":785,"line":786},[1814,1819,1824],{"type":415,"tag":783,"props":1815,"children":1816},{"style":790},[1817],{"type":420,"value":1818},"[",{"type":415,"tag":783,"props":1820,"children":1821},{"style":875},[1822],{"type":420,"value":1823},"ApiController",{"type":415,"tag":783,"props":1825,"children":1826},{"style":790},[1827],{"type":420,"value":1828},"]\n",{"type":415,"tag":783,"props":1830,"children":1831},{"class":785,"line":796},[1832,1836,1841,1846,1850,1855,1859],{"type":415,"tag":783,"props":1833,"children":1834},{"style":790},[1835],{"type":420,"value":1818},{"type":415,"tag":783,"props":1837,"children":1838},{"style":875},[1839],{"type":420,"value":1840},"Route",{"type":415,"tag":783,"props":1842,"children":1843},{"style":790},[1844],{"type":420,"value":1845},"(",{"type":415,"tag":783,"props":1847,"children":1848},{"style":790},[1849],{"type":420,"value":813},{"type":415,"tag":783,"props":1851,"children":1852},{"style":825},[1853],{"type":420,"value":1854},"[controller]",{"type":415,"tag":783,"props":1856,"children":1857},{"style":790},[1858],{"type":420,"value":813},{"type":415,"tag":783,"props":1860,"children":1861},{"style":790},[1862],{"type":420,"value":1863},")]\n",{"type":415,"tag":783,"props":1865,"children":1866},{"class":785,"line":840},[1867,1872,1877,1882,1887],{"type":415,"tag":783,"props":1868,"children":1869},{"style":805},[1870],{"type":420,"value":1871},"public",{"type":415,"tag":783,"props":1873,"children":1874},{"style":875},[1875],{"type":420,"value":1876}," class",{"type":415,"tag":783,"props":1878,"children":1879},{"style":875},[1880],{"type":420,"value":1881}," WeatherForecastController",{"type":415,"tag":783,"props":1883,"children":1884},{"style":790},[1885],{"type":420,"value":1886}," :",{"type":415,"tag":783,"props":1888,"children":1889},{"style":875},[1890],{"type":420,"value":1891}," ControllerBase\n",{"type":415,"tag":783,"props":1893,"children":1894},{"class":785,"line":866},[1895],{"type":415,"tag":783,"props":1896,"children":1897},{"style":790},[1898],{"type":420,"value":793},{"type":415,"tag":783,"props":1900,"children":1901},{"class":785,"line":893},[1902,1907,1912,1917,1922],{"type":415,"tag":783,"props":1903,"children":1904},{"style":805},[1905],{"type":420,"value":1906},"    private",{"type":415,"tag":783,"props":1908,"children":1909},{"style":805},[1910],{"type":420,"value":1911}," readonly",{"type":415,"tag":783,"props":1913,"children":1914},{"style":875},[1915],{"type":420,"value":1916}," IWeatherService",{"type":415,"tag":783,"props":1918,"children":1919},{"style":875},[1920],{"type":420,"value":1921}," _weatherService",{"type":415,"tag":783,"props":1923,"children":1924},{"style":790},[1925],{"type":420,"value":1926},";\n",{"type":415,"tag":783,"props":1928,"children":1929},{"class":785,"line":920},[1930],{"type":415,"tag":783,"props":1931,"children":1932},{"emptyLinePlaceholder":1624},[1933],{"type":420,"value":1627},{"type":415,"tag":783,"props":1935,"children":1936},{"class":785,"line":959},[1937,1942,1946,1950,1954,1959],{"type":415,"tag":783,"props":1938,"children":1939},{"style":805},[1940],{"type":420,"value":1941},"    public",{"type":415,"tag":783,"props":1943,"children":1944},{"style":1545},[1945],{"type":420,"value":1881},{"type":415,"tag":783,"props":1947,"children":1948},{"style":790},[1949],{"type":420,"value":1845},{"type":415,"tag":783,"props":1951,"children":1952},{"style":875},[1953],{"type":420,"value":1752},{"type":415,"tag":783,"props":1955,"children":1956},{"style":875},[1957],{"type":420,"value":1958}," weatherService",{"type":415,"tag":783,"props":1960,"children":1961},{"style":790},[1962],{"type":420,"value":1963},")\n",{"type":415,"tag":783,"props":1965,"children":1966},{"class":785,"line":997},[1967],{"type":415,"tag":783,"props":1968,"children":1969},{"style":790},[1970],{"type":420,"value":1971},"    {\n",{"type":415,"tag":783,"props":1973,"children":1974},{"class":785,"line":1023},[1975,1980,1985,1989],{"type":415,"tag":783,"props":1976,"children":1977},{"style":1362},[1978],{"type":420,"value":1979},"        _weatherService ",{"type":415,"tag":783,"props":1981,"children":1982},{"style":790},[1983],{"type":420,"value":1984},"=",{"type":415,"tag":783,"props":1986,"children":1987},{"style":1362},[1988],{"type":420,"value":1958},{"type":415,"tag":783,"props":1990,"children":1991},{"style":790},[1992],{"type":420,"value":1926},{"type":415,"tag":783,"props":1994,"children":1995},{"class":785,"line":1061},[1996],{"type":415,"tag":783,"props":1997,"children":1998},{"style":790},[1999],{"type":420,"value":1254},{"type":415,"tag":783,"props":2001,"children":2002},{"class":785,"line":1099},[2003],{"type":415,"tag":783,"props":2004,"children":2005},{"emptyLinePlaceholder":1624},[2006],{"type":420,"value":1627},{"type":415,"tag":783,"props":2008,"children":2009},{"class":785,"line":1137},[2010,2015,2020,2024,2029,2034,2038,2043,2047],{"type":415,"tag":783,"props":2011,"children":2012},{"style":790},[2013],{"type":420,"value":2014},"    [",{"type":415,"tag":783,"props":2016,"children":2017},{"style":875},[2018],{"type":420,"value":2019},"HttpGet",{"type":415,"tag":783,"props":2021,"children":2022},{"style":790},[2023],{"type":420,"value":1845},{"type":415,"tag":783,"props":2025,"children":2026},{"style":875},[2027],{"type":420,"value":2028},"Name",{"type":415,"tag":783,"props":2030,"children":2031},{"style":790},[2032],{"type":420,"value":2033}," =",{"type":415,"tag":783,"props":2035,"children":2036},{"style":790},[2037],{"type":420,"value":822},{"type":415,"tag":783,"props":2039,"children":2040},{"style":825},[2041],{"type":420,"value":2042},"GetWeatherForecast",{"type":415,"tag":783,"props":2044,"children":2045},{"style":790},[2046],{"type":420,"value":813},{"type":415,"tag":783,"props":2048,"children":2049},{"style":790},[2050],{"type":420,"value":1863},{"type":415,"tag":783,"props":2052,"children":2053},{"class":785,"line":1175},[2054,2058,2063,2068,2073,2078,2083,2087,2092],{"type":415,"tag":783,"props":2055,"children":2056},{"style":790},[2057],{"type":420,"value":2014},{"type":415,"tag":783,"props":2059,"children":2060},{"style":875},[2061],{"type":420,"value":2062},"ProducesResponseType",{"type":415,"tag":783,"props":2064,"children":2065},{"style":790},[2066],{"type":420,"value":2067},"(typeof(",{"type":415,"tag":783,"props":2069,"children":2070},{"style":875},[2071],{"type":420,"value":2072},"WeatherForecast",{"type":415,"tag":783,"props":2074,"children":2075},{"style":790},[2076],{"type":420,"value":2077},"),",{"type":415,"tag":783,"props":2079,"children":2080},{"style":1362},[2081],{"type":420,"value":2082}," StatusCodes",{"type":415,"tag":783,"props":2084,"children":2085},{"style":790},[2086],{"type":420,"value":755},{"type":415,"tag":783,"props":2088,"children":2089},{"style":1362},[2090],{"type":420,"value":2091},"Status200OK",{"type":415,"tag":783,"props":2093,"children":2094},{"style":790},[2095],{"type":420,"value":1863},{"type":415,"tag":783,"props":2097,"children":2098},{"class":785,"line":1213},[2099,2103,2108,2113,2117,2122,2127],{"type":415,"tag":783,"props":2100,"children":2101},{"style":805},[2102],{"type":420,"value":1941},{"type":415,"tag":783,"props":2104,"children":2105},{"style":875},[2106],{"type":420,"value":2107}," Task",{"type":415,"tag":783,"props":2109,"children":2110},{"style":790},[2111],{"type":420,"value":2112},"\u003C",{"type":415,"tag":783,"props":2114,"children":2115},{"style":875},[2116],{"type":420,"value":2072},{"type":415,"tag":783,"props":2118,"children":2119},{"style":790},[2120],{"type":420,"value":2121},"[]>",{"type":415,"tag":783,"props":2123,"children":2124},{"style":1545},[2125],{"type":420,"value":2126}," Get",{"type":415,"tag":783,"props":2128,"children":2129},{"style":790},[2130],{"type":420,"value":2131},"()\n",{"type":415,"tag":783,"props":2133,"children":2134},{"class":785,"line":1239},[2135],{"type":415,"tag":783,"props":2136,"children":2137},{"style":790},[2138],{"type":420,"value":1971},{"type":415,"tag":783,"props":2140,"children":2141},{"class":785,"line":1248},[2142,2147,2151,2155,2160],{"type":415,"tag":783,"props":2143,"children":2144},{"style":1356},[2145],{"type":420,"value":2146},"        return",{"type":415,"tag":783,"props":2148,"children":2149},{"style":1362},[2150],{"type":420,"value":1921},{"type":415,"tag":783,"props":2152,"children":2153},{"style":790},[2154],{"type":420,"value":755},{"type":415,"tag":783,"props":2156,"children":2157},{"style":1545},[2158],{"type":420,"value":2159},"GetWeatherForecasts",{"type":415,"tag":783,"props":2161,"children":2162},{"style":790},[2163],{"type":420,"value":2164},"();\n",{"type":415,"tag":783,"props":2166,"children":2167},{"class":785,"line":1257},[2168],{"type":415,"tag":783,"props":2169,"children":2170},{"style":790},[2171],{"type":420,"value":1254},{"type":415,"tag":783,"props":2173,"children":2174},{"class":785,"line":1266},[2175],{"type":415,"tag":783,"props":2176,"children":2177},{"style":790},[2178],{"type":420,"value":1272},{"type":415,"tag":416,"props":2180,"children":2181},{},[2182,2184,2190,2192,2199,2201],{"type":420,"value":2183},"We can get rid of the ",{"type":415,"tag":550,"props":2185,"children":2187},{"className":2186},[],[2188],{"type":420,"value":2189},"typeof",{"type":420,"value":2191}," because there are now ",{"type":415,"tag":423,"props":2193,"children":2196},{"href":2194,"rel":2195},"https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0#support-for-generic-attributes",[427],[2197],{"type":420,"value":2198},"generic attributes for some common ASP.NET Core attributes",{"type":420,"value":2200}," like ",{"type":415,"tag":550,"props":2202,"children":2204},{"className":2203},[],[2205],{"type":420,"value":2206},"ProducesResponseType.",{"type":415,"tag":773,"props":2208,"children":2210},{"className":1805,"code":2209,"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",[2211],{"type":415,"tag":550,"props":2212,"children":2213},{"__ignoreMap":401},[2214,2253,2298,2329,2336,2359],{"type":415,"tag":783,"props":2215,"children":2216},{"class":785,"line":786},[2217,2221,2225,2229,2233,2237,2241,2245,2249],{"type":415,"tag":783,"props":2218,"children":2219},{"style":790},[2220],{"type":420,"value":2014},{"type":415,"tag":783,"props":2222,"children":2223},{"style":875},[2224],{"type":420,"value":2019},{"type":415,"tag":783,"props":2226,"children":2227},{"style":790},[2228],{"type":420,"value":1845},{"type":415,"tag":783,"props":2230,"children":2231},{"style":875},[2232],{"type":420,"value":2028},{"type":415,"tag":783,"props":2234,"children":2235},{"style":790},[2236],{"type":420,"value":2033},{"type":415,"tag":783,"props":2238,"children":2239},{"style":790},[2240],{"type":420,"value":822},{"type":415,"tag":783,"props":2242,"children":2243},{"style":825},[2244],{"type":420,"value":2042},{"type":415,"tag":783,"props":2246,"children":2247},{"style":790},[2248],{"type":420,"value":813},{"type":415,"tag":783,"props":2250,"children":2251},{"style":790},[2252],{"type":420,"value":1863},{"type":415,"tag":783,"props":2254,"children":2255},{"class":785,"line":796},[2256,2260,2264,2268,2272,2277,2281,2286,2290,2294],{"type":415,"tag":783,"props":2257,"children":2258},{"style":790},[2259],{"type":420,"value":2014},{"type":415,"tag":783,"props":2261,"children":2262},{"style":875},[2263],{"type":420,"value":2062},{"type":415,"tag":783,"props":2265,"children":2266},{"style":1362},[2267],{"type":420,"value":2112},{"type":415,"tag":783,"props":2269,"children":2270},{"style":875},[2271],{"type":420,"value":2072},{"type":415,"tag":783,"props":2273,"children":2274},{"style":1362},[2275],{"type":420,"value":2276},">",{"type":415,"tag":783,"props":2278,"children":2279},{"style":790},[2280],{"type":420,"value":1845},{"type":415,"tag":783,"props":2282,"children":2283},{"style":1362},[2284],{"type":420,"value":2285},"StatusCodes",{"type":415,"tag":783,"props":2287,"children":2288},{"style":790},[2289],{"type":420,"value":755},{"type":415,"tag":783,"props":2291,"children":2292},{"style":1362},[2293],{"type":420,"value":2091},{"type":415,"tag":783,"props":2295,"children":2296},{"style":790},[2297],{"type":420,"value":1863},{"type":415,"tag":783,"props":2299,"children":2300},{"class":785,"line":840},[2301,2305,2309,2313,2317,2321,2325],{"type":415,"tag":783,"props":2302,"children":2303},{"style":805},[2304],{"type":420,"value":1941},{"type":415,"tag":783,"props":2306,"children":2307},{"style":875},[2308],{"type":420,"value":2107},{"type":415,"tag":783,"props":2310,"children":2311},{"style":790},[2312],{"type":420,"value":2112},{"type":415,"tag":783,"props":2314,"children":2315},{"style":875},[2316],{"type":420,"value":2072},{"type":415,"tag":783,"props":2318,"children":2319},{"style":790},[2320],{"type":420,"value":2121},{"type":415,"tag":783,"props":2322,"children":2323},{"style":1545},[2324],{"type":420,"value":2126},{"type":415,"tag":783,"props":2326,"children":2327},{"style":790},[2328],{"type":420,"value":2131},{"type":415,"tag":783,"props":2330,"children":2331},{"class":785,"line":866},[2332],{"type":415,"tag":783,"props":2333,"children":2334},{"style":790},[2335],{"type":420,"value":1971},{"type":415,"tag":783,"props":2337,"children":2338},{"class":785,"line":893},[2339,2343,2347,2351,2355],{"type":415,"tag":783,"props":2340,"children":2341},{"style":1356},[2342],{"type":420,"value":2146},{"type":415,"tag":783,"props":2344,"children":2345},{"style":1362},[2346],{"type":420,"value":1921},{"type":415,"tag":783,"props":2348,"children":2349},{"style":790},[2350],{"type":420,"value":755},{"type":415,"tag":783,"props":2352,"children":2353},{"style":1545},[2354],{"type":420,"value":2159},{"type":415,"tag":783,"props":2356,"children":2357},{"style":790},[2358],{"type":420,"value":2164},{"type":415,"tag":783,"props":2360,"children":2361},{"class":785,"line":920},[2362],{"type":415,"tag":783,"props":2363,"children":2364},{"style":790},[2365],{"type":420,"value":1254},{"type":415,"tag":416,"props":2367,"children":2368},{},[2369,2371,2376],{"type":420,"value":2370},"There are now 2 implementations of the ",{"type":415,"tag":550,"props":2372,"children":2374},{"className":2373},[],[2375],{"type":420,"value":1752},{"type":420,"value":2377}," interface:",{"type":415,"tag":493,"props":2379,"children":2380},{},[2381,2392],{"type":415,"tag":497,"props":2382,"children":2383},{},[2384,2390],{"type":415,"tag":550,"props":2385,"children":2387},{"className":2386},[],[2388],{"type":420,"value":2389},"RandomWeatherService",{"type":420,"value":2391}," that contains the code that previously was in the controller",{"type":415,"tag":497,"props":2393,"children":2394},{},[2395,2400,2402],{"type":415,"tag":550,"props":2396,"children":2398},{"className":2397},[],[2399],{"type":420,"value":1778},{"type":420,"value":2401}," 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":550,"props":2403,"children":2405},{"className":2404},[],[2406],{"type":420,"value":2072},{"type":415,"tag":773,"props":2408,"children":2410},{"className":1805,"code":2409,"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",[2411],{"type":415,"tag":550,"props":2412,"children":2413},{"__ignoreMap":401},[2414,2439,2446,2471,2553,2560,2589,2596,2616,2623,2630,2667,2674,2747,2755,2789,2802,2810,2845,2894,2940,2986,3032,3078,3124,3170,3216,3249,3276,3285,3306,3333,3347,3356,3433,3490,3535,3544,3561,3569],{"type":415,"tag":783,"props":2415,"children":2416},{"class":785,"line":786},[2417,2421,2425,2430,2434],{"type":415,"tag":783,"props":2418,"children":2419},{"style":805},[2420],{"type":420,"value":1871},{"type":415,"tag":783,"props":2422,"children":2423},{"style":875},[2424],{"type":420,"value":1876},{"type":415,"tag":783,"props":2426,"children":2427},{"style":875},[2428],{"type":420,"value":2429}," OpenWeatherService",{"type":415,"tag":783,"props":2431,"children":2432},{"style":790},[2433],{"type":420,"value":1886},{"type":415,"tag":783,"props":2435,"children":2436},{"style":875},[2437],{"type":420,"value":2438}," IWeatherService\n",{"type":415,"tag":783,"props":2440,"children":2441},{"class":785,"line":796},[2442],{"type":415,"tag":783,"props":2443,"children":2444},{"style":790},[2445],{"type":420,"value":793},{"type":415,"tag":783,"props":2447,"children":2448},{"class":785,"line":840},[2449,2453,2457,2462,2467],{"type":415,"tag":783,"props":2450,"children":2451},{"style":805},[2452],{"type":420,"value":1906},{"type":415,"tag":783,"props":2454,"children":2455},{"style":805},[2456],{"type":420,"value":1911},{"type":415,"tag":783,"props":2458,"children":2459},{"style":875},[2460],{"type":420,"value":2461}," IOpenWeatherMapApi",{"type":415,"tag":783,"props":2463,"children":2464},{"style":875},[2465],{"type":420,"value":2466}," _openWeatherMapApi",{"type":415,"tag":783,"props":2468,"children":2469},{"style":790},[2470],{"type":420,"value":1926},{"type":415,"tag":783,"props":2472,"children":2473},{"class":785,"line":866},[2474,2478,2483,2487,2492,2497,2502,2507,2512,2516,2521,2525,2530,2535,2539,2543,2548],{"type":415,"tag":783,"props":2475,"children":2476},{"style":805},[2477],{"type":420,"value":1906},{"type":415,"tag":783,"props":2479,"children":2480},{"style":805},[2481],{"type":420,"value":2482}," static",{"type":415,"tag":783,"props":2484,"children":2485},{"style":805},[2486],{"type":420,"value":1911},{"type":415,"tag":783,"props":2488,"children":2489},{"style":790},[2490],{"type":420,"value":2491}," (double",{"type":415,"tag":783,"props":2493,"children":2494},{"style":875},[2495],{"type":420,"value":2496}," Latitude",{"type":415,"tag":783,"props":2498,"children":2499},{"style":790},[2500],{"type":420,"value":2501},",",{"type":415,"tag":783,"props":2503,"children":2504},{"style":790},[2505],{"type":420,"value":2506}," double",{"type":415,"tag":783,"props":2508,"children":2509},{"style":875},[2510],{"type":420,"value":2511}," Longitude",{"type":415,"tag":783,"props":2513,"children":2514},{"style":790},[2515],{"type":420,"value":1678},{"type":415,"tag":783,"props":2517,"children":2518},{"style":875},[2519],{"type":420,"value":2520}," BordeauxCoordinates",{"type":415,"tag":783,"props":2522,"children":2523},{"style":790},[2524],{"type":420,"value":2033},{"type":415,"tag":783,"props":2526,"children":2527},{"style":790},[2528],{"type":420,"value":2529}," (",{"type":415,"tag":783,"props":2531,"children":2532},{"style":902},[2533],{"type":420,"value":2534},"44.837789",{"type":415,"tag":783,"props":2536,"children":2537},{"style":790},[2538],{"type":420,"value":2501},{"type":415,"tag":783,"props":2540,"children":2541},{"style":790},[2542],{"type":420,"value":1553},{"type":415,"tag":783,"props":2544,"children":2545},{"style":902},[2546],{"type":420,"value":2547},"0.57918",{"type":415,"tag":783,"props":2549,"children":2550},{"style":790},[2551],{"type":420,"value":2552},");\n",{"type":415,"tag":783,"props":2554,"children":2555},{"class":785,"line":893},[2556],{"type":415,"tag":783,"props":2557,"children":2558},{"emptyLinePlaceholder":1624},[2559],{"type":420,"value":1627},{"type":415,"tag":783,"props":2561,"children":2562},{"class":785,"line":920},[2563,2567,2571,2575,2580,2585],{"type":415,"tag":783,"props":2564,"children":2565},{"style":805},[2566],{"type":420,"value":1941},{"type":415,"tag":783,"props":2568,"children":2569},{"style":1545},[2570],{"type":420,"value":2429},{"type":415,"tag":783,"props":2572,"children":2573},{"style":790},[2574],{"type":420,"value":1845},{"type":415,"tag":783,"props":2576,"children":2577},{"style":875},[2578],{"type":420,"value":2579},"IOpenWeatherMapApi",{"type":415,"tag":783,"props":2581,"children":2582},{"style":875},[2583],{"type":420,"value":2584}," openWeatherMapApi",{"type":415,"tag":783,"props":2586,"children":2587},{"style":790},[2588],{"type":420,"value":1963},{"type":415,"tag":783,"props":2590,"children":2591},{"class":785,"line":959},[2592],{"type":415,"tag":783,"props":2593,"children":2594},{"style":790},[2595],{"type":420,"value":1971},{"type":415,"tag":783,"props":2597,"children":2598},{"class":785,"line":997},[2599,2604,2608,2612],{"type":415,"tag":783,"props":2600,"children":2601},{"style":1362},[2602],{"type":420,"value":2603},"        _openWeatherMapApi ",{"type":415,"tag":783,"props":2605,"children":2606},{"style":790},[2607],{"type":420,"value":1984},{"type":415,"tag":783,"props":2609,"children":2610},{"style":1362},[2611],{"type":420,"value":2584},{"type":415,"tag":783,"props":2613,"children":2614},{"style":790},[2615],{"type":420,"value":1926},{"type":415,"tag":783,"props":2617,"children":2618},{"class":785,"line":1023},[2619],{"type":415,"tag":783,"props":2620,"children":2621},{"style":790},[2622],{"type":420,"value":1254},{"type":415,"tag":783,"props":2624,"children":2625},{"class":785,"line":1061},[2626],{"type":415,"tag":783,"props":2627,"children":2628},{"emptyLinePlaceholder":1624},[2629],{"type":420,"value":1627},{"type":415,"tag":783,"props":2631,"children":2632},{"class":785,"line":1099},[2633,2637,2642,2646,2650,2654,2658,2663],{"type":415,"tag":783,"props":2634,"children":2635},{"style":805},[2636],{"type":420,"value":1941},{"type":415,"tag":783,"props":2638,"children":2639},{"style":805},[2640],{"type":420,"value":2641}," async",{"type":415,"tag":783,"props":2643,"children":2644},{"style":875},[2645],{"type":420,"value":2107},{"type":415,"tag":783,"props":2647,"children":2648},{"style":790},[2649],{"type":420,"value":2112},{"type":415,"tag":783,"props":2651,"children":2652},{"style":875},[2653],{"type":420,"value":2072},{"type":415,"tag":783,"props":2655,"children":2656},{"style":790},[2657],{"type":420,"value":2121},{"type":415,"tag":783,"props":2659,"children":2660},{"style":1545},[2661],{"type":420,"value":2662}," GetWeatherForecasts",{"type":415,"tag":783,"props":2664,"children":2665},{"style":790},[2666],{"type":420,"value":2131},{"type":415,"tag":783,"props":2668,"children":2669},{"class":785,"line":1137},[2670],{"type":415,"tag":783,"props":2671,"children":2672},{"style":790},[2673],{"type":420,"value":1971},{"type":415,"tag":783,"props":2675,"children":2676},{"class":785,"line":1175},[2677,2682,2687,2691,2696,2700,2704,2708,2712,2717,2721,2726,2730,2734,2738,2743],{"type":415,"tag":783,"props":2678,"children":2679},{"style":875},[2680],{"type":420,"value":2681},"        var",{"type":415,"tag":783,"props":2683,"children":2684},{"style":875},[2685],{"type":420,"value":2686}," weatherApiResponse",{"type":415,"tag":783,"props":2688,"children":2689},{"style":790},[2690],{"type":420,"value":2033},{"type":415,"tag":783,"props":2692,"children":2693},{"style":790},[2694],{"type":420,"value":2695}," await",{"type":415,"tag":783,"props":2697,"children":2698},{"style":1362},[2699],{"type":420,"value":2466},{"type":415,"tag":783,"props":2701,"children":2702},{"style":790},[2703],{"type":420,"value":755},{"type":415,"tag":783,"props":2705,"children":2706},{"style":1545},[2707],{"type":420,"value":2042},{"type":415,"tag":783,"props":2709,"children":2710},{"style":790},[2711],{"type":420,"value":1845},{"type":415,"tag":783,"props":2713,"children":2714},{"style":1362},[2715],{"type":420,"value":2716},"BordeauxCoordinates",{"type":415,"tag":783,"props":2718,"children":2719},{"style":790},[2720],{"type":420,"value":755},{"type":415,"tag":783,"props":2722,"children":2723},{"style":1362},[2724],{"type":420,"value":2725},"Latitude",{"type":415,"tag":783,"props":2727,"children":2728},{"style":790},[2729],{"type":420,"value":2501},{"type":415,"tag":783,"props":2731,"children":2732},{"style":1362},[2733],{"type":420,"value":2520},{"type":415,"tag":783,"props":2735,"children":2736},{"style":790},[2737],{"type":420,"value":755},{"type":415,"tag":783,"props":2739,"children":2740},{"style":1362},[2741],{"type":420,"value":2742},"Longitude",{"type":415,"tag":783,"props":2744,"children":2745},{"style":790},[2746],{"type":420,"value":2552},{"type":415,"tag":783,"props":2748,"children":2749},{"class":785,"line":1213},[2750],{"type":415,"tag":783,"props":2751,"children":2752},{"style":1362},[2753],{"type":420,"value":2754},"        \n",{"type":415,"tag":783,"props":2756,"children":2757},{"class":785,"line":1239},[2758,2762,2767,2771,2775,2780,2784],{"type":415,"tag":783,"props":2759,"children":2760},{"style":875},[2761],{"type":420,"value":2681},{"type":415,"tag":783,"props":2763,"children":2764},{"style":875},[2765],{"type":420,"value":2766}," computeWeatherSummary",{"type":415,"tag":783,"props":2768,"children":2769},{"style":790},[2770],{"type":420,"value":2033},{"type":415,"tag":783,"props":2772,"children":2773},{"style":790},[2774],{"type":420,"value":2491},{"type":415,"tag":783,"props":2776,"children":2777},{"style":875},[2778],{"type":420,"value":2779}," temperature",{"type":415,"tag":783,"props":2781,"children":2782},{"style":790},[2783],{"type":420,"value":1678},{"type":415,"tag":783,"props":2785,"children":2786},{"style":790},[2787],{"type":420,"value":2788}," =>\n",{"type":415,"tag":783,"props":2790,"children":2791},{"class":785,"line":1248},[2792,2797],{"type":415,"tag":783,"props":2793,"children":2794},{"style":1362},[2795],{"type":420,"value":2796},"            temperature ",{"type":415,"tag":783,"props":2798,"children":2799},{"style":1356},[2800],{"type":420,"value":2801},"switch\n",{"type":415,"tag":783,"props":2803,"children":2804},{"class":785,"line":1257},[2805],{"type":415,"tag":783,"props":2806,"children":2807},{"style":790},[2808],{"type":420,"value":2809},"            {\n",{"type":415,"tag":783,"props":2811,"children":2812},{"class":785,"line":1266},[2813,2818,2823,2828,2832,2837,2841],{"type":415,"tag":783,"props":2814,"children":2815},{"style":790},[2816],{"type":420,"value":2817},"                \u003C",{"type":415,"tag":783,"props":2819,"children":2820},{"style":902},[2821],{"type":420,"value":2822}," 0",{"type":415,"tag":783,"props":2824,"children":2825},{"style":790},[2826],{"type":420,"value":2827}," =>",{"type":415,"tag":783,"props":2829,"children":2830},{"style":790},[2831],{"type":420,"value":822},{"type":415,"tag":783,"props":2833,"children":2834},{"style":825},[2835],{"type":420,"value":2836},"Freezing",{"type":415,"tag":783,"props":2838,"children":2839},{"style":790},[2840],{"type":420,"value":813},{"type":415,"tag":783,"props":2842,"children":2843},{"style":790},[2844],{"type":420,"value":837},{"type":415,"tag":783,"props":2846,"children":2848},{"class":785,"line":2847},19,[2849,2854,2858,2863,2868,2873,2877,2881,2886,2890],{"type":415,"tag":783,"props":2850,"children":2851},{"style":790},[2852],{"type":420,"value":2853},"                >=",{"type":415,"tag":783,"props":2855,"children":2856},{"style":902},[2857],{"type":420,"value":2822},{"type":415,"tag":783,"props":2859,"children":2860},{"style":790},[2861],{"type":420,"value":2862}," and",{"type":415,"tag":783,"props":2864,"children":2865},{"style":790},[2866],{"type":420,"value":2867}," \u003C",{"type":415,"tag":783,"props":2869,"children":2870},{"style":902},[2871],{"type":420,"value":2872}," 5",{"type":415,"tag":783,"props":2874,"children":2875},{"style":790},[2876],{"type":420,"value":2827},{"type":415,"tag":783,"props":2878,"children":2879},{"style":790},[2880],{"type":420,"value":822},{"type":415,"tag":783,"props":2882,"children":2883},{"style":825},[2884],{"type":420,"value":2885},"Bracing",{"type":415,"tag":783,"props":2887,"children":2888},{"style":790},[2889],{"type":420,"value":813},{"type":415,"tag":783,"props":2891,"children":2892},{"style":790},[2893],{"type":420,"value":837},{"type":415,"tag":783,"props":2895,"children":2897},{"class":785,"line":2896},20,[2898,2902,2906,2910,2914,2919,2923,2927,2932,2936],{"type":415,"tag":783,"props":2899,"children":2900},{"style":790},[2901],{"type":420,"value":2853},{"type":415,"tag":783,"props":2903,"children":2904},{"style":902},[2905],{"type":420,"value":2872},{"type":415,"tag":783,"props":2907,"children":2908},{"style":790},[2909],{"type":420,"value":2862},{"type":415,"tag":783,"props":2911,"children":2912},{"style":790},[2913],{"type":420,"value":2867},{"type":415,"tag":783,"props":2915,"children":2916},{"style":902},[2917],{"type":420,"value":2918}," 12",{"type":415,"tag":783,"props":2920,"children":2921},{"style":790},[2922],{"type":420,"value":2827},{"type":415,"tag":783,"props":2924,"children":2925},{"style":790},[2926],{"type":420,"value":822},{"type":415,"tag":783,"props":2928,"children":2929},{"style":825},[2930],{"type":420,"value":2931},"Chilly",{"type":415,"tag":783,"props":2933,"children":2934},{"style":790},[2935],{"type":420,"value":813},{"type":415,"tag":783,"props":2937,"children":2938},{"style":790},[2939],{"type":420,"value":837},{"type":415,"tag":783,"props":2941,"children":2943},{"class":785,"line":2942},21,[2944,2948,2952,2956,2960,2965,2969,2973,2978,2982],{"type":415,"tag":783,"props":2945,"children":2946},{"style":790},[2947],{"type":420,"value":2853},{"type":415,"tag":783,"props":2949,"children":2950},{"style":902},[2951],{"type":420,"value":2918},{"type":415,"tag":783,"props":2953,"children":2954},{"style":790},[2955],{"type":420,"value":2862},{"type":415,"tag":783,"props":2957,"children":2958},{"style":790},[2959],{"type":420,"value":2867},{"type":415,"tag":783,"props":2961,"children":2962},{"style":902},[2963],{"type":420,"value":2964}," 18",{"type":415,"tag":783,"props":2966,"children":2967},{"style":790},[2968],{"type":420,"value":2827},{"type":415,"tag":783,"props":2970,"children":2971},{"style":790},[2972],{"type":420,"value":822},{"type":415,"tag":783,"props":2974,"children":2975},{"style":825},[2976],{"type":420,"value":2977},"Cool",{"type":415,"tag":783,"props":2979,"children":2980},{"style":790},[2981],{"type":420,"value":813},{"type":415,"tag":783,"props":2983,"children":2984},{"style":790},[2985],{"type":420,"value":837},{"type":415,"tag":783,"props":2987,"children":2989},{"class":785,"line":2988},22,[2990,2994,2998,3002,3006,3011,3015,3019,3024,3028],{"type":415,"tag":783,"props":2991,"children":2992},{"style":790},[2993],{"type":420,"value":2853},{"type":415,"tag":783,"props":2995,"children":2996},{"style":902},[2997],{"type":420,"value":2964},{"type":415,"tag":783,"props":2999,"children":3000},{"style":790},[3001],{"type":420,"value":2862},{"type":415,"tag":783,"props":3003,"children":3004},{"style":790},[3005],{"type":420,"value":2867},{"type":415,"tag":783,"props":3007,"children":3008},{"style":902},[3009],{"type":420,"value":3010}," 24",{"type":415,"tag":783,"props":3012,"children":3013},{"style":790},[3014],{"type":420,"value":2827},{"type":415,"tag":783,"props":3016,"children":3017},{"style":790},[3018],{"type":420,"value":822},{"type":415,"tag":783,"props":3020,"children":3021},{"style":825},[3022],{"type":420,"value":3023},"Mild",{"type":415,"tag":783,"props":3025,"children":3026},{"style":790},[3027],{"type":420,"value":813},{"type":415,"tag":783,"props":3029,"children":3030},{"style":790},[3031],{"type":420,"value":837},{"type":415,"tag":783,"props":3033,"children":3035},{"class":785,"line":3034},23,[3036,3040,3044,3048,3052,3057,3061,3065,3070,3074],{"type":415,"tag":783,"props":3037,"children":3038},{"style":790},[3039],{"type":420,"value":2853},{"type":415,"tag":783,"props":3041,"children":3042},{"style":902},[3043],{"type":420,"value":3010},{"type":415,"tag":783,"props":3045,"children":3046},{"style":790},[3047],{"type":420,"value":2862},{"type":415,"tag":783,"props":3049,"children":3050},{"style":790},[3051],{"type":420,"value":2867},{"type":415,"tag":783,"props":3053,"children":3054},{"style":902},[3055],{"type":420,"value":3056}," 30",{"type":415,"tag":783,"props":3058,"children":3059},{"style":790},[3060],{"type":420,"value":2827},{"type":415,"tag":783,"props":3062,"children":3063},{"style":790},[3064],{"type":420,"value":822},{"type":415,"tag":783,"props":3066,"children":3067},{"style":825},[3068],{"type":420,"value":3069},"Warm",{"type":415,"tag":783,"props":3071,"children":3072},{"style":790},[3073],{"type":420,"value":813},{"type":415,"tag":783,"props":3075,"children":3076},{"style":790},[3077],{"type":420,"value":837},{"type":415,"tag":783,"props":3079,"children":3081},{"class":785,"line":3080},24,[3082,3086,3090,3094,3098,3103,3107,3111,3116,3120],{"type":415,"tag":783,"props":3083,"children":3084},{"style":790},[3085],{"type":420,"value":2853},{"type":415,"tag":783,"props":3087,"children":3088},{"style":902},[3089],{"type":420,"value":3056},{"type":415,"tag":783,"props":3091,"children":3092},{"style":790},[3093],{"type":420,"value":2862},{"type":415,"tag":783,"props":3095,"children":3096},{"style":790},[3097],{"type":420,"value":2867},{"type":415,"tag":783,"props":3099,"children":3100},{"style":902},[3101],{"type":420,"value":3102}," 35",{"type":415,"tag":783,"props":3104,"children":3105},{"style":790},[3106],{"type":420,"value":2827},{"type":415,"tag":783,"props":3108,"children":3109},{"style":790},[3110],{"type":420,"value":822},{"type":415,"tag":783,"props":3112,"children":3113},{"style":825},[3114],{"type":420,"value":3115},"Balmy",{"type":415,"tag":783,"props":3117,"children":3118},{"style":790},[3119],{"type":420,"value":813},{"type":415,"tag":783,"props":3121,"children":3122},{"style":790},[3123],{"type":420,"value":837},{"type":415,"tag":783,"props":3125,"children":3127},{"class":785,"line":3126},25,[3128,3132,3136,3140,3144,3149,3153,3157,3162,3166],{"type":415,"tag":783,"props":3129,"children":3130},{"style":790},[3131],{"type":420,"value":2853},{"type":415,"tag":783,"props":3133,"children":3134},{"style":902},[3135],{"type":420,"value":3102},{"type":415,"tag":783,"props":3137,"children":3138},{"style":790},[3139],{"type":420,"value":2862},{"type":415,"tag":783,"props":3141,"children":3142},{"style":790},[3143],{"type":420,"value":2867},{"type":415,"tag":783,"props":3145,"children":3146},{"style":902},[3147],{"type":420,"value":3148}," 40",{"type":415,"tag":783,"props":3150,"children":3151},{"style":790},[3152],{"type":420,"value":2827},{"type":415,"tag":783,"props":3154,"children":3155},{"style":790},[3156],{"type":420,"value":822},{"type":415,"tag":783,"props":3158,"children":3159},{"style":825},[3160],{"type":420,"value":3161},"Hot",{"type":415,"tag":783,"props":3163,"children":3164},{"style":790},[3165],{"type":420,"value":813},{"type":415,"tag":783,"props":3167,"children":3168},{"style":790},[3169],{"type":420,"value":837},{"type":415,"tag":783,"props":3171,"children":3173},{"class":785,"line":3172},26,[3174,3178,3182,3186,3190,3195,3199,3203,3208,3212],{"type":415,"tag":783,"props":3175,"children":3176},{"style":790},[3177],{"type":420,"value":2853},{"type":415,"tag":783,"props":3179,"children":3180},{"style":902},[3181],{"type":420,"value":3148},{"type":415,"tag":783,"props":3183,"children":3184},{"style":790},[3185],{"type":420,"value":2862},{"type":415,"tag":783,"props":3187,"children":3188},{"style":790},[3189],{"type":420,"value":2867},{"type":415,"tag":783,"props":3191,"children":3192},{"style":902},[3193],{"type":420,"value":3194}," 45",{"type":415,"tag":783,"props":3196,"children":3197},{"style":790},[3198],{"type":420,"value":2827},{"type":415,"tag":783,"props":3200,"children":3201},{"style":790},[3202],{"type":420,"value":822},{"type":415,"tag":783,"props":3204,"children":3205},{"style":825},[3206],{"type":420,"value":3207},"Sweltering",{"type":415,"tag":783,"props":3209,"children":3210},{"style":790},[3211],{"type":420,"value":813},{"type":415,"tag":783,"props":3213,"children":3214},{"style":790},[3215],{"type":420,"value":837},{"type":415,"tag":783,"props":3217,"children":3219},{"class":785,"line":3218},27,[3220,3224,3228,3232,3236,3241,3245],{"type":415,"tag":783,"props":3221,"children":3222},{"style":790},[3223],{"type":420,"value":2853},{"type":415,"tag":783,"props":3225,"children":3226},{"style":902},[3227],{"type":420,"value":3194},{"type":415,"tag":783,"props":3229,"children":3230},{"style":790},[3231],{"type":420,"value":2827},{"type":415,"tag":783,"props":3233,"children":3234},{"style":790},[3235],{"type":420,"value":822},{"type":415,"tag":783,"props":3237,"children":3238},{"style":825},[3239],{"type":420,"value":3240},"Scorching",{"type":415,"tag":783,"props":3242,"children":3243},{"style":790},[3244],{"type":420,"value":813},{"type":415,"tag":783,"props":3246,"children":3247},{"style":790},[3248],{"type":420,"value":837},{"type":415,"tag":783,"props":3250,"children":3252},{"class":785,"line":3251},28,[3253,3258,3263,3267,3271],{"type":415,"tag":783,"props":3254,"children":3255},{"style":1362},[3256],{"type":420,"value":3257},"                _ ",{"type":415,"tag":783,"props":3259,"children":3260},{"style":790},[3261],{"type":420,"value":3262},"=>",{"type":415,"tag":783,"props":3264,"children":3265},{"style":790},[3266],{"type":420,"value":822},{"type":415,"tag":783,"props":3268,"children":3269},{"style":825},[3270],{"type":420,"value":3069},{"type":415,"tag":783,"props":3272,"children":3273},{"style":790},[3274],{"type":420,"value":3275},"\"\n",{"type":415,"tag":783,"props":3277,"children":3279},{"class":785,"line":3278},29,[3280],{"type":415,"tag":783,"props":3281,"children":3282},{"style":790},[3283],{"type":420,"value":3284},"            };\n",{"type":415,"tag":783,"props":3286,"children":3288},{"class":785,"line":3287},30,[3289,3293,3297,3301],{"type":415,"tag":783,"props":3290,"children":3291},{"style":1356},[3292],{"type":420,"value":2146},{"type":415,"tag":783,"props":3294,"children":3295},{"style":1362},[3296],{"type":420,"value":2686},{"type":415,"tag":783,"props":3298,"children":3299},{"style":790},[3300],{"type":420,"value":755},{"type":415,"tag":783,"props":3302,"children":3303},{"style":1362},[3304],{"type":420,"value":3305},"List\n",{"type":415,"tag":783,"props":3307,"children":3309},{"class":785,"line":3308},31,[3310,3315,3320,3324,3329],{"type":415,"tag":783,"props":3311,"children":3312},{"style":790},[3313],{"type":420,"value":3314},"            .",{"type":415,"tag":783,"props":3316,"children":3317},{"style":1545},[3318],{"type":420,"value":3319},"Select",{"type":415,"tag":783,"props":3321,"children":3322},{"style":790},[3323],{"type":420,"value":1845},{"type":415,"tag":783,"props":3325,"children":3326},{"style":875},[3327],{"type":420,"value":3328},"x",{"type":415,"tag":783,"props":3330,"children":3331},{"style":790},[3332],{"type":420,"value":2788},{"type":415,"tag":783,"props":3334,"children":3336},{"class":785,"line":3335},32,[3337,3342],{"type":415,"tag":783,"props":3338,"children":3339},{"style":790},[3340],{"type":420,"value":3341},"                new",{"type":415,"tag":783,"props":3343,"children":3344},{"style":875},[3345],{"type":420,"value":3346}," WeatherForecast\n",{"type":415,"tag":783,"props":3348,"children":3350},{"class":785,"line":3349},33,[3351],{"type":415,"tag":783,"props":3352,"children":3353},{"style":790},[3354],{"type":420,"value":3355},"                {\n",{"type":415,"tag":783,"props":3357,"children":3359},{"class":785,"line":3358},34,[3360,3365,3369,3374,3378,3383,3387,3392,3396,3401,3405,3409,3413,3418,3423,3428],{"type":415,"tag":783,"props":3361,"children":3362},{"style":1362},[3363],{"type":420,"value":3364},"                    Date ",{"type":415,"tag":783,"props":3366,"children":3367},{"style":790},[3368],{"type":420,"value":1984},{"type":415,"tag":783,"props":3370,"children":3371},{"style":1362},[3372],{"type":420,"value":3373}," DateOnly",{"type":415,"tag":783,"props":3375,"children":3376},{"style":790},[3377],{"type":420,"value":755},{"type":415,"tag":783,"props":3379,"children":3380},{"style":1545},[3381],{"type":420,"value":3382},"FromDateTime",{"type":415,"tag":783,"props":3384,"children":3385},{"style":790},[3386],{"type":420,"value":1845},{"type":415,"tag":783,"props":3388,"children":3389},{"style":1362},[3390],{"type":420,"value":3391},"DateTimeOffset",{"type":415,"tag":783,"props":3393,"children":3394},{"style":790},[3395],{"type":420,"value":755},{"type":415,"tag":783,"props":3397,"children":3398},{"style":1545},[3399],{"type":420,"value":3400},"FromUnixTimeSeconds",{"type":415,"tag":783,"props":3402,"children":3403},{"style":790},[3404],{"type":420,"value":1845},{"type":415,"tag":783,"props":3406,"children":3407},{"style":1362},[3408],{"type":420,"value":3328},{"type":415,"tag":783,"props":3410,"children":3411},{"style":790},[3412],{"type":420,"value":755},{"type":415,"tag":783,"props":3414,"children":3415},{"style":1362},[3416],{"type":420,"value":3417},"Dt",{"type":415,"tag":783,"props":3419,"children":3420},{"style":790},[3421],{"type":420,"value":3422},").",{"type":415,"tag":783,"props":3424,"children":3425},{"style":1362},[3426],{"type":420,"value":3427},"Date",{"type":415,"tag":783,"props":3429,"children":3430},{"style":790},[3431],{"type":420,"value":3432},"),\n",{"type":415,"tag":783,"props":3434,"children":3436},{"class":785,"line":3435},35,[3437,3442,3446,3451,3455,3460,3464,3468,3472,3477,3481,3486],{"type":415,"tag":783,"props":3438,"children":3439},{"style":1362},[3440],{"type":420,"value":3441},"                    TemperatureC ",{"type":415,"tag":783,"props":3443,"children":3444},{"style":790},[3445],{"type":420,"value":1984},{"type":415,"tag":783,"props":3447,"children":3448},{"style":1362},[3449],{"type":420,"value":3450}," Convert",{"type":415,"tag":783,"props":3452,"children":3453},{"style":790},[3454],{"type":420,"value":755},{"type":415,"tag":783,"props":3456,"children":3457},{"style":1545},[3458],{"type":420,"value":3459},"ToInt32",{"type":415,"tag":783,"props":3461,"children":3462},{"style":790},[3463],{"type":420,"value":1845},{"type":415,"tag":783,"props":3465,"children":3466},{"style":1362},[3467],{"type":420,"value":3328},{"type":415,"tag":783,"props":3469,"children":3470},{"style":790},[3471],{"type":420,"value":755},{"type":415,"tag":783,"props":3473,"children":3474},{"style":1362},[3475],{"type":420,"value":3476},"Main",{"type":415,"tag":783,"props":3478,"children":3479},{"style":790},[3480],{"type":420,"value":755},{"type":415,"tag":783,"props":3482,"children":3483},{"style":1362},[3484],{"type":420,"value":3485},"Temp",{"type":415,"tag":783,"props":3487,"children":3488},{"style":790},[3489],{"type":420,"value":3432},{"type":415,"tag":783,"props":3491,"children":3493},{"class":785,"line":3492},36,[3494,3499,3503,3507,3511,3515,3519,3523,3527,3531],{"type":415,"tag":783,"props":3495,"children":3496},{"style":1362},[3497],{"type":420,"value":3498},"                    Summary ",{"type":415,"tag":783,"props":3500,"children":3501},{"style":790},[3502],{"type":420,"value":1984},{"type":415,"tag":783,"props":3504,"children":3505},{"style":1545},[3506],{"type":420,"value":2766},{"type":415,"tag":783,"props":3508,"children":3509},{"style":790},[3510],{"type":420,"value":1845},{"type":415,"tag":783,"props":3512,"children":3513},{"style":1362},[3514],{"type":420,"value":3328},{"type":415,"tag":783,"props":3516,"children":3517},{"style":790},[3518],{"type":420,"value":755},{"type":415,"tag":783,"props":3520,"children":3521},{"style":1362},[3522],{"type":420,"value":3476},{"type":415,"tag":783,"props":3524,"children":3525},{"style":790},[3526],{"type":420,"value":755},{"type":415,"tag":783,"props":3528,"children":3529},{"style":1362},[3530],{"type":420,"value":3485},{"type":415,"tag":783,"props":3532,"children":3533},{"style":790},[3534],{"type":420,"value":1963},{"type":415,"tag":783,"props":3536,"children":3538},{"class":785,"line":3537},37,[3539],{"type":415,"tag":783,"props":3540,"children":3541},{"style":790},[3542],{"type":420,"value":3543},"                })\n",{"type":415,"tag":783,"props":3545,"children":3547},{"class":785,"line":3546},38,[3548,3552,3557],{"type":415,"tag":783,"props":3549,"children":3550},{"style":790},[3551],{"type":420,"value":3314},{"type":415,"tag":783,"props":3553,"children":3554},{"style":1545},[3555],{"type":420,"value":3556},"ToArray",{"type":415,"tag":783,"props":3558,"children":3559},{"style":790},[3560],{"type":420,"value":2164},{"type":415,"tag":783,"props":3562,"children":3564},{"class":785,"line":3563},39,[3565],{"type":415,"tag":783,"props":3566,"children":3567},{"style":790},[3568],{"type":420,"value":1254},{"type":415,"tag":783,"props":3570,"children":3572},{"class":785,"line":3571},40,[3573],{"type":415,"tag":783,"props":3574,"children":3575},{"style":790},[3576],{"type":420,"value":1272},{"type":415,"tag":416,"props":3578,"children":3579},{},[3580],{"type":420,"value":3581},"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":773,"props":3583,"children":3585},{"className":1805,"code":3584,"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",[3586],{"type":415,"tag":550,"props":3587,"children":3588},{"__ignoreMap":401},[3589,3630,3637,3660,3667,3690],{"type":415,"tag":783,"props":3590,"children":3591},{"class":785,"line":786},[3592,3597,3602,3606,3610,3614,3618,3622,3626],{"type":415,"tag":783,"props":3593,"children":3594},{"style":902},[3595],{"type":420,"value":3596},"using",{"type":415,"tag":783,"props":3598,"children":3599},{"style":875},[3600],{"type":420,"value":3601}," Coordinates",{"type":415,"tag":783,"props":3603,"children":3604},{"style":790},[3605],{"type":420,"value":2033},{"type":415,"tag":783,"props":3607,"children":3608},{"style":790},[3609],{"type":420,"value":2491},{"type":415,"tag":783,"props":3611,"children":3612},{"style":875},[3613],{"type":420,"value":2496},{"type":415,"tag":783,"props":3615,"children":3616},{"style":790},[3617],{"type":420,"value":2501},{"type":415,"tag":783,"props":3619,"children":3620},{"style":790},[3621],{"type":420,"value":2506},{"type":415,"tag":783,"props":3623,"children":3624},{"style":875},[3625],{"type":420,"value":2511},{"type":415,"tag":783,"props":3627,"children":3628},{"style":790},[3629],{"type":420,"value":2552},{"type":415,"tag":783,"props":3631,"children":3632},{"class":785,"line":796},[3633],{"type":415,"tag":783,"props":3634,"children":3635},{"emptyLinePlaceholder":1624},[3636],{"type":420,"value":1627},{"type":415,"tag":783,"props":3638,"children":3639},{"class":785,"line":840},[3640,3644,3648,3652,3656],{"type":415,"tag":783,"props":3641,"children":3642},{"style":805},[3643],{"type":420,"value":1871},{"type":415,"tag":783,"props":3645,"children":3646},{"style":875},[3647],{"type":420,"value":1876},{"type":415,"tag":783,"props":3649,"children":3650},{"style":875},[3651],{"type":420,"value":2429},{"type":415,"tag":783,"props":3653,"children":3654},{"style":790},[3655],{"type":420,"value":1886},{"type":415,"tag":783,"props":3657,"children":3658},{"style":875},[3659],{"type":420,"value":2438},{"type":415,"tag":783,"props":3661,"children":3662},{"class":785,"line":866},[3663],{"type":415,"tag":783,"props":3664,"children":3665},{"style":790},[3666],{"type":420,"value":793},{"type":415,"tag":783,"props":3668,"children":3669},{"class":785,"line":893},[3670,3674,3678,3682,3686],{"type":415,"tag":783,"props":3671,"children":3672},{"style":805},[3673],{"type":420,"value":1906},{"type":415,"tag":783,"props":3675,"children":3676},{"style":805},[3677],{"type":420,"value":1911},{"type":415,"tag":783,"props":3679,"children":3680},{"style":875},[3681],{"type":420,"value":2461},{"type":415,"tag":783,"props":3683,"children":3684},{"style":875},[3685],{"type":420,"value":2466},{"type":415,"tag":783,"props":3687,"children":3688},{"style":790},[3689],{"type":420,"value":1926},{"type":415,"tag":783,"props":3691,"children":3692},{"class":785,"line":920},[3693,3697,3701,3705,3709,3713,3717,3721,3725,3729,3733],{"type":415,"tag":783,"props":3694,"children":3695},{"style":805},[3696],{"type":420,"value":1906},{"type":415,"tag":783,"props":3698,"children":3699},{"style":805},[3700],{"type":420,"value":2482},{"type":415,"tag":783,"props":3702,"children":3703},{"style":805},[3704],{"type":420,"value":1911},{"type":415,"tag":783,"props":3706,"children":3707},{"style":875},[3708],{"type":420,"value":3601},{"type":415,"tag":783,"props":3710,"children":3711},{"style":875},[3712],{"type":420,"value":2520},{"type":415,"tag":783,"props":3714,"children":3715},{"style":790},[3716],{"type":420,"value":2033},{"type":415,"tag":783,"props":3718,"children":3719},{"style":790},[3720],{"type":420,"value":2529},{"type":415,"tag":783,"props":3722,"children":3723},{"style":902},[3724],{"type":420,"value":2534},{"type":415,"tag":783,"props":3726,"children":3727},{"style":790},[3728],{"type":420,"value":2501},{"type":415,"tag":783,"props":3730,"children":3731},{"style":790},[3732],{"type":420,"value":1553},{"type":415,"tag":783,"props":3734,"children":3735},{"style":902},[3736],{"type":420,"value":3737},"0.57918\n",{"type":415,"tag":416,"props":3739,"children":3740},{},[3741,3743,3748,3750,3757],{"type":420,"value":3742},"Once this call is done, results are mapped to the expected model ",{"type":415,"tag":550,"props":3744,"children":3746},{"className":3745},[],[3747],{"type":420,"value":2072},{"type":420,"value":3749},". 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":423,"props":3751,"children":3754},{"href":3752,"rel":3753},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#default-lambda-parameters",[427],[3755],{"type":420,"value":3756},"default lambda parameters",{"type":420,"value":3758}," in C#12.",{"type":415,"tag":773,"props":3760,"children":3762},{"className":1805,"code":3761,"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",[3763],{"type":415,"tag":550,"props":3764,"children":3765},{"__ignoreMap":401},[3766,3828,3840,3847,3879,3923,3966,4009,4052,4095,4138,4181,4224,4255,4272],{"type":415,"tag":783,"props":3767,"children":3768},{"class":785,"line":786},[3769,3774,3778,3782,3786,3790,3794,3799,3804,3808,3812,3816,3820,3824],{"type":415,"tag":783,"props":3770,"children":3771},{"style":875},[3772],{"type":420,"value":3773},"var",{"type":415,"tag":783,"props":3775,"children":3776},{"style":875},[3777],{"type":420,"value":2766},{"type":415,"tag":783,"props":3779,"children":3780},{"style":790},[3781],{"type":420,"value":2033},{"type":415,"tag":783,"props":3783,"children":3784},{"style":790},[3785],{"type":420,"value":2491},{"type":415,"tag":783,"props":3787,"children":3788},{"style":875},[3789],{"type":420,"value":2779},{"type":415,"tag":783,"props":3791,"children":3792},{"style":790},[3793],{"type":420,"value":2501},{"type":415,"tag":783,"props":3795,"children":3796},{"style":790},[3797],{"type":420,"value":3798}," string",{"type":415,"tag":783,"props":3800,"children":3801},{"style":875},[3802],{"type":420,"value":3803}," defaultSummary",{"type":415,"tag":783,"props":3805,"children":3806},{"style":790},[3807],{"type":420,"value":2033},{"type":415,"tag":783,"props":3809,"children":3810},{"style":790},[3811],{"type":420,"value":822},{"type":415,"tag":783,"props":3813,"children":3814},{"style":825},[3815],{"type":420,"value":3069},{"type":415,"tag":783,"props":3817,"children":3818},{"style":790},[3819],{"type":420,"value":813},{"type":415,"tag":783,"props":3821,"children":3822},{"style":790},[3823],{"type":420,"value":1678},{"type":415,"tag":783,"props":3825,"children":3826},{"style":790},[3827],{"type":420,"value":2788},{"type":415,"tag":783,"props":3829,"children":3830},{"class":785,"line":796},[3831,3836],{"type":415,"tag":783,"props":3832,"children":3833},{"style":1362},[3834],{"type":420,"value":3835},"    temperature ",{"type":415,"tag":783,"props":3837,"children":3838},{"style":1356},[3839],{"type":420,"value":2801},{"type":415,"tag":783,"props":3841,"children":3842},{"class":785,"line":840},[3843],{"type":415,"tag":783,"props":3844,"children":3845},{"style":790},[3846],{"type":420,"value":1971},{"type":415,"tag":783,"props":3848,"children":3849},{"class":785,"line":866},[3850,3855,3859,3863,3867,3871,3875],{"type":415,"tag":783,"props":3851,"children":3852},{"style":790},[3853],{"type":420,"value":3854},"        \u003C",{"type":415,"tag":783,"props":3856,"children":3857},{"style":902},[3858],{"type":420,"value":2822},{"type":415,"tag":783,"props":3860,"children":3861},{"style":790},[3862],{"type":420,"value":2827},{"type":415,"tag":783,"props":3864,"children":3865},{"style":790},[3866],{"type":420,"value":822},{"type":415,"tag":783,"props":3868,"children":3869},{"style":825},[3870],{"type":420,"value":2836},{"type":415,"tag":783,"props":3872,"children":3873},{"style":790},[3874],{"type":420,"value":813},{"type":415,"tag":783,"props":3876,"children":3877},{"style":790},[3878],{"type":420,"value":837},{"type":415,"tag":783,"props":3880,"children":3881},{"class":785,"line":893},[3882,3887,3891,3895,3899,3903,3907,3911,3915,3919],{"type":415,"tag":783,"props":3883,"children":3884},{"style":790},[3885],{"type":420,"value":3886},"        >=",{"type":415,"tag":783,"props":3888,"children":3889},{"style":902},[3890],{"type":420,"value":2822},{"type":415,"tag":783,"props":3892,"children":3893},{"style":790},[3894],{"type":420,"value":2862},{"type":415,"tag":783,"props":3896,"children":3897},{"style":790},[3898],{"type":420,"value":2867},{"type":415,"tag":783,"props":3900,"children":3901},{"style":902},[3902],{"type":420,"value":2872},{"type":415,"tag":783,"props":3904,"children":3905},{"style":790},[3906],{"type":420,"value":2827},{"type":415,"tag":783,"props":3908,"children":3909},{"style":790},[3910],{"type":420,"value":822},{"type":415,"tag":783,"props":3912,"children":3913},{"style":825},[3914],{"type":420,"value":2885},{"type":415,"tag":783,"props":3916,"children":3917},{"style":790},[3918],{"type":420,"value":813},{"type":415,"tag":783,"props":3920,"children":3921},{"style":790},[3922],{"type":420,"value":837},{"type":415,"tag":783,"props":3924,"children":3925},{"class":785,"line":920},[3926,3930,3934,3938,3942,3946,3950,3954,3958,3962],{"type":415,"tag":783,"props":3927,"children":3928},{"style":790},[3929],{"type":420,"value":3886},{"type":415,"tag":783,"props":3931,"children":3932},{"style":902},[3933],{"type":420,"value":2872},{"type":415,"tag":783,"props":3935,"children":3936},{"style":790},[3937],{"type":420,"value":2862},{"type":415,"tag":783,"props":3939,"children":3940},{"style":790},[3941],{"type":420,"value":2867},{"type":415,"tag":783,"props":3943,"children":3944},{"style":902},[3945],{"type":420,"value":2918},{"type":415,"tag":783,"props":3947,"children":3948},{"style":790},[3949],{"type":420,"value":2827},{"type":415,"tag":783,"props":3951,"children":3952},{"style":790},[3953],{"type":420,"value":822},{"type":415,"tag":783,"props":3955,"children":3956},{"style":825},[3957],{"type":420,"value":2931},{"type":415,"tag":783,"props":3959,"children":3960},{"style":790},[3961],{"type":420,"value":813},{"type":415,"tag":783,"props":3963,"children":3964},{"style":790},[3965],{"type":420,"value":837},{"type":415,"tag":783,"props":3967,"children":3968},{"class":785,"line":959},[3969,3973,3977,3981,3985,3989,3993,3997,4001,4005],{"type":415,"tag":783,"props":3970,"children":3971},{"style":790},[3972],{"type":420,"value":3886},{"type":415,"tag":783,"props":3974,"children":3975},{"style":902},[3976],{"type":420,"value":2918},{"type":415,"tag":783,"props":3978,"children":3979},{"style":790},[3980],{"type":420,"value":2862},{"type":415,"tag":783,"props":3982,"children":3983},{"style":790},[3984],{"type":420,"value":2867},{"type":415,"tag":783,"props":3986,"children":3987},{"style":902},[3988],{"type":420,"value":2964},{"type":415,"tag":783,"props":3990,"children":3991},{"style":790},[3992],{"type":420,"value":2827},{"type":415,"tag":783,"props":3994,"children":3995},{"style":790},[3996],{"type":420,"value":822},{"type":415,"tag":783,"props":3998,"children":3999},{"style":825},[4000],{"type":420,"value":2977},{"type":415,"tag":783,"props":4002,"children":4003},{"style":790},[4004],{"type":420,"value":813},{"type":415,"tag":783,"props":4006,"children":4007},{"style":790},[4008],{"type":420,"value":837},{"type":415,"tag":783,"props":4010,"children":4011},{"class":785,"line":997},[4012,4016,4020,4024,4028,4032,4036,4040,4044,4048],{"type":415,"tag":783,"props":4013,"children":4014},{"style":790},[4015],{"type":420,"value":3886},{"type":415,"tag":783,"props":4017,"children":4018},{"style":902},[4019],{"type":420,"value":2964},{"type":415,"tag":783,"props":4021,"children":4022},{"style":790},[4023],{"type":420,"value":2862},{"type":415,"tag":783,"props":4025,"children":4026},{"style":790},[4027],{"type":420,"value":2867},{"type":415,"tag":783,"props":4029,"children":4030},{"style":902},[4031],{"type":420,"value":3010},{"type":415,"tag":783,"props":4033,"children":4034},{"style":790},[4035],{"type":420,"value":2827},{"type":415,"tag":783,"props":4037,"children":4038},{"style":790},[4039],{"type":420,"value":822},{"type":415,"tag":783,"props":4041,"children":4042},{"style":825},[4043],{"type":420,"value":3023},{"type":415,"tag":783,"props":4045,"children":4046},{"style":790},[4047],{"type":420,"value":813},{"type":415,"tag":783,"props":4049,"children":4050},{"style":790},[4051],{"type":420,"value":837},{"type":415,"tag":783,"props":4053,"children":4054},{"class":785,"line":1023},[4055,4059,4063,4067,4071,4075,4079,4083,4087,4091],{"type":415,"tag":783,"props":4056,"children":4057},{"style":790},[4058],{"type":420,"value":3886},{"type":415,"tag":783,"props":4060,"children":4061},{"style":902},[4062],{"type":420,"value":3010},{"type":415,"tag":783,"props":4064,"children":4065},{"style":790},[4066],{"type":420,"value":2862},{"type":415,"tag":783,"props":4068,"children":4069},{"style":790},[4070],{"type":420,"value":2867},{"type":415,"tag":783,"props":4072,"children":4073},{"style":902},[4074],{"type":420,"value":3056},{"type":415,"tag":783,"props":4076,"children":4077},{"style":790},[4078],{"type":420,"value":2827},{"type":415,"tag":783,"props":4080,"children":4081},{"style":790},[4082],{"type":420,"value":822},{"type":415,"tag":783,"props":4084,"children":4085},{"style":825},[4086],{"type":420,"value":3069},{"type":415,"tag":783,"props":4088,"children":4089},{"style":790},[4090],{"type":420,"value":813},{"type":415,"tag":783,"props":4092,"children":4093},{"style":790},[4094],{"type":420,"value":837},{"type":415,"tag":783,"props":4096,"children":4097},{"class":785,"line":1061},[4098,4102,4106,4110,4114,4118,4122,4126,4130,4134],{"type":415,"tag":783,"props":4099,"children":4100},{"style":790},[4101],{"type":420,"value":3886},{"type":415,"tag":783,"props":4103,"children":4104},{"style":902},[4105],{"type":420,"value":3056},{"type":415,"tag":783,"props":4107,"children":4108},{"style":790},[4109],{"type":420,"value":2862},{"type":415,"tag":783,"props":4111,"children":4112},{"style":790},[4113],{"type":420,"value":2867},{"type":415,"tag":783,"props":4115,"children":4116},{"style":902},[4117],{"type":420,"value":3102},{"type":415,"tag":783,"props":4119,"children":4120},{"style":790},[4121],{"type":420,"value":2827},{"type":415,"tag":783,"props":4123,"children":4124},{"style":790},[4125],{"type":420,"value":822},{"type":415,"tag":783,"props":4127,"children":4128},{"style":825},[4129],{"type":420,"value":3115},{"type":415,"tag":783,"props":4131,"children":4132},{"style":790},[4133],{"type":420,"value":813},{"type":415,"tag":783,"props":4135,"children":4136},{"style":790},[4137],{"type":420,"value":837},{"type":415,"tag":783,"props":4139,"children":4140},{"class":785,"line":1099},[4141,4145,4149,4153,4157,4161,4165,4169,4173,4177],{"type":415,"tag":783,"props":4142,"children":4143},{"style":790},[4144],{"type":420,"value":3886},{"type":415,"tag":783,"props":4146,"children":4147},{"style":902},[4148],{"type":420,"value":3102},{"type":415,"tag":783,"props":4150,"children":4151},{"style":790},[4152],{"type":420,"value":2862},{"type":415,"tag":783,"props":4154,"children":4155},{"style":790},[4156],{"type":420,"value":2867},{"type":415,"tag":783,"props":4158,"children":4159},{"style":902},[4160],{"type":420,"value":3148},{"type":415,"tag":783,"props":4162,"children":4163},{"style":790},[4164],{"type":420,"value":2827},{"type":415,"tag":783,"props":4166,"children":4167},{"style":790},[4168],{"type":420,"value":822},{"type":415,"tag":783,"props":4170,"children":4171},{"style":825},[4172],{"type":420,"value":3161},{"type":415,"tag":783,"props":4174,"children":4175},{"style":790},[4176],{"type":420,"value":813},{"type":415,"tag":783,"props":4178,"children":4179},{"style":790},[4180],{"type":420,"value":837},{"type":415,"tag":783,"props":4182,"children":4183},{"class":785,"line":1137},[4184,4188,4192,4196,4200,4204,4208,4212,4216,4220],{"type":415,"tag":783,"props":4185,"children":4186},{"style":790},[4187],{"type":420,"value":3886},{"type":415,"tag":783,"props":4189,"children":4190},{"style":902},[4191],{"type":420,"value":3148},{"type":415,"tag":783,"props":4193,"children":4194},{"style":790},[4195],{"type":420,"value":2862},{"type":415,"tag":783,"props":4197,"children":4198},{"style":790},[4199],{"type":420,"value":2867},{"type":415,"tag":783,"props":4201,"children":4202},{"style":902},[4203],{"type":420,"value":3194},{"type":415,"tag":783,"props":4205,"children":4206},{"style":790},[4207],{"type":420,"value":2827},{"type":415,"tag":783,"props":4209,"children":4210},{"style":790},[4211],{"type":420,"value":822},{"type":415,"tag":783,"props":4213,"children":4214},{"style":825},[4215],{"type":420,"value":3207},{"type":415,"tag":783,"props":4217,"children":4218},{"style":790},[4219],{"type":420,"value":813},{"type":415,"tag":783,"props":4221,"children":4222},{"style":790},[4223],{"type":420,"value":837},{"type":415,"tag":783,"props":4225,"children":4226},{"class":785,"line":1175},[4227,4231,4235,4239,4243,4247,4251],{"type":415,"tag":783,"props":4228,"children":4229},{"style":790},[4230],{"type":420,"value":3886},{"type":415,"tag":783,"props":4232,"children":4233},{"style":902},[4234],{"type":420,"value":3194},{"type":415,"tag":783,"props":4236,"children":4237},{"style":790},[4238],{"type":420,"value":2827},{"type":415,"tag":783,"props":4240,"children":4241},{"style":790},[4242],{"type":420,"value":822},{"type":415,"tag":783,"props":4244,"children":4245},{"style":825},[4246],{"type":420,"value":3240},{"type":415,"tag":783,"props":4248,"children":4249},{"style":790},[4250],{"type":420,"value":813},{"type":415,"tag":783,"props":4252,"children":4253},{"style":790},[4254],{"type":420,"value":837},{"type":415,"tag":783,"props":4256,"children":4257},{"class":785,"line":1213},[4258,4263,4267],{"type":415,"tag":783,"props":4259,"children":4260},{"style":1362},[4261],{"type":420,"value":4262},"        _ ",{"type":415,"tag":783,"props":4264,"children":4265},{"style":790},[4266],{"type":420,"value":3262},{"type":415,"tag":783,"props":4268,"children":4269},{"style":1362},[4270],{"type":420,"value":4271}," defaultSummary\n",{"type":415,"tag":783,"props":4273,"children":4274},{"class":785,"line":1239},[4275],{"type":415,"tag":783,"props":4276,"children":4277},{"style":790},[4278],{"type":420,"value":4279},"    };\n",{"type":415,"tag":416,"props":4281,"children":4282},{},[4283,4288],{"type":415,"tag":550,"props":4284,"children":4286},{"className":4285},[],[4287],{"type":420,"value":2389},{"type":420,"value":4289}," does not have this logic because Summaries are randomly selected from an array containing possible summaries.",{"type":415,"tag":773,"props":4291,"children":4293},{"className":1805,"code":4292,"language":326,"meta":401,"style":401},"private static readonly string[] Summaries = new [] { \"Freezing\", \"Bracing\", \"Chilly\", \"Cool\", \"Mild\", \"Warm\", \"Balmy\", \"Hot\", \"Sweltering\", \"Scorching\" };\n",[4294],{"type":415,"tag":550,"props":4295,"children":4296},{"__ignoreMap":401},[4297],{"type":415,"tag":783,"props":4298,"children":4299},{"class":785,"line":786},[4300,4305,4309,4313,4317,4322,4327,4331,4336,4341,4346,4350,4354,4358,4362,4366,4370,4374,4378,4382,4386,4390,4394,4398,4402,4406,4410,4414,4418,4422,4426,4430,4434,4438,4442,4446,4450,4454,4458,4462,4466,4470,4474,4478,4482,4486,4490,4494,4498,4502],{"type":415,"tag":783,"props":4301,"children":4302},{"style":805},[4303],{"type":420,"value":4304},"private",{"type":415,"tag":783,"props":4306,"children":4307},{"style":805},[4308],{"type":420,"value":2482},{"type":415,"tag":783,"props":4310,"children":4311},{"style":805},[4312],{"type":420,"value":1911},{"type":415,"tag":783,"props":4314,"children":4315},{"style":790},[4316],{"type":420,"value":3798},{"type":415,"tag":783,"props":4318,"children":4319},{"style":790},[4320],{"type":420,"value":4321},"[]",{"type":415,"tag":783,"props":4323,"children":4324},{"style":875},[4325],{"type":420,"value":4326}," Summaries",{"type":415,"tag":783,"props":4328,"children":4329},{"style":790},[4330],{"type":420,"value":2033},{"type":415,"tag":783,"props":4332,"children":4333},{"style":790},[4334],{"type":420,"value":4335}," new",{"type":415,"tag":783,"props":4337,"children":4338},{"style":790},[4339],{"type":420,"value":4340}," []",{"type":415,"tag":783,"props":4342,"children":4343},{"style":790},[4344],{"type":420,"value":4345}," {",{"type":415,"tag":783,"props":4347,"children":4348},{"style":790},[4349],{"type":420,"value":822},{"type":415,"tag":783,"props":4351,"children":4352},{"style":825},[4353],{"type":420,"value":2836},{"type":415,"tag":783,"props":4355,"children":4356},{"style":790},[4357],{"type":420,"value":813},{"type":415,"tag":783,"props":4359,"children":4360},{"style":790},[4361],{"type":420,"value":2501},{"type":415,"tag":783,"props":4363,"children":4364},{"style":790},[4365],{"type":420,"value":822},{"type":415,"tag":783,"props":4367,"children":4368},{"style":825},[4369],{"type":420,"value":2885},{"type":415,"tag":783,"props":4371,"children":4372},{"style":790},[4373],{"type":420,"value":813},{"type":415,"tag":783,"props":4375,"children":4376},{"style":790},[4377],{"type":420,"value":2501},{"type":415,"tag":783,"props":4379,"children":4380},{"style":790},[4381],{"type":420,"value":822},{"type":415,"tag":783,"props":4383,"children":4384},{"style":825},[4385],{"type":420,"value":2931},{"type":415,"tag":783,"props":4387,"children":4388},{"style":790},[4389],{"type":420,"value":813},{"type":415,"tag":783,"props":4391,"children":4392},{"style":790},[4393],{"type":420,"value":2501},{"type":415,"tag":783,"props":4395,"children":4396},{"style":790},[4397],{"type":420,"value":822},{"type":415,"tag":783,"props":4399,"children":4400},{"style":825},[4401],{"type":420,"value":2977},{"type":415,"tag":783,"props":4403,"children":4404},{"style":790},[4405],{"type":420,"value":813},{"type":415,"tag":783,"props":4407,"children":4408},{"style":790},[4409],{"type":420,"value":2501},{"type":415,"tag":783,"props":4411,"children":4412},{"style":790},[4413],{"type":420,"value":822},{"type":415,"tag":783,"props":4415,"children":4416},{"style":825},[4417],{"type":420,"value":3023},{"type":415,"tag":783,"props":4419,"children":4420},{"style":790},[4421],{"type":420,"value":813},{"type":415,"tag":783,"props":4423,"children":4424},{"style":790},[4425],{"type":420,"value":2501},{"type":415,"tag":783,"props":4427,"children":4428},{"style":790},[4429],{"type":420,"value":822},{"type":415,"tag":783,"props":4431,"children":4432},{"style":825},[4433],{"type":420,"value":3069},{"type":415,"tag":783,"props":4435,"children":4436},{"style":790},[4437],{"type":420,"value":813},{"type":415,"tag":783,"props":4439,"children":4440},{"style":790},[4441],{"type":420,"value":2501},{"type":415,"tag":783,"props":4443,"children":4444},{"style":790},[4445],{"type":420,"value":822},{"type":415,"tag":783,"props":4447,"children":4448},{"style":825},[4449],{"type":420,"value":3115},{"type":415,"tag":783,"props":4451,"children":4452},{"style":790},[4453],{"type":420,"value":813},{"type":415,"tag":783,"props":4455,"children":4456},{"style":790},[4457],{"type":420,"value":2501},{"type":415,"tag":783,"props":4459,"children":4460},{"style":790},[4461],{"type":420,"value":822},{"type":415,"tag":783,"props":4463,"children":4464},{"style":825},[4465],{"type":420,"value":3161},{"type":415,"tag":783,"props":4467,"children":4468},{"style":790},[4469],{"type":420,"value":813},{"type":415,"tag":783,"props":4471,"children":4472},{"style":790},[4473],{"type":420,"value":2501},{"type":415,"tag":783,"props":4475,"children":4476},{"style":790},[4477],{"type":420,"value":822},{"type":415,"tag":783,"props":4479,"children":4480},{"style":825},[4481],{"type":420,"value":3207},{"type":415,"tag":783,"props":4483,"children":4484},{"style":790},[4485],{"type":420,"value":813},{"type":415,"tag":783,"props":4487,"children":4488},{"style":790},[4489],{"type":420,"value":2501},{"type":415,"tag":783,"props":4491,"children":4492},{"style":790},[4493],{"type":420,"value":822},{"type":415,"tag":783,"props":4495,"children":4496},{"style":825},[4497],{"type":420,"value":3240},{"type":415,"tag":783,"props":4499,"children":4500},{"style":790},[4501],{"type":420,"value":813},{"type":415,"tag":783,"props":4503,"children":4504},{"style":790},[4505],{"type":420,"value":4506}," };\n",{"type":415,"tag":416,"props":4508,"children":4509},{},[4510,4512,4519],{"type":420,"value":4511},"With ",{"type":415,"tag":423,"props":4513,"children":4516},{"href":4514,"rel":4515},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#collection-expressions",[427],[4517],{"type":420,"value":4518},"collection expressions",{"type":420,"value":4520},", this array can be defined directly with square brackets.",{"type":415,"tag":773,"props":4522,"children":4524},{"className":1805,"code":4523,"language":326,"meta":401,"style":401},"private static readonly string[] Summaries = [ \"Freezing\", \"Bracing\", \"Chilly\", \"Cool\", \"Mild\", \"Warm\", \"Balmy\", \"Hot\", \"Sweltering\", \"Scorching\"];\n",[4525],{"type":415,"tag":550,"props":4526,"children":4527},{"__ignoreMap":401},[4528],{"type":415,"tag":783,"props":4529,"children":4530},{"class":785,"line":786},[4531,4535,4539,4543,4547,4551,4555,4559,4564,4568,4572,4576,4580,4584,4588,4592,4596,4600,4604,4608,4612,4616,4620,4624,4628,4632,4636,4640,4644,4648,4652,4656,4660,4664,4668,4672,4676,4680,4684,4688,4692,4696,4700,4704,4708,4712,4716,4720],{"type":415,"tag":783,"props":4532,"children":4533},{"style":805},[4534],{"type":420,"value":4304},{"type":415,"tag":783,"props":4536,"children":4537},{"style":805},[4538],{"type":420,"value":2482},{"type":415,"tag":783,"props":4540,"children":4541},{"style":805},[4542],{"type":420,"value":1911},{"type":415,"tag":783,"props":4544,"children":4545},{"style":790},[4546],{"type":420,"value":3798},{"type":415,"tag":783,"props":4548,"children":4549},{"style":790},[4550],{"type":420,"value":4321},{"type":415,"tag":783,"props":4552,"children":4553},{"style":875},[4554],{"type":420,"value":4326},{"type":415,"tag":783,"props":4556,"children":4557},{"style":790},[4558],{"type":420,"value":2033},{"type":415,"tag":783,"props":4560,"children":4561},{"style":790},[4562],{"type":420,"value":4563}," [",{"type":415,"tag":783,"props":4565,"children":4566},{"style":790},[4567],{"type":420,"value":822},{"type":415,"tag":783,"props":4569,"children":4570},{"style":825},[4571],{"type":420,"value":2836},{"type":415,"tag":783,"props":4573,"children":4574},{"style":790},[4575],{"type":420,"value":813},{"type":415,"tag":783,"props":4577,"children":4578},{"style":790},[4579],{"type":420,"value":2501},{"type":415,"tag":783,"props":4581,"children":4582},{"style":790},[4583],{"type":420,"value":822},{"type":415,"tag":783,"props":4585,"children":4586},{"style":825},[4587],{"type":420,"value":2885},{"type":415,"tag":783,"props":4589,"children":4590},{"style":790},[4591],{"type":420,"value":813},{"type":415,"tag":783,"props":4593,"children":4594},{"style":790},[4595],{"type":420,"value":2501},{"type":415,"tag":783,"props":4597,"children":4598},{"style":790},[4599],{"type":420,"value":822},{"type":415,"tag":783,"props":4601,"children":4602},{"style":825},[4603],{"type":420,"value":2931},{"type":415,"tag":783,"props":4605,"children":4606},{"style":790},[4607],{"type":420,"value":813},{"type":415,"tag":783,"props":4609,"children":4610},{"style":790},[4611],{"type":420,"value":2501},{"type":415,"tag":783,"props":4613,"children":4614},{"style":790},[4615],{"type":420,"value":822},{"type":415,"tag":783,"props":4617,"children":4618},{"style":825},[4619],{"type":420,"value":2977},{"type":415,"tag":783,"props":4621,"children":4622},{"style":790},[4623],{"type":420,"value":813},{"type":415,"tag":783,"props":4625,"children":4626},{"style":790},[4627],{"type":420,"value":2501},{"type":415,"tag":783,"props":4629,"children":4630},{"style":790},[4631],{"type":420,"value":822},{"type":415,"tag":783,"props":4633,"children":4634},{"style":825},[4635],{"type":420,"value":3023},{"type":415,"tag":783,"props":4637,"children":4638},{"style":790},[4639],{"type":420,"value":813},{"type":415,"tag":783,"props":4641,"children":4642},{"style":790},[4643],{"type":420,"value":2501},{"type":415,"tag":783,"props":4645,"children":4646},{"style":790},[4647],{"type":420,"value":822},{"type":415,"tag":783,"props":4649,"children":4650},{"style":825},[4651],{"type":420,"value":3069},{"type":415,"tag":783,"props":4653,"children":4654},{"style":790},[4655],{"type":420,"value":813},{"type":415,"tag":783,"props":4657,"children":4658},{"style":790},[4659],{"type":420,"value":2501},{"type":415,"tag":783,"props":4661,"children":4662},{"style":790},[4663],{"type":420,"value":822},{"type":415,"tag":783,"props":4665,"children":4666},{"style":825},[4667],{"type":420,"value":3115},{"type":415,"tag":783,"props":4669,"children":4670},{"style":790},[4671],{"type":420,"value":813},{"type":415,"tag":783,"props":4673,"children":4674},{"style":790},[4675],{"type":420,"value":2501},{"type":415,"tag":783,"props":4677,"children":4678},{"style":790},[4679],{"type":420,"value":822},{"type":415,"tag":783,"props":4681,"children":4682},{"style":825},[4683],{"type":420,"value":3161},{"type":415,"tag":783,"props":4685,"children":4686},{"style":790},[4687],{"type":420,"value":813},{"type":415,"tag":783,"props":4689,"children":4690},{"style":790},[4691],{"type":420,"value":2501},{"type":415,"tag":783,"props":4693,"children":4694},{"style":790},[4695],{"type":420,"value":822},{"type":415,"tag":783,"props":4697,"children":4698},{"style":825},[4699],{"type":420,"value":3207},{"type":415,"tag":783,"props":4701,"children":4702},{"style":790},[4703],{"type":420,"value":813},{"type":415,"tag":783,"props":4705,"children":4706},{"style":790},[4707],{"type":420,"value":2501},{"type":415,"tag":783,"props":4709,"children":4710},{"style":790},[4711],{"type":420,"value":822},{"type":415,"tag":783,"props":4713,"children":4714},{"style":825},[4715],{"type":420,"value":3240},{"type":415,"tag":783,"props":4717,"children":4718},{"style":790},[4719],{"type":420,"value":813},{"type":415,"tag":783,"props":4721,"children":4722},{"style":790},[4723],{"type":420,"value":4724},"];\n",{"type":415,"tag":416,"props":4726,"children":4727},{},[4728],{"type":420,"value":4729},"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":773,"props":4731,"children":4733},{"className":1805,"code":4732,"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",[4734],{"type":415,"tag":550,"props":4735,"children":4736},{"__ignoreMap":401},[4737,4848],{"type":415,"tag":783,"props":4738,"children":4739},{"class":785,"line":786},[4740,4745,4749,4753,4758,4762,4767,4771,4776,4780,4784,4788,4792,4796,4800,4804,4808,4812,4816,4820,4824,4828,4832,4836,4840,4844],{"type":415,"tag":783,"props":4741,"children":4742},{"style":805},[4743],{"type":420,"value":4744}," private",{"type":415,"tag":783,"props":4746,"children":4747},{"style":805},[4748],{"type":420,"value":2482},{"type":415,"tag":783,"props":4750,"children":4751},{"style":805},[4752],{"type":420,"value":1911},{"type":415,"tag":783,"props":4754,"children":4755},{"style":875},[4756],{"type":420,"value":4757}," IList",{"type":415,"tag":783,"props":4759,"children":4760},{"style":790},[4761],{"type":420,"value":2112},{"type":415,"tag":783,"props":4763,"children":4764},{"style":790},[4765],{"type":420,"value":4766},"string",{"type":415,"tag":783,"props":4768,"children":4769},{"style":790},[4770],{"type":420,"value":2276},{"type":415,"tag":783,"props":4772,"children":4773},{"style":875},[4774],{"type":420,"value":4775}," ColdAdjectives",{"type":415,"tag":783,"props":4777,"children":4778},{"style":790},[4779],{"type":420,"value":2033},{"type":415,"tag":783,"props":4781,"children":4782},{"style":790},[4783],{"type":420,"value":4563},{"type":415,"tag":783,"props":4785,"children":4786},{"style":790},[4787],{"type":420,"value":813},{"type":415,"tag":783,"props":4789,"children":4790},{"style":825},[4791],{"type":420,"value":2836},{"type":415,"tag":783,"props":4793,"children":4794},{"style":790},[4795],{"type":420,"value":813},{"type":415,"tag":783,"props":4797,"children":4798},{"style":790},[4799],{"type":420,"value":2501},{"type":415,"tag":783,"props":4801,"children":4802},{"style":790},[4803],{"type":420,"value":822},{"type":415,"tag":783,"props":4805,"children":4806},{"style":825},[4807],{"type":420,"value":2885},{"type":415,"tag":783,"props":4809,"children":4810},{"style":790},[4811],{"type":420,"value":813},{"type":415,"tag":783,"props":4813,"children":4814},{"style":790},[4815],{"type":420,"value":2501},{"type":415,"tag":783,"props":4817,"children":4818},{"style":790},[4819],{"type":420,"value":822},{"type":415,"tag":783,"props":4821,"children":4822},{"style":825},[4823],{"type":420,"value":2931},{"type":415,"tag":783,"props":4825,"children":4826},{"style":790},[4827],{"type":420,"value":813},{"type":415,"tag":783,"props":4829,"children":4830},{"style":790},[4831],{"type":420,"value":2501},{"type":415,"tag":783,"props":4833,"children":4834},{"style":790},[4835],{"type":420,"value":822},{"type":415,"tag":783,"props":4837,"children":4838},{"style":825},[4839],{"type":420,"value":2977},{"type":415,"tag":783,"props":4841,"children":4842},{"style":790},[4843],{"type":420,"value":813},{"type":415,"tag":783,"props":4845,"children":4846},{"style":790},[4847],{"type":420,"value":4724},{"type":415,"tag":783,"props":4849,"children":4850},{"class":785,"line":796},[4851,4855,4859,4863,4867,4871,4875,4879,4883,4888,4893,4897,4901,4905,4909,4913,4917,4921,4925,4929,4933,4937,4941,4945,4949,4953,4957,4961,4965,4969,4973,4977,4981,4985,4989],{"type":415,"tag":783,"props":4852,"children":4853},{"style":805},[4854],{"type":420,"value":4744},{"type":415,"tag":783,"props":4856,"children":4857},{"style":805},[4858],{"type":420,"value":2482},{"type":415,"tag":783,"props":4860,"children":4861},{"style":805},[4862],{"type":420,"value":1911},{"type":415,"tag":783,"props":4864,"children":4865},{"style":790},[4866],{"type":420,"value":3798},{"type":415,"tag":783,"props":4868,"children":4869},{"style":790},[4870],{"type":420,"value":4321},{"type":415,"tag":783,"props":4872,"children":4873},{"style":875},[4874],{"type":420,"value":4326},{"type":415,"tag":783,"props":4876,"children":4877},{"style":790},[4878],{"type":420,"value":2033},{"type":415,"tag":783,"props":4880,"children":4881},{"style":790},[4882],{"type":420,"value":4563},{"type":415,"tag":783,"props":4884,"children":4885},{"style":790},[4886],{"type":420,"value":4887}," ..",{"type":415,"tag":783,"props":4889,"children":4890},{"style":1362},[4891],{"type":420,"value":4892},"ColdAdjectives",{"type":415,"tag":783,"props":4894,"children":4895},{"style":790},[4896],{"type":420,"value":2501},{"type":415,"tag":783,"props":4898,"children":4899},{"style":790},[4900],{"type":420,"value":822},{"type":415,"tag":783,"props":4902,"children":4903},{"style":825},[4904],{"type":420,"value":3023},{"type":415,"tag":783,"props":4906,"children":4907},{"style":790},[4908],{"type":420,"value":813},{"type":415,"tag":783,"props":4910,"children":4911},{"style":790},[4912],{"type":420,"value":2501},{"type":415,"tag":783,"props":4914,"children":4915},{"style":790},[4916],{"type":420,"value":822},{"type":415,"tag":783,"props":4918,"children":4919},{"style":825},[4920],{"type":420,"value":3069},{"type":415,"tag":783,"props":4922,"children":4923},{"style":790},[4924],{"type":420,"value":813},{"type":415,"tag":783,"props":4926,"children":4927},{"style":790},[4928],{"type":420,"value":2501},{"type":415,"tag":783,"props":4930,"children":4931},{"style":790},[4932],{"type":420,"value":822},{"type":415,"tag":783,"props":4934,"children":4935},{"style":825},[4936],{"type":420,"value":3115},{"type":415,"tag":783,"props":4938,"children":4939},{"style":790},[4940],{"type":420,"value":813},{"type":415,"tag":783,"props":4942,"children":4943},{"style":790},[4944],{"type":420,"value":2501},{"type":415,"tag":783,"props":4946,"children":4947},{"style":790},[4948],{"type":420,"value":822},{"type":415,"tag":783,"props":4950,"children":4951},{"style":825},[4952],{"type":420,"value":3161},{"type":415,"tag":783,"props":4954,"children":4955},{"style":790},[4956],{"type":420,"value":813},{"type":415,"tag":783,"props":4958,"children":4959},{"style":790},[4960],{"type":420,"value":2501},{"type":415,"tag":783,"props":4962,"children":4963},{"style":790},[4964],{"type":420,"value":822},{"type":415,"tag":783,"props":4966,"children":4967},{"style":825},[4968],{"type":420,"value":3207},{"type":415,"tag":783,"props":4970,"children":4971},{"style":790},[4972],{"type":420,"value":813},{"type":415,"tag":783,"props":4974,"children":4975},{"style":790},[4976],{"type":420,"value":2501},{"type":415,"tag":783,"props":4978,"children":4979},{"style":790},[4980],{"type":420,"value":822},{"type":415,"tag":783,"props":4982,"children":4983},{"style":825},[4984],{"type":420,"value":3240},{"type":415,"tag":783,"props":4986,"children":4987},{"style":790},[4988],{"type":420,"value":813},{"type":415,"tag":783,"props":4990,"children":4991},{"style":790},[4992],{"type":420,"value":4724},{"type":415,"tag":416,"props":4994,"children":4995},{},[4996],{"type":420,"value":4997},"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":4999,"children":5000},{},[5001,5002,5007],{"type":420,"value":1794},{"type":415,"tag":550,"props":5003,"children":5005},{"className":5004},[],[5006],{"type":420,"value":2072},{"type":420,"value":5008}," class could become the following:",{"type":415,"tag":773,"props":5010,"children":5012},{"className":1805,"code":5011,"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",[5013],{"type":415,"tag":550,"props":5014,"children":5015},{"__ignoreMap":401},[5016,5033,5040,5106,5113,5160,5168,5212,5219,5267,5274,5328],{"type":415,"tag":783,"props":5017,"children":5018},{"class":785,"line":786},[5019,5024,5029],{"type":415,"tag":783,"props":5020,"children":5021},{"style":875},[5022],{"type":420,"value":5023},"namespace",{"type":415,"tag":783,"props":5025,"children":5026},{"style":1362},[5027],{"type":420,"value":5028}," WeatherApi",{"type":415,"tag":783,"props":5030,"children":5031},{"style":790},[5032],{"type":420,"value":1926},{"type":415,"tag":783,"props":5034,"children":5035},{"class":785,"line":796},[5036],{"type":415,"tag":783,"props":5037,"children":5038},{"emptyLinePlaceholder":1624},[5039],{"type":420,"value":1627},{"type":415,"tag":783,"props":5041,"children":5042},{"class":785,"line":840},[5043,5047,5051,5056,5060,5065,5070,5074,5079,5084,5088,5092,5097,5102],{"type":415,"tag":783,"props":5044,"children":5045},{"style":805},[5046],{"type":420,"value":1871},{"type":415,"tag":783,"props":5048,"children":5049},{"style":875},[5050],{"type":420,"value":1876},{"type":415,"tag":783,"props":5052,"children":5053},{"style":875},[5054],{"type":420,"value":5055}," WeatherForecast",{"type":415,"tag":783,"props":5057,"children":5058},{"style":790},[5059],{"type":420,"value":1845},{"type":415,"tag":783,"props":5061,"children":5062},{"style":875},[5063],{"type":420,"value":5064},"DateOnly",{"type":415,"tag":783,"props":5066,"children":5067},{"style":875},[5068],{"type":420,"value":5069}," date",{"type":415,"tag":783,"props":5071,"children":5072},{"style":790},[5073],{"type":420,"value":2501},{"type":415,"tag":783,"props":5075,"children":5076},{"style":790},[5077],{"type":420,"value":5078}," int",{"type":415,"tag":783,"props":5080,"children":5081},{"style":875},[5082],{"type":420,"value":5083}," temperatureC",{"type":415,"tag":783,"props":5085,"children":5086},{"style":790},[5087],{"type":420,"value":2501},{"type":415,"tag":783,"props":5089,"children":5090},{"style":790},[5091],{"type":420,"value":3798},{"type":415,"tag":783,"props":5093,"children":5094},{"style":790},[5095],{"type":420,"value":5096},"?",{"type":415,"tag":783,"props":5098,"children":5099},{"style":875},[5100],{"type":420,"value":5101}," summary",{"type":415,"tag":783,"props":5103,"children":5104},{"style":790},[5105],{"type":420,"value":1963},{"type":415,"tag":783,"props":5107,"children":5108},{"class":785,"line":866},[5109],{"type":415,"tag":783,"props":5110,"children":5111},{"style":790},[5112],{"type":420,"value":793},{"type":415,"tag":783,"props":5114,"children":5115},{"class":785,"line":893},[5116,5120,5124,5129,5133,5138,5143,5148,5152,5156],{"type":415,"tag":783,"props":5117,"children":5118},{"style":805},[5119],{"type":420,"value":1941},{"type":415,"tag":783,"props":5121,"children":5122},{"style":790},[5123],{"type":420,"value":5078},{"type":415,"tag":783,"props":5125,"children":5126},{"style":875},[5127],{"type":420,"value":5128}," TemperatureC",{"type":415,"tag":783,"props":5130,"children":5131},{"style":790},[5132],{"type":420,"value":4345},{"type":415,"tag":783,"props":5134,"children":5135},{"style":875},[5136],{"type":420,"value":5137}," get",{"type":415,"tag":783,"props":5139,"children":5140},{"style":790},[5141],{"type":420,"value":5142},";",{"type":415,"tag":783,"props":5144,"children":5145},{"style":790},[5146],{"type":420,"value":5147}," }",{"type":415,"tag":783,"props":5149,"children":5150},{"style":790},[5151],{"type":420,"value":2033},{"type":415,"tag":783,"props":5153,"children":5154},{"style":1362},[5155],{"type":420,"value":5083},{"type":415,"tag":783,"props":5157,"children":5158},{"style":790},[5159],{"type":420,"value":1926},{"type":415,"tag":783,"props":5161,"children":5162},{"class":785,"line":920},[5163],{"type":415,"tag":783,"props":5164,"children":5165},{"style":1362},[5166],{"type":420,"value":5167},"    \n",{"type":415,"tag":783,"props":5169,"children":5170},{"class":785,"line":959},[5171,5175,5179,5184,5188,5192,5196,5200,5204,5208],{"type":415,"tag":783,"props":5172,"children":5173},{"style":805},[5174],{"type":420,"value":1941},{"type":415,"tag":783,"props":5176,"children":5177},{"style":875},[5178],{"type":420,"value":3373},{"type":415,"tag":783,"props":5180,"children":5181},{"style":875},[5182],{"type":420,"value":5183}," Date",{"type":415,"tag":783,"props":5185,"children":5186},{"style":790},[5187],{"type":420,"value":4345},{"type":415,"tag":783,"props":5189,"children":5190},{"style":875},[5191],{"type":420,"value":5137},{"type":415,"tag":783,"props":5193,"children":5194},{"style":790},[5195],{"type":420,"value":5142},{"type":415,"tag":783,"props":5197,"children":5198},{"style":790},[5199],{"type":420,"value":5147},{"type":415,"tag":783,"props":5201,"children":5202},{"style":790},[5203],{"type":420,"value":2033},{"type":415,"tag":783,"props":5205,"children":5206},{"style":1362},[5207],{"type":420,"value":5069},{"type":415,"tag":783,"props":5209,"children":5210},{"style":790},[5211],{"type":420,"value":1926},{"type":415,"tag":783,"props":5213,"children":5214},{"class":785,"line":997},[5215],{"type":415,"tag":783,"props":5216,"children":5217},{"style":1362},[5218],{"type":420,"value":5167},{"type":415,"tag":783,"props":5220,"children":5221},{"class":785,"line":1023},[5222,5226,5230,5234,5239,5243,5247,5251,5255,5259,5263],{"type":415,"tag":783,"props":5223,"children":5224},{"style":805},[5225],{"type":420,"value":1941},{"type":415,"tag":783,"props":5227,"children":5228},{"style":790},[5229],{"type":420,"value":3798},{"type":415,"tag":783,"props":5231,"children":5232},{"style":790},[5233],{"type":420,"value":5096},{"type":415,"tag":783,"props":5235,"children":5236},{"style":875},[5237],{"type":420,"value":5238}," Summary",{"type":415,"tag":783,"props":5240,"children":5241},{"style":790},[5242],{"type":420,"value":4345},{"type":415,"tag":783,"props":5244,"children":5245},{"style":875},[5246],{"type":420,"value":5137},{"type":415,"tag":783,"props":5248,"children":5249},{"style":790},[5250],{"type":420,"value":5142},{"type":415,"tag":783,"props":5252,"children":5253},{"style":790},[5254],{"type":420,"value":5147},{"type":415,"tag":783,"props":5256,"children":5257},{"style":790},[5258],{"type":420,"value":2033},{"type":415,"tag":783,"props":5260,"children":5261},{"style":1362},[5262],{"type":420,"value":5101},{"type":415,"tag":783,"props":5264,"children":5265},{"style":790},[5266],{"type":420,"value":1926},{"type":415,"tag":783,"props":5268,"children":5269},{"class":785,"line":1061},[5270],{"type":415,"tag":783,"props":5271,"children":5272},{"style":1362},[5273],{"type":420,"value":5167},{"type":415,"tag":783,"props":5275,"children":5276},{"class":785,"line":1099},[5277,5281,5285,5290,5294,5299,5304,5309,5314,5319,5324],{"type":415,"tag":783,"props":5278,"children":5279},{"style":805},[5280],{"type":420,"value":1941},{"type":415,"tag":783,"props":5282,"children":5283},{"style":790},[5284],{"type":420,"value":5078},{"type":415,"tag":783,"props":5286,"children":5287},{"style":875},[5288],{"type":420,"value":5289}," TemperatureF",{"type":415,"tag":783,"props":5291,"children":5292},{"style":790},[5293],{"type":420,"value":2827},{"type":415,"tag":783,"props":5295,"children":5296},{"style":902},[5297],{"type":420,"value":5298}," 32",{"type":415,"tag":783,"props":5300,"children":5301},{"style":790},[5302],{"type":420,"value":5303}," +",{"type":415,"tag":783,"props":5305,"children":5306},{"style":790},[5307],{"type":420,"value":5308}," (int)(",{"type":415,"tag":783,"props":5310,"children":5311},{"style":1362},[5312],{"type":420,"value":5313},"TemperatureC ",{"type":415,"tag":783,"props":5315,"children":5316},{"style":790},[5317],{"type":420,"value":5318},"/",{"type":415,"tag":783,"props":5320,"children":5321},{"style":902},[5322],{"type":420,"value":5323}," 0.5556",{"type":415,"tag":783,"props":5325,"children":5326},{"style":790},[5327],{"type":420,"value":2552},{"type":415,"tag":783,"props":5329,"children":5330},{"class":785,"line":1137},[5331],{"type":415,"tag":783,"props":5332,"children":5333},{"style":790},[5334],{"type":420,"value":1272},{"type":415,"tag":588,"props":5336,"children":5337},{"icon":590},[5338],{"type":415,"tag":416,"props":5339,"children":5340},{},[5341],{"type":420,"value":5342},"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":5344,"children":5345},{},[5346,5348,5354],{"type":420,"value":5347},"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":550,"props":5349,"children":5351},{"className":5350},[],[5352],{"type":420,"value":5353},"weatherService",{"type":420,"value":5355}," in this example:",{"type":415,"tag":773,"props":5357,"children":5359},{"className":1805,"code":5358,"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",[5360],{"type":415,"tag":550,"props":5361,"children":5362},{"__ignoreMap":401},[5363,5428,5435,5474,5513,5544,5551,5574,5581],{"type":415,"tag":783,"props":5364,"children":5365},{"class":785,"line":786},[5366,5370,5374,5378,5382,5386,5390,5394,5399,5403,5407,5411,5416,5420,5424],{"type":415,"tag":783,"props":5367,"children":5368},{"style":805},[5369],{"type":420,"value":1871},{"type":415,"tag":783,"props":5371,"children":5372},{"style":875},[5373],{"type":420,"value":1876},{"type":415,"tag":783,"props":5375,"children":5376},{"style":875},[5377],{"type":420,"value":1881},{"type":415,"tag":783,"props":5379,"children":5380},{"style":790},[5381],{"type":420,"value":1845},{"type":415,"tag":783,"props":5383,"children":5384},{"style":875},[5385],{"type":420,"value":1752},{"type":415,"tag":783,"props":5387,"children":5388},{"style":875},[5389],{"type":420,"value":1958},{"type":415,"tag":783,"props":5391,"children":5392},{"style":790},[5393],{"type":420,"value":2501},{"type":415,"tag":783,"props":5395,"children":5396},{"style":875},[5397],{"type":420,"value":5398}," ILogger",{"type":415,"tag":783,"props":5400,"children":5401},{"style":790},[5402],{"type":420,"value":2112},{"type":415,"tag":783,"props":5404,"children":5405},{"style":875},[5406],{"type":420,"value":1800},{"type":415,"tag":783,"props":5408,"children":5409},{"style":790},[5410],{"type":420,"value":2276},{"type":415,"tag":783,"props":5412,"children":5413},{"style":875},[5414],{"type":420,"value":5415}," logger",{"type":415,"tag":783,"props":5417,"children":5418},{"style":790},[5419],{"type":420,"value":1678},{"type":415,"tag":783,"props":5421,"children":5422},{"style":790},[5423],{"type":420,"value":1886},{"type":415,"tag":783,"props":5425,"children":5426},{"style":875},[5427],{"type":420,"value":1891},{"type":415,"tag":783,"props":5429,"children":5430},{"class":785,"line":796},[5431],{"type":415,"tag":783,"props":5432,"children":5433},{"style":790},[5434],{"type":420,"value":793},{"type":415,"tag":783,"props":5436,"children":5437},{"class":785,"line":840},[5438,5442,5446,5450,5454,5458,5462,5466,5470],{"type":415,"tag":783,"props":5439,"children":5440},{"style":790},[5441],{"type":420,"value":2014},{"type":415,"tag":783,"props":5443,"children":5444},{"style":875},[5445],{"type":420,"value":2019},{"type":415,"tag":783,"props":5447,"children":5448},{"style":790},[5449],{"type":420,"value":1845},{"type":415,"tag":783,"props":5451,"children":5452},{"style":875},[5453],{"type":420,"value":2028},{"type":415,"tag":783,"props":5455,"children":5456},{"style":790},[5457],{"type":420,"value":2033},{"type":415,"tag":783,"props":5459,"children":5460},{"style":790},[5461],{"type":420,"value":822},{"type":415,"tag":783,"props":5463,"children":5464},{"style":825},[5465],{"type":420,"value":2042},{"type":415,"tag":783,"props":5467,"children":5468},{"style":790},[5469],{"type":420,"value":813},{"type":415,"tag":783,"props":5471,"children":5472},{"style":790},[5473],{"type":420,"value":1863},{"type":415,"tag":783,"props":5475,"children":5476},{"class":785,"line":866},[5477,5481,5485,5489,5493,5497,5501,5505,5509],{"type":415,"tag":783,"props":5478,"children":5479},{"style":790},[5480],{"type":420,"value":2014},{"type":415,"tag":783,"props":5482,"children":5483},{"style":875},[5484],{"type":420,"value":2062},{"type":415,"tag":783,"props":5486,"children":5487},{"style":790},[5488],{"type":420,"value":2067},{"type":415,"tag":783,"props":5490,"children":5491},{"style":875},[5492],{"type":420,"value":2072},{"type":415,"tag":783,"props":5494,"children":5495},{"style":790},[5496],{"type":420,"value":2077},{"type":415,"tag":783,"props":5498,"children":5499},{"style":1362},[5500],{"type":420,"value":2082},{"type":415,"tag":783,"props":5502,"children":5503},{"style":790},[5504],{"type":420,"value":755},{"type":415,"tag":783,"props":5506,"children":5507},{"style":1362},[5508],{"type":420,"value":2091},{"type":415,"tag":783,"props":5510,"children":5511},{"style":790},[5512],{"type":420,"value":1863},{"type":415,"tag":783,"props":5514,"children":5515},{"class":785,"line":893},[5516,5520,5524,5528,5532,5536,5540],{"type":415,"tag":783,"props":5517,"children":5518},{"style":805},[5519],{"type":420,"value":1941},{"type":415,"tag":783,"props":5521,"children":5522},{"style":875},[5523],{"type":420,"value":2107},{"type":415,"tag":783,"props":5525,"children":5526},{"style":790},[5527],{"type":420,"value":2112},{"type":415,"tag":783,"props":5529,"children":5530},{"style":875},[5531],{"type":420,"value":2072},{"type":415,"tag":783,"props":5533,"children":5534},{"style":790},[5535],{"type":420,"value":2121},{"type":415,"tag":783,"props":5537,"children":5538},{"style":1545},[5539],{"type":420,"value":2126},{"type":415,"tag":783,"props":5541,"children":5542},{"style":790},[5543],{"type":420,"value":2131},{"type":415,"tag":783,"props":5545,"children":5546},{"class":785,"line":920},[5547],{"type":415,"tag":783,"props":5548,"children":5549},{"style":790},[5550],{"type":420,"value":1971},{"type":415,"tag":783,"props":5552,"children":5553},{"class":785,"line":959},[5554,5558,5562,5566,5570],{"type":415,"tag":783,"props":5555,"children":5556},{"style":1356},[5557],{"type":420,"value":2146},{"type":415,"tag":783,"props":5559,"children":5560},{"style":1362},[5561],{"type":420,"value":1958},{"type":415,"tag":783,"props":5563,"children":5564},{"style":790},[5565],{"type":420,"value":755},{"type":415,"tag":783,"props":5567,"children":5568},{"style":1545},[5569],{"type":420,"value":2159},{"type":415,"tag":783,"props":5571,"children":5572},{"style":790},[5573],{"type":420,"value":2164},{"type":415,"tag":783,"props":5575,"children":5576},{"class":785,"line":997},[5577],{"type":415,"tag":783,"props":5578,"children":5579},{"style":790},[5580],{"type":420,"value":1254},{"type":415,"tag":783,"props":5582,"children":5583},{"class":785,"line":1023},[5584],{"type":415,"tag":783,"props":5585,"children":5586},{"style":790},[5587],{"type":420,"value":1272},{"type":415,"tag":416,"props":5589,"children":5590},{},[5591,5593,5598,5600,5606,5608,5615],{"type":420,"value":5592},"Having 2 different implementations of the ",{"type":415,"tag":550,"props":5594,"children":5596},{"className":5595},[],[5597],{"type":420,"value":1752},{"type":420,"value":5599}," 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":550,"props":5601,"children":5603},{"className":5602},[],[5604],{"type":420,"value":5605},"IEnumerable\u003CIWeatherService>",{"type":420,"value":5607}," 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":423,"props":5609,"children":5612},{"href":5610,"rel":5611},"https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#keyed-di-services",[427],[5613],{"type":420,"value":5614},"keyed DI Services",{"type":420,"value":755},{"type":415,"tag":416,"props":5617,"children":5618},{},[5619],{"type":420,"value":5620},"Specifying a key (that can be anything, not necessarily a string) is done when registering the services in the DI container.",{"type":415,"tag":773,"props":5622,"children":5624},{"className":1805,"code":5623,"language":326,"meta":401,"style":401},"builder.Services.AddKeyedTransient\u003CIWeatherService, RandomWeatherService>(\"random\");\nbuilder.Services.AddKeyedTransient\u003CIWeatherService, OpenWeatherService>(\"api\");\n",[5625],{"type":415,"tag":550,"props":5626,"children":5627},{"__ignoreMap":401},[5628,5693],{"type":415,"tag":783,"props":5629,"children":5630},{"class":785,"line":786},[5631,5636,5640,5645,5649,5654,5658,5662,5666,5671,5676,5680,5685,5689],{"type":415,"tag":783,"props":5632,"children":5633},{"style":1362},[5634],{"type":420,"value":5635},"builder",{"type":415,"tag":783,"props":5637,"children":5638},{"style":790},[5639],{"type":420,"value":755},{"type":415,"tag":783,"props":5641,"children":5642},{"style":1362},[5643],{"type":420,"value":5644},"Services",{"type":415,"tag":783,"props":5646,"children":5647},{"style":790},[5648],{"type":420,"value":755},{"type":415,"tag":783,"props":5650,"children":5651},{"style":1545},[5652],{"type":420,"value":5653},"AddKeyedTransient",{"type":415,"tag":783,"props":5655,"children":5656},{"style":790},[5657],{"type":420,"value":2112},{"type":415,"tag":783,"props":5659,"children":5660},{"style":875},[5661],{"type":420,"value":1752},{"type":415,"tag":783,"props":5663,"children":5664},{"style":790},[5665],{"type":420,"value":2501},{"type":415,"tag":783,"props":5667,"children":5668},{"style":875},[5669],{"type":420,"value":5670}," RandomWeatherService",{"type":415,"tag":783,"props":5672,"children":5673},{"style":790},[5674],{"type":420,"value":5675},">(",{"type":415,"tag":783,"props":5677,"children":5678},{"style":790},[5679],{"type":420,"value":813},{"type":415,"tag":783,"props":5681,"children":5682},{"style":825},[5683],{"type":420,"value":5684},"random",{"type":415,"tag":783,"props":5686,"children":5687},{"style":790},[5688],{"type":420,"value":813},{"type":415,"tag":783,"props":5690,"children":5691},{"style":790},[5692],{"type":420,"value":2552},{"type":415,"tag":783,"props":5694,"children":5695},{"class":785,"line":796},[5696,5700,5704,5708,5712,5716,5720,5724,5728,5732,5736,5740,5745,5749],{"type":415,"tag":783,"props":5697,"children":5698},{"style":1362},[5699],{"type":420,"value":5635},{"type":415,"tag":783,"props":5701,"children":5702},{"style":790},[5703],{"type":420,"value":755},{"type":415,"tag":783,"props":5705,"children":5706},{"style":1362},[5707],{"type":420,"value":5644},{"type":415,"tag":783,"props":5709,"children":5710},{"style":790},[5711],{"type":420,"value":755},{"type":415,"tag":783,"props":5713,"children":5714},{"style":1545},[5715],{"type":420,"value":5653},{"type":415,"tag":783,"props":5717,"children":5718},{"style":790},[5719],{"type":420,"value":2112},{"type":415,"tag":783,"props":5721,"children":5722},{"style":875},[5723],{"type":420,"value":1752},{"type":415,"tag":783,"props":5725,"children":5726},{"style":790},[5727],{"type":420,"value":2501},{"type":415,"tag":783,"props":5729,"children":5730},{"style":875},[5731],{"type":420,"value":2429},{"type":415,"tag":783,"props":5733,"children":5734},{"style":790},[5735],{"type":420,"value":5675},{"type":415,"tag":783,"props":5737,"children":5738},{"style":790},[5739],{"type":420,"value":813},{"type":415,"tag":783,"props":5741,"children":5742},{"style":825},[5743],{"type":420,"value":5744},"api",{"type":415,"tag":783,"props":5746,"children":5747},{"style":790},[5748],{"type":420,"value":813},{"type":415,"tag":783,"props":5750,"children":5751},{"style":790},[5752],{"type":420,"value":2552},{"type":415,"tag":416,"props":5754,"children":5755},{},[5756],{"type":420,"value":5757},"With this key, retrieving a specific implementation becomes easy.",{"type":415,"tag":773,"props":5759,"children":5761},{"className":1805,"code":5760,"language":326,"meta":401,"style":401},"    public WeatherForecastController([FromKeyedServices(\"random\")] IWeatherService weatherService, ILogger\u003CWeatherForecastController> logger)\n    {\n        _logger = logger;\n        _weatherService = weatherService;\n    }\n",[5762],{"type":415,"tag":550,"props":5763,"children":5764},{"__ignoreMap":401},[5765,5840,5847,5867,5886],{"type":415,"tag":783,"props":5766,"children":5767},{"class":785,"line":786},[5768,5772,5776,5781,5786,5790,5794,5798,5802,5807,5812,5816,5820,5824,5828,5832,5836],{"type":415,"tag":783,"props":5769,"children":5770},{"style":805},[5771],{"type":420,"value":1941},{"type":415,"tag":783,"props":5773,"children":5774},{"style":1545},[5775],{"type":420,"value":1881},{"type":415,"tag":783,"props":5777,"children":5778},{"style":790},[5779],{"type":420,"value":5780},"([",{"type":415,"tag":783,"props":5782,"children":5783},{"style":1545},[5784],{"type":420,"value":5785},"FromKeyedServices",{"type":415,"tag":783,"props":5787,"children":5788},{"style":790},[5789],{"type":420,"value":1845},{"type":415,"tag":783,"props":5791,"children":5792},{"style":790},[5793],{"type":420,"value":813},{"type":415,"tag":783,"props":5795,"children":5796},{"style":825},[5797],{"type":420,"value":5684},{"type":415,"tag":783,"props":5799,"children":5800},{"style":790},[5801],{"type":420,"value":813},{"type":415,"tag":783,"props":5803,"children":5804},{"style":790},[5805],{"type":420,"value":5806},")]",{"type":415,"tag":783,"props":5808,"children":5809},{"style":1362},[5810],{"type":420,"value":5811}," IWeatherService weatherService",{"type":415,"tag":783,"props":5813,"children":5814},{"style":790},[5815],{"type":420,"value":2501},{"type":415,"tag":783,"props":5817,"children":5818},{"style":1362},[5819],{"type":420,"value":5398},{"type":415,"tag":783,"props":5821,"children":5822},{"style":790},[5823],{"type":420,"value":2112},{"type":415,"tag":783,"props":5825,"children":5826},{"style":1362},[5827],{"type":420,"value":1800},{"type":415,"tag":783,"props":5829,"children":5830},{"style":790},[5831],{"type":420,"value":2276},{"type":415,"tag":783,"props":5833,"children":5834},{"style":1362},[5835],{"type":420,"value":5415},{"type":415,"tag":783,"props":5837,"children":5838},{"style":790},[5839],{"type":420,"value":1963},{"type":415,"tag":783,"props":5841,"children":5842},{"class":785,"line":796},[5843],{"type":415,"tag":783,"props":5844,"children":5845},{"style":790},[5846],{"type":420,"value":1971},{"type":415,"tag":783,"props":5848,"children":5849},{"class":785,"line":840},[5850,5855,5859,5863],{"type":415,"tag":783,"props":5851,"children":5852},{"style":1362},[5853],{"type":420,"value":5854},"        _logger ",{"type":415,"tag":783,"props":5856,"children":5857},{"style":790},[5858],{"type":420,"value":1984},{"type":415,"tag":783,"props":5860,"children":5861},{"style":1362},[5862],{"type":420,"value":5415},{"type":415,"tag":783,"props":5864,"children":5865},{"style":790},[5866],{"type":420,"value":1926},{"type":415,"tag":783,"props":5868,"children":5869},{"class":785,"line":866},[5870,5874,5878,5882],{"type":415,"tag":783,"props":5871,"children":5872},{"style":1362},[5873],{"type":420,"value":1979},{"type":415,"tag":783,"props":5875,"children":5876},{"style":790},[5877],{"type":420,"value":1984},{"type":415,"tag":783,"props":5879,"children":5880},{"style":1362},[5881],{"type":420,"value":1958},{"type":415,"tag":783,"props":5883,"children":5884},{"style":790},[5885],{"type":420,"value":1926},{"type":415,"tag":783,"props":5887,"children":5888},{"class":785,"line":893},[5889],{"type":415,"tag":783,"props":5890,"children":5891},{"style":790},[5892],{"type":420,"value":1254},{"type":415,"tag":416,"props":5894,"children":5895},{},[5896,5898,5905],{"type":420,"value":5897},"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":423,"props":5899,"children":5902},{"href":5900,"rel":5901},"https://github.com/reactiveui/refit",[427],[5903],{"type":420,"value":5904},"Refit",{"type":420,"value":755},{"type":415,"tag":773,"props":5907,"children":5909},{"className":1805,"code":5908,"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",[5910],{"type":415,"tag":550,"props":5911,"children":5912},{"__ignoreMap":401},[5913,5929,5936,5968,5975,5992,5999,6032,6085,6092,6099,6147,6154,6198,6205],{"type":415,"tag":783,"props":5914,"children":5915},{"class":785,"line":786},[5916,5920,5925],{"type":415,"tag":783,"props":5917,"children":5918},{"style":902},[5919],{"type":420,"value":3596},{"type":415,"tag":783,"props":5921,"children":5922},{"style":1362},[5923],{"type":420,"value":5924}," Refit",{"type":415,"tag":783,"props":5926,"children":5927},{"style":790},[5928],{"type":420,"value":1926},{"type":415,"tag":783,"props":5930,"children":5931},{"class":785,"line":796},[5932],{"type":415,"tag":783,"props":5933,"children":5934},{"emptyLinePlaceholder":1624},[5935],{"type":420,"value":1627},{"type":415,"tag":783,"props":5937,"children":5938},{"class":785,"line":840},[5939,5943,5947,5951,5955,5959,5964],{"type":415,"tag":783,"props":5940,"children":5941},{"style":875},[5942],{"type":420,"value":5023},{"type":415,"tag":783,"props":5944,"children":5945},{"style":1362},[5946],{"type":420,"value":5028},{"type":415,"tag":783,"props":5948,"children":5949},{"style":790},[5950],{"type":420,"value":755},{"type":415,"tag":783,"props":5952,"children":5953},{"style":1362},[5954],{"type":420,"value":5644},{"type":415,"tag":783,"props":5956,"children":5957},{"style":790},[5958],{"type":420,"value":755},{"type":415,"tag":783,"props":5960,"children":5961},{"style":1362},[5962],{"type":420,"value":5963},"OpenWeatherMap",{"type":415,"tag":783,"props":5965,"children":5966},{"style":790},[5967],{"type":420,"value":1926},{"type":415,"tag":783,"props":5969,"children":5970},{"class":785,"line":866},[5971],{"type":415,"tag":783,"props":5972,"children":5973},{"emptyLinePlaceholder":1624},[5974],{"type":420,"value":1627},{"type":415,"tag":783,"props":5976,"children":5977},{"class":785,"line":893},[5978,5982,5987],{"type":415,"tag":783,"props":5979,"children":5980},{"style":805},[5981],{"type":420,"value":1871},{"type":415,"tag":783,"props":5983,"children":5984},{"style":875},[5985],{"type":420,"value":5986}," interface",{"type":415,"tag":783,"props":5988,"children":5989},{"style":875},[5990],{"type":420,"value":5991}," IOpenWeatherMapApi\n",{"type":415,"tag":783,"props":5993,"children":5994},{"class":785,"line":920},[5995],{"type":415,"tag":783,"props":5996,"children":5997},{"style":790},[5998],{"type":420,"value":793},{"type":415,"tag":783,"props":6000,"children":6001},{"class":785,"line":959},[6002,6006,6011,6015,6019,6024,6028],{"type":415,"tag":783,"props":6003,"children":6004},{"style":790},[6005],{"type":420,"value":2014},{"type":415,"tag":783,"props":6007,"children":6008},{"style":875},[6009],{"type":420,"value":6010},"Get",{"type":415,"tag":783,"props":6012,"children":6013},{"style":790},[6014],{"type":420,"value":1845},{"type":415,"tag":783,"props":6016,"children":6017},{"style":790},[6018],{"type":420,"value":813},{"type":415,"tag":783,"props":6020,"children":6021},{"style":825},[6022],{"type":420,"value":6023},"/forecast?lat={latitude}&lon={longitude}&units=metric",{"type":415,"tag":783,"props":6025,"children":6026},{"style":790},[6027],{"type":420,"value":813},{"type":415,"tag":783,"props":6029,"children":6030},{"style":790},[6031],{"type":420,"value":1863},{"type":415,"tag":783,"props":6033,"children":6034},{"class":785,"line":997},[6035,6040,6044,6049,6053,6058,6063,6068,6072,6076,6081],{"type":415,"tag":783,"props":6036,"children":6037},{"style":875},[6038],{"type":420,"value":6039},"    Task",{"type":415,"tag":783,"props":6041,"children":6042},{"style":790},[6043],{"type":420,"value":2112},{"type":415,"tag":783,"props":6045,"children":6046},{"style":875},[6047],{"type":420,"value":6048},"WeatherMapResponse",{"type":415,"tag":783,"props":6050,"children":6051},{"style":790},[6052],{"type":420,"value":2276},{"type":415,"tag":783,"props":6054,"children":6055},{"style":1545},[6056],{"type":420,"value":6057}," GetWeatherForecast",{"type":415,"tag":783,"props":6059,"children":6060},{"style":790},[6061],{"type":420,"value":6062},"(double",{"type":415,"tag":783,"props":6064,"children":6065},{"style":875},[6066],{"type":420,"value":6067}," latitude",{"type":415,"tag":783,"props":6069,"children":6070},{"style":790},[6071],{"type":420,"value":2501},{"type":415,"tag":783,"props":6073,"children":6074},{"style":790},[6075],{"type":420,"value":2506},{"type":415,"tag":783,"props":6077,"children":6078},{"style":875},[6079],{"type":420,"value":6080}," longitude",{"type":415,"tag":783,"props":6082,"children":6083},{"style":790},[6084],{"type":420,"value":2552},{"type":415,"tag":783,"props":6086,"children":6087},{"class":785,"line":1023},[6088],{"type":415,"tag":783,"props":6089,"children":6090},{"style":790},[6091],{"type":420,"value":1272},{"type":415,"tag":783,"props":6093,"children":6094},{"class":785,"line":1061},[6095],{"type":415,"tag":783,"props":6096,"children":6097},{"emptyLinePlaceholder":1624},[6098],{"type":420,"value":1627},{"type":415,"tag":783,"props":6100,"children":6101},{"class":785,"line":1099},[6102,6106,6111,6116,6120,6125,6129,6134,6138,6143],{"type":415,"tag":783,"props":6103,"children":6104},{"style":805},[6105],{"type":420,"value":1871},{"type":415,"tag":783,"props":6107,"children":6108},{"style":875},[6109],{"type":420,"value":6110}," record",{"type":415,"tag":783,"props":6112,"children":6113},{"style":875},[6114],{"type":420,"value":6115}," WeatherMapResponse",{"type":415,"tag":783,"props":6117,"children":6118},{"style":790},[6119],{"type":420,"value":1845},{"type":415,"tag":783,"props":6121,"children":6122},{"style":875},[6123],{"type":420,"value":6124},"IList",{"type":415,"tag":783,"props":6126,"children":6127},{"style":790},[6128],{"type":420,"value":2112},{"type":415,"tag":783,"props":6130,"children":6131},{"style":875},[6132],{"type":420,"value":6133},"WeatherMapForecast",{"type":415,"tag":783,"props":6135,"children":6136},{"style":790},[6137],{"type":420,"value":2276},{"type":415,"tag":783,"props":6139,"children":6140},{"style":875},[6141],{"type":420,"value":6142}," List",{"type":415,"tag":783,"props":6144,"children":6145},{"style":790},[6146],{"type":420,"value":2552},{"type":415,"tag":783,"props":6148,"children":6149},{"class":785,"line":1137},[6150],{"type":415,"tag":783,"props":6151,"children":6152},{"emptyLinePlaceholder":1624},[6153],{"type":420,"value":1627},{"type":415,"tag":783,"props":6155,"children":6156},{"class":785,"line":1175},[6157,6161,6165,6170,6175,6180,6184,6189,6194],{"type":415,"tag":783,"props":6158,"children":6159},{"style":805},[6160],{"type":420,"value":1871},{"type":415,"tag":783,"props":6162,"children":6163},{"style":875},[6164],{"type":420,"value":6110},{"type":415,"tag":783,"props":6166,"children":6167},{"style":875},[6168],{"type":420,"value":6169}," WeatherMapForecast",{"type":415,"tag":783,"props":6171,"children":6172},{"style":790},[6173],{"type":420,"value":6174},"(int",{"type":415,"tag":783,"props":6176,"children":6177},{"style":875},[6178],{"type":420,"value":6179}," Dt",{"type":415,"tag":783,"props":6181,"children":6182},{"style":790},[6183],{"type":420,"value":2501},{"type":415,"tag":783,"props":6185,"children":6186},{"style":875},[6187],{"type":420,"value":6188}," WeatherMapMain",{"type":415,"tag":783,"props":6190,"children":6191},{"style":875},[6192],{"type":420,"value":6193}," Main",{"type":415,"tag":783,"props":6195,"children":6196},{"style":790},[6197],{"type":420,"value":2552},{"type":415,"tag":783,"props":6199,"children":6200},{"class":785,"line":1213},[6201],{"type":415,"tag":783,"props":6202,"children":6203},{"emptyLinePlaceholder":1624},[6204],{"type":420,"value":1627},{"type":415,"tag":783,"props":6206,"children":6207},{"class":785,"line":1239},[6208,6212,6216,6220,6224,6229],{"type":415,"tag":783,"props":6209,"children":6210},{"style":805},[6211],{"type":420,"value":1871},{"type":415,"tag":783,"props":6213,"children":6214},{"style":875},[6215],{"type":420,"value":6110},{"type":415,"tag":783,"props":6217,"children":6218},{"style":875},[6219],{"type":420,"value":6188},{"type":415,"tag":783,"props":6221,"children":6222},{"style":790},[6223],{"type":420,"value":6062},{"type":415,"tag":783,"props":6225,"children":6226},{"style":875},[6227],{"type":420,"value":6228}," Temp",{"type":415,"tag":783,"props":6230,"children":6231},{"style":790},[6232],{"type":420,"value":2552},{"type":415,"tag":416,"props":6234,"children":6235},{},[6236,6238,6244],{"type":420,"value":6237},"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":550,"props":6239,"children":6241},{"className":6240},[],[6242],{"type":420,"value":6243},"WeatherMapConfiguration",{"type":420,"value":755},{"type":415,"tag":416,"props":6246,"children":6247},{},[6248,6250,6257,6259,6266],{"type":420,"value":6249},"In .NET 8, we can use ",{"type":415,"tag":423,"props":6251,"children":6254},{"href":6252,"rel":6253},"https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#data-validation",[427],[6255],{"type":420,"value":6256},"data validation attributes",{"type":420,"value":6258}," for data like configuration options. There is also a ",{"type":415,"tag":423,"props":6260,"children":6263},{"href":6261,"rel":6262},"https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#options-validation",[427],[6264],{"type":420,"value":6265},"source code generator",{"type":420,"value":6267}," that can implement the validation logic:",{"type":415,"tag":773,"props":6269,"children":6271},{"className":1805,"code":6270,"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",[6272],{"type":415,"tag":550,"props":6273,"children":6274},{"__ignoreMap":401},[6275,6306,6313,6329,6336,6352,6399,6406,6421,6437,6481,6488,6495,6502,6518,6561,6568],{"type":415,"tag":783,"props":6276,"children":6277},{"class":785,"line":786},[6278,6282,6286,6290,6294,6298,6302],{"type":415,"tag":783,"props":6279,"children":6280},{"style":875},[6281],{"type":420,"value":5023},{"type":415,"tag":783,"props":6283,"children":6284},{"style":1362},[6285],{"type":420,"value":5028},{"type":415,"tag":783,"props":6287,"children":6288},{"style":790},[6289],{"type":420,"value":755},{"type":415,"tag":783,"props":6291,"children":6292},{"style":1362},[6293],{"type":420,"value":5644},{"type":415,"tag":783,"props":6295,"children":6296},{"style":790},[6297],{"type":420,"value":755},{"type":415,"tag":783,"props":6299,"children":6300},{"style":1362},[6301],{"type":420,"value":5963},{"type":415,"tag":783,"props":6303,"children":6304},{"style":790},[6305],{"type":420,"value":1926},{"type":415,"tag":783,"props":6307,"children":6308},{"class":785,"line":796},[6309],{"type":415,"tag":783,"props":6310,"children":6311},{"emptyLinePlaceholder":1624},[6312],{"type":420,"value":1627},{"type":415,"tag":783,"props":6314,"children":6315},{"class":785,"line":840},[6316,6320,6324],{"type":415,"tag":783,"props":6317,"children":6318},{"style":805},[6319],{"type":420,"value":1871},{"type":415,"tag":783,"props":6321,"children":6322},{"style":875},[6323],{"type":420,"value":1876},{"type":415,"tag":783,"props":6325,"children":6326},{"style":875},[6327],{"type":420,"value":6328}," WeatherMapConfiguration\n",{"type":415,"tag":783,"props":6330,"children":6331},{"class":785,"line":866},[6332],{"type":415,"tag":783,"props":6333,"children":6334},{"style":790},[6335],{"type":420,"value":793},{"type":415,"tag":783,"props":6337,"children":6338},{"class":785,"line":893},[6339,6343,6348],{"type":415,"tag":783,"props":6340,"children":6341},{"style":790},[6342],{"type":420,"value":2014},{"type":415,"tag":783,"props":6344,"children":6345},{"style":875},[6346],{"type":420,"value":6347},"Required",{"type":415,"tag":783,"props":6349,"children":6350},{"style":790},[6351],{"type":420,"value":1828},{"type":415,"tag":783,"props":6353,"children":6354},{"class":785,"line":920},[6355,6359,6364,6368,6373,6377,6381,6385,6390,6394],{"type":415,"tag":783,"props":6356,"children":6357},{"style":805},[6358],{"type":420,"value":1941},{"type":415,"tag":783,"props":6360,"children":6361},{"style":805},[6362],{"type":420,"value":6363}," required",{"type":415,"tag":783,"props":6365,"children":6366},{"style":790},[6367],{"type":420,"value":3798},{"type":415,"tag":783,"props":6369,"children":6370},{"style":875},[6371],{"type":420,"value":6372}," ApiKey",{"type":415,"tag":783,"props":6374,"children":6375},{"style":790},[6376],{"type":420,"value":4345},{"type":415,"tag":783,"props":6378,"children":6379},{"style":875},[6380],{"type":420,"value":5137},{"type":415,"tag":783,"props":6382,"children":6383},{"style":790},[6384],{"type":420,"value":5142},{"type":415,"tag":783,"props":6386,"children":6387},{"style":875},[6388],{"type":420,"value":6389}," init",{"type":415,"tag":783,"props":6391,"children":6392},{"style":790},[6393],{"type":420,"value":5142},{"type":415,"tag":783,"props":6395,"children":6396},{"style":790},[6397],{"type":420,"value":6398}," }\n",{"type":415,"tag":783,"props":6400,"children":6401},{"class":785,"line":959},[6402],{"type":415,"tag":783,"props":6403,"children":6404},{"emptyLinePlaceholder":1624},[6405],{"type":420,"value":1627},{"type":415,"tag":783,"props":6407,"children":6408},{"class":785,"line":997},[6409,6413,6417],{"type":415,"tag":783,"props":6410,"children":6411},{"style":790},[6412],{"type":420,"value":2014},{"type":415,"tag":783,"props":6414,"children":6415},{"style":875},[6416],{"type":420,"value":6347},{"type":415,"tag":783,"props":6418,"children":6419},{"style":790},[6420],{"type":420,"value":1828},{"type":415,"tag":783,"props":6422,"children":6423},{"class":785,"line":1023},[6424,6428,6433],{"type":415,"tag":783,"props":6425,"children":6426},{"style":790},[6427],{"type":420,"value":2014},{"type":415,"tag":783,"props":6429,"children":6430},{"style":875},[6431],{"type":420,"value":6432},"Url",{"type":415,"tag":783,"props":6434,"children":6435},{"style":790},[6436],{"type":420,"value":1828},{"type":415,"tag":783,"props":6438,"children":6439},{"class":785,"line":1061},[6440,6444,6448,6452,6457,6461,6465,6469,6473,6477],{"type":415,"tag":783,"props":6441,"children":6442},{"style":805},[6443],{"type":420,"value":1941},{"type":415,"tag":783,"props":6445,"children":6446},{"style":805},[6447],{"type":420,"value":6363},{"type":415,"tag":783,"props":6449,"children":6450},{"style":790},[6451],{"type":420,"value":3798},{"type":415,"tag":783,"props":6453,"children":6454},{"style":875},[6455],{"type":420,"value":6456}," Uri",{"type":415,"tag":783,"props":6458,"children":6459},{"style":790},[6460],{"type":420,"value":4345},{"type":415,"tag":783,"props":6462,"children":6463},{"style":875},[6464],{"type":420,"value":5137},{"type":415,"tag":783,"props":6466,"children":6467},{"style":790},[6468],{"type":420,"value":5142},{"type":415,"tag":783,"props":6470,"children":6471},{"style":875},[6472],{"type":420,"value":6389},{"type":415,"tag":783,"props":6474,"children":6475},{"style":790},[6476],{"type":420,"value":5142},{"type":415,"tag":783,"props":6478,"children":6479},{"style":790},[6480],{"type":420,"value":6398},{"type":415,"tag":783,"props":6482,"children":6483},{"class":785,"line":1099},[6484],{"type":415,"tag":783,"props":6485,"children":6486},{"style":1362},[6487],{"type":420,"value":5167},{"type":415,"tag":783,"props":6489,"children":6490},{"class":785,"line":1137},[6491],{"type":415,"tag":783,"props":6492,"children":6493},{"style":790},[6494],{"type":420,"value":1272},{"type":415,"tag":783,"props":6496,"children":6497},{"class":785,"line":1175},[6498],{"type":415,"tag":783,"props":6499,"children":6500},{"emptyLinePlaceholder":1624},[6501],{"type":420,"value":1627},{"type":415,"tag":783,"props":6503,"children":6504},{"class":785,"line":1213},[6505,6509,6514],{"type":415,"tag":783,"props":6506,"children":6507},{"style":790},[6508],{"type":420,"value":1818},{"type":415,"tag":783,"props":6510,"children":6511},{"style":875},[6512],{"type":420,"value":6513},"OptionsValidator",{"type":415,"tag":783,"props":6515,"children":6516},{"style":790},[6517],{"type":420,"value":1828},{"type":415,"tag":783,"props":6519,"children":6520},{"class":785,"line":1239},[6521,6525,6530,6534,6539,6543,6548,6552,6556],{"type":415,"tag":783,"props":6522,"children":6523},{"style":805},[6524],{"type":420,"value":1871},{"type":415,"tag":783,"props":6526,"children":6527},{"style":805},[6528],{"type":420,"value":6529}," partial",{"type":415,"tag":783,"props":6531,"children":6532},{"style":875},[6533],{"type":420,"value":1876},{"type":415,"tag":783,"props":6535,"children":6536},{"style":875},[6537],{"type":420,"value":6538}," WeatherMapConfigurationValidator",{"type":415,"tag":783,"props":6540,"children":6541},{"style":790},[6542],{"type":420,"value":1886},{"type":415,"tag":783,"props":6544,"children":6545},{"style":875},[6546],{"type":420,"value":6547}," IValidateOptions",{"type":415,"tag":783,"props":6549,"children":6550},{"style":790},[6551],{"type":420,"value":2112},{"type":415,"tag":783,"props":6553,"children":6554},{"style":875},[6555],{"type":420,"value":6243},{"type":415,"tag":783,"props":6557,"children":6558},{"style":790},[6559],{"type":420,"value":6560},">\n",{"type":415,"tag":783,"props":6562,"children":6563},{"class":785,"line":1248},[6564],{"type":415,"tag":783,"props":6565,"children":6566},{"style":790},[6567],{"type":420,"value":793},{"type":415,"tag":783,"props":6569,"children":6570},{"class":785,"line":1257},[6571],{"type":415,"tag":783,"props":6572,"children":6573},{"style":790},[6574],{"type":420,"value":1272},{"type":415,"tag":416,"props":6576,"children":6577},{},[6578,6580,6585,6587,6593],{"type":420,"value":6579},"This way we can make sure that the configuration contains the API Key and the URI that has the ",{"type":415,"tag":550,"props":6581,"children":6583},{"className":6582},[],[6584],{"type":420,"value":6432},{"type":420,"value":6586}," format. The configuration in the ",{"type":415,"tag":550,"props":6588,"children":6590},{"className":6589},[],[6591],{"type":420,"value":6592},"Program.cs",{"type":420,"value":6594}," looks like that:",{"type":415,"tag":773,"props":6596,"children":6598},{"className":1805,"code":6597,"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",[6599],{"type":415,"tag":550,"props":6600,"children":6601},{"__ignoreMap":401},[6602,6681,6736,6743,6780,6817,6857,6864,6925,6975,6983],{"type":415,"tag":783,"props":6603,"children":6604},{"class":785,"line":786},[6605,6609,6613,6617,6621,6626,6630,6634,6638,6642,6646,6650,6654,6659,6663,6667,6672,6676],{"type":415,"tag":783,"props":6606,"children":6607},{"style":1362},[6608],{"type":420,"value":5635},{"type":415,"tag":783,"props":6610,"children":6611},{"style":790},[6612],{"type":420,"value":755},{"type":415,"tag":783,"props":6614,"children":6615},{"style":1362},[6616],{"type":420,"value":5644},{"type":415,"tag":783,"props":6618,"children":6619},{"style":790},[6620],{"type":420,"value":755},{"type":415,"tag":783,"props":6622,"children":6623},{"style":1545},[6624],{"type":420,"value":6625},"Configure",{"type":415,"tag":783,"props":6627,"children":6628},{"style":790},[6629],{"type":420,"value":2112},{"type":415,"tag":783,"props":6631,"children":6632},{"style":875},[6633],{"type":420,"value":6243},{"type":415,"tag":783,"props":6635,"children":6636},{"style":790},[6637],{"type":420,"value":5675},{"type":415,"tag":783,"props":6639,"children":6640},{"style":1362},[6641],{"type":420,"value":5635},{"type":415,"tag":783,"props":6643,"children":6644},{"style":790},[6645],{"type":420,"value":755},{"type":415,"tag":783,"props":6647,"children":6648},{"style":1362},[6649],{"type":420,"value":263},{"type":415,"tag":783,"props":6651,"children":6652},{"style":790},[6653],{"type":420,"value":755},{"type":415,"tag":783,"props":6655,"children":6656},{"style":1545},[6657],{"type":420,"value":6658},"GetSection",{"type":415,"tag":783,"props":6660,"children":6661},{"style":790},[6662],{"type":420,"value":1845},{"type":415,"tag":783,"props":6664,"children":6665},{"style":790},[6666],{"type":420,"value":813},{"type":415,"tag":783,"props":6668,"children":6669},{"style":825},[6670],{"type":420,"value":6671},"WeatherMap",{"type":415,"tag":783,"props":6673,"children":6674},{"style":790},[6675],{"type":420,"value":813},{"type":415,"tag":783,"props":6677,"children":6678},{"style":790},[6679],{"type":420,"value":6680},"));\n",{"type":415,"tag":783,"props":6682,"children":6683},{"class":785,"line":796},[6684,6688,6692,6696,6700,6705,6709,6714,6718,6722,6727,6731],{"type":415,"tag":783,"props":6685,"children":6686},{"style":1362},[6687],{"type":420,"value":5635},{"type":415,"tag":783,"props":6689,"children":6690},{"style":790},[6691],{"type":420,"value":755},{"type":415,"tag":783,"props":6693,"children":6694},{"style":1362},[6695],{"type":420,"value":5644},{"type":415,"tag":783,"props":6697,"children":6698},{"style":790},[6699],{"type":420,"value":755},{"type":415,"tag":783,"props":6701,"children":6702},{"style":1545},[6703],{"type":420,"value":6704},"AddSingleton",{"type":415,"tag":783,"props":6706,"children":6707},{"style":790},[6708],{"type":420,"value":2112},{"type":415,"tag":783,"props":6710,"children":6711},{"style":875},[6712],{"type":420,"value":6713},"IValidateOptions",{"type":415,"tag":783,"props":6715,"children":6716},{"style":790},[6717],{"type":420,"value":2112},{"type":415,"tag":783,"props":6719,"children":6720},{"style":875},[6721],{"type":420,"value":6243},{"type":415,"tag":783,"props":6723,"children":6724},{"style":790},[6725],{"type":420,"value":6726},">,",{"type":415,"tag":783,"props":6728,"children":6729},{"style":875},[6730],{"type":420,"value":6538},{"type":415,"tag":783,"props":6732,"children":6733},{"style":790},[6734],{"type":420,"value":6735},">();\n",{"type":415,"tag":783,"props":6737,"children":6738},{"class":785,"line":840},[6739],{"type":415,"tag":783,"props":6740,"children":6741},{"emptyLinePlaceholder":1624},[6742],{"type":420,"value":1627},{"type":415,"tag":783,"props":6744,"children":6745},{"class":785,"line":866},[6746,6750,6754,6758,6762,6767,6771,6776],{"type":415,"tag":783,"props":6747,"children":6748},{"style":1362},[6749],{"type":420,"value":5635},{"type":415,"tag":783,"props":6751,"children":6752},{"style":790},[6753],{"type":420,"value":755},{"type":415,"tag":783,"props":6755,"children":6756},{"style":1362},[6757],{"type":420,"value":5644},{"type":415,"tag":783,"props":6759,"children":6760},{"style":790},[6761],{"type":420,"value":755},{"type":415,"tag":783,"props":6763,"children":6764},{"style":1545},[6765],{"type":420,"value":6766},"AddTransient",{"type":415,"tag":783,"props":6768,"children":6769},{"style":790},[6770],{"type":420,"value":2112},{"type":415,"tag":783,"props":6772,"children":6773},{"style":875},[6774],{"type":420,"value":6775},"ApiKeyHandler",{"type":415,"tag":783,"props":6777,"children":6778},{"style":790},[6779],{"type":420,"value":6735},{"type":415,"tag":783,"props":6781,"children":6782},{"class":785,"line":893},[6783,6787,6791,6795,6799,6804,6808,6812],{"type":415,"tag":783,"props":6784,"children":6785},{"style":1362},[6786],{"type":420,"value":5635},{"type":415,"tag":783,"props":6788,"children":6789},{"style":790},[6790],{"type":420,"value":755},{"type":415,"tag":783,"props":6792,"children":6793},{"style":1362},[6794],{"type":420,"value":5644},{"type":415,"tag":783,"props":6796,"children":6797},{"style":790},[6798],{"type":420,"value":755},{"type":415,"tag":783,"props":6800,"children":6801},{"style":1545},[6802],{"type":420,"value":6803},"AddRefitClient",{"type":415,"tag":783,"props":6805,"children":6806},{"style":790},[6807],{"type":420,"value":2112},{"type":415,"tag":783,"props":6809,"children":6810},{"style":875},[6811],{"type":420,"value":2579},{"type":415,"tag":783,"props":6813,"children":6814},{"style":790},[6815],{"type":420,"value":6816},">()\n",{"type":415,"tag":783,"props":6818,"children":6819},{"class":785,"line":920},[6820,6825,6830,6835,6840,6844,6849,6853],{"type":415,"tag":783,"props":6821,"children":6822},{"style":790},[6823],{"type":420,"value":6824},"    .",{"type":415,"tag":783,"props":6826,"children":6827},{"style":1545},[6828],{"type":420,"value":6829},"ConfigureHttpClient",{"type":415,"tag":783,"props":6831,"children":6832},{"style":790},[6833],{"type":420,"value":6834},"((",{"type":415,"tag":783,"props":6836,"children":6837},{"style":875},[6838],{"type":420,"value":6839},"provider",{"type":415,"tag":783,"props":6841,"children":6842},{"style":790},[6843],{"type":420,"value":2501},{"type":415,"tag":783,"props":6845,"children":6846},{"style":875},[6847],{"type":420,"value":6848}," client",{"type":415,"tag":783,"props":6850,"children":6851},{"style":790},[6852],{"type":420,"value":1678},{"type":415,"tag":783,"props":6854,"children":6855},{"style":790},[6856],{"type":420,"value":2788},{"type":415,"tag":783,"props":6858,"children":6859},{"class":785,"line":959},[6860],{"type":415,"tag":783,"props":6861,"children":6862},{"style":790},[6863],{"type":420,"value":1971},{"type":415,"tag":783,"props":6865,"children":6866},{"class":785,"line":997},[6867,6871,6876,6880,6885,6889,6894,6898,6903,6907,6911,6916,6921],{"type":415,"tag":783,"props":6868,"children":6869},{"style":875},[6870],{"type":420,"value":2681},{"type":415,"tag":783,"props":6872,"children":6873},{"style":875},[6874],{"type":420,"value":6875}," configuration",{"type":415,"tag":783,"props":6877,"children":6878},{"style":790},[6879],{"type":420,"value":2033},{"type":415,"tag":783,"props":6881,"children":6882},{"style":1362},[6883],{"type":420,"value":6884}," provider",{"type":415,"tag":783,"props":6886,"children":6887},{"style":790},[6888],{"type":420,"value":755},{"type":415,"tag":783,"props":6890,"children":6891},{"style":1545},[6892],{"type":420,"value":6893},"GetRequiredService",{"type":415,"tag":783,"props":6895,"children":6896},{"style":790},[6897],{"type":420,"value":2112},{"type":415,"tag":783,"props":6899,"children":6900},{"style":875},[6901],{"type":420,"value":6902},"IOptions",{"type":415,"tag":783,"props":6904,"children":6905},{"style":790},[6906],{"type":420,"value":2112},{"type":415,"tag":783,"props":6908,"children":6909},{"style":875},[6910],{"type":420,"value":6243},{"type":415,"tag":783,"props":6912,"children":6913},{"style":790},[6914],{"type":420,"value":6915},">>().",{"type":415,"tag":783,"props":6917,"children":6918},{"style":1362},[6919],{"type":420,"value":6920},"Value",{"type":415,"tag":783,"props":6922,"children":6923},{"style":790},[6924],{"type":420,"value":1926},{"type":415,"tag":783,"props":6926,"children":6927},{"class":785,"line":1023},[6928,6933,6937,6942,6946,6950,6954,6958,6962,6966,6971],{"type":415,"tag":783,"props":6929,"children":6930},{"style":1362},[6931],{"type":420,"value":6932},"        client",{"type":415,"tag":783,"props":6934,"children":6935},{"style":790},[6936],{"type":420,"value":755},{"type":415,"tag":783,"props":6938,"children":6939},{"style":1362},[6940],{"type":420,"value":6941},"BaseAddress ",{"type":415,"tag":783,"props":6943,"children":6944},{"style":790},[6945],{"type":420,"value":1984},{"type":415,"tag":783,"props":6947,"children":6948},{"style":790},[6949],{"type":420,"value":4335},{"type":415,"tag":783,"props":6951,"children":6952},{"style":875},[6953],{"type":420,"value":6456},{"type":415,"tag":783,"props":6955,"children":6956},{"style":790},[6957],{"type":420,"value":1845},{"type":415,"tag":783,"props":6959,"children":6960},{"style":1362},[6961],{"type":420,"value":262},{"type":415,"tag":783,"props":6963,"children":6964},{"style":790},[6965],{"type":420,"value":755},{"type":415,"tag":783,"props":6967,"children":6968},{"style":1362},[6969],{"type":420,"value":6970},"Uri",{"type":415,"tag":783,"props":6972,"children":6973},{"style":790},[6974],{"type":420,"value":2552},{"type":415,"tag":783,"props":6976,"children":6977},{"class":785,"line":1061},[6978],{"type":415,"tag":783,"props":6979,"children":6980},{"style":790},[6981],{"type":420,"value":6982},"    })\n",{"type":415,"tag":783,"props":6984,"children":6985},{"class":785,"line":1099},[6986,6990,6995,6999,7003],{"type":415,"tag":783,"props":6987,"children":6988},{"style":790},[6989],{"type":420,"value":6824},{"type":415,"tag":783,"props":6991,"children":6992},{"style":1545},[6993],{"type":420,"value":6994},"AddHttpMessageHandler",{"type":415,"tag":783,"props":6996,"children":6997},{"style":790},[6998],{"type":420,"value":2112},{"type":415,"tag":783,"props":7000,"children":7001},{"style":875},[7002],{"type":420,"value":6775},{"type":415,"tag":783,"props":7004,"children":7005},{"style":790},[7006],{"type":420,"value":6735},{"type":415,"tag":443,"props":7008,"children":7010},{"id":7009},"a-few-closing-words",[7011],{"type":420,"value":7012},"A few closing words",{"type":415,"tag":416,"props":7014,"children":7015},{},[7016],{"type":420,"value":7017},"Here is the recap of what we talked about:",{"type":420,"value":7019},"\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":7021,"props":7022,"children":7023},"table",{},[7024,7043],{"type":415,"tag":7025,"props":7026,"children":7027},"thead",{},[7028],{"type":415,"tag":7029,"props":7030,"children":7031},"tr",{},[7032,7038],{"type":415,"tag":7033,"props":7034,"children":7035},"th",{},[7036],{"type":420,"value":7037},"Feature",{"type":415,"tag":7033,"props":7039,"children":7040},{},[7041],{"type":420,"value":7042},"Area",{"type":415,"tag":7044,"props":7045,"children":7046},"tbody",{},[7047,7065,7083,7099,7115,7132,7150,7166],{"type":415,"tag":7029,"props":7048,"children":7049},{},[7050,7060],{"type":415,"tag":7051,"props":7052,"children":7053},"td",{},[7054],{"type":415,"tag":423,"props":7055,"children":7057},{"href":2194,"rel":7056},[427],[7058],{"type":420,"value":7059},"Support for generic attributes",{"type":415,"tag":7051,"props":7061,"children":7062},{},[7063],{"type":420,"value":7064},".NET 8",{"type":415,"tag":7029,"props":7066,"children":7067},{},[7068,7078],{"type":415,"tag":7051,"props":7069,"children":7070},{},[7071],{"type":415,"tag":423,"props":7072,"children":7075},{"href":7073,"rel":7074},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#primary-constructors",[427],[7076],{"type":420,"value":7077},"Primary constructors",{"type":415,"tag":7051,"props":7079,"children":7080},{},[7081],{"type":420,"value":7082},"C# 12",{"type":415,"tag":7029,"props":7084,"children":7085},{},[7086,7095],{"type":415,"tag":7051,"props":7087,"children":7088},{},[7089],{"type":415,"tag":423,"props":7090,"children":7092},{"href":4514,"rel":7091},[427],[7093],{"type":420,"value":7094},"Collection expressions",{"type":415,"tag":7051,"props":7096,"children":7097},{},[7098],{"type":420,"value":7082},{"type":415,"tag":7029,"props":7100,"children":7101},{},[7102,7111],{"type":415,"tag":7051,"props":7103,"children":7104},{},[7105],{"type":415,"tag":423,"props":7106,"children":7108},{"href":3752,"rel":7107},[427],[7109],{"type":420,"value":7110},"Optional parameters in lambda expressions",{"type":415,"tag":7051,"props":7112,"children":7113},{},[7114],{"type":420,"value":7082},{"type":415,"tag":7029,"props":7116,"children":7117},{},[7118,7128],{"type":415,"tag":7051,"props":7119,"children":7120},{},[7121],{"type":415,"tag":423,"props":7122,"children":7125},{"href":7123,"rel":7124},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#alias-any-type",[427],[7126],{"type":420,"value":7127},"Alias any type",{"type":415,"tag":7051,"props":7129,"children":7130},{},[7131],{"type":420,"value":7082},{"type":415,"tag":7029,"props":7133,"children":7134},{},[7135,7145],{"type":415,"tag":7051,"props":7136,"children":7137},{},[7138],{"type":415,"tag":423,"props":7139,"children":7142},{"href":7140,"rel":7141},"https://learn.microsoft.com/en-us/visualstudio/debugger/using-the-debuggerdisplay-attribute",[427],[7143],{"type":420,"value":7144},"Debug customization attributes on ASP.NET Core types      ",{"type":415,"tag":7051,"props":7146,"children":7147},{},[7148],{"type":420,"value":7149},"ASP.NET Core 8",{"type":415,"tag":7029,"props":7151,"children":7152},{},[7153,7162],{"type":415,"tag":7051,"props":7154,"children":7155},{},[7156],{"type":415,"tag":423,"props":7157,"children":7159},{"href":6261,"rel":7158},[427],[7160],{"type":420,"value":7161},"Options validation",{"type":415,"tag":7051,"props":7163,"children":7164},{},[7165],{"type":420,"value":7064},{"type":415,"tag":7029,"props":7167,"children":7168},{},[7169,7178],{"type":415,"tag":7051,"props":7170,"children":7171},{},[7172],{"type":415,"tag":423,"props":7173,"children":7175},{"href":5610,"rel":7174},[427],[7176],{"type":420,"value":7177},"Keyed DI Services",{"type":415,"tag":7051,"props":7179,"children":7180},{},[7181],{"type":420,"value":7064},{"type":415,"tag":416,"props":7183,"children":7184},{},[7185,7187,7193,7195,7200,7202,7208],{"type":420,"value":7186},"There are many more interesting features in ",{"type":415,"tag":423,"props":7188,"children":7191},{"href":7189,"rel":7190},"https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12",[427],[7192],{"type":420,"value":7082},{"type":420,"value":7194},", ",{"type":415,"tag":423,"props":7196,"children":7198},{"href":5610,"rel":7197},[427],[7199],{"type":420,"value":7064},{"type":420,"value":7201},", or ",{"type":415,"tag":423,"props":7203,"children":7206},{"href":7204,"rel":7205},"https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0",[427],[7207],{"type":420,"value":7149},{"type":420,"value":7209},". Yet, the ones I introduced in this article are the ones I will probably use the most.",{"type":415,"tag":416,"props":7211,"children":7212},{},[7213,7215,7222,7224,7230],{"type":420,"value":7214},"You can find the complete code sample ",{"type":415,"tag":423,"props":7216,"children":7219},{"href":7217,"rel":7218},"https://github.com/TechWatching/CodeAppAndInfraInDotnet8",[427],[7220],{"type":420,"value":7221},"here",{"type":420,"value":7223},". The repository also contains a folder ",{"type":415,"tag":550,"props":7225,"children":7227},{"className":7226},[],[7228],{"type":420,"value":7229},"infra",{"type":420,"value":7231}," 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":7233,"children":7234},{},[7235,7237,7244],{"type":420,"value":7236},"This article was published as part of the ",{"type":415,"tag":423,"props":7238,"children":7241},{"href":7239,"rel":7240},"https://www.csadvent.christmas/",[427],[7242],{"type":420,"value":7243},"C# Advent 2023",{"type":420,"value":7245}," which is a nice initiative. Make sure to check the other blog articles on the advent calendar.",{"type":415,"tag":1420,"props":7247,"children":7248},{},[7249],{"type":420,"value":1424},{"title":401,"searchDepth":796,"depth":796,"links":7251},[7252,7253,7254],{"id":1457,"depth":796,"text":1460},{"id":1725,"depth":796,"text":1728},{"id":7009,"depth":796,"text":7012},"content:1.posts:56.playing-with-dotnet8.md","1.posts/56.playing-with-dotnet8.md",{"_path":136,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":135,"description":7258,"lead":7259,"date":7260,"image":7261,"badge":7263,"tags":7264,"body":7265,"_type":1435,"_id":7911,"_source":1437,"_file":7912,"_extension":1439},"This article is a discussion about API clients. Without being a comparison between the best API clients, this article talks about the pros and cons of some popular tools to send HTTP requests to an API. The goal is not to elect the best one, but rather to try to answer the following question: what we should consider when choosing an API client, and what are the challenges when using one?","What should you consider when choosing an API client?","2022-09-08T00:00:00.000Z",{"src":7262},"/images/tools_1.jpg",{"label":408},[206,213,360,210],{"type":412,"children":7266,"toc":7893},[7267,7271,7277,7291,7361,7389,7394,7400,7405,7414,7420,7425,7430,7439,7444,7462,7467,7473,7478,7491,7497,7502,7507,7528,7537,7557,7600,7606,7611,7620,7626,7648,7653,7659,7664,7669,7677,7683,7688,7693,7711,7720,7732,7737,7743,7749,7754,7759,7764,7769,7774,7780,7793,7798,7811,7839,7853,7865,7882,7888],{"type":415,"tag":416,"props":7268,"children":7269},{},[7270],{"type":420,"value":7258},{"type":415,"tag":443,"props":7272,"children":7274},{"id":7273},"some-context",[7275],{"type":420,"value":7276},"Some context",{"type":415,"tag":416,"props":7278,"children":7279},{},[7280,7282,7289],{"type":420,"value":7281},"I like discussing tooling because as a developer choosing the right tool is often what makes me more productive in my job. I am talking about the \"right tool\" because I am not necessarily looking for the best one but the most appropriate one for my needs in a given context. The topic of API clients is not new to me, indeed the first post I wrote on this blog in March 2019 (and my most-read article on DEV.to where I re-posted it) was about using the vscode extension \"REST Client\" instead of Postman. ",{"type":415,"tag":423,"props":7283,"children":7286},{"href":7284,"rel":7285},"https://www.techwatching.dev/posts/testing-your-api-with-rest-client",[427],[7287],{"type":420,"value":7288},"This article",{"type":420,"value":7290}," is still relevant and in fact, I have been using REST Client as my main API client for a few years on different projects and in different teams.",{"type":415,"tag":416,"props":7292,"children":7293},{},[7294,7296,7303,7304,7310,7311,7318,7319,7326,7327,7334,7335,7342,7343,7350,7352,7359],{"type":420,"value":7295},"Yet I am not writing now to convince you to use \"REST Client\" or any other tool. Besides, you probably already have a favorite tool you are using to send HTTP requests. Indeed, there are many options: ",{"type":415,"tag":423,"props":7297,"children":7300},{"href":7298,"rel":7299},"https://www.postman.com",[427],[7301],{"type":420,"value":7302},"Postman",{"type":420,"value":7194},{"type":415,"tag":423,"props":7305,"children":7307},{"href":1672,"rel":7306},[427],[7308],{"type":420,"value":7309},"REST Client",{"type":420,"value":7194},{"type":415,"tag":423,"props":7312,"children":7315},{"href":7313,"rel":7314},"https://www.thunderclient.com/",[427],[7316],{"type":420,"value":7317},"Thunder Client",{"type":420,"value":7194},{"type":415,"tag":423,"props":7320,"children":7323},{"href":7321,"rel":7322},"https://nightingale.rest/",[427],[7324],{"type":420,"value":7325},"Nightingale",{"type":420,"value":7194},{"type":415,"tag":423,"props":7328,"children":7331},{"href":7329,"rel":7330},"https://insomnia.rest/",[427],[7332],{"type":420,"value":7333},"Insomnia",{"type":420,"value":7194},{"type":415,"tag":423,"props":7336,"children":7339},{"href":7337,"rel":7338},"https://rapidapi.com/products/api-design/",[427],[7340],{"type":420,"value":7341},"RapidAPI Client",{"type":420,"value":7194},{"type":415,"tag":423,"props":7344,"children":7347},{"href":7345,"rel":7346},"https://hoppscotch.io/fr/",[427],[7348],{"type":420,"value":7349},"Hoppscotch",{"type":420,"value":7351},", and ",{"type":415,"tag":423,"props":7353,"children":7356},{"href":7354,"rel":7355},"https://httpie.io/",[427],[7357],{"type":420,"value":7358},"HTTPie",{"type":420,"value":7360}," just to name a few. There are many reasons why people choose one tool over another:",{"type":415,"tag":493,"props":7362,"children":7363},{},[7364,7369,7374,7379,7384],{"type":415,"tag":497,"props":7365,"children":7366},{},[7367],{"type":420,"value":7368},"it has more features than others",{"type":415,"tag":497,"props":7370,"children":7371},{},[7372],{"type":420,"value":7373},"some colleagues suggested it",{"type":415,"tag":497,"props":7375,"children":7376},{},[7377],{"type":420,"value":7378},"it's the latest tool featured on ProductHunt",{"type":415,"tag":497,"props":7380,"children":7381},{},[7382],{"type":420,"value":7383},"everyone in the company uses this API client",{"type":415,"tag":497,"props":7385,"children":7386},{},[7387],{"type":420,"value":7388},"it would be time-consuming to learn how to use another API Client",{"type":415,"tag":416,"props":7390,"children":7391},{},[7392],{"type":420,"value":7393},"I don't think these are good enough reasons, so I will talk to you about what matters to me when using an API Client.",{"type":415,"tag":443,"props":7395,"children":7397},{"id":7396},"ease-of-use",[7398],{"type":420,"value":7399},"Ease of use",{"type":415,"tag":416,"props":7401,"children":7402},{},[7403],{"type":420,"value":7404},"When I am using an API client, it's to make requests to an API and get responses. It's often to test an API or to debug the API I am developing. Therefore what's important to me is to have a simple tool that makes it easy to write HTTP requests, and display the responses and that's it.",{"type":415,"tag":416,"props":7406,"children":7407},{},[7408],{"type":415,"tag":1322,"props":7409,"children":7413},{"alt":7410,"className":7411,"src":7412},"A scrabble tile that says keep things simple.",[1326,1327],"/posts/images/httpclients_1.jpg",[],{"type":415,"tag":616,"props":7415,"children":7417},{"id":7416},"all-conceivable-functionalities-vs-essentials-features",[7418],{"type":420,"value":7419},"All conceivable functionalities vs. essentials features",{"type":415,"tag":416,"props":7421,"children":7422},{},[7423],{"type":420,"value":7424},"A lot of tools try to compete with each other by providing more features or very advanced features. First, it's useless because you are not going to use most of them. Second, it's counterproductive because having too many features will make an API client more complicated to use.",{"type":415,"tag":416,"props":7426,"children":7427},{},[7428],{"type":420,"value":7429},"One good example is Postman which went from a simple tool that makes HTTP requests to a real white elephant. To be honest, I am quite impressed with all the features you can find in Postman: the company has done an amazing job to build a platform that helps you in each step of your API lifecycle (specifications, design, documentation, testing, monitoring, ...). However, the downside is that Postman became bigger, slower, and less easy to use. I have no doubt Postman brings a lot of value to many developers that are building their APIs, yet a lot of people (like me) don't need all these unnecessary features and would be better with a simpler tool. Postman is just an example, there are many other API clients that overwhelm you with concepts you don't need (workspace, collections, mocks, flows), that require you to sign in and configure a bunch of things before being able to write an HTTP request.",{"type":415,"tag":416,"props":7431,"children":7432},{},[7433],{"type":415,"tag":1322,"props":7434,"children":7438},{"alt":7435,"className":7436,"src":7437},"Logo of Postman.",[1326,1327],"/posts/images/httpclients_2.jpg",[],{"type":415,"tag":416,"props":7440,"children":7441},{},[7442],{"type":420,"value":7443},"So what are the essentials features an API Client should have besides sending requests to an API and displaying the response?",{"type":415,"tag":493,"props":7445,"children":7446},{},[7447,7452,7457],{"type":415,"tag":497,"props":7448,"children":7449},{},[7450],{"type":420,"value":7451},"First, it should support the \"protocol\" (REST, SOAP, GraphQL, gRPC) used by the API you want to query (pretty obvious but not all API clients support gRPC or GraphQL for instance).",{"type":415,"tag":497,"props":7453,"children":7454},{},[7455],{"type":420,"value":7456},"Second, it should support environment variables. You will need them to easily switch between environments: sending requests to an API in QA and to the same API in Production for instance. Variables can also be useful to store the result of a previous request and use it in another request.",{"type":415,"tag":497,"props":7458,"children":7459},{},[7460],{"type":420,"value":7461},"Third, it should allow version control of your request (we will come back to this later).",{"type":415,"tag":416,"props":7463,"children":7464},{},[7465],{"type":420,"value":7466},"I think that's all you need. In my opinion, testing and integration with CI/CD pipelines (to automate testing) are nice-to-have functionalities but not mandatory. Indeed, if you want to do some complex tests with big scenarios that run in parallel, you are probably not using an API Client for that and rather develop proper integration tests using more appropriate tools.",{"type":415,"tag":616,"props":7468,"children":7470},{"id":7469},"integrated-tools-vs-standalone-tools",[7471],{"type":420,"value":7472},"Integrated tools vs. standalone tools",{"type":415,"tag":416,"props":7474,"children":7475},{},[7476],{"type":420,"value":7477},"Some API Clients are standalone software, whether rich clients (like Postman, or Nightingale) or web applications (like Hoppscotch). Some are directly integrated with your developer tools and IDEs. I feel more productive when everything is in one place and I leave my IDE as little as possible, so that's why I prefer an API Client integrated with my IDE. I find it easier to use a familiar UI in a tool I already know and like rather than using a completely different tool. Everyone has his own way of working so you may prefer a standalone tool and that's fine as well. Just take the time to think about what's best for you.",{"type":415,"tag":416,"props":7479,"children":7480},{},[7481,7483,7489],{"type":420,"value":7482},"If you are fond of vscode, you have different API clients available as extensions, for instance: REST Client, Thunder Client, and RapidAPI Client for VS Code. If your everyday IDE is Visual Studio, there is an extension ",{"type":415,"tag":423,"props":7484,"children":7487},{"href":7485,"rel":7486},"https://marketplace.visualstudio.com/items?itemName=MadsKristensen.RestClient",[427],[7488],{"type":420,"value":7309},{"type":420,"value":7490}," based on the REST Client for vscode. If you only swear by IntelliJ IDEA or Rider, all JetBrains IDEs have a built-in HTTP Client.",{"type":415,"tag":616,"props":7492,"children":7494},{"id":7493},"gui-tools-vs-text-based-tools",[7495],{"type":420,"value":7496},"GUI tools vs. text-based tools",{"type":415,"tag":416,"props":7498,"children":7499},{},[7500],{"type":420,"value":7501},"There are 2 types of tools: GUI tools and text-based tools.",{"type":415,"tag":416,"props":7503,"children":7504},{},[7505],{"type":420,"value":7506},"Generally, GUI tools are easier to use than text-based tools because they offer a simple way to create and send an HTTP request. Of course, this is not always the case: I already talked about some API clients that have a complex UI because of their many features. Fortunately, other GUI tools have managed to keep a simple and clean user interface. That is precisely how Thunder Client has been designed: a lightweight API client with an easy-to-use UI; and it's a success. I particularly like the GUI-based tests of Thunder Client that allow you to quickly do basic tests on HTTP responses without scripting anything. Test scenarios will be quite limited, yet you probably don't want to use an API client for more complex scenarios. There are many other API clients with a great UI, take the time to test several, the choice will probably be a matter of personal preference.",{"type":415,"tag":416,"props":7508,"children":7509},{},[7510,7512,7517,7519,7526],{"type":420,"value":7511},"Then, why bother with a text-based tool instead? How could it be easier to manually write an HTTP request in a plain text file than using a GUI for that? Because when you use a text-based API client like ",{"type":415,"tag":550,"props":7513,"children":7515},{"className":7514},[],[7516],{"type":420,"value":7309},{"type":420,"value":7518}," you write your request following the standard ",{"type":415,"tag":423,"props":7520,"children":7523},{"href":7521,"rel":7522},"https://www.rfc-editor.org/rfc/rfc7230#section-3",[427],[7524],{"type":420,"value":7525},"RFC 2730",{"type":420,"value":7527},". It's a standard so you will find it everywhere to describe the requests, including in the documentation of most popular APIs. It's quite straightforward so you won't have a hard time writing the requests.",{"type":415,"tag":416,"props":7529,"children":7530},{},[7531],{"type":415,"tag":1322,"props":7532,"children":7536},{"alt":7533,"className":7534,"src":7535},"REST Client in vscode.",[1326,1327],"/posts/images/httpclients_3.png",[],{"type":415,"tag":416,"props":7538,"children":7539},{},[7540,7542,7548,7550,7555],{"type":420,"value":7541},"Moreover, these kinds of API clients (which are often IDEs extensions or built-in in an IDE) will understand the HTTP text files (with ",{"type":415,"tag":7543,"props":7544,"children":7545},"em",{},[7546],{"type":420,"value":7547},".rest",{"type":420,"value":7549}," or ",{"type":415,"tag":7543,"props":7551,"children":7552},{},[7553],{"type":420,"value":7554},".http",{"type":420,"value":7556}," extension) and help you write the requests. You can write multiple requests in the same file and don't have to learn how to use a specific tool, just to write requests in plain text. Therefore, once you are used to the raw syntax of HTTP requests, using a text-based tool becomes even easier to use than the simplest GUI tool.",{"type":415,"tag":588,"props":7558,"children":7559},{"icon":728},[7560,7565],{"type":415,"tag":416,"props":7561,"children":7562},{},[7563],{"type":420,"value":7564},"I already mentioned them before but examples of such text-based tools are:",{"type":415,"tag":493,"props":7566,"children":7567},{},[7568,7578,7588],{"type":415,"tag":497,"props":7569,"children":7570},{},[7571,7576],{"type":415,"tag":423,"props":7572,"children":7574},{"href":1672,"rel":7573},[427],[7575],{"type":420,"value":7309},{"type":420,"value":7577}," in vscode",{"type":415,"tag":497,"props":7579,"children":7580},{},[7581,7586],{"type":415,"tag":423,"props":7582,"children":7584},{"href":7485,"rel":7583},[427],[7585],{"type":420,"value":7309},{"type":420,"value":7587}," in Visual Studio",{"type":415,"tag":497,"props":7589,"children":7590},{},[7591,7598],{"type":415,"tag":423,"props":7592,"children":7595},{"href":7593,"rel":7594},"https://www.jetbrains.com/help/rider/Http_client_in__product__code_editor.html",[427],[7596],{"type":420,"value":7597},"HTTP Client",{"type":420,"value":7599}," in Rider or any other JetBrains IDE",{"type":415,"tag":443,"props":7601,"children":7603},{"id":7602},"collaboration",[7604],{"type":420,"value":7605},"Collaboration",{"type":415,"tag":416,"props":7607,"children":7608},{},[7609],{"type":420,"value":7610},"The reason why most API clients are a no go for me is that they don't facilitate collaboration. Collaboration is an important part of my job so I need an API client that makes it easy to share requests with others.",{"type":415,"tag":416,"props":7612,"children":7613},{},[7614],{"type":415,"tag":1322,"props":7615,"children":7619},{"alt":7616,"className":7617,"src":7618},"A scrabble board with words spelling teamwork.",[1326,1327],"/posts/images/httpclients_4.jpg",[],{"type":415,"tag":616,"props":7621,"children":7623},{"id":7622},"are-you-ready-to-pay-the-price-for-team-collaboration",[7624],{"type":420,"value":7625},"Are you ready to pay the price for team collaboration?",{"type":415,"tag":416,"props":7627,"children":7628},{},[7629,7631,7637,7639,7646],{"type":420,"value":7630},"Although a few API clients totally lack collaboration features, many of them have nice features to collaborate with your team. However, that is also how the companies behind these tools make money: charging for collaboration features. Usually working with an API client is free for individuals but you have to pay when you are a company or a team. You can see for instance the pricing page of ",{"type":415,"tag":423,"props":7632,"children":7635},{"href":7633,"rel":7634},"https://www.postman.com/pricing/",[427],[7636],{"type":420,"value":7302},{"type":420,"value":7638}," or the one from ",{"type":415,"tag":423,"props":7640,"children":7643},{"href":7641,"rel":7642},"https://rapidapi.com/products/api-design",[427],[7644],{"type":420,"value":7645},"RapidAPI",{"type":420,"value":7647},". I have nothing against that: these companies put a lot of work and money into making these great tools, they need to be profitable and make money. Yet the question is: are you (or is your company) willing to pay for an API client?",{"type":415,"tag":416,"props":7649,"children":7650},{},[7651],{"type":420,"value":7652},"If the answer is yes, then fine, choose the best tool for your team, buy some licenses and enjoy. If the answer is no, then how do you intend to work with your colleagues without these collaboration features? Let me guess, you have found a way to export your collection of requests to a file. So each time a new colleague joins your team, you send him/her the file by mail; no one has the same version of the file but you don't care. Or maybe you have put it in a shared drive so everyone can edit the requests; you just have to hope that 2 people don't edit it at the same time. Why not put the file on a flash drive and pass it on to each other while you're at it? I think you understood what I was getting at: if you work with a team, pay for collaboration features, or choose a free API client suitable for teamwork.",{"type":415,"tag":616,"props":7654,"children":7656},{"id":7655},"version-control-is-the-key",[7657],{"type":420,"value":7658},"Version control is the key",{"type":415,"tag":416,"props":7660,"children":7661},{},[7662],{"type":420,"value":7663},"In my daily work as a developer, I work in a team and I want to share requests with them, allow them to edit them, and see the history of changes made. It's funny because it's the same kind of thing you want for your application code when developing. And what helps you with that? Version control. So if you use a git repository to version your application code, there is no reason why it would not be a good fit for your collection of HTTP requests.",{"type":415,"tag":416,"props":7665,"children":7666},{},[7667],{"type":420,"value":7668},"Besides, that is exactly what some API clients like Thunder Client or Postman offer: integration with external git repositories. Please note that is not necessary for your API client to have a git integration to share your requests through git, as long as your requests are available in a text file you can version it's fine. So why bother with an obscure \"cloud synchronization\" of your requests when you can share them with your team through a git repository?",{"type":415,"tag":588,"props":7670,"children":7671},{"icon":590},[7672],{"type":415,"tag":416,"props":7673,"children":7674},{},[7675],{"type":420,"value":7676},"The sweet spot when you are building an API is to store your API application code and your requests to call/test this API in the same git repository.",{"type":415,"tag":616,"props":7678,"children":7680},{"id":7679},"how-requests-are-stored-is-important",[7681],{"type":420,"value":7682},"How requests are stored is important",{"type":415,"tag":416,"props":7684,"children":7685},{},[7686],{"type":420,"value":7687},"I previously mentioned how some tools like Thunder Client offer a git integration with external git repositories. Requests and environment variables used by Thunder Client are stored in JSON files that you can add to your git repository. In a similar way, with Postman you can export requests and environment variables in JSON files and version them. There is a big problem with this way of doing things: using JSON files to version HTTP requests is not convenient at all! I have no problem with the JSON format itself, as a developer, it's something I often use. However, HTTP requests stored in a JSON file are not easily readable by a human. If you version HTTP requests, it is not to struggle to understand the history of changes or to have a hard time resolving conflicts between changes made by you and other developers of the team.",{"type":415,"tag":416,"props":7689,"children":7690},{},[7691],{"type":420,"value":7692},"I have seen some QA people using Postman for integration testing that were exporting their Postman data (collection, environments, ...) and versioning it in a git repository. What started out as a good intention turned out to be a very bad idea:",{"type":415,"tag":493,"props":7694,"children":7695},{},[7696,7701,7706],{"type":415,"tag":497,"props":7697,"children":7698},{},[7699],{"type":420,"value":7700},"the exported collection was just a huge JSON file that contained all the requests and tests, so each change was made to this same file with the inconveniences I mentioned previously",{"type":415,"tag":497,"props":7702,"children":7703},{},[7704],{"type":420,"value":7705},"editing the JSON file directly and especially the tests written in javascript is a nightmare because with the Postman export the code is stored as string in the JSON (forget about using code quality tools 🥲)",{"type":415,"tag":497,"props":7707,"children":7708},{},[7709],{"type":420,"value":7710},"the environment files versioned were containing secrets so secrets were committed in clear text in the git repository 😱",{"type":415,"tag":416,"props":7712,"children":7713},{},[7714],{"type":415,"tag":1322,"props":7715,"children":7719},{"alt":7716,"className":7717,"src":7718},"A silhouette of a man.",[1326,1327],"/posts/images/httpclients_5.jpg",[],{"type":415,"tag":416,"props":7721,"children":7722},{},[7723,7725,7730],{"type":420,"value":7724},"To avoid these caveats, I think the best way to store HTTP requests is to store them in HTTP text files following the standard ",{"type":415,"tag":423,"props":7726,"children":7728},{"href":7521,"rel":7727},[427],[7729],{"type":420,"value":7525},{"type":420,"value":7731},". I already talked about text-based tools that were following this approach, unfortunately, I did not find any GUI tool that was doing that (probably because GUI tools always have extra features with things that can't be easily stored in an HTTP file).",{"type":415,"tag":416,"props":7733,"children":7734},{},[7735],{"type":420,"value":7736},"If you pay for an API client with which your requests are synchronized in the cloud with your colleagues, you probably don't care how the requests are stored. However, I hope your API client knows how to handle merge and conflicts (1 or more requests edited by several colleagues at the same time for example). Even if it does, be aware it can be not that easy to manually resolve these conflicts in a GUI tool.",{"type":415,"tag":443,"props":7738,"children":7740},{"id":7739},"final-thoughts",[7741],{"type":420,"value":7742},"Final thoughts",{"type":415,"tag":616,"props":7744,"children":7746},{"id":7745},"using-the-right-tool-for-a-given-context",[7747],{"type":420,"value":7748},"Using the right tool for a given context",{"type":415,"tag":416,"props":7750,"children":7751},{},[7752],{"type":420,"value":7753},"I think you understood that there was no perfect API client. So once again, the answer to choosing the right one will be \"it depends\".",{"type":415,"tag":416,"props":7755,"children":7756},{},[7757],{"type":420,"value":7758},"If for your project, you need to choose an API client that will only be used by developers of your team that are coding in vscode, maybe REST Client, Thunder Client, or RapidAPI Client for VS Code are interesting choices.",{"type":415,"tag":416,"props":7760,"children":7761},{},[7762],{"type":420,"value":7763},"For a lot of reasons I explained previously I am not a big fan of big standalone tools like Postman. Yet, Postman is installed on my laptop, and if people send me their requests collection to test their API, I would be crazy not to take advantage of it and rewrite every request just because I prefer to use other tools.",{"type":415,"tag":416,"props":7765,"children":7766},{},[7767],{"type":420,"value":7768},"I like the HTTP request format and I think people using API clients should be familiar with it. Unfortunately, sometimes people that need to use an API client don't have a technical background. In that case, maybe GUI tools with a simple interface are better suited than a text-based tool. Thunder Client with its scriptless testing feature might be a good option (although it requires you to install vscode which is more intended for developers).",{"type":415,"tag":416,"props":7770,"children":7771},{},[7772],{"type":420,"value":7773},"There are many API clients that you can use. Without knowing all of them, it can be a good idea to know what are the alternatives to the most famous ones, in order to choose the right one for your current context.",{"type":415,"tag":616,"props":7775,"children":7777},{"id":7776},"what-am-i-currently-using",[7778],{"type":420,"value":7779},"What am I currently using?",{"type":415,"tag":416,"props":7781,"children":7782},{},[7783,7785,7791],{"type":420,"value":7784},"As far as I'm concerned, I prefer using HTTP requests in HTTP files that I edit in a text editor or an IDE and that I commit to a git repository. That way, I have several HTTP files with HTTP requests grouped by concern. When I or one of my colleagues make a change to a request, the others just have to do a ",{"type":415,"tag":550,"props":7786,"children":7788},{"className":7787},[],[7789],{"type":420,"value":7790},"git pull",{"type":420,"value":7792}," to get the change. We use something standard and we are not directly dependent on a specific tool because HTTP files are supported by several tools.",{"type":415,"tag":416,"props":7794,"children":7795},{},[7796],{"type":420,"value":7797},"I have used REST Client for quite a while now, and I am happy with it: simple but works fine, no need to pay a subscription, it's just a vscode extension to install.",{"type":415,"tag":416,"props":7799,"children":7800},{},[7801,7803,7809],{"type":420,"value":7802},"However, as I have started recently to use more and more Rider, I am also using more and more its built-in HTTP Client which is awesome. If you are using Rider or one of the other JetBrains IDEs I recommend you to try the ",{"type":415,"tag":423,"props":7804,"children":7806},{"href":7593,"rel":7805},[427],[7807],{"type":420,"value":7808},"built-in HTTP Client",{"type":420,"value":7810}," because:",{"type":415,"tag":493,"props":7812,"children":7813},{},[7814,7819,7824,7829,7834],{"type":415,"tag":497,"props":7815,"children":7816},{},[7817],{"type":420,"value":7818},"you don't have to leave your favorite IDE to make HTTP requests to an API",{"type":415,"tag":497,"props":7820,"children":7821},{},[7822],{"type":420,"value":7823},"it supports HTTP requests, gRPC requests, WebSocket requests, GraphQL",{"type":415,"tag":497,"props":7825,"children":7826},{},[7827],{"type":420,"value":7828},"it has many features to help you write the requests like converting cURL requests to the HTTP request format",{"type":415,"tag":497,"props":7830,"children":7831},{},[7832],{"type":420,"value":7833},"it supports environment variables that can be stored in a public environment file (stored in the git repository) or private environment file (local file containing sensitive information that will not be committed to the repository)",{"type":415,"tag":497,"props":7835,"children":7836},{},[7837],{"type":420,"value":7838},"it allows you to write response handler scripts in JavaScript (directly in the HTTP files or in external js files), which opens the door to many possibilities like writing tests",{"type":415,"tag":416,"props":7840,"children":7841},{},[7842,7844,7851],{"type":420,"value":7843},"And the icing on the cake, as you see on the tweet below there is a ",{"type":415,"tag":423,"props":7845,"children":7848},{"href":7846,"rel":7847},"https://github.com/restcli/restcli",[427],[7849],{"type":420,"value":7850},"CLI",{"type":420,"value":7852}," to execute these HTTP files from the command line. It means that if you have written tests for your HTTP requests with the HTTP Client, you can execute them in your CI/CD pipeline. It also means that even without a JetBrains' IDE you can execute HTTP request files.",{"type":415,"tag":7854,"props":7855,"children":7859},"div",{"className":7856},[7857,7858],"flex","justify-center",[7860],{"type":415,"tag":7861,"props":7862,"children":7864},"tweet",{"id":7863},"1546831245274931201",[],{"type":415,"tag":588,"props":7866,"children":7867},{"icon":728},[7868],{"type":415,"tag":416,"props":7869,"children":7870},{},[7871,7873,7880],{"type":420,"value":7872},"Even if you are using a private environment file to store secrets environments variables, it's often not very convenient to share it with your news colleagues. I wrote ",{"type":415,"tag":423,"props":7874,"children":7877},{"href":7875,"rel":7876},"https://www.techwatching.dev/posts/http-clients-secrets",[427],[7878],{"type":420,"value":7879},"an article",{"type":420,"value":7881}," on the topic that showed how you can store secrets in Azure Key Vault and script their retrieval and the generation of the secret environment file using Azure CLI.",{"type":415,"tag":616,"props":7883,"children":7885},{"id":7884},"in-summary",[7886],{"type":420,"value":7887},"In summary",{"type":415,"tag":416,"props":7889,"children":7890},{},[7891],{"type":420,"value":7892},"I talked about a lot of things but in concrete terms what matters to me when using an API Client is ease of use and collaboration. You may not have exactly the same needs, yet I think these are 2 aspects you should pay attention to when choosing an API Client. As you have read in this article, each API client has its advantages and inconveniences so even if you favor simplicity and collaboration you won't find a perfect tool. So what should you choose? I don't have the answer to that, I think you should try different tools and find what is the most appropriate in your context. But you should definitely not take the first one that comes along just because others use it.",{"title":401,"searchDepth":796,"depth":796,"links":7894},[7895,7896,7901,7906],{"id":7273,"depth":796,"text":7276},{"id":7396,"depth":796,"text":7399,"children":7897},[7898,7899,7900],{"id":7416,"depth":840,"text":7419},{"id":7469,"depth":840,"text":7472},{"id":7493,"depth":840,"text":7496},{"id":7602,"depth":796,"text":7605,"children":7902},[7903,7904,7905],{"id":7622,"depth":840,"text":7625},{"id":7655,"depth":840,"text":7658},{"id":7679,"depth":840,"text":7682},{"id":7739,"depth":796,"text":7742,"children":7907},[7908,7909,7910],{"id":7745,"depth":840,"text":7748},{"id":7776,"depth":840,"text":7779},{"id":7884,"depth":840,"text":7887},"content:1.posts:43.http-clients.md","1.posts/43.http-clients.md",{"_path":124,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":123,"description":7914,"lead":7915,"date":7916,"image":7917,"badge":7919,"tags":7920,"body":7921,"_type":1435,"_id":8924,"_source":1437,"_file":8925,"_extension":1439},"When using some API Clients (like REST Client or the HTTP Client of JetBrains' IDEs), environment variables are stored in JSON files that can contain secrets. To share these files within a team, developers tend to send them by email or by messaging applications, which is not very convenient nor secure 🔐. I thought it would be a good idea to store these secrets directly in an Azure Key Vault and automate the generation of a JSON file containing the secrets using Azure CLI and Nushell.","Playing with Azure CLI and Nushell to generate a secret environment file to send HTTP requests","2022-08-01T00:00:00.000Z",{"src":7918},"/images/padlock_1.jpg",{"label":408},[206,213,243,225,260],{"type":412,"children":7922,"toc":8918},[7923,7959,7965,7997,8038,8088,8097,8102,8123,8129,8134,8142,8147,8153,8174,8187,8196,8207,8371,8376,8385,8390,8399,8412,8421,8437,8449,8458,8478,8487,8500,8509,8537,8542,8551,8564,8572,8577,8586,8598,8607,8619,8624,8886,8890,8895,8909,8914],{"type":415,"tag":416,"props":7924,"children":7925},{},[7926,7928,7933,7935,7941,7943,7949,7951,7958],{"type":420,"value":7927},"When using some API Clients (like ",{"type":415,"tag":423,"props":7929,"children":7931},{"href":1672,"rel":7930},[427],[7932],{"type":420,"value":7309},{"type":420,"value":7934}," or the ",{"type":415,"tag":423,"props":7936,"children":7938},{"href":7593,"rel":7937},[427],[7939],{"type":420,"value":7940},"HTTP Client of JetBrains' IDEs",{"type":420,"value":7942},"), environment variables are stored in JSON files that can contain secrets. To share these files within a team, developers tend to send them by email or by messaging applications, which is not very convenient nor secure 🔐. I thought it would be a good idea to store these secrets directly in an Azure Key Vault and automate the generation of a JSON file containing the secrets using ",{"type":415,"tag":423,"props":7944,"children":7947},{"href":7945,"rel":7946},"https://docs.microsoft.com/en-us/cli/azure/",[427],[7948],{"type":420,"value":225},{"type":420,"value":7950}," and ",{"type":415,"tag":423,"props":7952,"children":7955},{"href":7953,"rel":7954},"https://www.nushell.sh/",[427],[7956],{"type":420,"value":7957},"Nushell",{"type":420,"value":755},{"type":415,"tag":443,"props":7960,"children":7962},{"id":7961},"the-problem-keep-secrets-secure-while-making-http-requests",[7963],{"type":420,"value":7964},"The problem: keep secrets secure while making HTTP requests",{"type":415,"tag":416,"props":7966,"children":7967},{},[7968,7970,7975,7977,7982,7984,7989,7990,7995],{"type":420,"value":7969},"If you have read my article \"",{"type":415,"tag":423,"props":7971,"children":7973},{"href":7284,"rel":7972},[427],[7974],{"type":420,"value":9},{"type":420,"value":7976},"\", you know I am a big fan of using the vscode extension ",{"type":415,"tag":550,"props":7978,"children":7980},{"className":7979},[],[7981],{"type":420,"value":7309},{"type":420,"value":7983}," to make HTTP requests instead of using GUI tools like Postman. With REST Client, you write your HTTP requests using the standard RFC 2616 in ",{"type":415,"tag":550,"props":7985,"children":7987},{"className":7986},[],[7988],{"type":420,"value":7554},{"type":420,"value":7549},{"type":415,"tag":550,"props":7991,"children":7993},{"className":7992},[],[7994],{"type":420,"value":7547},{"type":420,"value":7996}," files and commit them to your git repository. You can define environments and their associated variables in the workspace settings file of vscode (you can also store them in the user settings file but I don't recommend it as they would apply to every vscode workspace). If you have some secrets among your environment variables (like an API key for instance), you obviously can't commit this settings file (you should never commit secrets to a git repository). So sharing among your developer team the environment variables needed to run the requests can be difficult.",{"type":415,"tag":773,"props":7998,"children":8000},{"className":1345,"code":7999,"language":212,"meta":401,"style":401},"### Get Luke Skywalker\nGET https://swapi.co/api/people/?search=Luke HTTP/1.1\n",[8001],{"type":415,"tag":550,"props":8002,"children":8003},{"__ignoreMap":401},[8004,8013],{"type":415,"tag":783,"props":8005,"children":8006},{"class":785,"line":786},[8007],{"type":415,"tag":783,"props":8008,"children":8010},{"style":8009},"--shiki-light:#90A4AE;--shiki-default:#546E7A;--shiki-dark:#676E95;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[8011],{"type":420,"value":8012},"### Get Luke Skywalker\n",{"type":415,"tag":783,"props":8014,"children":8015},{"class":785,"line":796},[8016,8020,8025,8029,8033],{"type":415,"tag":783,"props":8017,"children":8018},{"style":1356},[8019],{"type":420,"value":1359},{"type":415,"tag":783,"props":8021,"children":8022},{"style":1362},[8023],{"type":420,"value":8024}," https://swapi.co/api/people/?search=Luke ",{"type":415,"tag":783,"props":8026,"children":8027},{"style":902},[8028],{"type":420,"value":213},{"type":415,"tag":783,"props":8030,"children":8031},{"style":1362},[8032],{"type":420,"value":5318},{"type":415,"tag":783,"props":8034,"children":8035},{"style":902},[8036],{"type":420,"value":8037},"1.1\n",{"type":415,"tag":416,"props":8039,"children":8040},{},[8041,8043,8050,8052,8057,8059,8064,8065,8070,8072,8078,8080,8086],{"type":420,"value":8042},"I have been using recently the IDE ",{"type":415,"tag":423,"props":8044,"children":8047},{"href":8045,"rel":8046},"https://www.jetbrains.com/fr-fr/rider/",[427],[8048],{"type":420,"value":8049},"Rider",{"type":420,"value":8051},", which has (like all the other JetBrains' IDEs) an integrated ",{"type":415,"tag":423,"props":8053,"children":8055},{"href":7593,"rel":8054},[427],[8056],{"type":420,"value":7597},{"type":420,"value":8058},". It's very similar to REST Client (same syntax for the requests that are written in ",{"type":415,"tag":550,"props":8060,"children":8062},{"className":8061},[],[8063],{"type":420,"value":7554},{"type":420,"value":7549},{"type":415,"tag":550,"props":8066,"children":8068},{"className":8067},[],[8069],{"type":420,"value":7547},{"type":420,"value":8071}," files) with some extra features. With this HTTP Client, environment variables are stored in a public JSON environment file ",{"type":415,"tag":550,"props":8073,"children":8075},{"className":8074},[],[8076],{"type":420,"value":8077},"http-client.env.json",{"type":420,"value":8079}," that can be committed. However, secrets can be stored in a private JSON environment file ",{"type":415,"tag":550,"props":8081,"children":8083},{"className":8082},[],[8084],{"type":420,"value":8085},"http-client.private.env.json",{"type":420,"value":8087}," that will not be committed and whose values will override the values in the public file. It's well thought out, yet we still have the problem of sharing with our team the private file containing the secrets.",{"type":415,"tag":416,"props":8089,"children":8090},{},[8091],{"type":415,"tag":1322,"props":8092,"children":8096},{"alt":8093,"className":8094,"src":8095},"HTTP file, HTTP environment file, and HTTP private environment opnened file in Rider.",[1326,1327],"/posts/images/httpclientssecrets_rider_1.png",[],{"type":415,"tag":416,"props":8098,"children":8099},{},[8100],{"type":420,"value":8101},"When someone joins the team or new environment variables have been added, the developer in the team that has the latest version of the environment file usually share it by sending it by email or private message in Microsoft Teams, or Slack... to those who need it. This is not very convenient and this is not a good practice because you don't want secrets floating around. So what can we do about that?",{"type":415,"tag":588,"props":8103,"children":8104},{"icon":590},[8105],{"type":415,"tag":416,"props":8106,"children":8107},{},[8108,8110,8115,8116,8121],{"type":420,"value":8109},"To be honest, even if sharing secrets like that bothered me a bit, I only decided to think of a solution when a friend pointed out to me that the big challenge with tools like ",{"type":415,"tag":550,"props":8111,"children":8113},{"className":8112},[],[8114],{"type":420,"value":7309},{"type":420,"value":7549},{"type":415,"tag":550,"props":8117,"children":8119},{"className":8118},[],[8120],{"type":420,"value":7597},{"type":420,"value":8122}," from JetBrains was managing secrets.",{"type":415,"tag":443,"props":8124,"children":8126},{"id":8125},"the-solution-use-azure-key-vault-and-scripting",[8127],{"type":420,"value":8128},"The solution: use Azure Key Vault and scripting",{"type":415,"tag":416,"props":8130,"children":8131},{},[8132],{"type":420,"value":8133},"The solution is not complicated. I asked myself: where do I usually store secrets? The answer is \"a vault\". Whether it is Azure Key Vault, AWS Secret Manager, Google Cloud Secret Manager, or HashiCorp Vault it does not matter, secrets have to be stored somewhere safe, and it's precisely the purpose of a vault 🔒. I use Azure Key Vault when developing applications so that's what I am going to use as well for secrets needed for sending HTTP requests. If I want my team to be able to retrieve the secrets I just have to ensure everyone has access to the Key Vault.",{"type":415,"tag":588,"props":8135,"children":8136},{"icon":728},[8137],{"type":415,"tag":416,"props":8138,"children":8139},{},[8140],{"type":420,"value":8141},"By the way, I like to create an Azure AD Group for my team so that all the permissions given in Azure (for the project the team is working on) are assigned to this group instead of to each developer. When someone joins or leaves the team, we then can simply add him to the group or remove him from it.",{"type":415,"tag":416,"props":8143,"children":8144},{},[8145],{"type":420,"value":8146},"If the secrets are stored in an Azure Key Vault, we can let each developer retrieve the secrets from the vault and put them in their private environment file. But honestly, it's not convenient, especially with many secrets. A better solution is to make a script that automatically retrieves the secrets and generates the JSON file. That way the git repository will contain the HTTP requests, the public environment file, and a script to generate the private environment file so that any new joiner will have everything he needs to get started and run the requests.",{"type":415,"tag":443,"props":8148,"children":8150},{"id":8149},"lets-script-that-with-azure-cli-and-nushell",[8151],{"type":420,"value":8152},"Let's script that with Azure CLI and Nushell!",{"type":415,"tag":416,"props":8154,"children":8155},{},[8156,8158,8164,8166,8172],{"type":420,"value":8157},"I have chosen to script that using Azure CLI and Nushell because these are 2 tools I like and I am confident the resulting script will be concise and not too difficult to write. If you are not familiar with Azure CLI, you can check my article \"",{"type":415,"tag":423,"props":8159,"children":8162},{"href":8160,"rel":8161},"https://www.techwatching.dev/posts/welcome-azure-cli",[427],[8163],{"type":420,"value":15},{"type":420,"value":8165},"\". If you don't know Nushell you can check its ",{"type":415,"tag":423,"props":8167,"children":8169},{"href":7953,"rel":8168},[427],[8170],{"type":420,"value":8171},"website",{"type":420,"value":8173}," or just continue reading this article to see how nice this shell is.",{"type":415,"tag":416,"props":8175,"children":8176},{},[8177,8179,8185],{"type":420,"value":8178},"I have already created an Azure Key Vault named ",{"type":415,"tag":550,"props":8180,"children":8182},{"className":8181},[],[8183],{"type":420,"value":8184},"httpclient-vault",{"type":420,"value":8186}," and set 3 secrets in it.",{"type":415,"tag":416,"props":8188,"children":8189},{},[8190],{"type":415,"tag":1322,"props":8191,"children":8195},{"alt":8192,"className":8193,"src":8194},"The Secrets view of an Azure Key Vault resource in Azure Portal",[1326,1327],"/posts/images/httpclientssecrets_keyvault_1.png",[],{"type":415,"tag":416,"props":8197,"children":8198},{},[8199,8201,8206],{"type":420,"value":8200},"What I am trying to achieve is to produce the following file ",{"type":415,"tag":550,"props":8202,"children":8204},{"className":8203},[],[8205],{"type":420,"value":8085},{"type":420,"value":635},{"type":415,"tag":773,"props":8208,"children":8210},{"className":775,"code":8209,"language":777,"meta":401,"style":401},"{\n  \"development\":\n  {\n    \"ApiKey\": \"12345678\",\n    \"Username\": \"admin\",\n    \"UserPassword\": \"Password\"\n  }\n}\n",[8211],{"type":415,"tag":550,"props":8212,"children":8213},{"__ignoreMap":401},[8214,8221,8242,8250,8287,8324,8357,8364],{"type":415,"tag":783,"props":8215,"children":8216},{"class":785,"line":786},[8217],{"type":415,"tag":783,"props":8218,"children":8219},{"style":790},[8220],{"type":420,"value":793},{"type":415,"tag":783,"props":8222,"children":8223},{"class":785,"line":796},[8224,8228,8233,8237],{"type":415,"tag":783,"props":8225,"children":8226},{"style":790},[8227],{"type":420,"value":802},{"type":415,"tag":783,"props":8229,"children":8230},{"style":805},[8231],{"type":420,"value":8232},"development",{"type":415,"tag":783,"props":8234,"children":8235},{"style":790},[8236],{"type":420,"value":813},{"type":415,"tag":783,"props":8238,"children":8239},{"style":790},[8240],{"type":420,"value":8241},":\n",{"type":415,"tag":783,"props":8243,"children":8244},{"class":785,"line":840},[8245],{"type":415,"tag":783,"props":8246,"children":8247},{"style":790},[8248],{"type":420,"value":8249},"  {\n",{"type":415,"tag":783,"props":8251,"children":8252},{"class":785,"line":866},[8253,8257,8262,8266,8270,8274,8279,8283],{"type":415,"tag":783,"props":8254,"children":8255},{"style":790},[8256],{"type":420,"value":872},{"type":415,"tag":783,"props":8258,"children":8259},{"style":875},[8260],{"type":420,"value":8261},"ApiKey",{"type":415,"tag":783,"props":8263,"children":8264},{"style":790},[8265],{"type":420,"value":813},{"type":415,"tag":783,"props":8267,"children":8268},{"style":790},[8269],{"type":420,"value":635},{"type":415,"tag":783,"props":8271,"children":8272},{"style":790},[8273],{"type":420,"value":822},{"type":415,"tag":783,"props":8275,"children":8276},{"style":825},[8277],{"type":420,"value":8278},"12345678",{"type":415,"tag":783,"props":8280,"children":8281},{"style":790},[8282],{"type":420,"value":813},{"type":415,"tag":783,"props":8284,"children":8285},{"style":790},[8286],{"type":420,"value":837},{"type":415,"tag":783,"props":8288,"children":8289},{"class":785,"line":893},[8290,8294,8299,8303,8307,8311,8316,8320],{"type":415,"tag":783,"props":8291,"children":8292},{"style":790},[8293],{"type":420,"value":872},{"type":415,"tag":783,"props":8295,"children":8296},{"style":875},[8297],{"type":420,"value":8298},"Username",{"type":415,"tag":783,"props":8300,"children":8301},{"style":790},[8302],{"type":420,"value":813},{"type":415,"tag":783,"props":8304,"children":8305},{"style":790},[8306],{"type":420,"value":635},{"type":415,"tag":783,"props":8308,"children":8309},{"style":790},[8310],{"type":420,"value":822},{"type":415,"tag":783,"props":8312,"children":8313},{"style":825},[8314],{"type":420,"value":8315},"admin",{"type":415,"tag":783,"props":8317,"children":8318},{"style":790},[8319],{"type":420,"value":813},{"type":415,"tag":783,"props":8321,"children":8322},{"style":790},[8323],{"type":420,"value":837},{"type":415,"tag":783,"props":8325,"children":8326},{"class":785,"line":920},[8327,8331,8336,8340,8344,8348,8353],{"type":415,"tag":783,"props":8328,"children":8329},{"style":790},[8330],{"type":420,"value":872},{"type":415,"tag":783,"props":8332,"children":8333},{"style":875},[8334],{"type":420,"value":8335},"UserPassword",{"type":415,"tag":783,"props":8337,"children":8338},{"style":790},[8339],{"type":420,"value":813},{"type":415,"tag":783,"props":8341,"children":8342},{"style":790},[8343],{"type":420,"value":635},{"type":415,"tag":783,"props":8345,"children":8346},{"style":790},[8347],{"type":420,"value":822},{"type":415,"tag":783,"props":8349,"children":8350},{"style":825},[8351],{"type":420,"value":8352},"Password",{"type":415,"tag":783,"props":8354,"children":8355},{"style":790},[8356],{"type":420,"value":3275},{"type":415,"tag":783,"props":8358,"children":8359},{"class":785,"line":959},[8360],{"type":415,"tag":783,"props":8361,"children":8362},{"style":790},[8363],{"type":420,"value":1263},{"type":415,"tag":783,"props":8365,"children":8366},{"class":785,"line":997},[8367],{"type":415,"tag":783,"props":8368,"children":8369},{"style":790},[8370],{"type":420,"value":1272},{"type":415,"tag":416,"props":8372,"children":8373},{},[8374],{"type":420,"value":8375},"First, let's list the secrets in the Key Vault:",{"type":415,"tag":416,"props":8377,"children":8378},{},[8379],{"type":415,"tag":1322,"props":8380,"children":8384},{"alt":8381,"className":8382,"src":8383},"An Azure CLI command that lists Key Vault secrets in terminal.",[1326,1327],"/posts/images/httpclientssecrets_script_1.png",[],{"type":415,"tag":416,"props":8386,"children":8387},{},[8388],{"type":420,"value":8389},"The output of the command is not that easy to read because it's JSON and there are some properties we are not interested in. However, Azure CLI supports different output formats and can be used with JMESPath expressions to query the output of a command like this:",{"type":415,"tag":416,"props":8391,"children":8392},{},[8393],{"type":415,"tag":1322,"props":8394,"children":8398},{"alt":8395,"className":8396,"src":8397},"An Azure CLI command using JMESPath that lists Key Vault secrets in terminal.",[1326,1327],"/posts/images/httpclientssecrets_script_2.png",[],{"type":415,"tag":416,"props":8400,"children":8401},{},[8402,8404,8410],{"type":420,"value":8403},"It's nice but I won't need to use this because I can use Nushell (aka Nu) pipelines where everything is structured data that can be filtered, selected, and sorted. To bring the Azure CLI command output into a Nu pipeline, I can use the ",{"type":415,"tag":550,"props":8405,"children":8407},{"className":8406},[],[8408],{"type":420,"value":8409},"from json",{"type":420,"value":8411}," command.",{"type":415,"tag":416,"props":8413,"children":8414},{},[8415],{"type":415,"tag":1322,"props":8416,"children":8420},{"alt":8417,"className":8418,"src":8419},"The output of the \"az keyvault secret list --vault-name httpclient-vault | from json\" command in terminal.",[1326,1327],"/posts/images/httpclientssecrets_script_3.png",[],{"type":415,"tag":588,"props":8422,"children":8423},{"icon":728},[8424],{"type":415,"tag":416,"props":8425,"children":8426},{},[8427,8429,8435],{"type":420,"value":8428},"Nu has many ",{"type":415,"tag":550,"props":8430,"children":8432},{"className":8431},[],[8433],{"type":420,"value":8434},"from",{"type":420,"value":8436}," commands to convert data from different formats to structured data/table.",{"type":415,"tag":416,"props":8438,"children":8439},{},[8440,8442,8448],{"type":420,"value":8441},"You probably have noticed that the Azure CLI command we used to list the secrets does not provide their values. To retrieve the secret values we have to call another command for each secret using the id of the secret like this: ",{"type":415,"tag":550,"props":8443,"children":8445},{"className":8444},[],[8446],{"type":420,"value":8447},"az keyvault secret show --id $secretId",{"type":420,"value":755},{"type":415,"tag":416,"props":8450,"children":8451},{},[8452],{"type":415,"tag":1322,"props":8453,"children":8457},{"alt":8454,"className":8455,"src":8456},"An Azure CLI command that get a secret from Key Vault in terminal.",[1326,1327],"/posts/images/httpclientssecrets_script_4.png",[],{"type":415,"tag":416,"props":8459,"children":8460},{},[8461,8463,8468,8470,8476],{"type":420,"value":8462},"Again we can use the ",{"type":415,"tag":550,"props":8464,"children":8466},{"className":8465},[],[8467],{"type":420,"value":8409},{"type":420,"value":8469}," command, and the ",{"type":415,"tag":550,"props":8471,"children":8473},{"className":8472},[],[8474],{"type":420,"value":8475},"get",{"type":420,"value":8477}," command to only retrieve the value of a secret.",{"type":415,"tag":416,"props":8479,"children":8480},{},[8481],{"type":415,"tag":1322,"props":8482,"children":8486},{"alt":8483,"className":8484,"src":8485},"The output of the nushell script retrieving a secret value from keyvault.",[1326,1327],"/posts/images/httpclientssecrets_script_5.png",[],{"type":415,"tag":416,"props":8488,"children":8489},{},[8490,8492,8498],{"type":420,"value":8491},"Now that we know how to retrieve the value of a secret, we can insert a new column ",{"type":415,"tag":550,"props":8493,"children":8495},{"className":8494},[],[8496],{"type":420,"value":8497},"value",{"type":420,"value":8499}," into our table that will be filled with the value of each secret retrieved   using the previous command:",{"type":415,"tag":416,"props":8501,"children":8502},{},[8503],{"type":415,"tag":1322,"props":8504,"children":8508},{"alt":8505,"className":8506,"src":8507},"The output of the nushell script retrieving a list of secrets from keyvault.",[1326,1327],"/posts/images/httpclientssecrets_script_6.png",[],{"type":415,"tag":416,"props":8510,"children":8511},{},[8512,8513,8519,8521,8527,8529,8535],{"type":420,"value":1794},{"type":415,"tag":550,"props":8514,"children":8516},{"className":8515},[],[8517],{"type":420,"value":8518},"{|secret| (az keyvault secret show --id $secret.id | from json | get value)}",{"type":420,"value":8520}," part is a block that is executed for each row. The ",{"type":415,"tag":550,"props":8522,"children":8524},{"className":8523},[],[8525],{"type":420,"value":8526},"secret",{"type":420,"value":8528}," is the parameter of the block which represents the row, with the values of the columns for this row being available as properties of the variable ",{"type":415,"tag":550,"props":8530,"children":8532},{"className":8531},[],[8533],{"type":420,"value":8534},"$secret",{"type":420,"value":8536},". As the command was becoming long for a single line, we wrapped it in parentheses that allow us to write the command on multiple lines.",{"type":415,"tag":416,"props":8538,"children":8539},{},[8540],{"type":420,"value":8541},"As we are only interested in the columns \"name\" and \"value\", we only select them.",{"type":415,"tag":416,"props":8543,"children":8544},{},[8545],{"type":415,"tag":1322,"props":8546,"children":8550},{"alt":8547,"className":8548,"src":8549},"The output of the nushell script retrieving Azure Key Vault secrets (name and value).",[1326,1327],"/posts/images/httpclientssecrets_script_7.png",[],{"type":415,"tag":416,"props":8552,"children":8553},{},[8554,8556,8562],{"type":420,"value":8555},"We have to reorganize the data to make key-value pairs where keys come from the column name and values from the column value. We can use the ",{"type":415,"tag":550,"props":8557,"children":8559},{"className":8558},[],[8560],{"type":420,"value":8561},"transpose",{"type":420,"value":8563}," with the proper flags to do that:",{"type":415,"tag":416,"props":8565,"children":8566},{},[8567],{"type":415,"tag":1322,"props":8568,"children":8571},{"alt":8547,"className":8569,"src":8570},[1326,1327],"/posts/images/httpclientssecrets_script_8.png",[],{"type":415,"tag":416,"props":8573,"children":8574},{},[8575],{"type":420,"value":8576},"Then we wrap the key-value pairs in a JSON object corresponding to the development environment:",{"type":415,"tag":416,"props":8578,"children":8579},{},[8580],{"type":415,"tag":1322,"props":8581,"children":8585},{"alt":8582,"className":8583,"src":8584},"The output of the nushell script creating a JSON object from Azure Key Vault secrets.",[1326,1327],"/posts/images/httpclientssecrets_script_9.png",[],{"type":415,"tag":416,"props":8587,"children":8588},{},[8589,8591,8597],{"type":420,"value":8590},"We can check we get the JSON we want with the ",{"type":415,"tag":550,"props":8592,"children":8594},{"className":8593},[],[8595],{"type":420,"value":8596},"to json",{"type":420,"value":8411},{"type":415,"tag":416,"props":8599,"children":8600},{},[8601],{"type":415,"tag":1322,"props":8602,"children":8606},{"alt":8603,"className":8604,"src":8605},"The output of the nushell script creating a JSON string from Azure Key Vault secrets.",[1326,1327],"/posts/images/httpclientssecrets_script_10.png",[],{"type":415,"tag":416,"props":8608,"children":8609},{},[8610,8612,8617],{"type":420,"value":8611},"And finally, we can save the data in a ",{"type":415,"tag":550,"props":8613,"children":8615},{"className":8614},[],[8616],{"type":420,"value":8085},{"type":420,"value":8618}," file using the save command.",{"type":415,"tag":416,"props":8620,"children":8621},{},[8622],{"type":420,"value":8623},"Here is the final script 🔽:",{"type":415,"tag":773,"props":8625,"children":8628},{"className":8626,"code":8627,"language":243,"meta":401,"style":401},"language-nushell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","(\n  az keyvault secret list --vault-name httpclient-vault |\n  from json |\n  insert value {|secret| (az keyvault secret show --id $secret.id | from json | get value)} |\n  select name value |\n  transpose -rd |\n  { development: $in } |\n  save http-client.private.env.json\n)\n",[8629],{"type":415,"tag":550,"props":8630,"children":8631},{"__ignoreMap":401},[8632,8640,8684,8696,8794,8815,8836,8866,8879],{"type":415,"tag":783,"props":8633,"children":8634},{"class":785,"line":786},[8635],{"type":415,"tag":783,"props":8636,"children":8637},{"style":1362},[8638],{"type":420,"value":8639},"(\n",{"type":415,"tag":783,"props":8641,"children":8642},{"class":785,"line":796},[8643,8648,8653,8658,8663,8668,8674,8679],{"type":415,"tag":783,"props":8644,"children":8645},{"style":875},[8646],{"type":420,"value":8647},"  az",{"type":415,"tag":783,"props":8649,"children":8650},{"style":825},[8651],{"type":420,"value":8652}," keyvault",{"type":415,"tag":783,"props":8654,"children":8655},{"style":825},[8656],{"type":420,"value":8657}," secret",{"type":415,"tag":783,"props":8659,"children":8660},{"style":825},[8661],{"type":420,"value":8662}," list",{"type":415,"tag":783,"props":8664,"children":8665},{"style":1356},[8666],{"type":420,"value":8667}," --",{"type":415,"tag":783,"props":8669,"children":8671},{"style":8670},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[8672],{"type":420,"value":8673},"vault-name",{"type":415,"tag":783,"props":8675,"children":8676},{"style":825},[8677],{"type":420,"value":8678}," httpclient-vault",{"type":415,"tag":783,"props":8680,"children":8681},{"style":1356},[8682],{"type":420,"value":8683}," |\n",{"type":415,"tag":783,"props":8685,"children":8686},{"class":785,"line":840},[8687,8692],{"type":415,"tag":783,"props":8688,"children":8689},{"style":902},[8690],{"type":420,"value":8691},"  from json",{"type":415,"tag":783,"props":8693,"children":8694},{"style":1356},[8695],{"type":420,"value":8683},{"type":415,"tag":783,"props":8697,"children":8698},{"class":785,"line":866},[8699,8704,8709,8713,8718,8722,8727,8732,8736,8740,8745,8749,8754,8759,8763,8768,8773,8777,8781,8785,8790],{"type":415,"tag":783,"props":8700,"children":8701},{"style":902},[8702],{"type":420,"value":8703},"  insert",{"type":415,"tag":783,"props":8705,"children":8706},{"style":825},[8707],{"type":420,"value":8708}," value",{"type":415,"tag":783,"props":8710,"children":8711},{"style":790},[8712],{"type":420,"value":4345},{"type":415,"tag":783,"props":8714,"children":8715},{"style":1362},[8716],{"type":420,"value":8717},"|",{"type":415,"tag":783,"props":8719,"children":8720},{"style":8670},[8721],{"type":420,"value":8526},{"type":415,"tag":783,"props":8723,"children":8724},{"style":1362},[8725],{"type":420,"value":8726},"| (",{"type":415,"tag":783,"props":8728,"children":8729},{"style":875},[8730],{"type":420,"value":8731},"az",{"type":415,"tag":783,"props":8733,"children":8734},{"style":825},[8735],{"type":420,"value":8652},{"type":415,"tag":783,"props":8737,"children":8738},{"style":825},[8739],{"type":420,"value":8657},{"type":415,"tag":783,"props":8741,"children":8742},{"style":825},[8743],{"type":420,"value":8744}," show",{"type":415,"tag":783,"props":8746,"children":8747},{"style":1356},[8748],{"type":420,"value":8667},{"type":415,"tag":783,"props":8750,"children":8751},{"style":8670},[8752],{"type":420,"value":8753},"id",{"type":415,"tag":783,"props":8755,"children":8756},{"style":1362},[8757],{"type":420,"value":8758}," $secret.id ",{"type":415,"tag":783,"props":8760,"children":8761},{"style":1356},[8762],{"type":420,"value":8717},{"type":415,"tag":783,"props":8764,"children":8765},{"style":902},[8766],{"type":420,"value":8767}," from json",{"type":415,"tag":783,"props":8769,"children":8770},{"style":1356},[8771],{"type":420,"value":8772}," |",{"type":415,"tag":783,"props":8774,"children":8775},{"style":902},[8776],{"type":420,"value":5137},{"type":415,"tag":783,"props":8778,"children":8779},{"style":825},[8780],{"type":420,"value":8708},{"type":415,"tag":783,"props":8782,"children":8783},{"style":1362},[8784],{"type":420,"value":1678},{"type":415,"tag":783,"props":8786,"children":8787},{"style":790},[8788],{"type":420,"value":8789},"}",{"type":415,"tag":783,"props":8791,"children":8792},{"style":1356},[8793],{"type":420,"value":8683},{"type":415,"tag":783,"props":8795,"children":8796},{"class":785,"line":893},[8797,8802,8807,8811],{"type":415,"tag":783,"props":8798,"children":8799},{"style":902},[8800],{"type":420,"value":8801},"  select",{"type":415,"tag":783,"props":8803,"children":8804},{"style":825},[8805],{"type":420,"value":8806}," name",{"type":415,"tag":783,"props":8808,"children":8809},{"style":825},[8810],{"type":420,"value":8708},{"type":415,"tag":783,"props":8812,"children":8813},{"style":1356},[8814],{"type":420,"value":8683},{"type":415,"tag":783,"props":8816,"children":8817},{"class":785,"line":920},[8818,8823,8827,8832],{"type":415,"tag":783,"props":8819,"children":8820},{"style":902},[8821],{"type":420,"value":8822},"  transpose",{"type":415,"tag":783,"props":8824,"children":8825},{"style":1356},[8826],{"type":420,"value":1553},{"type":415,"tag":783,"props":8828,"children":8829},{"style":8670},[8830],{"type":420,"value":8831},"rd",{"type":415,"tag":783,"props":8833,"children":8834},{"style":1356},[8835],{"type":420,"value":8683},{"type":415,"tag":783,"props":8837,"children":8838},{"class":785,"line":959},[8839,8844,8849,8853,8858,8862],{"type":415,"tag":783,"props":8840,"children":8841},{"style":790},[8842],{"type":420,"value":8843},"  {",{"type":415,"tag":783,"props":8845,"children":8846},{"style":1362},[8847],{"type":420,"value":8848}," development",{"type":415,"tag":783,"props":8850,"children":8851},{"style":1356},[8852],{"type":420,"value":635},{"type":415,"tag":783,"props":8854,"children":8855},{"style":1362},[8856],{"type":420,"value":8857}," $in ",{"type":415,"tag":783,"props":8859,"children":8860},{"style":790},[8861],{"type":420,"value":8789},{"type":415,"tag":783,"props":8863,"children":8864},{"style":1356},[8865],{"type":420,"value":8683},{"type":415,"tag":783,"props":8867,"children":8868},{"class":785,"line":997},[8869,8874],{"type":415,"tag":783,"props":8870,"children":8871},{"style":902},[8872],{"type":420,"value":8873},"  save",{"type":415,"tag":783,"props":8875,"children":8876},{"style":825},[8877],{"type":420,"value":8878}," http-client.private.env.json\n",{"type":415,"tag":783,"props":8880,"children":8881},{"class":785,"line":1023},[8882],{"type":415,"tag":783,"props":8883,"children":8884},{"style":1362},[8885],{"type":420,"value":1963},{"type":415,"tag":443,"props":8887,"children":8888},{"id":7739},[8889],{"type":420,"value":7742},{"type":415,"tag":416,"props":8891,"children":8892},{},[8893],{"type":420,"value":8894},"In this example, I scripted with Nu the retrieval of secrets from an Azure Key Vault, but it should not be too difficult to apply the same concepts to fetch secrets from another vault.",{"type":415,"tag":416,"props":8896,"children":8897},{},[8898,8900,8907],{"type":420,"value":8899},"I had fun playing with Azure CLI and Nushell to write this script but there are many other ways to do the same thing. There are also probably other tools or services (I have just came across ",{"type":415,"tag":423,"props":8901,"children":8904},{"href":8902,"rel":8903},"https://www.doppler.com/",[427],[8905],{"type":420,"value":8906},"Doppler",{"type":420,"value":8908}," which seems nice) that can help you manage secrets securely.",{"type":415,"tag":416,"props":8910,"children":8911},{},[8912],{"type":420,"value":8913},"I am not a Nushell expert but I find it awesome, and am considering making it my main shell. You should give it a try too. A big thank you to the people in the Nushell Discord that help me with my script ❤️.",{"type":415,"tag":1420,"props":8915,"children":8916},{},[8917],{"type":420,"value":1424},{"title":401,"searchDepth":796,"depth":796,"links":8919},[8920,8921,8922,8923],{"id":7961,"depth":796,"text":7964},{"id":8125,"depth":796,"text":8128},{"id":8149,"depth":796,"text":8152},{"id":7739,"depth":796,"text":7742},"content:1.posts:39.http-clients-secrets.md","1.posts/39.http-clients-secrets.md",{"_path":55,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":54,"description":8927,"lead":8928,"date":8929,"image":8930,"badge":8932,"tags":8933,"body":8934,"_type":1435,"_id":10218,"_source":1437,"_file":10219,"_extension":1439},"In this article, I want to talk about a few things in .NET such as HTTP requests with an Http Client, HTTP message handlers, records... For the theoretical aspect of these topics, I think the official documentation on docs.microsoft.com and many blog articles already explain them very well, better than I could ever do. But what I am interested in here is to talk about these topics through a case study.","A story about records, HTTP message handlers, HTTP client extensions...","2021-04-24T00:00:00.000Z",{"src":8931},"/images/western_1.jpg",{"label":1447},[236,213,286,210,288],{"type":412,"children":8935,"toc":10204},[8936,8940,8946,8977,9074,9080,9093,9107,9187,9207,9626,9652,9661,9674,9683,9731,9740,9752,9777,9786,9791,9797,9825,9834,9846,9851,9859,9892,9900,9933,9941,9953,9958,9969,9975,10004,10013,10025,10039,10044,10064,10073,10084,10098,10119,10128,10148,10157,10169,10178,10189,10195,10200],{"type":415,"tag":416,"props":8937,"children":8938},{},[8939],{"type":420,"value":8927},{"type":415,"tag":443,"props":8941,"children":8943},{"id":8942},"introducing-the-case-study",[8944],{"type":420,"value":8945},"Introducing the case study",{"type":415,"tag":416,"props":8947,"children":8948},{},[8949,8951,8962,8964,8975],{"type":420,"value":8950},"I wrote a very basic ASP.NET Core API ",{"type":415,"tag":423,"props":8952,"children":8955},{"href":8953,"rel":8954},"https://github.com/TechWatching/MyLotrApi/tree/a70b6f91fcbcc30a3c3a3616799e3e85817b7906",[427],[8956],{"type":415,"tag":550,"props":8957,"children":8959},{"className":8958},[],[8960],{"type":420,"value":8961},"MyLotrApi",{"type":420,"value":8963}," that exposes some data from the \"Lord of the Rings\" universe. This API calls another existing API ",{"type":415,"tag":423,"props":8965,"children":8968},{"href":8966,"rel":8967},"https://the-one-api.dev/",[427],[8969],{"type":415,"tag":550,"props":8970,"children":8972},{"className":8971},[],[8973],{"type":420,"value":8974},"The One API",{"type":420,"value":8976}," to retrieve this data. The code is quite simple:",{"type":415,"tag":493,"props":8978,"children":8979},{},[8980,9018,9061],{"type":415,"tag":497,"props":8981,"children":8982},{},[8983,8985,8991,8993],{"type":420,"value":8984},"a controller ",{"type":415,"tag":550,"props":8986,"children":8988},{"className":8987},[],[8989],{"type":420,"value":8990},"LotrController",{"type":420,"value":8992}," with 2 routes\n",{"type":415,"tag":493,"props":8994,"children":8995},{},[8996,9007],{"type":415,"tag":497,"props":8997,"children":8998},{},[8999,9005],{"type":415,"tag":550,"props":9000,"children":9002},{"className":9001},[],[9003],{"type":420,"value":9004},"GET /popularmovies",{"type":420,"value":9006}," that returns the movies in the \"Lord of the Rings\" universe with a rotten tomatoes score above 80",{"type":415,"tag":497,"props":9008,"children":9009},{},[9010,9016],{"type":415,"tag":550,"props":9011,"children":9013},{"className":9012},[],[9014],{"type":420,"value":9015},"GET /famousorcs",{"type":420,"value":9017}," that returns orc characters from the \"Lord of the Rings\" universe",{"type":415,"tag":497,"props":9019,"children":9020},{},[9021,9023,9029,9031],{"type":420,"value":9022},"a service ",{"type":415,"tag":550,"props":9024,"children":9026},{"className":9025},[],[9027],{"type":420,"value":9028},"TheOneApiService",{"type":420,"value":9030}," that\n",{"type":415,"tag":493,"props":9032,"children":9033},{},[9034,9044,9056],{"type":415,"tag":497,"props":9035,"children":9036},{},[9037,9039],{"type":420,"value":9038},"makes the HTTP calls to the API ",{"type":415,"tag":550,"props":9040,"children":9042},{"className":9041},[],[9043],{"type":420,"value":8974},{"type":415,"tag":497,"props":9045,"children":9046},{},[9047,9049,9054],{"type":420,"value":9048},"has one method for each endpoint of the API ",{"type":415,"tag":550,"props":9050,"children":9052},{"className":9051},[],[9053],{"type":420,"value":8974},{"type":420,"value":9055}," that is used",{"type":415,"tag":497,"props":9057,"children":9058},{},[9059],{"type":420,"value":9060},"uses NewtonSoft for deserializing responses",{"type":415,"tag":497,"props":9062,"children":9063},{},[9064,9066,9072],{"type":420,"value":9065},"a ",{"type":415,"tag":550,"props":9067,"children":9069},{"className":9068},[],[9070],{"type":420,"value":9071},"Models",{"type":420,"value":9073}," class that contains the different data models used by the API",{"type":415,"tag":443,"props":9075,"children":9077},{"id":9076},"about-using-records",[9078],{"type":420,"value":9079},"About using records",{"type":415,"tag":416,"props":9081,"children":9082},{},[9083,9085,9091],{"type":420,"value":9084},"Instead of using basic C# classes for the models in this API, I used ",{"type":415,"tag":423,"props":9086,"children":9089},{"href":9087,"rel":9088},"https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#record-types",[427],[9090],{"type":420,"value":286},{"type":420,"value":9092},". Many people are talking about records nowadays because it is one of the latest trendy features of C# 9. Unfortunately, that makes other people think records are just another syntactic sugar added to C# that they do not need to use in their code. Yet, there are a lot of benefits in using records.",{"type":415,"tag":416,"props":9094,"children":9095},{},[9096,9098,9105],{"type":420,"value":9097},"In my sample, I declared my models with the ",{"type":415,"tag":423,"props":9099,"children":9102},{"href":9100,"rel":9101},"https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#positional-syntax-for-property-definition",[427],[9103],{"type":420,"value":9104},"positional syntax for property definition",{"type":420,"value":9106}," which is very concise. Conciseness might not be something important for you but for me, it means fewer lines of code to write and to maintain and more clearness.",{"type":415,"tag":773,"props":9108,"children":9110},{"className":1805,"code":9109,"language":326,"meta":401,"style":401},"public record Movie(string Name, int RuntimeInMinutes, int BudgetInMillions, float RottenTomatesScore);\n",[9111],{"type":415,"tag":550,"props":9112,"children":9113},{"__ignoreMap":401},[9114],{"type":415,"tag":783,"props":9115,"children":9116},{"class":785,"line":786},[9117,9121,9125,9130,9134,9138,9143,9147,9151,9156,9160,9164,9169,9173,9178,9183],{"type":415,"tag":783,"props":9118,"children":9119},{"style":805},[9120],{"type":420,"value":1871},{"type":415,"tag":783,"props":9122,"children":9123},{"style":875},[9124],{"type":420,"value":6110},{"type":415,"tag":783,"props":9126,"children":9127},{"style":875},[9128],{"type":420,"value":9129}," Movie",{"type":415,"tag":783,"props":9131,"children":9132},{"style":790},[9133],{"type":420,"value":1845},{"type":415,"tag":783,"props":9135,"children":9136},{"style":790},[9137],{"type":420,"value":4766},{"type":415,"tag":783,"props":9139,"children":9140},{"style":875},[9141],{"type":420,"value":9142}," Name",{"type":415,"tag":783,"props":9144,"children":9145},{"style":790},[9146],{"type":420,"value":2501},{"type":415,"tag":783,"props":9148,"children":9149},{"style":790},[9150],{"type":420,"value":5078},{"type":415,"tag":783,"props":9152,"children":9153},{"style":875},[9154],{"type":420,"value":9155}," RuntimeInMinutes",{"type":415,"tag":783,"props":9157,"children":9158},{"style":790},[9159],{"type":420,"value":2501},{"type":415,"tag":783,"props":9161,"children":9162},{"style":790},[9163],{"type":420,"value":5078},{"type":415,"tag":783,"props":9165,"children":9166},{"style":875},[9167],{"type":420,"value":9168}," BudgetInMillions",{"type":415,"tag":783,"props":9170,"children":9171},{"style":790},[9172],{"type":420,"value":2501},{"type":415,"tag":783,"props":9174,"children":9175},{"style":790},[9176],{"type":420,"value":9177}," float",{"type":415,"tag":783,"props":9179,"children":9180},{"style":875},[9181],{"type":420,"value":9182}," RottenTomatesScore",{"type":415,"tag":783,"props":9184,"children":9185},{"style":790},[9186],{"type":420,"value":2552},{"type":415,"tag":416,"props":9188,"children":9189},{},[9190,9192,9198,9200,9205],{"type":420,"value":9191},"You can notice that I put my records in one place (the ",{"type":415,"tag":550,"props":9193,"children":9195},{"className":9194},[],[9196],{"type":420,"value":9197},"Models.cs",{"type":420,"value":9199}," file), partly because for this example it was faster and simpler than creating a file for each model. But when you think carefully about it, it is not such a bad thing: in one look you have a pretty good view of the different models the code is using without having to browse different files. Of course, in a real project with a lot of code, I would have grouped my models by business concern and separated these different concerns in different files with more expressive names than ",{"type":415,"tag":550,"props":9201,"children":9203},{"className":9202},[],[9204],{"type":420,"value":9071},{"type":420,"value":9206},". But I think the convention of using one file by class is not completely relevant in the case of records.",{"type":415,"tag":773,"props":9208,"children":9210},{"className":1805,"code":9209,"language":326,"meta":401,"style":401},"using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MyLotrApi\n{\n    public record Movie(string Name, int RuntimeInMinutes, int BudgetInMillions, float RottenTomatesScore);\n    \n    public record MovieResponse(IList\u003CMovie> Docs, int Total);\n\n    public record Character(string Name, string Realm);\n\n    public record CharacterResponse(IList\u003CCharacter> Docs, int Total);\n}\n",[9211],{"type":415,"tag":550,"props":9212,"children":9213},{"__ignoreMap":401},[9214,9230,9263,9287,9311,9344,9351,9363,9370,9437,9444,9503,9510,9555,9562,9619],{"type":415,"tag":783,"props":9215,"children":9216},{"class":785,"line":786},[9217,9221,9226],{"type":415,"tag":783,"props":9218,"children":9219},{"style":902},[9220],{"type":420,"value":3596},{"type":415,"tag":783,"props":9222,"children":9223},{"style":1362},[9224],{"type":420,"value":9225}," System",{"type":415,"tag":783,"props":9227,"children":9228},{"style":790},[9229],{"type":420,"value":1926},{"type":415,"tag":783,"props":9231,"children":9232},{"class":785,"line":796},[9233,9237,9241,9245,9250,9254,9259],{"type":415,"tag":783,"props":9234,"children":9235},{"style":902},[9236],{"type":420,"value":3596},{"type":415,"tag":783,"props":9238,"children":9239},{"style":1362},[9240],{"type":420,"value":9225},{"type":415,"tag":783,"props":9242,"children":9243},{"style":790},[9244],{"type":420,"value":755},{"type":415,"tag":783,"props":9246,"children":9247},{"style":1362},[9248],{"type":420,"value":9249},"Collections",{"type":415,"tag":783,"props":9251,"children":9252},{"style":790},[9253],{"type":420,"value":755},{"type":415,"tag":783,"props":9255,"children":9256},{"style":1362},[9257],{"type":420,"value":9258},"Generic",{"type":415,"tag":783,"props":9260,"children":9261},{"style":790},[9262],{"type":420,"value":1926},{"type":415,"tag":783,"props":9264,"children":9265},{"class":785,"line":840},[9266,9270,9274,9278,9283],{"type":415,"tag":783,"props":9267,"children":9268},{"style":902},[9269],{"type":420,"value":3596},{"type":415,"tag":783,"props":9271,"children":9272},{"style":1362},[9273],{"type":420,"value":9225},{"type":415,"tag":783,"props":9275,"children":9276},{"style":790},[9277],{"type":420,"value":755},{"type":415,"tag":783,"props":9279,"children":9280},{"style":1362},[9281],{"type":420,"value":9282},"Linq",{"type":415,"tag":783,"props":9284,"children":9285},{"style":790},[9286],{"type":420,"value":1926},{"type":415,"tag":783,"props":9288,"children":9289},{"class":785,"line":866},[9290,9294,9298,9302,9307],{"type":415,"tag":783,"props":9291,"children":9292},{"style":902},[9293],{"type":420,"value":3596},{"type":415,"tag":783,"props":9295,"children":9296},{"style":1362},[9297],{"type":420,"value":9225},{"type":415,"tag":783,"props":9299,"children":9300},{"style":790},[9301],{"type":420,"value":755},{"type":415,"tag":783,"props":9303,"children":9304},{"style":1362},[9305],{"type":420,"value":9306},"Text",{"type":415,"tag":783,"props":9308,"children":9309},{"style":790},[9310],{"type":420,"value":1926},{"type":415,"tag":783,"props":9312,"children":9313},{"class":785,"line":893},[9314,9318,9322,9326,9331,9335,9340],{"type":415,"tag":783,"props":9315,"children":9316},{"style":902},[9317],{"type":420,"value":3596},{"type":415,"tag":783,"props":9319,"children":9320},{"style":1362},[9321],{"type":420,"value":9225},{"type":415,"tag":783,"props":9323,"children":9324},{"style":790},[9325],{"type":420,"value":755},{"type":415,"tag":783,"props":9327,"children":9328},{"style":1362},[9329],{"type":420,"value":9330},"Threading",{"type":415,"tag":783,"props":9332,"children":9333},{"style":790},[9334],{"type":420,"value":755},{"type":415,"tag":783,"props":9336,"children":9337},{"style":1362},[9338],{"type":420,"value":9339},"Tasks",{"type":415,"tag":783,"props":9341,"children":9342},{"style":790},[9343],{"type":420,"value":1926},{"type":415,"tag":783,"props":9345,"children":9346},{"class":785,"line":920},[9347],{"type":415,"tag":783,"props":9348,"children":9349},{"emptyLinePlaceholder":1624},[9350],{"type":420,"value":1627},{"type":415,"tag":783,"props":9352,"children":9353},{"class":785,"line":959},[9354,9358],{"type":415,"tag":783,"props":9355,"children":9356},{"style":875},[9357],{"type":420,"value":5023},{"type":415,"tag":783,"props":9359,"children":9360},{"style":1362},[9361],{"type":420,"value":9362}," MyLotrApi\n",{"type":415,"tag":783,"props":9364,"children":9365},{"class":785,"line":997},[9366],{"type":415,"tag":783,"props":9367,"children":9368},{"style":790},[9369],{"type":420,"value":793},{"type":415,"tag":783,"props":9371,"children":9372},{"class":785,"line":1023},[9373,9377,9381,9385,9389,9393,9397,9401,9405,9409,9413,9417,9421,9425,9429,9433],{"type":415,"tag":783,"props":9374,"children":9375},{"style":805},[9376],{"type":420,"value":1941},{"type":415,"tag":783,"props":9378,"children":9379},{"style":875},[9380],{"type":420,"value":6110},{"type":415,"tag":783,"props":9382,"children":9383},{"style":875},[9384],{"type":420,"value":9129},{"type":415,"tag":783,"props":9386,"children":9387},{"style":790},[9388],{"type":420,"value":1845},{"type":415,"tag":783,"props":9390,"children":9391},{"style":790},[9392],{"type":420,"value":4766},{"type":415,"tag":783,"props":9394,"children":9395},{"style":875},[9396],{"type":420,"value":9142},{"type":415,"tag":783,"props":9398,"children":9399},{"style":790},[9400],{"type":420,"value":2501},{"type":415,"tag":783,"props":9402,"children":9403},{"style":790},[9404],{"type":420,"value":5078},{"type":415,"tag":783,"props":9406,"children":9407},{"style":875},[9408],{"type":420,"value":9155},{"type":415,"tag":783,"props":9410,"children":9411},{"style":790},[9412],{"type":420,"value":2501},{"type":415,"tag":783,"props":9414,"children":9415},{"style":790},[9416],{"type":420,"value":5078},{"type":415,"tag":783,"props":9418,"children":9419},{"style":875},[9420],{"type":420,"value":9168},{"type":415,"tag":783,"props":9422,"children":9423},{"style":790},[9424],{"type":420,"value":2501},{"type":415,"tag":783,"props":9426,"children":9427},{"style":790},[9428],{"type":420,"value":9177},{"type":415,"tag":783,"props":9430,"children":9431},{"style":875},[9432],{"type":420,"value":9182},{"type":415,"tag":783,"props":9434,"children":9435},{"style":790},[9436],{"type":420,"value":2552},{"type":415,"tag":783,"props":9438,"children":9439},{"class":785,"line":1061},[9440],{"type":415,"tag":783,"props":9441,"children":9442},{"style":1362},[9443],{"type":420,"value":5167},{"type":415,"tag":783,"props":9445,"children":9446},{"class":785,"line":1099},[9447,9451,9455,9460,9464,9468,9472,9477,9481,9486,9490,9494,9499],{"type":415,"tag":783,"props":9448,"children":9449},{"style":805},[9450],{"type":420,"value":1941},{"type":415,"tag":783,"props":9452,"children":9453},{"style":875},[9454],{"type":420,"value":6110},{"type":415,"tag":783,"props":9456,"children":9457},{"style":875},[9458],{"type":420,"value":9459}," MovieResponse",{"type":415,"tag":783,"props":9461,"children":9462},{"style":790},[9463],{"type":420,"value":1845},{"type":415,"tag":783,"props":9465,"children":9466},{"style":875},[9467],{"type":420,"value":6124},{"type":415,"tag":783,"props":9469,"children":9470},{"style":790},[9471],{"type":420,"value":2112},{"type":415,"tag":783,"props":9473,"children":9474},{"style":875},[9475],{"type":420,"value":9476},"Movie",{"type":415,"tag":783,"props":9478,"children":9479},{"style":790},[9480],{"type":420,"value":2276},{"type":415,"tag":783,"props":9482,"children":9483},{"style":875},[9484],{"type":420,"value":9485}," Docs",{"type":415,"tag":783,"props":9487,"children":9488},{"style":790},[9489],{"type":420,"value":2501},{"type":415,"tag":783,"props":9491,"children":9492},{"style":790},[9493],{"type":420,"value":5078},{"type":415,"tag":783,"props":9495,"children":9496},{"style":875},[9497],{"type":420,"value":9498}," Total",{"type":415,"tag":783,"props":9500,"children":9501},{"style":790},[9502],{"type":420,"value":2552},{"type":415,"tag":783,"props":9504,"children":9505},{"class":785,"line":1137},[9506],{"type":415,"tag":783,"props":9507,"children":9508},{"emptyLinePlaceholder":1624},[9509],{"type":420,"value":1627},{"type":415,"tag":783,"props":9511,"children":9512},{"class":785,"line":1175},[9513,9517,9521,9526,9530,9534,9538,9542,9546,9551],{"type":415,"tag":783,"props":9514,"children":9515},{"style":805},[9516],{"type":420,"value":1941},{"type":415,"tag":783,"props":9518,"children":9519},{"style":875},[9520],{"type":420,"value":6110},{"type":415,"tag":783,"props":9522,"children":9523},{"style":875},[9524],{"type":420,"value":9525}," Character",{"type":415,"tag":783,"props":9527,"children":9528},{"style":790},[9529],{"type":420,"value":1845},{"type":415,"tag":783,"props":9531,"children":9532},{"style":790},[9533],{"type":420,"value":4766},{"type":415,"tag":783,"props":9535,"children":9536},{"style":875},[9537],{"type":420,"value":9142},{"type":415,"tag":783,"props":9539,"children":9540},{"style":790},[9541],{"type":420,"value":2501},{"type":415,"tag":783,"props":9543,"children":9544},{"style":790},[9545],{"type":420,"value":3798},{"type":415,"tag":783,"props":9547,"children":9548},{"style":875},[9549],{"type":420,"value":9550}," Realm",{"type":415,"tag":783,"props":9552,"children":9553},{"style":790},[9554],{"type":420,"value":2552},{"type":415,"tag":783,"props":9556,"children":9557},{"class":785,"line":1213},[9558],{"type":415,"tag":783,"props":9559,"children":9560},{"emptyLinePlaceholder":1624},[9561],{"type":420,"value":1627},{"type":415,"tag":783,"props":9563,"children":9564},{"class":785,"line":1239},[9565,9569,9573,9578,9582,9586,9590,9595,9599,9603,9607,9611,9615],{"type":415,"tag":783,"props":9566,"children":9567},{"style":805},[9568],{"type":420,"value":1941},{"type":415,"tag":783,"props":9570,"children":9571},{"style":875},[9572],{"type":420,"value":6110},{"type":415,"tag":783,"props":9574,"children":9575},{"style":875},[9576],{"type":420,"value":9577}," CharacterResponse",{"type":415,"tag":783,"props":9579,"children":9580},{"style":790},[9581],{"type":420,"value":1845},{"type":415,"tag":783,"props":9583,"children":9584},{"style":875},[9585],{"type":420,"value":6124},{"type":415,"tag":783,"props":9587,"children":9588},{"style":790},[9589],{"type":420,"value":2112},{"type":415,"tag":783,"props":9591,"children":9592},{"style":875},[9593],{"type":420,"value":9594},"Character",{"type":415,"tag":783,"props":9596,"children":9597},{"style":790},[9598],{"type":420,"value":2276},{"type":415,"tag":783,"props":9600,"children":9601},{"style":875},[9602],{"type":420,"value":9485},{"type":415,"tag":783,"props":9604,"children":9605},{"style":790},[9606],{"type":420,"value":2501},{"type":415,"tag":783,"props":9608,"children":9609},{"style":790},[9610],{"type":420,"value":5078},{"type":415,"tag":783,"props":9612,"children":9613},{"style":875},[9614],{"type":420,"value":9498},{"type":415,"tag":783,"props":9616,"children":9617},{"style":790},[9618],{"type":420,"value":2552},{"type":415,"tag":783,"props":9620,"children":9621},{"class":785,"line":1248},[9622],{"type":415,"tag":783,"props":9623,"children":9624},{"style":790},[9625],{"type":420,"value":1272},{"type":415,"tag":416,"props":9627,"children":9628},{},[9629,9631,9636,9638,9643,9645,9650],{"type":420,"value":9630},"Another interesting feature of records is that it is easy to declare immutable data models with them. That is exactly what I did here by declaring my data models as immutable records for the objects returned by ",{"type":415,"tag":550,"props":9632,"children":9634},{"className":9633},[],[9635],{"type":420,"value":8974},{"type":420,"value":9637},". Indeed it makes perfect sense in this context where my API queries ",{"type":415,"tag":550,"props":9639,"children":9641},{"className":9640},[],[9642],{"type":420,"value":8974},{"type":420,"value":9644},", eventually filters the objects returned depending on what it is looking to expose and returns them without modifying their content. In no way the code should modify the data retrieved from ",{"type":415,"tag":550,"props":9646,"children":9648},{"className":9647},[],[9649],{"type":420,"value":8974},{"type":420,"value":9651}," and immutable records can easily guarantee that: if the code tries to change something it won't compile.",{"type":415,"tag":416,"props":9653,"children":9654},{},[9655],{"type":415,"tag":1322,"props":9656,"children":9660},{"alt":9657,"className":9658,"src":9659},"Code showing immutability of records.",[1326,1327],"/posts/images/onceuponatime_records_1.png",[],{"type":415,"tag":416,"props":9662,"children":9663},{},[9664,9666,9672],{"type":420,"value":9665},"There is one more reason why using records in this API is a good idea: value equality. When writing unit tests I often have the case where I want to assert that an object (or a collection of objects) returned by the method under test is the same that the object(s) I was expected. However, doing an ",{"type":415,"tag":550,"props":9667,"children":9669},{"className":9668},[],[9670],{"type":420,"value":9671},"Assert.AreEqual",{"type":420,"value":9673}," on two variables of a reference type does not work because by default they are only equal if they refer to the same object.",{"type":415,"tag":416,"props":9675,"children":9676},{},[9677],{"type":415,"tag":1322,"props":9678,"children":9682},{"alt":9679,"className":9680,"src":9681},"Code showing classes not having value equality",[1326,1327],"onceuponatime_records_3.png",[],{"type":415,"tag":416,"props":9684,"children":9685},{},[9686,9688,9699,9701,9707,9709,9715,9716,9722,9724,9729],{"type":420,"value":9687},"As a workaround, you can compare the properties of your two variables (if they are value type properties) or you can use the library ",{"type":415,"tag":423,"props":9689,"children":9692},{"href":9690,"rel":9691},"https://github.com/fluentassertions/fluentassertions",[427],[9693],{"type":415,"tag":550,"props":9694,"children":9696},{"className":9695},[],[9697],{"type":420,"value":9698},"FluentAssertions",{"type":420,"value":9700}," for your asserts. But the real solution to make your asserts work is to implement ",{"type":415,"tag":550,"props":9702,"children":9704},{"className":9703},[],[9705],{"type":420,"value":9706},"IEquatable\u003CT>",{"type":420,"value":9708},", and overrides ",{"type":415,"tag":550,"props":9710,"children":9712},{"className":9711},[],[9713],{"type":420,"value":9714},"Object.Equals(Object)",{"type":420,"value":7950},{"type":415,"tag":550,"props":9717,"children":9719},{"className":9718},[],[9720],{"type":420,"value":9721},"Object.GetHashCode()",{"type":420,"value":9723}," on the classes you want to compare. It's the solution I often use, it's a bit cumbersome because it makes you write a lot of boilerplate for your data models but it helps you a lot with your unit tests assertions. The good news, if you are using records is that all this code is already done for you, you have value equality by default so an ",{"type":415,"tag":550,"props":9725,"children":9727},{"className":9726},[],[9728],{"type":420,"value":9671},{"type":420,"value":9730}," between two variables of a record type will work if all the property and field values match.",{"type":415,"tag":416,"props":9732,"children":9733},{},[9734],{"type":415,"tag":1322,"props":9735,"children":9739},{"alt":9736,"className":9737,"src":9738},"Code showing value equality of records",[1326,1327],"/posts/images/onceuponatime_records_2.png",[],{"type":415,"tag":443,"props":9741,"children":9743},{"id":9742},"what-can-be-improved-in-theoneapiservice",[9744,9746,9751],{"type":420,"value":9745},"What can be improved in ",{"type":415,"tag":550,"props":9747,"children":9749},{"className":9748},[],[9750],{"type":420,"value":9028},{"type":420,"value":5096},{"type":415,"tag":416,"props":9753,"children":9754},{},[9755,9757,9767,9769,9775],{"type":420,"value":9756},"Enough talking about records, let's have a closer look at ",{"type":415,"tag":423,"props":9758,"children":9761},{"href":9759,"rel":9760},"https://github.com/TechWatching/MyLotrApi/blob/a70b6f91fcbcc30a3c3a3616799e3e85817b7906/src/MyLotrApi/TheOneApiService.cs",[427],[9762],{"type":415,"tag":550,"props":9763,"children":9765},{"className":9764},[],[9766],{"type":420,"value":9028},{"type":420,"value":9768}," and see what we can improve. At first sight, the code looks fine, just 2 methods that use an ",{"type":415,"tag":550,"props":9770,"children":9772},{"className":9771},[],[9773],{"type":420,"value":9774},"HttpClient",{"type":420,"value":9776}," to make a get request, ensure that the response is ok (throw an exception otherwise), retrieve the response content as a string, and deserialize it into their corresponding types with NewtonSoft. Basic code that we can often see.",{"type":415,"tag":416,"props":9778,"children":9779},{},[9780],{"type":415,"tag":1322,"props":9781,"children":9785},{"alt":9782,"className":9783,"src":9784},"The OneApiService first code version.",[1326,1327],"/posts/images/onceuponatime_theoneapiservice_1.png",[],{"type":415,"tag":416,"props":9787,"children":9788},{},[9789],{"type":420,"value":9790},"Yet, it seems that there is a bit of code duplication between the methods, not a problem as we only have two methods but it can quickly become one if we add other methods. So what can we do about that?",{"type":415,"tag":616,"props":9792,"children":9794},{"id":9793},"adding-a-private-method-that-factorizes-the-code",[9795],{"type":420,"value":9796},"Adding a private method that factorizes the code",{"type":415,"tag":416,"props":9798,"children":9799},{},[9800,9802,9808,9810,9816,9817,9823],{"type":420,"value":9801},"This solution is something I often see: people wrap the common logic between their methods in a private method that gets called by the others. So we end up having a generic ",{"type":415,"tag":550,"props":9803,"children":9805},{"className":9804},[],[9806],{"type":420,"value":9807},"Send",{"type":420,"value":9809}," that does all the job (request, response handling, deserialization ...), and our 2 methods ",{"type":415,"tag":550,"props":9811,"children":9813},{"className":9812},[],[9814],{"type":420,"value":9815},"GetMovies",{"type":420,"value":7950},{"type":415,"tag":550,"props":9818,"children":9820},{"className":9819},[],[9821],{"type":420,"value":9822},"GetCharacters",{"type":420,"value":9824}," that have become quite trivial.",{"type":415,"tag":416,"props":9826,"children":9827},{},[9828],{"type":415,"tag":1322,"props":9829,"children":9833},{"alt":9830,"className":9831,"src":9832},"The OneApiService factorizing code in a private method.",[1326,1327],"/posts/images/onceuponatime_theoneapiservice_2.png",[],{"type":415,"tag":416,"props":9835,"children":9836},{},[9837,9839,9845],{"type":420,"value":9838},"(this code can be found ",{"type":415,"tag":423,"props":9840,"children":9843},{"href":9841,"rel":9842},"https://github.com/TechWatching/MyLotrApi/blob/3e5561cb71678e432e970edcac6509581e3aaecd/src/MyLotrApi/TheOneApiService.cs",[427],[9844],{"type":420,"value":7221},{"type":420,"value":1678},{"type":415,"tag":416,"props":9847,"children":9848},{},[9849],{"type":420,"value":9850},"Well, the code is fine, nothing to say about that but I don't like this solution at all 😁. And here is why:",{"type":415,"tag":637,"props":9852,"children":9853},{},[9854],{"type":415,"tag":497,"props":9855,"children":9856},{},[9857],{"type":420,"value":9858},"It adds complexity and makes the code more difficult to read",{"type":415,"tag":416,"props":9860,"children":9861},{},[9862,9864,9869,9870,9875,9877,9882,9884,9890],{"type":420,"value":9863},"When I look at the ",{"type":415,"tag":550,"props":9865,"children":9867},{"className":9866},[],[9868],{"type":420,"value":9815},{"type":420,"value":7549},{"type":415,"tag":550,"props":9871,"children":9873},{"className":9872},[],[9874],{"type":420,"value":9822},{"type":420,"value":9876}," I don't know exactly what they do, the business logic is hidden in the private ",{"type":415,"tag":550,"props":9878,"children":9880},{"className":9879},[],[9881],{"type":420,"value":9807},{"type":420,"value":9883}," method. This private method in itself is more complicated than the previous duplicated code because it has to handle different cases, like the fact that the request can be a POST or a PUT, hence the use of an ",{"type":415,"tag":550,"props":9885,"children":9887},{"className":9886},[],[9888],{"type":420,"value":9889},"HttpRequestMessage",{"type":420,"value":9891}," with the potential content to send in the request. In fact, it's quite clear that this method does too many different things.",{"type":415,"tag":637,"props":9893,"children":9894},{"start":796},[9895],{"type":415,"tag":497,"props":9896,"children":9897},{},[9898],{"type":420,"value":9899},"It abstracts the use of the HttpClient",{"type":415,"tag":416,"props":9901,"children":9902},{},[9903,9905,9910,9912,9917,9919,9924,9926,9931],{"type":420,"value":9904},"I have nothing against abstractions, on the contrary, but I think they should add value and not completely hide what we are using under the hood. And here we are concealing the fact we are using an HttpClient, that does a ",{"type":415,"tag":550,"props":9906,"children":9908},{"className":9907},[],[9909],{"type":420,"value":1359},{"type":420,"value":9911}," request on the \"character\" route for instance. Of course, we can find part of that information in the parameters provided to the ",{"type":415,"tag":550,"props":9913,"children":9915},{"className":9914},[],[9916],{"type":420,"value":9807},{"type":420,"value":9918}," method but it is not as clear as calling the ",{"type":415,"tag":550,"props":9920,"children":9922},{"className":9921},[],[9923],{"type":420,"value":6010},{"type":420,"value":9925}," method of the ",{"type":415,"tag":550,"props":9927,"children":9929},{"className":9928},[],[9930],{"type":420,"value":9774},{"type":420,"value":9932}," as we are used to doing. Using an HttpClient already abstracts the complexity of creating an Http request and sending it, we do not need to trade this abstraction off for another less understandable abstraction.",{"type":415,"tag":637,"props":9934,"children":9935},{"start":840},[9936],{"type":415,"tag":497,"props":9937,"children":9938},{},[9939],{"type":420,"value":9940},"It makes the code hard to maintain",{"type":415,"tag":416,"props":9942,"children":9943},{},[9944,9946,9951],{"type":420,"value":9945},"Because all the main methods of this service call this private method, it will be difficult to change something in it without breaking something else. If someday we need to do something specific linked to the HTTP call for one case it will be hard to implement it in the ",{"type":415,"tag":550,"props":9947,"children":9949},{"className":9948},[],[9950],{"type":420,"value":9807},{"type":420,"value":9952}," method, the only solution will be to add optional parameters and do a lot of conditions in the code which will quickly become dirty.",{"type":415,"tag":416,"props":9954,"children":9955},{},[9956],{"type":420,"value":9957},"If you are fond of SOLID, what I am just saying is that this solution does not satisfy several SOLID principles like the Single responsibility principle and the Open-closed principle.",{"type":415,"tag":416,"props":9959,"children":9960},{},[9961,9963,9968],{"type":420,"value":9962},"So what could be done to improve this code if it is not by factorizing it in a private method. As we said, the code in the service does too much things so maybe it's time to remove some concerns from the ",{"type":415,"tag":550,"props":9964,"children":9966},{"className":9965},[],[9967],{"type":420,"value":9028},{"type":420,"value":755},{"type":415,"tag":616,"props":9970,"children":9972},{"id":9971},"implementing-an-http-message-handler-to-simplify-the-code",[9973],{"type":420,"value":9974},"Implementing an HTTP message handler to simplify the code",{"type":415,"tag":416,"props":9976,"children":9977},{},[9978,9980,9987,9989,9994,9996,10002],{"type":420,"value":9979},"I already talked about using an HTTP message handler / delegating handler in ",{"type":415,"tag":423,"props":9981,"children":9984},{"href":9982,"rel":9983},"https://www.techwatching.dev/posts/delegating-handler",[427],[9985],{"type":420,"value":9986},"a previous article",{"type":420,"value":9988},". When registered with an HTTP client, it is a piece of code that all the HTTP requests you do on this HTTP client will go through. Hence it is a nice way of factorizing code that we want to apply to all the requests to ",{"type":415,"tag":550,"props":9990,"children":9992},{"className":9991},[],[9993],{"type":420,"value":8974},{"type":420,"value":9995}," like the fact of throwing the ",{"type":415,"tag":550,"props":9997,"children":9999},{"className":9998},[],[10000],{"type":420,"value":10001},"TheOneApiException",{"type":420,"value":10003}," when the HTTP responses are not successful.",{"type":415,"tag":416,"props":10005,"children":10006},{},[10007],{"type":415,"tag":1322,"props":10008,"children":10012},{"alt":10009,"className":10010,"src":10011},"The code the OneApiErrorDelegatingHandler.",[1326,1327],"/posts/images/onceuponatime_handler_1.png",[],{"type":415,"tag":416,"props":10014,"children":10015},{},[10016,10018,10024],{"type":420,"value":10017},"(This code can be found ",{"type":415,"tag":423,"props":10019,"children":10022},{"href":10020,"rel":10021},"https://github.com/TechWatching/MyLotrApi/blob/9dfd9966044560d6e13c71d93eeba775e02bd18d/src/MyLotrApi/Services/HttpMessageHandlers/TheOneApiErrorDelegatingHandler.cs",[427],[10023],{"type":420,"value":7221},{"type":420,"value":1678},{"type":415,"tag":616,"props":10026,"children":10028},{"id":10027},"using-httpclientjsonextensions-to-get-rid-of-the-deserialization-code",[10029,10031,10037],{"type":420,"value":10030},"Using ",{"type":415,"tag":550,"props":10032,"children":10034},{"className":10033},[],[10035],{"type":420,"value":10036},"HttpClientJsonExtensions",{"type":420,"value":10038}," to get rid of the deserialization code",{"type":415,"tag":416,"props":10040,"children":10041},{},[10042],{"type":420,"value":10043},"In the current code, there are some lines to read the response content as a string and deserialize it. The interesting code in the service is the fact of doing a GET or a POST to retrieve some data, not the boilerplate code to handle deserialization. So it would be great to be able to remove it. In .NET Framework, there used to be some HTTP client extensions that worked with NewtonSoft to do that.",{"type":415,"tag":416,"props":10045,"children":10046},{},[10047,10049,10062],{"type":420,"value":10048},"In .NET Core there is no longer that, however, there are HttpClient method extensions that use System.Text.Json to make the request and deserialize the response content in one line. For that, you need to reference the ",{"type":415,"tag":423,"props":10050,"children":10053},{"href":10051,"rel":10052},"https://www.nuget.org/packages/System.Net.Http.Json",[427],[10054,10060],{"type":415,"tag":550,"props":10055,"children":10057},{"className":10056},[],[10058],{"type":420,"value":10059},"System.Net.Http.Json",{"type":420,"value":10061}," NuGet package",{"type":420,"value":10063}," and the code becomes simpler.",{"type":415,"tag":416,"props":10065,"children":10066},{},[10067],{"type":415,"tag":1322,"props":10068,"children":10072},{"alt":10069,"className":10070,"src":10071},"The code of GetCharacters method without manual deserialization.",[1326,1327],"/posts/images/onceuponatime_theoneapiservice_3.png",[],{"type":415,"tag":416,"props":10074,"children":10075},{},[10076,10077,10083],{"type":420,"value":10017},{"type":415,"tag":423,"props":10078,"children":10081},{"href":10079,"rel":10080},"https://github.com/TechWatching/MyLotrApi/blob/4ceca01826a0de4cca593c731f812ace874924a8/src/MyLotrApi/Services/TheOneApiService.cs",[427],[10082],{"type":420,"value":7221},{"type":420,"value":1678},{"type":415,"tag":616,"props":10085,"children":10087},{"id":10086},"exploring-an-alternative-to-implementing-the-interface-itheoneapiservice-with-refit",[10088,10090,10096],{"type":420,"value":10089},"Exploring an alternative to implementing the interface ",{"type":415,"tag":550,"props":10091,"children":10093},{"className":10092},[],[10094],{"type":420,"value":10095},"ITheOneApiService",{"type":420,"value":10097}," with Refit",{"type":415,"tag":416,"props":10099,"children":10100},{},[10101,10103,10108,10110,10117],{"type":420,"value":10102},"I am pretty happy with how we improved and simplified the code thanks to the handler and the HTTP extensions methods. Yet I think I cannot end this article without mentioning ",{"type":415,"tag":423,"props":10104,"children":10106},{"href":5900,"rel":10105},[427],[10107],{"type":420,"value":5904},{"type":420,"value":10109},": the automatic type-safe REST library for .NET. The idea behind this ",{"type":415,"tag":423,"props":10111,"children":10114},{"href":10112,"rel":10113},"https://reactiveui.github.io/refit/",[427],[10115],{"type":420,"value":10116},"library",{"type":420,"value":10118}," is that you only have to define the interface specifying the routes you want to query and the library will generate an implementation that does the calls for you with an HttpClient. No need to implement that yourself anymore, so less code to maintain for the same result.",{"type":415,"tag":416,"props":10120,"children":10121},{},[10122],{"type":415,"tag":1322,"props":10123,"children":10127},{"alt":10124,"className":10125,"src":10126},"The code of the IOneApiService interface using Refit.",[1326,1327],"/posts/images/onceuponatime_refit_2.png",[],{"type":415,"tag":416,"props":10129,"children":10130},{},[10131,10133,10138,10140,10146],{"type":420,"value":10132},"Refit even automatically handles query parameters by mapping them to the public properties of the object in parameter of a ",{"type":415,"tag":550,"props":10134,"children":10136},{"className":10135},[],[10137],{"type":420,"value":1359},{"type":420,"value":10139}," method in the interface. To name differently your property from the query parameter you can simply add an ",{"type":415,"tag":550,"props":10141,"children":10143},{"className":10142},[],[10144],{"type":420,"value":10145},"AliasAs",{"type":420,"value":10147}," attribute as I did here.",{"type":415,"tag":416,"props":10149,"children":10150},{},[10151],{"type":415,"tag":1322,"props":10152,"children":10156},{"alt":10153,"className":10154,"src":10155},"The code of CharacterQueryParam.",[1326,1327],"/posts/images/onceuponatime_refit_3.png",[],{"type":415,"tag":416,"props":10158,"children":10159},{},[10160,10162,10167],{"type":420,"value":10161},"Using Refit might not be appropriate to your use case when you have very specific things to do but for a basic REST service like ",{"type":415,"tag":550,"props":10163,"children":10165},{"className":10164},[],[10166],{"type":420,"value":9028},{"type":420,"value":10168},", it is perfect. Refit has other nice features but what I really appreciate is that it also works with delegating handlers. So I can use Refit and still use the delegating handler I previously created.",{"type":415,"tag":416,"props":10170,"children":10171},{},[10172],{"type":415,"tag":1322,"props":10173,"children":10177},{"alt":10174,"className":10175,"src":10176},"The code for registering the services using Refit.",[1326,1327],"/posts/images/onceuponatime_refit_1.png",[],{"type":415,"tag":416,"props":10179,"children":10180},{},[10181,10182,10188],{"type":420,"value":10017},{"type":415,"tag":423,"props":10183,"children":10186},{"href":10184,"rel":10185},"https://github.com/TechWatching/MyLotrApi/blob/76f85099bdb8c747717bf3e61007c276d5055e6f/src/MyLotrApi/Startup.cs",[427],[10187],{"type":420,"value":7221},{"type":420,"value":1678},{"type":415,"tag":443,"props":10190,"children":10192},{"id":10191},"to-conclude",[10193],{"type":420,"value":10194},"To conclude",{"type":415,"tag":416,"props":10196,"children":10197},{},[10198],{"type":420,"value":10199},"In this article, we have seen how we can improve some .NET code while talking about records, delegating handlers, refit...",{"type":415,"tag":1420,"props":10201,"children":10202},{},[10203],{"type":420,"value":1424},{"title":401,"searchDepth":796,"depth":796,"links":10205},[10206,10207,10208,10217],{"id":8942,"depth":796,"text":8945},{"id":9076,"depth":796,"text":9079},{"id":9742,"depth":796,"text":10209,"children":10210},"What can be improved in TheOneApiService?",[10211,10212,10213,10215],{"id":9793,"depth":840,"text":9796},{"id":9971,"depth":840,"text":9974},{"id":10027,"depth":840,"text":10214},"Using HttpClientJsonExtensions to get rid of the deserialization code",{"id":10086,"depth":840,"text":10216},"Exploring an alternative to implementing the interface ITheOneApiService with Refit",{"id":10191,"depth":796,"text":10194},"content:1.posts:16.once-upon-a-time-in-dotnet.md","1.posts/16.once-upon-a-time-in-dotnet.md",{"_path":22,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":21,"description":10221,"lead":10222,"date":10223,"image":10224,"badge":10226,"tags":10227,"body":10228,"_type":1435,"_id":14074,"_source":1437,"_file":14075,"_extension":1439},"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":10225},"/images/keyboard_1.jpg",{"label":1447},[213,210,236,239],{"type":412,"children":10229,"toc":14067},[10230,10234,10238,10243,10252,10286,10291,10329,10434,10446,10451,10683,10701,10821,10833,10839,10865,11972,11977,12012,12018,12059,12714,12734,12740,12779,12813,12825,13194,13199,13726,13739,14054,14058,14063],{"type":415,"tag":416,"props":10231,"children":10232},{},[10233],{"type":420,"value":10221},{"type":415,"tag":443,"props":10235,"children":10236},{"id":445},[10237],{"type":420,"value":448},{"type":415,"tag":416,"props":10239,"children":10240},{},[10241],{"type":420,"value":10242},"Let's imagine we have a very simple API that contains the following routes :",{"type":415,"tag":416,"props":10244,"children":10245},{},[10246],{"type":415,"tag":1322,"props":10247,"children":10251},{"alt":10248,"className":10249,"src":10250},"Open API specifications of the Users API",[1326,1327],"/posts/images/delegatinghandler_api_1.png",[],{"type":415,"tag":416,"props":10253,"children":10254},{},[10255,10256,10262,10264,10270,10272,10278,10279,10285],{"type":420,"value":1794},{"type":415,"tag":550,"props":10257,"children":10259},{"className":10258},[],[10260],{"type":420,"value":10261},"POST /login",{"type":420,"value":10263}," route returns an ",{"type":415,"tag":550,"props":10265,"children":10267},{"className":10266},[],[10268],{"type":420,"value":10269},"AuthResponse",{"type":420,"value":10271}," that contains the necessary Bearer token to call the 2 protected routes ",{"type":415,"tag":550,"props":10273,"children":10275},{"className":10274},[],[10276],{"type":420,"value":10277},"GET /users",{"type":420,"value":7950},{"type":415,"tag":550,"props":10280,"children":10282},{"className":10281},[],[10283],{"type":420,"value":10284},"PUT /users/{username}",{"type":420,"value":755},{"type":415,"tag":416,"props":10287,"children":10288},{},[10289],{"type":420,"value":10290},"We want to implement an IUserService that has 2 methods:",{"type":415,"tag":493,"props":10292,"children":10293},{},[10294,10312],{"type":415,"tag":497,"props":10295,"children":10296},{},[10297,10303,10305,10310],{"type":415,"tag":550,"props":10298,"children":10300},{"className":10299},[],[10301],{"type":420,"value":10302},"GetAllUsers",{"type":420,"value":10304}," to retrieve the list of users that will use the ",{"type":415,"tag":550,"props":10306,"children":10308},{"className":10307},[],[10309],{"type":420,"value":10277},{"type":420,"value":10311}," route",{"type":415,"tag":497,"props":10313,"children":10314},{},[10315,10321,10323,10328],{"type":415,"tag":550,"props":10316,"children":10318},{"className":10317},[],[10319],{"type":420,"value":10320},"UpdateUser",{"type":420,"value":10322}," to update a user that will use the ",{"type":415,"tag":550,"props":10324,"children":10326},{"className":10325},[],[10327],{"type":420,"value":10284},{"type":420,"value":10311},{"type":415,"tag":773,"props":10330,"children":10332},{"className":1805,"code":10331,"language":326,"meta":401,"style":401},"public interface IUserService\n{\n    Task\u003CIReadOnlyCollection\u003CUser>> GetAllUsers();\n    Task UpdateUser(User userToUpdate);\n}\n",[10333],{"type":415,"tag":550,"props":10334,"children":10335},{"__ignoreMap":401},[10336,10352,10359,10398,10427],{"type":415,"tag":783,"props":10337,"children":10338},{"class":785,"line":786},[10339,10343,10347],{"type":415,"tag":783,"props":10340,"children":10341},{"style":805},[10342],{"type":420,"value":1871},{"type":415,"tag":783,"props":10344,"children":10345},{"style":875},[10346],{"type":420,"value":5986},{"type":415,"tag":783,"props":10348,"children":10349},{"style":875},[10350],{"type":420,"value":10351}," IUserService\n",{"type":415,"tag":783,"props":10353,"children":10354},{"class":785,"line":796},[10355],{"type":415,"tag":783,"props":10356,"children":10357},{"style":790},[10358],{"type":420,"value":793},{"type":415,"tag":783,"props":10360,"children":10361},{"class":785,"line":840},[10362,10366,10370,10375,10379,10384,10389,10394],{"type":415,"tag":783,"props":10363,"children":10364},{"style":875},[10365],{"type":420,"value":6039},{"type":415,"tag":783,"props":10367,"children":10368},{"style":790},[10369],{"type":420,"value":2112},{"type":415,"tag":783,"props":10371,"children":10372},{"style":875},[10373],{"type":420,"value":10374},"IReadOnlyCollection",{"type":415,"tag":783,"props":10376,"children":10377},{"style":790},[10378],{"type":420,"value":2112},{"type":415,"tag":783,"props":10380,"children":10381},{"style":875},[10382],{"type":420,"value":10383},"User",{"type":415,"tag":783,"props":10385,"children":10386},{"style":790},[10387],{"type":420,"value":10388},">>",{"type":415,"tag":783,"props":10390,"children":10391},{"style":1545},[10392],{"type":420,"value":10393}," GetAllUsers",{"type":415,"tag":783,"props":10395,"children":10396},{"style":790},[10397],{"type":420,"value":2164},{"type":415,"tag":783,"props":10399,"children":10400},{"class":785,"line":866},[10401,10405,10410,10414,10418,10423],{"type":415,"tag":783,"props":10402,"children":10403},{"style":875},[10404],{"type":420,"value":6039},{"type":415,"tag":783,"props":10406,"children":10407},{"style":1545},[10408],{"type":420,"value":10409}," UpdateUser",{"type":415,"tag":783,"props":10411,"children":10412},{"style":790},[10413],{"type":420,"value":1845},{"type":415,"tag":783,"props":10415,"children":10416},{"style":875},[10417],{"type":420,"value":10383},{"type":415,"tag":783,"props":10419,"children":10420},{"style":875},[10421],{"type":420,"value":10422}," userToUpdate",{"type":415,"tag":783,"props":10424,"children":10425},{"style":790},[10426],{"type":420,"value":2552},{"type":415,"tag":783,"props":10428,"children":10429},{"class":785,"line":893},[10430],{"type":415,"tag":783,"props":10431,"children":10432},{"style":790},[10433],{"type":420,"value":1272},{"type":415,"tag":416,"props":10435,"children":10436},{},[10437,10439,10444],{"type":420,"value":10438},"Each of these methods needs to retrieve a valid token from the ",{"type":415,"tag":550,"props":10440,"children":10442},{"className":10441},[],[10443],{"type":420,"value":10261},{"type":420,"value":10445}," route and set the Authorization header with this token in the HTTP request to each of the protected routes.",{"type":415,"tag":416,"props":10447,"children":10448},{},[10449],{"type":420,"value":10450},"The following code shows how to retrieve the token:",{"type":415,"tag":773,"props":10452,"children":10454},{"className":1805,"code":10453,"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",[10455],{"type":415,"tag":550,"props":10456,"children":10457},{"__ignoreMap":401},[10458,10534,10629],{"type":415,"tag":783,"props":10459,"children":10460},{"class":785,"line":786},[10461,10465,10470,10474,10478,10482,10487,10491,10495,10500,10504,10508,10513,10517,10521,10526,10530],{"type":415,"tag":783,"props":10462,"children":10463},{"style":875},[10464],{"type":420,"value":3773},{"type":415,"tag":783,"props":10466,"children":10467},{"style":875},[10468],{"type":420,"value":10469}," body",{"type":415,"tag":783,"props":10471,"children":10472},{"style":790},[10473],{"type":420,"value":2033},{"type":415,"tag":783,"props":10475,"children":10476},{"style":790},[10477],{"type":420,"value":4335},{"type":415,"tag":783,"props":10479,"children":10480},{"style":790},[10481],{"type":420,"value":4345},{"type":415,"tag":783,"props":10483,"children":10484},{"style":1362},[10485],{"type":420,"value":10486}," login ",{"type":415,"tag":783,"props":10488,"children":10489},{"style":790},[10490],{"type":420,"value":1984},{"type":415,"tag":783,"props":10492,"children":10493},{"style":790},[10494],{"type":420,"value":822},{"type":415,"tag":783,"props":10496,"children":10497},{"style":825},[10498],{"type":420,"value":10499},"login",{"type":415,"tag":783,"props":10501,"children":10502},{"style":790},[10503],{"type":420,"value":813},{"type":415,"tag":783,"props":10505,"children":10506},{"style":790},[10507],{"type":420,"value":2501},{"type":415,"tag":783,"props":10509,"children":10510},{"style":1362},[10511],{"type":420,"value":10512}," password ",{"type":415,"tag":783,"props":10514,"children":10515},{"style":790},[10516],{"type":420,"value":1984},{"type":415,"tag":783,"props":10518,"children":10519},{"style":790},[10520],{"type":420,"value":822},{"type":415,"tag":783,"props":10522,"children":10523},{"style":825},[10524],{"type":420,"value":10525},"password",{"type":415,"tag":783,"props":10527,"children":10528},{"style":790},[10529],{"type":420,"value":813},{"type":415,"tag":783,"props":10531,"children":10532},{"style":790},[10533],{"type":420,"value":4506},{"type":415,"tag":783,"props":10535,"children":10536},{"class":785,"line":796},[10537,10541,10546,10550,10554,10559,10563,10568,10572,10576,10580,10584,10588,10592,10597,10601,10606,10610,10615,10619,10624],{"type":415,"tag":783,"props":10538,"children":10539},{"style":875},[10540],{"type":420,"value":3773},{"type":415,"tag":783,"props":10542,"children":10543},{"style":875},[10544],{"type":420,"value":10545}," response",{"type":415,"tag":783,"props":10547,"children":10548},{"style":790},[10549],{"type":420,"value":2033},{"type":415,"tag":783,"props":10551,"children":10552},{"style":790},[10553],{"type":420,"value":2695},{"type":415,"tag":783,"props":10555,"children":10556},{"style":1362},[10557],{"type":420,"value":10558}," _httpClient",{"type":415,"tag":783,"props":10560,"children":10561},{"style":790},[10562],{"type":420,"value":755},{"type":415,"tag":783,"props":10564,"children":10565},{"style":1545},[10566],{"type":420,"value":10567},"PostAsync",{"type":415,"tag":783,"props":10569,"children":10570},{"style":790},[10571],{"type":420,"value":1845},{"type":415,"tag":783,"props":10573,"children":10574},{"style":790},[10575],{"type":420,"value":813},{"type":415,"tag":783,"props":10577,"children":10578},{"style":825},[10579],{"type":420,"value":10499},{"type":415,"tag":783,"props":10581,"children":10582},{"style":790},[10583],{"type":420,"value":813},{"type":415,"tag":783,"props":10585,"children":10586},{"style":790},[10587],{"type":420,"value":2501},{"type":415,"tag":783,"props":10589,"children":10590},{"style":790},[10591],{"type":420,"value":4335},{"type":415,"tag":783,"props":10593,"children":10594},{"style":875},[10595],{"type":420,"value":10596}," StringContent",{"type":415,"tag":783,"props":10598,"children":10599},{"style":790},[10600],{"type":420,"value":1845},{"type":415,"tag":783,"props":10602,"children":10603},{"style":1362},[10604],{"type":420,"value":10605},"JsonConvert",{"type":415,"tag":783,"props":10607,"children":10608},{"style":790},[10609],{"type":420,"value":755},{"type":415,"tag":783,"props":10611,"children":10612},{"style":1545},[10613],{"type":420,"value":10614},"SerializeObject",{"type":415,"tag":783,"props":10616,"children":10617},{"style":790},[10618],{"type":420,"value":1845},{"type":415,"tag":783,"props":10620,"children":10621},{"style":1362},[10622],{"type":420,"value":10623},"body",{"type":415,"tag":783,"props":10625,"children":10626},{"style":790},[10627],{"type":420,"value":10628},")));\n",{"type":415,"tag":783,"props":10630,"children":10631},{"class":785,"line":840},[10632,10636,10641,10645,10649,10653,10657,10662,10666,10671,10675,10679],{"type":415,"tag":783,"props":10633,"children":10634},{"style":875},[10635],{"type":420,"value":3773},{"type":415,"tag":783,"props":10637,"children":10638},{"style":875},[10639],{"type":420,"value":10640}," authResponse",{"type":415,"tag":783,"props":10642,"children":10643},{"style":790},[10644],{"type":420,"value":2033},{"type":415,"tag":783,"props":10646,"children":10647},{"style":790},[10648],{"type":420,"value":2695},{"type":415,"tag":783,"props":10650,"children":10651},{"style":1362},[10652],{"type":420,"value":10545},{"type":415,"tag":783,"props":10654,"children":10655},{"style":790},[10656],{"type":420,"value":755},{"type":415,"tag":783,"props":10658,"children":10659},{"style":1362},[10660],{"type":420,"value":10661},"Content",{"type":415,"tag":783,"props":10663,"children":10664},{"style":790},[10665],{"type":420,"value":755},{"type":415,"tag":783,"props":10667,"children":10668},{"style":1545},[10669],{"type":420,"value":10670},"ReadAsAsync",{"type":415,"tag":783,"props":10672,"children":10673},{"style":790},[10674],{"type":420,"value":2112},{"type":415,"tag":783,"props":10676,"children":10677},{"style":875},[10678],{"type":420,"value":10269},{"type":415,"tag":783,"props":10680,"children":10681},{"style":790},[10682],{"type":420,"value":6735},{"type":415,"tag":416,"props":10684,"children":10685},{},[10686,10688,10693,10695,10700],{"type":420,"value":10687},"where ",{"type":415,"tag":550,"props":10689,"children":10691},{"className":10690},[],[10692],{"type":420,"value":10269},{"type":420,"value":10694}," is a class we defined to map the response of the ",{"type":415,"tag":550,"props":10696,"children":10698},{"className":10697},[],[10699],{"type":420,"value":10261},{"type":420,"value":10311},{"type":415,"tag":773,"props":10702,"children":10704},{"className":1805,"code":10703,"language":326,"meta":401,"style":401},"public class AuthResponse\n{\n  public string Token { get; set; }\n  public DateTime Expiration { get; set; }\n}\n",[10705],{"type":415,"tag":550,"props":10706,"children":10707},{"__ignoreMap":401},[10708,10724,10731,10773,10814],{"type":415,"tag":783,"props":10709,"children":10710},{"class":785,"line":786},[10711,10715,10719],{"type":415,"tag":783,"props":10712,"children":10713},{"style":805},[10714],{"type":420,"value":1871},{"type":415,"tag":783,"props":10716,"children":10717},{"style":875},[10718],{"type":420,"value":1876},{"type":415,"tag":783,"props":10720,"children":10721},{"style":875},[10722],{"type":420,"value":10723}," AuthResponse\n",{"type":415,"tag":783,"props":10725,"children":10726},{"class":785,"line":796},[10727],{"type":415,"tag":783,"props":10728,"children":10729},{"style":790},[10730],{"type":420,"value":793},{"type":415,"tag":783,"props":10732,"children":10733},{"class":785,"line":840},[10734,10739,10743,10748,10752,10756,10760,10765,10769],{"type":415,"tag":783,"props":10735,"children":10736},{"style":805},[10737],{"type":420,"value":10738},"  public",{"type":415,"tag":783,"props":10740,"children":10741},{"style":790},[10742],{"type":420,"value":3798},{"type":415,"tag":783,"props":10744,"children":10745},{"style":875},[10746],{"type":420,"value":10747}," Token",{"type":415,"tag":783,"props":10749,"children":10750},{"style":790},[10751],{"type":420,"value":4345},{"type":415,"tag":783,"props":10753,"children":10754},{"style":875},[10755],{"type":420,"value":5137},{"type":415,"tag":783,"props":10757,"children":10758},{"style":790},[10759],{"type":420,"value":5142},{"type":415,"tag":783,"props":10761,"children":10762},{"style":875},[10763],{"type":420,"value":10764}," set",{"type":415,"tag":783,"props":10766,"children":10767},{"style":790},[10768],{"type":420,"value":5142},{"type":415,"tag":783,"props":10770,"children":10771},{"style":790},[10772],{"type":420,"value":6398},{"type":415,"tag":783,"props":10774,"children":10775},{"class":785,"line":866},[10776,10780,10785,10790,10794,10798,10802,10806,10810],{"type":415,"tag":783,"props":10777,"children":10778},{"style":805},[10779],{"type":420,"value":10738},{"type":415,"tag":783,"props":10781,"children":10782},{"style":875},[10783],{"type":420,"value":10784}," DateTime",{"type":415,"tag":783,"props":10786,"children":10787},{"style":875},[10788],{"type":420,"value":10789}," Expiration",{"type":415,"tag":783,"props":10791,"children":10792},{"style":790},[10793],{"type":420,"value":4345},{"type":415,"tag":783,"props":10795,"children":10796},{"style":875},[10797],{"type":420,"value":5137},{"type":415,"tag":783,"props":10799,"children":10800},{"style":790},[10801],{"type":420,"value":5142},{"type":415,"tag":783,"props":10803,"children":10804},{"style":875},[10805],{"type":420,"value":10764},{"type":415,"tag":783,"props":10807,"children":10808},{"style":790},[10809],{"type":420,"value":5142},{"type":415,"tag":783,"props":10811,"children":10812},{"style":790},[10813],{"type":420,"value":6398},{"type":415,"tag":783,"props":10815,"children":10816},{"class":785,"line":893},[10817],{"type":415,"tag":783,"props":10818,"children":10819},{"style":790},[10820],{"type":420,"value":1272},{"type":415,"tag":416,"props":10822,"children":10823},{},[10824,10826,10832],{"type":420,"value":10825},"So now we have the code to retrieve the token, how do we use it to implement our ",{"type":415,"tag":550,"props":10827,"children":10829},{"className":10828},[],[10830],{"type":420,"value":10831},"IUserService",{"type":420,"value":5096},{"type":415,"tag":443,"props":10834,"children":10836},{"id":10835},"retrieve-the-token-from-a-private-method",[10837],{"type":420,"value":10838},"Retrieve the token from a private method",{"type":415,"tag":416,"props":10840,"children":10841},{},[10842,10844,10850,10852,10857,10858,10863],{"type":420,"value":10843},"The easiest way to do that is to create a private method in ",{"type":415,"tag":550,"props":10845,"children":10847},{"className":10846},[],[10848],{"type":420,"value":10849},"UserService",{"type":420,"value":10851}," that returns this token and to call it from ",{"type":415,"tag":550,"props":10853,"children":10855},{"className":10854},[],[10856],{"type":420,"value":10302},{"type":420,"value":7950},{"type":415,"tag":550,"props":10859,"children":10861},{"className":10860},[],[10862],{"type":420,"value":10320},{"type":420,"value":10864},". That would give us something like that :",{"type":415,"tag":773,"props":10866,"children":10868},{"className":1805,"code":10867,"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",[10869],{"type":415,"tag":550,"props":10870,"children":10871},{"__ignoreMap":401},[10872,10896,10903,10927,10955,10962,10982,10989,10996,11039,11046,11075,11138,11206,11251,11272,11324,11331,11338,11373,11380,11407,11488,11551,11607,11650,11669,11676,11683,11718,11725,11796,11883,11934,11958,11965],{"type":415,"tag":783,"props":10873,"children":10874},{"class":785,"line":786},[10875,10879,10883,10888,10892],{"type":415,"tag":783,"props":10876,"children":10877},{"style":805},[10878],{"type":420,"value":1871},{"type":415,"tag":783,"props":10880,"children":10881},{"style":875},[10882],{"type":420,"value":1876},{"type":415,"tag":783,"props":10884,"children":10885},{"style":875},[10886],{"type":420,"value":10887}," UserService",{"type":415,"tag":783,"props":10889,"children":10890},{"style":790},[10891],{"type":420,"value":1886},{"type":415,"tag":783,"props":10893,"children":10894},{"style":875},[10895],{"type":420,"value":10351},{"type":415,"tag":783,"props":10897,"children":10898},{"class":785,"line":796},[10899],{"type":415,"tag":783,"props":10900,"children":10901},{"style":790},[10902],{"type":420,"value":793},{"type":415,"tag":783,"props":10904,"children":10905},{"class":785,"line":840},[10906,10910,10914,10919,10923],{"type":415,"tag":783,"props":10907,"children":10908},{"style":805},[10909],{"type":420,"value":1906},{"type":415,"tag":783,"props":10911,"children":10912},{"style":805},[10913],{"type":420,"value":1911},{"type":415,"tag":783,"props":10915,"children":10916},{"style":875},[10917],{"type":420,"value":10918}," HttpClient",{"type":415,"tag":783,"props":10920,"children":10921},{"style":875},[10922],{"type":420,"value":10558},{"type":415,"tag":783,"props":10924,"children":10925},{"style":790},[10926],{"type":420,"value":1926},{"type":415,"tag":783,"props":10928,"children":10929},{"class":785,"line":866},[10930,10934,10938,10942,10946,10951],{"type":415,"tag":783,"props":10931,"children":10932},{"style":805},[10933],{"type":420,"value":1941},{"type":415,"tag":783,"props":10935,"children":10936},{"style":1545},[10937],{"type":420,"value":10887},{"type":415,"tag":783,"props":10939,"children":10940},{"style":790},[10941],{"type":420,"value":1845},{"type":415,"tag":783,"props":10943,"children":10944},{"style":875},[10945],{"type":420,"value":9774},{"type":415,"tag":783,"props":10947,"children":10948},{"style":875},[10949],{"type":420,"value":10950}," httpClient",{"type":415,"tag":783,"props":10952,"children":10953},{"style":790},[10954],{"type":420,"value":1963},{"type":415,"tag":783,"props":10956,"children":10957},{"class":785,"line":893},[10958],{"type":415,"tag":783,"props":10959,"children":10960},{"style":790},[10961],{"type":420,"value":1971},{"type":415,"tag":783,"props":10963,"children":10964},{"class":785,"line":920},[10965,10970,10974,10978],{"type":415,"tag":783,"props":10966,"children":10967},{"style":1362},[10968],{"type":420,"value":10969},"        _httpClient ",{"type":415,"tag":783,"props":10971,"children":10972},{"style":790},[10973],{"type":420,"value":1984},{"type":415,"tag":783,"props":10975,"children":10976},{"style":1362},[10977],{"type":420,"value":10950},{"type":415,"tag":783,"props":10979,"children":10980},{"style":790},[10981],{"type":420,"value":1926},{"type":415,"tag":783,"props":10983,"children":10984},{"class":785,"line":959},[10985],{"type":415,"tag":783,"props":10986,"children":10987},{"style":790},[10988],{"type":420,"value":1254},{"type":415,"tag":783,"props":10990,"children":10991},{"class":785,"line":997},[10992],{"type":415,"tag":783,"props":10993,"children":10994},{"emptyLinePlaceholder":1624},[10995],{"type":420,"value":1627},{"type":415,"tag":783,"props":10997,"children":10998},{"class":785,"line":1023},[10999,11003,11007,11011,11015,11019,11023,11027,11031,11035],{"type":415,"tag":783,"props":11000,"children":11001},{"style":805},[11002],{"type":420,"value":1941},{"type":415,"tag":783,"props":11004,"children":11005},{"style":805},[11006],{"type":420,"value":2641},{"type":415,"tag":783,"props":11008,"children":11009},{"style":875},[11010],{"type":420,"value":2107},{"type":415,"tag":783,"props":11012,"children":11013},{"style":790},[11014],{"type":420,"value":2112},{"type":415,"tag":783,"props":11016,"children":11017},{"style":875},[11018],{"type":420,"value":10374},{"type":415,"tag":783,"props":11020,"children":11021},{"style":790},[11022],{"type":420,"value":2112},{"type":415,"tag":783,"props":11024,"children":11025},{"style":875},[11026],{"type":420,"value":10383},{"type":415,"tag":783,"props":11028,"children":11029},{"style":790},[11030],{"type":420,"value":10388},{"type":415,"tag":783,"props":11032,"children":11033},{"style":1545},[11034],{"type":420,"value":10393},{"type":415,"tag":783,"props":11036,"children":11037},{"style":790},[11038],{"type":420,"value":2131},{"type":415,"tag":783,"props":11040,"children":11041},{"class":785,"line":1061},[11042],{"type":415,"tag":783,"props":11043,"children":11044},{"style":790},[11045],{"type":420,"value":1971},{"type":415,"tag":783,"props":11047,"children":11048},{"class":785,"line":1099},[11049,11053,11058,11062,11066,11071],{"type":415,"tag":783,"props":11050,"children":11051},{"style":875},[11052],{"type":420,"value":2681},{"type":415,"tag":783,"props":11054,"children":11055},{"style":875},[11056],{"type":420,"value":11057}," token",{"type":415,"tag":783,"props":11059,"children":11060},{"style":790},[11061],{"type":420,"value":2033},{"type":415,"tag":783,"props":11063,"children":11064},{"style":790},[11065],{"type":420,"value":2695},{"type":415,"tag":783,"props":11067,"children":11068},{"style":1545},[11069],{"type":420,"value":11070}," RetrieveToken",{"type":415,"tag":783,"props":11072,"children":11073},{"style":790},[11074],{"type":420,"value":2164},{"type":415,"tag":783,"props":11076,"children":11077},{"class":785,"line":1137},[11078,11082,11087,11091,11095,11100,11104,11109,11113,11117,11121,11125,11130,11134],{"type":415,"tag":783,"props":11079,"children":11080},{"style":875},[11081],{"type":420,"value":2681},{"type":415,"tag":783,"props":11083,"children":11084},{"style":875},[11085],{"type":420,"value":11086}," request",{"type":415,"tag":783,"props":11088,"children":11089},{"style":790},[11090],{"type":420,"value":2033},{"type":415,"tag":783,"props":11092,"children":11093},{"style":790},[11094],{"type":420,"value":4335},{"type":415,"tag":783,"props":11096,"children":11097},{"style":875},[11098],{"type":420,"value":11099}," HttpRequestMessage",{"type":415,"tag":783,"props":11101,"children":11102},{"style":790},[11103],{"type":420,"value":1845},{"type":415,"tag":783,"props":11105,"children":11106},{"style":1362},[11107],{"type":420,"value":11108},"HttpMethod",{"type":415,"tag":783,"props":11110,"children":11111},{"style":790},[11112],{"type":420,"value":755},{"type":415,"tag":783,"props":11114,"children":11115},{"style":1362},[11116],{"type":420,"value":6010},{"type":415,"tag":783,"props":11118,"children":11119},{"style":790},[11120],{"type":420,"value":2501},{"type":415,"tag":783,"props":11122,"children":11123},{"style":790},[11124],{"type":420,"value":822},{"type":415,"tag":783,"props":11126,"children":11127},{"style":825},[11128],{"type":420,"value":11129},"user",{"type":415,"tag":783,"props":11131,"children":11132},{"style":790},[11133],{"type":420,"value":813},{"type":415,"tag":783,"props":11135,"children":11136},{"style":790},[11137],{"type":420,"value":2552},{"type":415,"tag":783,"props":11139,"children":11140},{"class":785,"line":1175},[11141,11146,11150,11155,11159,11164,11168,11172,11177,11181,11185,11190,11194,11198,11202],{"type":415,"tag":783,"props":11142,"children":11143},{"style":1362},[11144],{"type":420,"value":11145},"        request",{"type":415,"tag":783,"props":11147,"children":11148},{"style":790},[11149],{"type":420,"value":755},{"type":415,"tag":783,"props":11151,"children":11152},{"style":1362},[11153],{"type":420,"value":11154},"Headers",{"type":415,"tag":783,"props":11156,"children":11157},{"style":790},[11158],{"type":420,"value":755},{"type":415,"tag":783,"props":11160,"children":11161},{"style":1362},[11162],{"type":420,"value":11163},"Authorization ",{"type":415,"tag":783,"props":11165,"children":11166},{"style":790},[11167],{"type":420,"value":1984},{"type":415,"tag":783,"props":11169,"children":11170},{"style":790},[11171],{"type":420,"value":4335},{"type":415,"tag":783,"props":11173,"children":11174},{"style":875},[11175],{"type":420,"value":11176}," AuthenticationHeaderValue",{"type":415,"tag":783,"props":11178,"children":11179},{"style":790},[11180],{"type":420,"value":1845},{"type":415,"tag":783,"props":11182,"children":11183},{"style":790},[11184],{"type":420,"value":813},{"type":415,"tag":783,"props":11186,"children":11187},{"style":825},[11188],{"type":420,"value":11189},"Bearer",{"type":415,"tag":783,"props":11191,"children":11192},{"style":790},[11193],{"type":420,"value":813},{"type":415,"tag":783,"props":11195,"children":11196},{"style":790},[11197],{"type":420,"value":2501},{"type":415,"tag":783,"props":11199,"children":11200},{"style":1362},[11201],{"type":420,"value":11057},{"type":415,"tag":783,"props":11203,"children":11204},{"style":790},[11205],{"type":420,"value":2552},{"type":415,"tag":783,"props":11207,"children":11208},{"class":785,"line":1213},[11209,11213,11217,11221,11225,11229,11233,11238,11242,11247],{"type":415,"tag":783,"props":11210,"children":11211},{"style":875},[11212],{"type":420,"value":2681},{"type":415,"tag":783,"props":11214,"children":11215},{"style":875},[11216],{"type":420,"value":10545},{"type":415,"tag":783,"props":11218,"children":11219},{"style":790},[11220],{"type":420,"value":2033},{"type":415,"tag":783,"props":11222,"children":11223},{"style":790},[11224],{"type":420,"value":2695},{"type":415,"tag":783,"props":11226,"children":11227},{"style":1362},[11228],{"type":420,"value":10558},{"type":415,"tag":783,"props":11230,"children":11231},{"style":790},[11232],{"type":420,"value":755},{"type":415,"tag":783,"props":11234,"children":11235},{"style":1545},[11236],{"type":420,"value":11237},"SendAsync",{"type":415,"tag":783,"props":11239,"children":11240},{"style":790},[11241],{"type":420,"value":1845},{"type":415,"tag":783,"props":11243,"children":11244},{"style":1362},[11245],{"type":420,"value":11246},"request",{"type":415,"tag":783,"props":11248,"children":11249},{"style":790},[11250],{"type":420,"value":2552},{"type":415,"tag":783,"props":11252,"children":11253},{"class":785,"line":1239},[11254,11259,11263,11268],{"type":415,"tag":783,"props":11255,"children":11256},{"style":1362},[11257],{"type":420,"value":11258},"        response",{"type":415,"tag":783,"props":11260,"children":11261},{"style":790},[11262],{"type":420,"value":755},{"type":415,"tag":783,"props":11264,"children":11265},{"style":1545},[11266],{"type":420,"value":11267},"EnsureSuccessStatusCode",{"type":415,"tag":783,"props":11269,"children":11270},{"style":790},[11271],{"type":420,"value":2164},{"type":415,"tag":783,"props":11273,"children":11274},{"class":785,"line":1248},[11275,11279,11283,11287,11291,11295,11299,11303,11307,11311,11315,11319],{"type":415,"tag":783,"props":11276,"children":11277},{"style":1356},[11278],{"type":420,"value":2146},{"type":415,"tag":783,"props":11280,"children":11281},{"style":790},[11282],{"type":420,"value":2695},{"type":415,"tag":783,"props":11284,"children":11285},{"style":1362},[11286],{"type":420,"value":10545},{"type":415,"tag":783,"props":11288,"children":11289},{"style":790},[11290],{"type":420,"value":755},{"type":415,"tag":783,"props":11292,"children":11293},{"style":1362},[11294],{"type":420,"value":10661},{"type":415,"tag":783,"props":11296,"children":11297},{"style":790},[11298],{"type":420,"value":755},{"type":415,"tag":783,"props":11300,"children":11301},{"style":1545},[11302],{"type":420,"value":10670},{"type":415,"tag":783,"props":11304,"children":11305},{"style":790},[11306],{"type":420,"value":2112},{"type":415,"tag":783,"props":11308,"children":11309},{"style":875},[11310],{"type":420,"value":10374},{"type":415,"tag":783,"props":11312,"children":11313},{"style":790},[11314],{"type":420,"value":2112},{"type":415,"tag":783,"props":11316,"children":11317},{"style":875},[11318],{"type":420,"value":10383},{"type":415,"tag":783,"props":11320,"children":11321},{"style":790},[11322],{"type":420,"value":11323},">>();\n",{"type":415,"tag":783,"props":11325,"children":11326},{"class":785,"line":1257},[11327],{"type":415,"tag":783,"props":11328,"children":11329},{"style":790},[11330],{"type":420,"value":1254},{"type":415,"tag":783,"props":11332,"children":11333},{"class":785,"line":1266},[11334],{"type":415,"tag":783,"props":11335,"children":11336},{"emptyLinePlaceholder":1624},[11337],{"type":420,"value":1627},{"type":415,"tag":783,"props":11339,"children":11340},{"class":785,"line":2847},[11341,11345,11349,11353,11357,11361,11365,11369],{"type":415,"tag":783,"props":11342,"children":11343},{"style":805},[11344],{"type":420,"value":1941},{"type":415,"tag":783,"props":11346,"children":11347},{"style":805},[11348],{"type":420,"value":2641},{"type":415,"tag":783,"props":11350,"children":11351},{"style":875},[11352],{"type":420,"value":2107},{"type":415,"tag":783,"props":11354,"children":11355},{"style":1545},[11356],{"type":420,"value":10409},{"type":415,"tag":783,"props":11358,"children":11359},{"style":790},[11360],{"type":420,"value":1845},{"type":415,"tag":783,"props":11362,"children":11363},{"style":875},[11364],{"type":420,"value":10383},{"type":415,"tag":783,"props":11366,"children":11367},{"style":875},[11368],{"type":420,"value":10422},{"type":415,"tag":783,"props":11370,"children":11371},{"style":790},[11372],{"type":420,"value":1963},{"type":415,"tag":783,"props":11374,"children":11375},{"class":785,"line":2896},[11376],{"type":415,"tag":783,"props":11377,"children":11378},{"style":790},[11379],{"type":420,"value":1971},{"type":415,"tag":783,"props":11381,"children":11382},{"class":785,"line":2942},[11383,11387,11391,11395,11399,11403],{"type":415,"tag":783,"props":11384,"children":11385},{"style":875},[11386],{"type":420,"value":2681},{"type":415,"tag":783,"props":11388,"children":11389},{"style":875},[11390],{"type":420,"value":11057},{"type":415,"tag":783,"props":11392,"children":11393},{"style":790},[11394],{"type":420,"value":2033},{"type":415,"tag":783,"props":11396,"children":11397},{"style":790},[11398],{"type":420,"value":2695},{"type":415,"tag":783,"props":11400,"children":11401},{"style":1545},[11402],{"type":420,"value":11070},{"type":415,"tag":783,"props":11404,"children":11405},{"style":790},[11406],{"type":420,"value":2164},{"type":415,"tag":783,"props":11408,"children":11409},{"class":785,"line":2988},[11410,11414,11418,11422,11426,11430,11434,11438,11442,11447,11451,11456,11461,11466,11471,11475,11479,11484],{"type":415,"tag":783,"props":11411,"children":11412},{"style":875},[11413],{"type":420,"value":2681},{"type":415,"tag":783,"props":11415,"children":11416},{"style":875},[11417],{"type":420,"value":11086},{"type":415,"tag":783,"props":11419,"children":11420},{"style":790},[11421],{"type":420,"value":2033},{"type":415,"tag":783,"props":11423,"children":11424},{"style":790},[11425],{"type":420,"value":4335},{"type":415,"tag":783,"props":11427,"children":11428},{"style":875},[11429],{"type":420,"value":11099},{"type":415,"tag":783,"props":11431,"children":11432},{"style":790},[11433],{"type":420,"value":1845},{"type":415,"tag":783,"props":11435,"children":11436},{"style":1362},[11437],{"type":420,"value":11108},{"type":415,"tag":783,"props":11439,"children":11440},{"style":790},[11441],{"type":420,"value":755},{"type":415,"tag":783,"props":11443,"children":11444},{"style":1362},[11445],{"type":420,"value":11446},"Put",{"type":415,"tag":783,"props":11448,"children":11449},{"style":790},[11450],{"type":420,"value":2501},{"type":415,"tag":783,"props":11452,"children":11453},{"style":790},[11454],{"type":420,"value":11455}," $\"",{"type":415,"tag":783,"props":11457,"children":11458},{"style":825},[11459],{"type":420,"value":11460},"user/",{"type":415,"tag":783,"props":11462,"children":11463},{"style":790},[11464],{"type":420,"value":11465},"{",{"type":415,"tag":783,"props":11467,"children":11468},{"style":1362},[11469],{"type":420,"value":11470},"userToUpdate",{"type":415,"tag":783,"props":11472,"children":11473},{"style":790},[11474],{"type":420,"value":755},{"type":415,"tag":783,"props":11476,"children":11477},{"style":1362},[11478],{"type":420,"value":2028},{"type":415,"tag":783,"props":11480,"children":11481},{"style":790},[11482],{"type":420,"value":11483},"}\"",{"type":415,"tag":783,"props":11485,"children":11486},{"style":790},[11487],{"type":420,"value":2552},{"type":415,"tag":783,"props":11489,"children":11490},{"class":785,"line":3034},[11491,11495,11499,11503,11507,11511,11515,11519,11523,11527,11531,11535,11539,11543,11547],{"type":415,"tag":783,"props":11492,"children":11493},{"style":1362},[11494],{"type":420,"value":11145},{"type":415,"tag":783,"props":11496,"children":11497},{"style":790},[11498],{"type":420,"value":755},{"type":415,"tag":783,"props":11500,"children":11501},{"style":1362},[11502],{"type":420,"value":11154},{"type":415,"tag":783,"props":11504,"children":11505},{"style":790},[11506],{"type":420,"value":755},{"type":415,"tag":783,"props":11508,"children":11509},{"style":1362},[11510],{"type":420,"value":11163},{"type":415,"tag":783,"props":11512,"children":11513},{"style":790},[11514],{"type":420,"value":1984},{"type":415,"tag":783,"props":11516,"children":11517},{"style":790},[11518],{"type":420,"value":4335},{"type":415,"tag":783,"props":11520,"children":11521},{"style":875},[11522],{"type":420,"value":11176},{"type":415,"tag":783,"props":11524,"children":11525},{"style":790},[11526],{"type":420,"value":1845},{"type":415,"tag":783,"props":11528,"children":11529},{"style":790},[11530],{"type":420,"value":813},{"type":415,"tag":783,"props":11532,"children":11533},{"style":825},[11534],{"type":420,"value":11189},{"type":415,"tag":783,"props":11536,"children":11537},{"style":790},[11538],{"type":420,"value":813},{"type":415,"tag":783,"props":11540,"children":11541},{"style":790},[11542],{"type":420,"value":2501},{"type":415,"tag":783,"props":11544,"children":11545},{"style":1362},[11546],{"type":420,"value":11057},{"type":415,"tag":783,"props":11548,"children":11549},{"style":790},[11550],{"type":420,"value":2552},{"type":415,"tag":783,"props":11552,"children":11553},{"class":785,"line":3080},[11554,11558,11562,11567,11571,11575,11579,11583,11587,11591,11595,11599,11603],{"type":415,"tag":783,"props":11555,"children":11556},{"style":1362},[11557],{"type":420,"value":11145},{"type":415,"tag":783,"props":11559,"children":11560},{"style":790},[11561],{"type":420,"value":755},{"type":415,"tag":783,"props":11563,"children":11564},{"style":1362},[11565],{"type":420,"value":11566},"Content ",{"type":415,"tag":783,"props":11568,"children":11569},{"style":790},[11570],{"type":420,"value":1984},{"type":415,"tag":783,"props":11572,"children":11573},{"style":790},[11574],{"type":420,"value":4335},{"type":415,"tag":783,"props":11576,"children":11577},{"style":875},[11578],{"type":420,"value":10596},{"type":415,"tag":783,"props":11580,"children":11581},{"style":790},[11582],{"type":420,"value":1845},{"type":415,"tag":783,"props":11584,"children":11585},{"style":1362},[11586],{"type":420,"value":10605},{"type":415,"tag":783,"props":11588,"children":11589},{"style":790},[11590],{"type":420,"value":755},{"type":415,"tag":783,"props":11592,"children":11593},{"style":1545},[11594],{"type":420,"value":10614},{"type":415,"tag":783,"props":11596,"children":11597},{"style":790},[11598],{"type":420,"value":1845},{"type":415,"tag":783,"props":11600,"children":11601},{"style":1362},[11602],{"type":420,"value":11470},{"type":415,"tag":783,"props":11604,"children":11605},{"style":790},[11606],{"type":420,"value":6680},{"type":415,"tag":783,"props":11608,"children":11609},{"class":785,"line":3126},[11610,11614,11618,11622,11626,11630,11634,11638,11642,11646],{"type":415,"tag":783,"props":11611,"children":11612},{"style":875},[11613],{"type":420,"value":2681},{"type":415,"tag":783,"props":11615,"children":11616},{"style":875},[11617],{"type":420,"value":10545},{"type":415,"tag":783,"props":11619,"children":11620},{"style":790},[11621],{"type":420,"value":2033},{"type":415,"tag":783,"props":11623,"children":11624},{"style":790},[11625],{"type":420,"value":2695},{"type":415,"tag":783,"props":11627,"children":11628},{"style":1362},[11629],{"type":420,"value":10558},{"type":415,"tag":783,"props":11631,"children":11632},{"style":790},[11633],{"type":420,"value":755},{"type":415,"tag":783,"props":11635,"children":11636},{"style":1545},[11637],{"type":420,"value":11237},{"type":415,"tag":783,"props":11639,"children":11640},{"style":790},[11641],{"type":420,"value":1845},{"type":415,"tag":783,"props":11643,"children":11644},{"style":1362},[11645],{"type":420,"value":11246},{"type":415,"tag":783,"props":11647,"children":11648},{"style":790},[11649],{"type":420,"value":2552},{"type":415,"tag":783,"props":11651,"children":11652},{"class":785,"line":3172},[11653,11657,11661,11665],{"type":415,"tag":783,"props":11654,"children":11655},{"style":1362},[11656],{"type":420,"value":11258},{"type":415,"tag":783,"props":11658,"children":11659},{"style":790},[11660],{"type":420,"value":755},{"type":415,"tag":783,"props":11662,"children":11663},{"style":1545},[11664],{"type":420,"value":11267},{"type":415,"tag":783,"props":11666,"children":11667},{"style":790},[11668],{"type":420,"value":2164},{"type":415,"tag":783,"props":11670,"children":11671},{"class":785,"line":3218},[11672],{"type":415,"tag":783,"props":11673,"children":11674},{"style":790},[11675],{"type":420,"value":1254},{"type":415,"tag":783,"props":11677,"children":11678},{"class":785,"line":3251},[11679],{"type":415,"tag":783,"props":11680,"children":11681},{"emptyLinePlaceholder":1624},[11682],{"type":420,"value":1627},{"type":415,"tag":783,"props":11684,"children":11685},{"class":785,"line":3278},[11686,11690,11694,11698,11702,11706,11710,11714],{"type":415,"tag":783,"props":11687,"children":11688},{"style":805},[11689],{"type":420,"value":1906},{"type":415,"tag":783,"props":11691,"children":11692},{"style":805},[11693],{"type":420,"value":2641},{"type":415,"tag":783,"props":11695,"children":11696},{"style":875},[11697],{"type":420,"value":2107},{"type":415,"tag":783,"props":11699,"children":11700},{"style":790},[11701],{"type":420,"value":2112},{"type":415,"tag":783,"props":11703,"children":11704},{"style":790},[11705],{"type":420,"value":4766},{"type":415,"tag":783,"props":11707,"children":11708},{"style":790},[11709],{"type":420,"value":2276},{"type":415,"tag":783,"props":11711,"children":11712},{"style":1545},[11713],{"type":420,"value":11070},{"type":415,"tag":783,"props":11715,"children":11716},{"style":790},[11717],{"type":420,"value":2131},{"type":415,"tag":783,"props":11719,"children":11720},{"class":785,"line":3287},[11721],{"type":415,"tag":783,"props":11722,"children":11723},{"style":790},[11724],{"type":420,"value":1971},{"type":415,"tag":783,"props":11726,"children":11727},{"class":785,"line":3308},[11728,11732,11736,11740,11744,11748,11752,11756,11760,11764,11768,11772,11776,11780,11784,11788,11792],{"type":415,"tag":783,"props":11729,"children":11730},{"style":875},[11731],{"type":420,"value":2681},{"type":415,"tag":783,"props":11733,"children":11734},{"style":875},[11735],{"type":420,"value":10469},{"type":415,"tag":783,"props":11737,"children":11738},{"style":790},[11739],{"type":420,"value":2033},{"type":415,"tag":783,"props":11741,"children":11742},{"style":790},[11743],{"type":420,"value":4335},{"type":415,"tag":783,"props":11745,"children":11746},{"style":790},[11747],{"type":420,"value":4345},{"type":415,"tag":783,"props":11749,"children":11750},{"style":1362},[11751],{"type":420,"value":10486},{"type":415,"tag":783,"props":11753,"children":11754},{"style":790},[11755],{"type":420,"value":1984},{"type":415,"tag":783,"props":11757,"children":11758},{"style":790},[11759],{"type":420,"value":822},{"type":415,"tag":783,"props":11761,"children":11762},{"style":825},[11763],{"type":420,"value":10499},{"type":415,"tag":783,"props":11765,"children":11766},{"style":790},[11767],{"type":420,"value":813},{"type":415,"tag":783,"props":11769,"children":11770},{"style":790},[11771],{"type":420,"value":2501},{"type":415,"tag":783,"props":11773,"children":11774},{"style":1362},[11775],{"type":420,"value":10512},{"type":415,"tag":783,"props":11777,"children":11778},{"style":790},[11779],{"type":420,"value":1984},{"type":415,"tag":783,"props":11781,"children":11782},{"style":790},[11783],{"type":420,"value":822},{"type":415,"tag":783,"props":11785,"children":11786},{"style":825},[11787],{"type":420,"value":10525},{"type":415,"tag":783,"props":11789,"children":11790},{"style":790},[11791],{"type":420,"value":813},{"type":415,"tag":783,"props":11793,"children":11794},{"style":790},[11795],{"type":420,"value":4506},{"type":415,"tag":783,"props":11797,"children":11798},{"class":785,"line":3335},[11799,11803,11807,11811,11815,11819,11823,11827,11831,11835,11839,11843,11847,11851,11855,11859,11863,11867,11871,11875,11879],{"type":415,"tag":783,"props":11800,"children":11801},{"style":875},[11802],{"type":420,"value":2681},{"type":415,"tag":783,"props":11804,"children":11805},{"style":875},[11806],{"type":420,"value":10545},{"type":415,"tag":783,"props":11808,"children":11809},{"style":790},[11810],{"type":420,"value":2033},{"type":415,"tag":783,"props":11812,"children":11813},{"style":790},[11814],{"type":420,"value":2695},{"type":415,"tag":783,"props":11816,"children":11817},{"style":1362},[11818],{"type":420,"value":10558},{"type":415,"tag":783,"props":11820,"children":11821},{"style":790},[11822],{"type":420,"value":755},{"type":415,"tag":783,"props":11824,"children":11825},{"style":1545},[11826],{"type":420,"value":10567},{"type":415,"tag":783,"props":11828,"children":11829},{"style":790},[11830],{"type":420,"value":1845},{"type":415,"tag":783,"props":11832,"children":11833},{"style":790},[11834],{"type":420,"value":813},{"type":415,"tag":783,"props":11836,"children":11837},{"style":825},[11838],{"type":420,"value":10499},{"type":415,"tag":783,"props":11840,"children":11841},{"style":790},[11842],{"type":420,"value":813},{"type":415,"tag":783,"props":11844,"children":11845},{"style":790},[11846],{"type":420,"value":2501},{"type":415,"tag":783,"props":11848,"children":11849},{"style":790},[11850],{"type":420,"value":4335},{"type":415,"tag":783,"props":11852,"children":11853},{"style":875},[11854],{"type":420,"value":10596},{"type":415,"tag":783,"props":11856,"children":11857},{"style":790},[11858],{"type":420,"value":1845},{"type":415,"tag":783,"props":11860,"children":11861},{"style":1362},[11862],{"type":420,"value":10605},{"type":415,"tag":783,"props":11864,"children":11865},{"style":790},[11866],{"type":420,"value":755},{"type":415,"tag":783,"props":11868,"children":11869},{"style":1545},[11870],{"type":420,"value":10614},{"type":415,"tag":783,"props":11872,"children":11873},{"style":790},[11874],{"type":420,"value":1845},{"type":415,"tag":783,"props":11876,"children":11877},{"style":1362},[11878],{"type":420,"value":10623},{"type":415,"tag":783,"props":11880,"children":11881},{"style":790},[11882],{"type":420,"value":10628},{"type":415,"tag":783,"props":11884,"children":11885},{"class":785,"line":3349},[11886,11890,11894,11898,11902,11906,11910,11914,11918,11922,11926,11930],{"type":415,"tag":783,"props":11887,"children":11888},{"style":875},[11889],{"type":420,"value":2681},{"type":415,"tag":783,"props":11891,"children":11892},{"style":875},[11893],{"type":420,"value":10640},{"type":415,"tag":783,"props":11895,"children":11896},{"style":790},[11897],{"type":420,"value":2033},{"type":415,"tag":783,"props":11899,"children":11900},{"style":790},[11901],{"type":420,"value":2695},{"type":415,"tag":783,"props":11903,"children":11904},{"style":1362},[11905],{"type":420,"value":10545},{"type":415,"tag":783,"props":11907,"children":11908},{"style":790},[11909],{"type":420,"value":755},{"type":415,"tag":783,"props":11911,"children":11912},{"style":1362},[11913],{"type":420,"value":10661},{"type":415,"tag":783,"props":11915,"children":11916},{"style":790},[11917],{"type":420,"value":755},{"type":415,"tag":783,"props":11919,"children":11920},{"style":1545},[11921],{"type":420,"value":10670},{"type":415,"tag":783,"props":11923,"children":11924},{"style":790},[11925],{"type":420,"value":2112},{"type":415,"tag":783,"props":11927,"children":11928},{"style":875},[11929],{"type":420,"value":10269},{"type":415,"tag":783,"props":11931,"children":11932},{"style":790},[11933],{"type":420,"value":6735},{"type":415,"tag":783,"props":11935,"children":11936},{"class":785,"line":3358},[11937,11941,11945,11949,11954],{"type":415,"tag":783,"props":11938,"children":11939},{"style":1356},[11940],{"type":420,"value":2146},{"type":415,"tag":783,"props":11942,"children":11943},{"style":1362},[11944],{"type":420,"value":10640},{"type":415,"tag":783,"props":11946,"children":11947},{"style":790},[11948],{"type":420,"value":755},{"type":415,"tag":783,"props":11950,"children":11951},{"style":1362},[11952],{"type":420,"value":11953},"Token",{"type":415,"tag":783,"props":11955,"children":11956},{"style":790},[11957],{"type":420,"value":1926},{"type":415,"tag":783,"props":11959,"children":11960},{"class":785,"line":3435},[11961],{"type":415,"tag":783,"props":11962,"children":11963},{"style":790},[11964],{"type":420,"value":1254},{"type":415,"tag":783,"props":11966,"children":11967},{"class":785,"line":3492},[11968],{"type":415,"tag":783,"props":11969,"children":11970},{"style":790},[11971],{"type":420,"value":1272},{"type":415,"tag":416,"props":11973,"children":11974},{},[11975],{"type":420,"value":11976},"There are two main problems with this way of doing things:",{"type":415,"tag":493,"props":11978,"children":11979},{},[11980,12000],{"type":415,"tag":497,"props":11981,"children":11982},{},[11983,11985,11991,11993,11998],{"type":420,"value":11984},"We have some code duplication as we are calling the ",{"type":415,"tag":550,"props":11986,"children":11988},{"className":11987},[],[11989],{"type":420,"value":11990},"RetrieveToken",{"type":420,"value":11992}," 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":550,"props":11994,"children":11996},{"className":11995},[],[11997],{"type":420,"value":11990},{"type":420,"value":11999},"in each method.",{"type":415,"tag":497,"props":12001,"children":12002},{},[12003,12005,12010],{"type":420,"value":12004},"For each call to an authenticated route of the API, we are making a call to the ",{"type":415,"tag":550,"props":12006,"children":12008},{"className":12007},[],[12009],{"type":420,"value":10499},{"type":420,"value":12011}," route even if our token from a previous call is probably still valid.",{"type":415,"tag":443,"props":12013,"children":12015},{"id":12014},"use-a-dedicated-service-to-retrieve-the-token-and-save-it-for-future-calls",[12016],{"type":420,"value":12017},"Use a dedicated service to retrieve the token and save it for future calls",{"type":415,"tag":416,"props":12019,"children":12020},{},[12021,12023,12028,12030,12036,12038,12043,12045,12050,12052,12057],{"type":420,"value":12022},"Although it's not necessary at this point, it can be interesting to move the code of our private method ",{"type":415,"tag":550,"props":12024,"children":12026},{"className":12025},[],[12027],{"type":420,"value":11990},{"type":420,"value":12029}," into a separate service ",{"type":415,"tag":550,"props":12031,"children":12033},{"className":12032},[],[12034],{"type":420,"value":12035},"UserApiAuthenticationService",{"type":420,"value":12037}," that will be injected in ",{"type":415,"tag":550,"props":12039,"children":12041},{"className":12040},[],[12042],{"type":420,"value":10849},{"type":420,"value":12044},". That way, if the authentication method changes someday, ",{"type":415,"tag":550,"props":12046,"children":12048},{"className":12047},[],[12049],{"type":420,"value":10849},{"type":420,"value":12051}," implementation won't change. Moreover, we won't mess with the same ",{"type":415,"tag":550,"props":12053,"children":12055},{"className":12054},[],[12056],{"type":420,"value":9774},{"type":420,"value":12058}," for authentication and other calls.",{"type":415,"tag":773,"props":12060,"children":12062},{"className":1805,"code":12061,"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",[12063],{"type":415,"tag":550,"props":12064,"children":12065},{"__ignoreMap":401},[12066,12091,12098,12123,12146,12153,12193,12200,12219,12239,12246,12253,12288,12295,12312,12377,12385,12457,12544,12610,12677,12685,12700,12707],{"type":415,"tag":783,"props":12067,"children":12068},{"class":785,"line":786},[12069,12073,12077,12082,12086],{"type":415,"tag":783,"props":12070,"children":12071},{"style":805},[12072],{"type":420,"value":1871},{"type":415,"tag":783,"props":12074,"children":12075},{"style":875},[12076],{"type":420,"value":1876},{"type":415,"tag":783,"props":12078,"children":12079},{"style":875},[12080],{"type":420,"value":12081}," UserApiAuthenticationService",{"type":415,"tag":783,"props":12083,"children":12084},{"style":790},[12085],{"type":420,"value":1886},{"type":415,"tag":783,"props":12087,"children":12088},{"style":875},[12089],{"type":420,"value":12090}," IUserApiAuthenticationService\n",{"type":415,"tag":783,"props":12092,"children":12093},{"class":785,"line":796},[12094],{"type":415,"tag":783,"props":12095,"children":12096},{"style":790},[12097],{"type":420,"value":793},{"type":415,"tag":783,"props":12099,"children":12100},{"class":785,"line":840},[12101,12105,12109,12114,12119],{"type":415,"tag":783,"props":12102,"children":12103},{"style":805},[12104],{"type":420,"value":1906},{"type":415,"tag":783,"props":12106,"children":12107},{"style":805},[12108],{"type":420,"value":1911},{"type":415,"tag":783,"props":12110,"children":12111},{"style":875},[12112],{"type":420,"value":12113}," IMemoryCache",{"type":415,"tag":783,"props":12115,"children":12116},{"style":875},[12117],{"type":420,"value":12118}," _memoryCache",{"type":415,"tag":783,"props":12120,"children":12121},{"style":790},[12122],{"type":420,"value":1926},{"type":415,"tag":783,"props":12124,"children":12125},{"class":785,"line":866},[12126,12130,12134,12138,12142],{"type":415,"tag":783,"props":12127,"children":12128},{"style":805},[12129],{"type":420,"value":1906},{"type":415,"tag":783,"props":12131,"children":12132},{"style":805},[12133],{"type":420,"value":1911},{"type":415,"tag":783,"props":12135,"children":12136},{"style":875},[12137],{"type":420,"value":10918},{"type":415,"tag":783,"props":12139,"children":12140},{"style":875},[12141],{"type":420,"value":10558},{"type":415,"tag":783,"props":12143,"children":12144},{"style":790},[12145],{"type":420,"value":1926},{"type":415,"tag":783,"props":12147,"children":12148},{"class":785,"line":893},[12149],{"type":415,"tag":783,"props":12150,"children":12151},{"emptyLinePlaceholder":1624},[12152],{"type":420,"value":1627},{"type":415,"tag":783,"props":12154,"children":12155},{"class":785,"line":920},[12156,12160,12164,12168,12172,12176,12180,12184,12189],{"type":415,"tag":783,"props":12157,"children":12158},{"style":805},[12159],{"type":420,"value":1941},{"type":415,"tag":783,"props":12161,"children":12162},{"style":1545},[12163],{"type":420,"value":12081},{"type":415,"tag":783,"props":12165,"children":12166},{"style":790},[12167],{"type":420,"value":1845},{"type":415,"tag":783,"props":12169,"children":12170},{"style":875},[12171],{"type":420,"value":9774},{"type":415,"tag":783,"props":12173,"children":12174},{"style":875},[12175],{"type":420,"value":10950},{"type":415,"tag":783,"props":12177,"children":12178},{"style":790},[12179],{"type":420,"value":2501},{"type":415,"tag":783,"props":12181,"children":12182},{"style":875},[12183],{"type":420,"value":12113},{"type":415,"tag":783,"props":12185,"children":12186},{"style":875},[12187],{"type":420,"value":12188}," memoryCache",{"type":415,"tag":783,"props":12190,"children":12191},{"style":790},[12192],{"type":420,"value":1963},{"type":415,"tag":783,"props":12194,"children":12195},{"class":785,"line":959},[12196],{"type":415,"tag":783,"props":12197,"children":12198},{"style":790},[12199],{"type":420,"value":1971},{"type":415,"tag":783,"props":12201,"children":12202},{"class":785,"line":997},[12203,12207,12211,12215],{"type":415,"tag":783,"props":12204,"children":12205},{"style":1362},[12206],{"type":420,"value":10969},{"type":415,"tag":783,"props":12208,"children":12209},{"style":790},[12210],{"type":420,"value":1984},{"type":415,"tag":783,"props":12212,"children":12213},{"style":1362},[12214],{"type":420,"value":10950},{"type":415,"tag":783,"props":12216,"children":12217},{"style":790},[12218],{"type":420,"value":1926},{"type":415,"tag":783,"props":12220,"children":12221},{"class":785,"line":1023},[12222,12227,12231,12235],{"type":415,"tag":783,"props":12223,"children":12224},{"style":1362},[12225],{"type":420,"value":12226},"        _memoryCache ",{"type":415,"tag":783,"props":12228,"children":12229},{"style":790},[12230],{"type":420,"value":1984},{"type":415,"tag":783,"props":12232,"children":12233},{"style":1362},[12234],{"type":420,"value":12188},{"type":415,"tag":783,"props":12236,"children":12237},{"style":790},[12238],{"type":420,"value":1926},{"type":415,"tag":783,"props":12240,"children":12241},{"class":785,"line":1061},[12242],{"type":415,"tag":783,"props":12243,"children":12244},{"style":790},[12245],{"type":420,"value":1254},{"type":415,"tag":783,"props":12247,"children":12248},{"class":785,"line":1099},[12249],{"type":415,"tag":783,"props":12250,"children":12251},{"emptyLinePlaceholder":1624},[12252],{"type":420,"value":1627},{"type":415,"tag":783,"props":12254,"children":12255},{"class":785,"line":1137},[12256,12260,12264,12268,12272,12276,12280,12284],{"type":415,"tag":783,"props":12257,"children":12258},{"style":805},[12259],{"type":420,"value":1941},{"type":415,"tag":783,"props":12261,"children":12262},{"style":805},[12263],{"type":420,"value":2641},{"type":415,"tag":783,"props":12265,"children":12266},{"style":875},[12267],{"type":420,"value":2107},{"type":415,"tag":783,"props":12269,"children":12270},{"style":790},[12271],{"type":420,"value":2112},{"type":415,"tag":783,"props":12273,"children":12274},{"style":790},[12275],{"type":420,"value":4766},{"type":415,"tag":783,"props":12277,"children":12278},{"style":790},[12279],{"type":420,"value":2276},{"type":415,"tag":783,"props":12281,"children":12282},{"style":1545},[12283],{"type":420,"value":11070},{"type":415,"tag":783,"props":12285,"children":12286},{"style":790},[12287],{"type":420,"value":2131},{"type":415,"tag":783,"props":12289,"children":12290},{"class":785,"line":1175},[12291],{"type":415,"tag":783,"props":12292,"children":12293},{"style":790},[12294],{"type":420,"value":1971},{"type":415,"tag":783,"props":12296,"children":12297},{"class":785,"line":1213},[12298,12303,12308],{"type":415,"tag":783,"props":12299,"children":12300},{"style":875},[12301],{"type":420,"value":12302},"        DateTime",{"type":415,"tag":783,"props":12304,"children":12305},{"style":875},[12306],{"type":420,"value":12307}," expirationDate",{"type":415,"tag":783,"props":12309,"children":12310},{"style":790},[12311],{"type":420,"value":1926},{"type":415,"tag":783,"props":12313,"children":12314},{"class":785,"line":1239},[12315,12320,12325,12330,12334,12339,12343,12347,12351,12355,12359,12364,12368,12372],{"type":415,"tag":783,"props":12316,"children":12317},{"style":1356},[12318],{"type":420,"value":12319},"        if",{"type":415,"tag":783,"props":12321,"children":12322},{"style":790},[12323],{"type":420,"value":12324}," (!",{"type":415,"tag":783,"props":12326,"children":12327},{"style":1362},[12328],{"type":420,"value":12329},"_memoryCache",{"type":415,"tag":783,"props":12331,"children":12332},{"style":790},[12333],{"type":420,"value":755},{"type":415,"tag":783,"props":12335,"children":12336},{"style":1545},[12337],{"type":420,"value":12338},"TryGetValue",{"type":415,"tag":783,"props":12340,"children":12341},{"style":790},[12342],{"type":420,"value":1845},{"type":415,"tag":783,"props":12344,"children":12345},{"style":790},[12346],{"type":420,"value":813},{"type":415,"tag":783,"props":12348,"children":12349},{"style":825},[12350],{"type":420,"value":11953},{"type":415,"tag":783,"props":12352,"children":12353},{"style":790},[12354],{"type":420,"value":813},{"type":415,"tag":783,"props":12356,"children":12357},{"style":790},[12358],{"type":420,"value":2501},{"type":415,"tag":783,"props":12360,"children":12361},{"style":805},[12362],{"type":420,"value":12363}," out",{"type":415,"tag":783,"props":12365,"children":12366},{"style":790},[12367],{"type":420,"value":3798},{"type":415,"tag":783,"props":12369,"children":12370},{"style":875},[12371],{"type":420,"value":11057},{"type":415,"tag":783,"props":12373,"children":12374},{"style":790},[12375],{"type":420,"value":12376},"))\n",{"type":415,"tag":783,"props":12378,"children":12379},{"class":785,"line":1248},[12380],{"type":415,"tag":783,"props":12381,"children":12382},{"style":790},[12383],{"type":420,"value":12384},"        {\n",{"type":415,"tag":783,"props":12386,"children":12387},{"class":785,"line":1257},[12388,12393,12397,12401,12405,12409,12413,12417,12421,12425,12429,12433,12437,12441,12445,12449,12453],{"type":415,"tag":783,"props":12389,"children":12390},{"style":875},[12391],{"type":420,"value":12392},"            var",{"type":415,"tag":783,"props":12394,"children":12395},{"style":875},[12396],{"type":420,"value":10469},{"type":415,"tag":783,"props":12398,"children":12399},{"style":790},[12400],{"type":420,"value":2033},{"type":415,"tag":783,"props":12402,"children":12403},{"style":790},[12404],{"type":420,"value":4335},{"type":415,"tag":783,"props":12406,"children":12407},{"style":790},[12408],{"type":420,"value":4345},{"type":415,"tag":783,"props":12410,"children":12411},{"style":1362},[12412],{"type":420,"value":10486},{"type":415,"tag":783,"props":12414,"children":12415},{"style":790},[12416],{"type":420,"value":1984},{"type":415,"tag":783,"props":12418,"children":12419},{"style":790},[12420],{"type":420,"value":822},{"type":415,"tag":783,"props":12422,"children":12423},{"style":825},[12424],{"type":420,"value":10499},{"type":415,"tag":783,"props":12426,"children":12427},{"style":790},[12428],{"type":420,"value":813},{"type":415,"tag":783,"props":12430,"children":12431},{"style":790},[12432],{"type":420,"value":2501},{"type":415,"tag":783,"props":12434,"children":12435},{"style":1362},[12436],{"type":420,"value":10512},{"type":415,"tag":783,"props":12438,"children":12439},{"style":790},[12440],{"type":420,"value":1984},{"type":415,"tag":783,"props":12442,"children":12443},{"style":790},[12444],{"type":420,"value":822},{"type":415,"tag":783,"props":12446,"children":12447},{"style":825},[12448],{"type":420,"value":10525},{"type":415,"tag":783,"props":12450,"children":12451},{"style":790},[12452],{"type":420,"value":813},{"type":415,"tag":783,"props":12454,"children":12455},{"style":790},[12456],{"type":420,"value":4506},{"type":415,"tag":783,"props":12458,"children":12459},{"class":785,"line":1266},[12460,12464,12468,12472,12476,12480,12484,12488,12492,12496,12500,12504,12508,12512,12516,12520,12524,12528,12532,12536,12540],{"type":415,"tag":783,"props":12461,"children":12462},{"style":875},[12463],{"type":420,"value":12392},{"type":415,"tag":783,"props":12465,"children":12466},{"style":875},[12467],{"type":420,"value":10545},{"type":415,"tag":783,"props":12469,"children":12470},{"style":790},[12471],{"type":420,"value":2033},{"type":415,"tag":783,"props":12473,"children":12474},{"style":790},[12475],{"type":420,"value":2695},{"type":415,"tag":783,"props":12477,"children":12478},{"style":1362},[12479],{"type":420,"value":10558},{"type":415,"tag":783,"props":12481,"children":12482},{"style":790},[12483],{"type":420,"value":755},{"type":415,"tag":783,"props":12485,"children":12486},{"style":1545},[12487],{"type":420,"value":10567},{"type":415,"tag":783,"props":12489,"children":12490},{"style":790},[12491],{"type":420,"value":1845},{"type":415,"tag":783,"props":12493,"children":12494},{"style":790},[12495],{"type":420,"value":813},{"type":415,"tag":783,"props":12497,"children":12498},{"style":825},[12499],{"type":420,"value":10499},{"type":415,"tag":783,"props":12501,"children":12502},{"style":790},[12503],{"type":420,"value":813},{"type":415,"tag":783,"props":12505,"children":12506},{"style":790},[12507],{"type":420,"value":2501},{"type":415,"tag":783,"props":12509,"children":12510},{"style":790},[12511],{"type":420,"value":4335},{"type":415,"tag":783,"props":12513,"children":12514},{"style":875},[12515],{"type":420,"value":10596},{"type":415,"tag":783,"props":12517,"children":12518},{"style":790},[12519],{"type":420,"value":1845},{"type":415,"tag":783,"props":12521,"children":12522},{"style":1362},[12523],{"type":420,"value":10605},{"type":415,"tag":783,"props":12525,"children":12526},{"style":790},[12527],{"type":420,"value":755},{"type":415,"tag":783,"props":12529,"children":12530},{"style":1545},[12531],{"type":420,"value":10614},{"type":415,"tag":783,"props":12533,"children":12534},{"style":790},[12535],{"type":420,"value":1845},{"type":415,"tag":783,"props":12537,"children":12538},{"style":1362},[12539],{"type":420,"value":10623},{"type":415,"tag":783,"props":12541,"children":12542},{"style":790},[12543],{"type":420,"value":10628},{"type":415,"tag":783,"props":12545,"children":12546},{"class":785,"line":2847},[12547,12552,12557,12561,12566,12570,12574,12578,12582,12586,12590,12594,12598,12602,12606],{"type":415,"tag":783,"props":12548,"children":12549},{"style":790},[12550],{"type":420,"value":12551},"            (",{"type":415,"tag":783,"props":12553,"children":12554},{"style":1362},[12555],{"type":420,"value":12556},"token",{"type":415,"tag":783,"props":12558,"children":12559},{"style":790},[12560],{"type":420,"value":2501},{"type":415,"tag":783,"props":12562,"children":12563},{"style":1362},[12564],{"type":420,"value":12565},"  expirationDate",{"type":415,"tag":783,"props":12567,"children":12568},{"style":790},[12569],{"type":420,"value":1678},{"type":415,"tag":783,"props":12571,"children":12572},{"style":790},[12573],{"type":420,"value":2033},{"type":415,"tag":783,"props":12575,"children":12576},{"style":790},[12577],{"type":420,"value":2695},{"type":415,"tag":783,"props":12579,"children":12580},{"style":1362},[12581],{"type":420,"value":10545},{"type":415,"tag":783,"props":12583,"children":12584},{"style":790},[12585],{"type":420,"value":755},{"type":415,"tag":783,"props":12587,"children":12588},{"style":1362},[12589],{"type":420,"value":10661},{"type":415,"tag":783,"props":12591,"children":12592},{"style":790},[12593],{"type":420,"value":755},{"type":415,"tag":783,"props":12595,"children":12596},{"style":1545},[12597],{"type":420,"value":10670},{"type":415,"tag":783,"props":12599,"children":12600},{"style":790},[12601],{"type":420,"value":2112},{"type":415,"tag":783,"props":12603,"children":12604},{"style":875},[12605],{"type":420,"value":10269},{"type":415,"tag":783,"props":12607,"children":12608},{"style":790},[12609],{"type":420,"value":6735},{"type":415,"tag":783,"props":12611,"children":12612},{"class":785,"line":2896},[12613,12618,12622,12627,12631,12635,12639,12643,12647,12651,12655,12659,12664,12668,12673],{"type":415,"tag":783,"props":12614,"children":12615},{"style":1362},[12616],{"type":420,"value":12617},"            _memoryCache",{"type":415,"tag":783,"props":12619,"children":12620},{"style":790},[12621],{"type":420,"value":755},{"type":415,"tag":783,"props":12623,"children":12624},{"style":1545},[12625],{"type":420,"value":12626},"Set",{"type":415,"tag":783,"props":12628,"children":12629},{"style":790},[12630],{"type":420,"value":1845},{"type":415,"tag":783,"props":12632,"children":12633},{"style":790},[12634],{"type":420,"value":813},{"type":415,"tag":783,"props":12636,"children":12637},{"style":825},[12638],{"type":420,"value":11953},{"type":415,"tag":783,"props":12640,"children":12641},{"style":790},[12642],{"type":420,"value":813},{"type":415,"tag":783,"props":12644,"children":12645},{"style":790},[12646],{"type":420,"value":2501},{"type":415,"tag":783,"props":12648,"children":12649},{"style":1362},[12650],{"type":420,"value":11057},{"type":415,"tag":783,"props":12652,"children":12653},{"style":790},[12654],{"type":420,"value":2501},{"type":415,"tag":783,"props":12656,"children":12657},{"style":790},[12658],{"type":420,"value":4335},{"type":415,"tag":783,"props":12660,"children":12661},{"style":875},[12662],{"type":420,"value":12663}," DateTimeOffset",{"type":415,"tag":783,"props":12665,"children":12666},{"style":790},[12667],{"type":420,"value":1845},{"type":415,"tag":783,"props":12669,"children":12670},{"style":1362},[12671],{"type":420,"value":12672},"expirationDate",{"type":415,"tag":783,"props":12674,"children":12675},{"style":790},[12676],{"type":420,"value":6680},{"type":415,"tag":783,"props":12678,"children":12679},{"class":785,"line":2942},[12680],{"type":415,"tag":783,"props":12681,"children":12682},{"style":790},[12683],{"type":420,"value":12684},"        }\n",{"type":415,"tag":783,"props":12686,"children":12687},{"class":785,"line":2988},[12688,12692,12696],{"type":415,"tag":783,"props":12689,"children":12690},{"style":1356},[12691],{"type":420,"value":2146},{"type":415,"tag":783,"props":12693,"children":12694},{"style":1362},[12695],{"type":420,"value":11057},{"type":415,"tag":783,"props":12697,"children":12698},{"style":790},[12699],{"type":420,"value":1926},{"type":415,"tag":783,"props":12701,"children":12702},{"class":785,"line":3034},[12703],{"type":415,"tag":783,"props":12704,"children":12705},{"style":790},[12706],{"type":420,"value":1254},{"type":415,"tag":783,"props":12708,"children":12709},{"class":785,"line":3080},[12710],{"type":415,"tag":783,"props":12711,"children":12712},{"style":790},[12713],{"type":420,"value":1272},{"type":415,"tag":416,"props":12715,"children":12716},{},[12717,12719,12725,12727,12733],{"type":420,"value":12718},"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":550,"props":12720,"children":12722},{"className":12721},[],[12723],{"type":420,"value":12724},"IMemoryCache",{"type":420,"value":12726}," 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":423,"props":12728,"children":12731},{"href":12729,"rel":12730},"https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1",[427],[12732],{"type":420,"value":7221},{"type":420,"value":755},{"type":415,"tag":443,"props":12735,"children":12737},{"id":12736},"use-a-delegating-handler-to-directly-set-the-token-in-the-httpclient-request",[12738],{"type":420,"value":12739},"Use a Delegating handler to directly set the token in the HttpClient request",{"type":415,"tag":416,"props":12741,"children":12742},{},[12743,12745,12750,12752,12757,12759,12764,12766,12771,12773,12778],{"type":420,"value":12744},"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":550,"props":12746,"children":12748},{"className":12747},[],[12749],{"type":420,"value":11990},{"type":420,"value":12751}," method is now part of ",{"type":415,"tag":550,"props":12753,"children":12755},{"className":12754},[],[12756],{"type":420,"value":12035},{"type":420,"value":12758},", each method of ",{"type":415,"tag":550,"props":12760,"children":12762},{"className":12761},[],[12763],{"type":420,"value":10849},{"type":420,"value":12765}," will still call ",{"type":415,"tag":550,"props":12767,"children":12769},{"className":12768},[],[12770],{"type":420,"value":11990},{"type":420,"value":12772},". Moreover setting the token on each request should not be a concern of ",{"type":415,"tag":550,"props":12774,"children":12776},{"className":12775},[],[12777],{"type":420,"value":10849},{"type":420,"value":755},{"type":415,"tag":416,"props":12780,"children":12781},{},[12782,12784,12789,12791,12796,12798,12802,12804,12811],{"type":420,"value":12783},"That's where come ",{"type":415,"tag":7543,"props":12785,"children":12786},{},[12787],{"type":420,"value":12788},"delegating handlers",{"type":420,"value":12790},". 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":550,"props":12792,"children":12794},{"className":12793},[],[12795],{"type":420,"value":9774},{"type":420,"value":12797},". To learn more about ",{"type":415,"tag":7543,"props":12799,"children":12800},{},[12801],{"type":420,"value":12788},{"type":420,"value":12803}," there is a nice ",{"type":415,"tag":423,"props":12805,"children":12808},{"href":12806,"rel":12807},"https://www.stevejgordon.co.uk/httpclientfactory-aspnetcore-outgoing-request-middleware-pipeline-delegatinghandlers",[427],[12809],{"type":420,"value":12810},"article",{"type":420,"value":12812}," from Steve Gordon on the topic.",{"type":415,"tag":416,"props":12814,"children":12815},{},[12816,12818,12823],{"type":420,"value":12817},"A custom delegating handler is exactly what we need: a piece of code that all our HTTP requests from ",{"type":415,"tag":550,"props":12819,"children":12821},{"className":12820},[],[12822],{"type":420,"value":10849},{"type":420,"value":12824}," 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":773,"props":12826,"children":12828},{"className":1805,"code":12827,"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",[12829],{"type":415,"tag":550,"props":12830,"children":12831},{"__ignoreMap":401},[12832,12857,12864,12889,12896,12925,12932,12952,12959,12966,13030,13037,13072,13135,13180,13187],{"type":415,"tag":783,"props":12833,"children":12834},{"class":785,"line":786},[12835,12839,12843,12848,12852],{"type":415,"tag":783,"props":12836,"children":12837},{"style":805},[12838],{"type":420,"value":1871},{"type":415,"tag":783,"props":12840,"children":12841},{"style":875},[12842],{"type":420,"value":1876},{"type":415,"tag":783,"props":12844,"children":12845},{"style":875},[12846],{"type":420,"value":12847}," UserApiAuthenticationHandler",{"type":415,"tag":783,"props":12849,"children":12850},{"style":790},[12851],{"type":420,"value":1886},{"type":415,"tag":783,"props":12853,"children":12854},{"style":875},[12855],{"type":420,"value":12856}," DelegatingHandler\n",{"type":415,"tag":783,"props":12858,"children":12859},{"class":785,"line":796},[12860],{"type":415,"tag":783,"props":12861,"children":12862},{"style":790},[12863],{"type":420,"value":793},{"type":415,"tag":783,"props":12865,"children":12866},{"class":785,"line":840},[12867,12871,12875,12880,12885],{"type":415,"tag":783,"props":12868,"children":12869},{"style":805},[12870],{"type":420,"value":1906},{"type":415,"tag":783,"props":12872,"children":12873},{"style":805},[12874],{"type":420,"value":1911},{"type":415,"tag":783,"props":12876,"children":12877},{"style":875},[12878],{"type":420,"value":12879}," IUserApiAuthenticationService",{"type":415,"tag":783,"props":12881,"children":12882},{"style":875},[12883],{"type":420,"value":12884}," _authenticationService",{"type":415,"tag":783,"props":12886,"children":12887},{"style":790},[12888],{"type":420,"value":1926},{"type":415,"tag":783,"props":12890,"children":12891},{"class":785,"line":866},[12892],{"type":415,"tag":783,"props":12893,"children":12894},{"emptyLinePlaceholder":1624},[12895],{"type":420,"value":1627},{"type":415,"tag":783,"props":12897,"children":12898},{"class":785,"line":893},[12899,12903,12907,12911,12916,12921],{"type":415,"tag":783,"props":12900,"children":12901},{"style":805},[12902],{"type":420,"value":1941},{"type":415,"tag":783,"props":12904,"children":12905},{"style":1545},[12906],{"type":420,"value":12847},{"type":415,"tag":783,"props":12908,"children":12909},{"style":790},[12910],{"type":420,"value":1845},{"type":415,"tag":783,"props":12912,"children":12913},{"style":875},[12914],{"type":420,"value":12915},"IUserApiAuthenticationService",{"type":415,"tag":783,"props":12917,"children":12918},{"style":875},[12919],{"type":420,"value":12920}," authenticationService",{"type":415,"tag":783,"props":12922,"children":12923},{"style":790},[12924],{"type":420,"value":1963},{"type":415,"tag":783,"props":12926,"children":12927},{"class":785,"line":920},[12928],{"type":415,"tag":783,"props":12929,"children":12930},{"style":790},[12931],{"type":420,"value":1971},{"type":415,"tag":783,"props":12933,"children":12934},{"class":785,"line":959},[12935,12940,12944,12948],{"type":415,"tag":783,"props":12936,"children":12937},{"style":1362},[12938],{"type":420,"value":12939},"        _authenticationService ",{"type":415,"tag":783,"props":12941,"children":12942},{"style":790},[12943],{"type":420,"value":1984},{"type":415,"tag":783,"props":12945,"children":12946},{"style":1362},[12947],{"type":420,"value":12920},{"type":415,"tag":783,"props":12949,"children":12950},{"style":790},[12951],{"type":420,"value":1926},{"type":415,"tag":783,"props":12953,"children":12954},{"class":785,"line":997},[12955],{"type":415,"tag":783,"props":12956,"children":12957},{"style":790},[12958],{"type":420,"value":1254},{"type":415,"tag":783,"props":12960,"children":12961},{"class":785,"line":1023},[12962],{"type":415,"tag":783,"props":12963,"children":12964},{"style":1362},[12965],{"type":420,"value":5167},{"type":415,"tag":783,"props":12967,"children":12968},{"class":785,"line":1061},[12969,12974,12978,12983,12987,12991,12996,13000,13005,13009,13013,13017,13021,13026],{"type":415,"tag":783,"props":12970,"children":12971},{"style":805},[12972],{"type":420,"value":12973},"    protected",{"type":415,"tag":783,"props":12975,"children":12976},{"style":805},[12977],{"type":420,"value":2641},{"type":415,"tag":783,"props":12979,"children":12980},{"style":805},[12981],{"type":420,"value":12982}," override",{"type":415,"tag":783,"props":12984,"children":12985},{"style":875},[12986],{"type":420,"value":2107},{"type":415,"tag":783,"props":12988,"children":12989},{"style":790},[12990],{"type":420,"value":2112},{"type":415,"tag":783,"props":12992,"children":12993},{"style":875},[12994],{"type":420,"value":12995},"HttpResponseMessage",{"type":415,"tag":783,"props":12997,"children":12998},{"style":790},[12999],{"type":420,"value":2276},{"type":415,"tag":783,"props":13001,"children":13002},{"style":1545},[13003],{"type":420,"value":13004}," SendAsync",{"type":415,"tag":783,"props":13006,"children":13007},{"style":790},[13008],{"type":420,"value":1845},{"type":415,"tag":783,"props":13010,"children":13011},{"style":875},[13012],{"type":420,"value":9889},{"type":415,"tag":783,"props":13014,"children":13015},{"style":875},[13016],{"type":420,"value":11086},{"type":415,"tag":783,"props":13018,"children":13019},{"style":790},[13020],{"type":420,"value":2501},{"type":415,"tag":783,"props":13022,"children":13023},{"style":1362},[13024],{"type":420,"value":13025}," CancellationTokencancellationToken",{"type":415,"tag":783,"props":13027,"children":13028},{"style":790},[13029],{"type":420,"value":1963},{"type":415,"tag":783,"props":13031,"children":13032},{"class":785,"line":1099},[13033],{"type":415,"tag":783,"props":13034,"children":13035},{"style":790},[13036],{"type":420,"value":1971},{"type":415,"tag":783,"props":13038,"children":13039},{"class":785,"line":1137},[13040,13044,13048,13052,13056,13060,13064,13068],{"type":415,"tag":783,"props":13041,"children":13042},{"style":875},[13043],{"type":420,"value":2681},{"type":415,"tag":783,"props":13045,"children":13046},{"style":875},[13047],{"type":420,"value":11057},{"type":415,"tag":783,"props":13049,"children":13050},{"style":790},[13051],{"type":420,"value":2033},{"type":415,"tag":783,"props":13053,"children":13054},{"style":790},[13055],{"type":420,"value":2695},{"type":415,"tag":783,"props":13057,"children":13058},{"style":1362},[13059],{"type":420,"value":12884},{"type":415,"tag":783,"props":13061,"children":13062},{"style":790},[13063],{"type":420,"value":755},{"type":415,"tag":783,"props":13065,"children":13066},{"style":1545},[13067],{"type":420,"value":11990},{"type":415,"tag":783,"props":13069,"children":13070},{"style":790},[13071],{"type":420,"value":2164},{"type":415,"tag":783,"props":13073,"children":13074},{"class":785,"line":1175},[13075,13079,13083,13087,13091,13095,13099,13103,13107,13111,13115,13119,13123,13127,13131],{"type":415,"tag":783,"props":13076,"children":13077},{"style":1362},[13078],{"type":420,"value":11145},{"type":415,"tag":783,"props":13080,"children":13081},{"style":790},[13082],{"type":420,"value":755},{"type":415,"tag":783,"props":13084,"children":13085},{"style":1362},[13086],{"type":420,"value":11154},{"type":415,"tag":783,"props":13088,"children":13089},{"style":790},[13090],{"type":420,"value":755},{"type":415,"tag":783,"props":13092,"children":13093},{"style":1362},[13094],{"type":420,"value":11163},{"type":415,"tag":783,"props":13096,"children":13097},{"style":790},[13098],{"type":420,"value":1984},{"type":415,"tag":783,"props":13100,"children":13101},{"style":790},[13102],{"type":420,"value":4335},{"type":415,"tag":783,"props":13104,"children":13105},{"style":875},[13106],{"type":420,"value":11176},{"type":415,"tag":783,"props":13108,"children":13109},{"style":790},[13110],{"type":420,"value":1845},{"type":415,"tag":783,"props":13112,"children":13113},{"style":790},[13114],{"type":420,"value":813},{"type":415,"tag":783,"props":13116,"children":13117},{"style":825},[13118],{"type":420,"value":11189},{"type":415,"tag":783,"props":13120,"children":13121},{"style":790},[13122],{"type":420,"value":813},{"type":415,"tag":783,"props":13124,"children":13125},{"style":790},[13126],{"type":420,"value":2501},{"type":415,"tag":783,"props":13128,"children":13129},{"style":1362},[13130],{"type":420,"value":11057},{"type":415,"tag":783,"props":13132,"children":13133},{"style":790},[13134],{"type":420,"value":2552},{"type":415,"tag":783,"props":13136,"children":13137},{"class":785,"line":1213},[13138,13142,13146,13151,13155,13159,13163,13167,13171,13176],{"type":415,"tag":783,"props":13139,"children":13140},{"style":1356},[13141],{"type":420,"value":2146},{"type":415,"tag":783,"props":13143,"children":13144},{"style":790},[13145],{"type":420,"value":2695},{"type":415,"tag":783,"props":13147,"children":13148},{"style":1362},[13149],{"type":420,"value":13150}," base",{"type":415,"tag":783,"props":13152,"children":13153},{"style":790},[13154],{"type":420,"value":755},{"type":415,"tag":783,"props":13156,"children":13157},{"style":1545},[13158],{"type":420,"value":11237},{"type":415,"tag":783,"props":13160,"children":13161},{"style":790},[13162],{"type":420,"value":1845},{"type":415,"tag":783,"props":13164,"children":13165},{"style":1362},[13166],{"type":420,"value":11246},{"type":415,"tag":783,"props":13168,"children":13169},{"style":790},[13170],{"type":420,"value":2501},{"type":415,"tag":783,"props":13172,"children":13173},{"style":1362},[13174],{"type":420,"value":13175}," cancellationToken",{"type":415,"tag":783,"props":13177,"children":13178},{"style":790},[13179],{"type":420,"value":2552},{"type":415,"tag":783,"props":13181,"children":13182},{"class":785,"line":1239},[13183],{"type":415,"tag":783,"props":13184,"children":13185},{"style":790},[13186],{"type":420,"value":1254},{"type":415,"tag":783,"props":13188,"children":13189},{"class":785,"line":1248},[13190],{"type":415,"tag":783,"props":13191,"children":13192},{"style":790},[13193],{"type":420,"value":1272},{"type":415,"tag":416,"props":13195,"children":13196},{},[13197],{"type":420,"value":13198},"That's it, we don't need anymore to handle token retrieval on UserService which becomes simpler:",{"type":415,"tag":773,"props":13200,"children":13202},{"className":1805,"code":13201,"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",[13203],{"type":415,"tag":550,"props":13204,"children":13205},{"__ignoreMap":401},[13206,13230,13237,13260,13287,13294,13313,13320,13327,13370,13377,13438,13457,13508,13515,13522,13557,13564,13616,13693,13712,13719],{"type":415,"tag":783,"props":13207,"children":13208},{"class":785,"line":786},[13209,13213,13217,13221,13225],{"type":415,"tag":783,"props":13210,"children":13211},{"style":805},[13212],{"type":420,"value":1871},{"type":415,"tag":783,"props":13214,"children":13215},{"style":875},[13216],{"type":420,"value":1876},{"type":415,"tag":783,"props":13218,"children":13219},{"style":875},[13220],{"type":420,"value":10887},{"type":415,"tag":783,"props":13222,"children":13223},{"style":790},[13224],{"type":420,"value":1886},{"type":415,"tag":783,"props":13226,"children":13227},{"style":1362},[13228],{"type":420,"value":13229}," \n",{"type":415,"tag":783,"props":13231,"children":13232},{"class":785,"line":796},[13233],{"type":415,"tag":783,"props":13234,"children":13235},{"style":790},[13236],{"type":420,"value":793},{"type":415,"tag":783,"props":13238,"children":13239},{"class":785,"line":840},[13240,13244,13248,13252,13256],{"type":415,"tag":783,"props":13241,"children":13242},{"style":805},[13243],{"type":420,"value":1906},{"type":415,"tag":783,"props":13245,"children":13246},{"style":805},[13247],{"type":420,"value":1911},{"type":415,"tag":783,"props":13249,"children":13250},{"style":875},[13251],{"type":420,"value":10918},{"type":415,"tag":783,"props":13253,"children":13254},{"style":875},[13255],{"type":420,"value":10558},{"type":415,"tag":783,"props":13257,"children":13258},{"style":790},[13259],{"type":420,"value":1926},{"type":415,"tag":783,"props":13261,"children":13262},{"class":785,"line":866},[13263,13267,13271,13275,13279,13283],{"type":415,"tag":783,"props":13264,"children":13265},{"style":805},[13266],{"type":420,"value":1941},{"type":415,"tag":783,"props":13268,"children":13269},{"style":1545},[13270],{"type":420,"value":10887},{"type":415,"tag":783,"props":13272,"children":13273},{"style":790},[13274],{"type":420,"value":1845},{"type":415,"tag":783,"props":13276,"children":13277},{"style":875},[13278],{"type":420,"value":9774},{"type":415,"tag":783,"props":13280,"children":13281},{"style":875},[13282],{"type":420,"value":10950},{"type":415,"tag":783,"props":13284,"children":13285},{"style":790},[13286],{"type":420,"value":1963},{"type":415,"tag":783,"props":13288,"children":13289},{"class":785,"line":893},[13290],{"type":415,"tag":783,"props":13291,"children":13292},{"style":790},[13293],{"type":420,"value":1971},{"type":415,"tag":783,"props":13295,"children":13296},{"class":785,"line":920},[13297,13301,13305,13309],{"type":415,"tag":783,"props":13298,"children":13299},{"style":1362},[13300],{"type":420,"value":10969},{"type":415,"tag":783,"props":13302,"children":13303},{"style":790},[13304],{"type":420,"value":1984},{"type":415,"tag":783,"props":13306,"children":13307},{"style":1362},[13308],{"type":420,"value":10950},{"type":415,"tag":783,"props":13310,"children":13311},{"style":790},[13312],{"type":420,"value":1926},{"type":415,"tag":783,"props":13314,"children":13315},{"class":785,"line":959},[13316],{"type":415,"tag":783,"props":13317,"children":13318},{"style":790},[13319],{"type":420,"value":1254},{"type":415,"tag":783,"props":13321,"children":13322},{"class":785,"line":997},[13323],{"type":415,"tag":783,"props":13324,"children":13325},{"emptyLinePlaceholder":1624},[13326],{"type":420,"value":1627},{"type":415,"tag":783,"props":13328,"children":13329},{"class":785,"line":1023},[13330,13334,13338,13342,13346,13350,13354,13358,13362,13366],{"type":415,"tag":783,"props":13331,"children":13332},{"style":805},[13333],{"type":420,"value":1941},{"type":415,"tag":783,"props":13335,"children":13336},{"style":805},[13337],{"type":420,"value":2641},{"type":415,"tag":783,"props":13339,"children":13340},{"style":875},[13341],{"type":420,"value":2107},{"type":415,"tag":783,"props":13343,"children":13344},{"style":790},[13345],{"type":420,"value":2112},{"type":415,"tag":783,"props":13347,"children":13348},{"style":875},[13349],{"type":420,"value":10374},{"type":415,"tag":783,"props":13351,"children":13352},{"style":790},[13353],{"type":420,"value":2112},{"type":415,"tag":783,"props":13355,"children":13356},{"style":875},[13357],{"type":420,"value":10383},{"type":415,"tag":783,"props":13359,"children":13360},{"style":790},[13361],{"type":420,"value":10388},{"type":415,"tag":783,"props":13363,"children":13364},{"style":1545},[13365],{"type":420,"value":10393},{"type":415,"tag":783,"props":13367,"children":13368},{"style":790},[13369],{"type":420,"value":2131},{"type":415,"tag":783,"props":13371,"children":13372},{"class":785,"line":1061},[13373],{"type":415,"tag":783,"props":13374,"children":13375},{"style":790},[13376],{"type":420,"value":1971},{"type":415,"tag":783,"props":13378,"children":13379},{"class":785,"line":1099},[13380,13384,13388,13392,13396,13400,13404,13409,13414,13418,13422,13426,13430,13434],{"type":415,"tag":783,"props":13381,"children":13382},{"style":875},[13383],{"type":420,"value":2681},{"type":415,"tag":783,"props":13385,"children":13386},{"style":875},[13387],{"type":420,"value":10545},{"type":415,"tag":783,"props":13389,"children":13390},{"style":790},[13391],{"type":420,"value":2033},{"type":415,"tag":783,"props":13393,"children":13394},{"style":790},[13395],{"type":420,"value":2695},{"type":415,"tag":783,"props":13397,"children":13398},{"style":1362},[13399],{"type":420,"value":10558},{"type":415,"tag":783,"props":13401,"children":13402},{"style":790},[13403],{"type":420,"value":755},{"type":415,"tag":783,"props":13405,"children":13406},{"style":1545},[13407],{"type":420,"value":13408},"GetAsync",{"type":415,"tag":783,"props":13410,"children":13411},{"style":790},[13412],{"type":420,"value":13413},"(new",{"type":415,"tag":783,"props":13415,"children":13416},{"style":875},[13417],{"type":420,"value":6456},{"type":415,"tag":783,"props":13419,"children":13420},{"style":790},[13421],{"type":420,"value":1845},{"type":415,"tag":783,"props":13423,"children":13424},{"style":790},[13425],{"type":420,"value":813},{"type":415,"tag":783,"props":13427,"children":13428},{"style":825},[13429],{"type":420,"value":11129},{"type":415,"tag":783,"props":13431,"children":13432},{"style":790},[13433],{"type":420,"value":813},{"type":415,"tag":783,"props":13435,"children":13436},{"style":790},[13437],{"type":420,"value":6680},{"type":415,"tag":783,"props":13439,"children":13440},{"class":785,"line":1137},[13441,13445,13449,13453],{"type":415,"tag":783,"props":13442,"children":13443},{"style":1362},[13444],{"type":420,"value":11258},{"type":415,"tag":783,"props":13446,"children":13447},{"style":790},[13448],{"type":420,"value":755},{"type":415,"tag":783,"props":13450,"children":13451},{"style":1545},[13452],{"type":420,"value":11267},{"type":415,"tag":783,"props":13454,"children":13455},{"style":790},[13456],{"type":420,"value":2164},{"type":415,"tag":783,"props":13458,"children":13459},{"class":785,"line":1175},[13460,13464,13468,13472,13476,13480,13484,13488,13492,13496,13500,13504],{"type":415,"tag":783,"props":13461,"children":13462},{"style":1356},[13463],{"type":420,"value":2146},{"type":415,"tag":783,"props":13465,"children":13466},{"style":790},[13467],{"type":420,"value":2695},{"type":415,"tag":783,"props":13469,"children":13470},{"style":1362},[13471],{"type":420,"value":10545},{"type":415,"tag":783,"props":13473,"children":13474},{"style":790},[13475],{"type":420,"value":755},{"type":415,"tag":783,"props":13477,"children":13478},{"style":1362},[13479],{"type":420,"value":10661},{"type":415,"tag":783,"props":13481,"children":13482},{"style":790},[13483],{"type":420,"value":755},{"type":415,"tag":783,"props":13485,"children":13486},{"style":1545},[13487],{"type":420,"value":10670},{"type":415,"tag":783,"props":13489,"children":13490},{"style":790},[13491],{"type":420,"value":2112},{"type":415,"tag":783,"props":13493,"children":13494},{"style":875},[13495],{"type":420,"value":10374},{"type":415,"tag":783,"props":13497,"children":13498},{"style":790},[13499],{"type":420,"value":2112},{"type":415,"tag":783,"props":13501,"children":13502},{"style":875},[13503],{"type":420,"value":10383},{"type":415,"tag":783,"props":13505,"children":13506},{"style":790},[13507],{"type":420,"value":11323},{"type":415,"tag":783,"props":13509,"children":13510},{"class":785,"line":1213},[13511],{"type":415,"tag":783,"props":13512,"children":13513},{"style":790},[13514],{"type":420,"value":1254},{"type":415,"tag":783,"props":13516,"children":13517},{"class":785,"line":1239},[13518],{"type":415,"tag":783,"props":13519,"children":13520},{"emptyLinePlaceholder":1624},[13521],{"type":420,"value":1627},{"type":415,"tag":783,"props":13523,"children":13524},{"class":785,"line":1248},[13525,13529,13533,13537,13541,13545,13549,13553],{"type":415,"tag":783,"props":13526,"children":13527},{"style":805},[13528],{"type":420,"value":1941},{"type":415,"tag":783,"props":13530,"children":13531},{"style":805},[13532],{"type":420,"value":2641},{"type":415,"tag":783,"props":13534,"children":13535},{"style":875},[13536],{"type":420,"value":2107},{"type":415,"tag":783,"props":13538,"children":13539},{"style":1545},[13540],{"type":420,"value":10409},{"type":415,"tag":783,"props":13542,"children":13543},{"style":790},[13544],{"type":420,"value":1845},{"type":415,"tag":783,"props":13546,"children":13547},{"style":875},[13548],{"type":420,"value":10383},{"type":415,"tag":783,"props":13550,"children":13551},{"style":875},[13552],{"type":420,"value":10422},{"type":415,"tag":783,"props":13554,"children":13555},{"style":790},[13556],{"type":420,"value":1963},{"type":415,"tag":783,"props":13558,"children":13559},{"class":785,"line":1257},[13560],{"type":415,"tag":783,"props":13561,"children":13562},{"style":790},[13563],{"type":420,"value":1971},{"type":415,"tag":783,"props":13565,"children":13566},{"class":785,"line":1266},[13567,13571,13576,13580,13584,13588,13592,13596,13600,13604,13608,13612],{"type":415,"tag":783,"props":13568,"children":13569},{"style":875},[13570],{"type":420,"value":2681},{"type":415,"tag":783,"props":13572,"children":13573},{"style":875},[13574],{"type":420,"value":13575}," content",{"type":415,"tag":783,"props":13577,"children":13578},{"style":790},[13579],{"type":420,"value":2033},{"type":415,"tag":783,"props":13581,"children":13582},{"style":790},[13583],{"type":420,"value":4335},{"type":415,"tag":783,"props":13585,"children":13586},{"style":875},[13587],{"type":420,"value":10596},{"type":415,"tag":783,"props":13589,"children":13590},{"style":790},[13591],{"type":420,"value":1845},{"type":415,"tag":783,"props":13593,"children":13594},{"style":1362},[13595],{"type":420,"value":10605},{"type":415,"tag":783,"props":13597,"children":13598},{"style":790},[13599],{"type":420,"value":755},{"type":415,"tag":783,"props":13601,"children":13602},{"style":1545},[13603],{"type":420,"value":10614},{"type":415,"tag":783,"props":13605,"children":13606},{"style":790},[13607],{"type":420,"value":1845},{"type":415,"tag":783,"props":13609,"children":13610},{"style":1362},[13611],{"type":420,"value":11470},{"type":415,"tag":783,"props":13613,"children":13614},{"style":790},[13615],{"type":420,"value":6680},{"type":415,"tag":783,"props":13617,"children":13618},{"class":785,"line":2847},[13619,13623,13627,13631,13635,13639,13643,13648,13652,13657,13661,13665,13669,13673,13677,13681,13685,13689],{"type":415,"tag":783,"props":13620,"children":13621},{"style":875},[13622],{"type":420,"value":2681},{"type":415,"tag":783,"props":13624,"children":13625},{"style":875},[13626],{"type":420,"value":10545},{"type":415,"tag":783,"props":13628,"children":13629},{"style":790},[13630],{"type":420,"value":2033},{"type":415,"tag":783,"props":13632,"children":13633},{"style":790},[13634],{"type":420,"value":2695},{"type":415,"tag":783,"props":13636,"children":13637},{"style":1362},[13638],{"type":420,"value":10558},{"type":415,"tag":783,"props":13640,"children":13641},{"style":790},[13642],{"type":420,"value":755},{"type":415,"tag":783,"props":13644,"children":13645},{"style":1545},[13646],{"type":420,"value":13647},"PutAsync",{"type":415,"tag":783,"props":13649,"children":13650},{"style":790},[13651],{"type":420,"value":1845},{"type":415,"tag":783,"props":13653,"children":13654},{"style":790},[13655],{"type":420,"value":13656},"$\"",{"type":415,"tag":783,"props":13658,"children":13659},{"style":825},[13660],{"type":420,"value":11460},{"type":415,"tag":783,"props":13662,"children":13663},{"style":790},[13664],{"type":420,"value":11465},{"type":415,"tag":783,"props":13666,"children":13667},{"style":1362},[13668],{"type":420,"value":11470},{"type":415,"tag":783,"props":13670,"children":13671},{"style":790},[13672],{"type":420,"value":755},{"type":415,"tag":783,"props":13674,"children":13675},{"style":1362},[13676],{"type":420,"value":2028},{"type":415,"tag":783,"props":13678,"children":13679},{"style":790},[13680],{"type":420,"value":11483},{"type":415,"tag":783,"props":13682,"children":13683},{"style":790},[13684],{"type":420,"value":2501},{"type":415,"tag":783,"props":13686,"children":13687},{"style":1362},[13688],{"type":420,"value":13575},{"type":415,"tag":783,"props":13690,"children":13691},{"style":790},[13692],{"type":420,"value":2552},{"type":415,"tag":783,"props":13694,"children":13695},{"class":785,"line":2896},[13696,13700,13704,13708],{"type":415,"tag":783,"props":13697,"children":13698},{"style":1362},[13699],{"type":420,"value":11258},{"type":415,"tag":783,"props":13701,"children":13702},{"style":790},[13703],{"type":420,"value":755},{"type":415,"tag":783,"props":13705,"children":13706},{"style":1545},[13707],{"type":420,"value":11267},{"type":415,"tag":783,"props":13709,"children":13710},{"style":790},[13711],{"type":420,"value":2164},{"type":415,"tag":783,"props":13713,"children":13714},{"class":785,"line":2942},[13715],{"type":415,"tag":783,"props":13716,"children":13717},{"style":790},[13718],{"type":420,"value":1254},{"type":415,"tag":783,"props":13720,"children":13721},{"class":785,"line":2988},[13722],{"type":415,"tag":783,"props":13723,"children":13724},{"style":790},[13725],{"type":420,"value":1272},{"type":415,"tag":416,"props":13727,"children":13728},{},[13729,13731,13737],{"type":420,"value":13730},"To finish we just have to specify in the ",{"type":415,"tag":550,"props":13732,"children":13734},{"className":13733},[],[13735],{"type":420,"value":13736},"Startup.cs",{"type":420,"value":13738}," on which HttpClient to apply the delegating handler we have just created.",{"type":415,"tag":773,"props":13740,"children":13742},{"className":1805,"code":13741,"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",[13743],{"type":415,"tag":550,"props":13744,"children":13745},{"__ignoreMap":401},[13746,13776,13783,13804,13840,13898,13905,13933,13968,14023,14047],{"type":415,"tag":783,"props":13747,"children":13748},{"class":785,"line":786},[13749,13753,13758,13763,13767,13772],{"type":415,"tag":783,"props":13750,"children":13751},{"style":805},[13752],{"type":420,"value":1871},{"type":415,"tag":783,"props":13754,"children":13755},{"style":790},[13756],{"type":420,"value":13757}," void",{"type":415,"tag":783,"props":13759,"children":13760},{"style":1545},[13761],{"type":420,"value":13762}," ConfigureServices",{"type":415,"tag":783,"props":13764,"children":13765},{"style":790},[13766],{"type":420,"value":1845},{"type":415,"tag":783,"props":13768,"children":13769},{"style":1362},[13770],{"type":420,"value":13771},"IServiceCollectionservices",{"type":415,"tag":783,"props":13773,"children":13774},{"style":790},[13775],{"type":420,"value":1963},{"type":415,"tag":783,"props":13777,"children":13778},{"class":785,"line":796},[13779],{"type":415,"tag":783,"props":13780,"children":13781},{"style":790},[13782],{"type":420,"value":793},{"type":415,"tag":783,"props":13784,"children":13785},{"class":785,"line":840},[13786,13791,13795,13800],{"type":415,"tag":783,"props":13787,"children":13788},{"style":1362},[13789],{"type":420,"value":13790},"    services",{"type":415,"tag":783,"props":13792,"children":13793},{"style":790},[13794],{"type":420,"value":755},{"type":415,"tag":783,"props":13796,"children":13797},{"style":1545},[13798],{"type":420,"value":13799},"AddMemoryCache",{"type":415,"tag":783,"props":13801,"children":13802},{"style":790},[13803],{"type":420,"value":2164},{"type":415,"tag":783,"props":13805,"children":13806},{"class":785,"line":866},[13807,13811,13815,13820,13824,13828,13832,13836],{"type":415,"tag":783,"props":13808,"children":13809},{"style":1362},[13810],{"type":420,"value":13790},{"type":415,"tag":783,"props":13812,"children":13813},{"style":790},[13814],{"type":420,"value":755},{"type":415,"tag":783,"props":13816,"children":13817},{"style":1545},[13818],{"type":420,"value":13819},"AddHttpClient",{"type":415,"tag":783,"props":13821,"children":13822},{"style":790},[13823],{"type":420,"value":2112},{"type":415,"tag":783,"props":13825,"children":13826},{"style":875},[13827],{"type":420,"value":12915},{"type":415,"tag":783,"props":13829,"children":13830},{"style":790},[13831],{"type":420,"value":2501},{"type":415,"tag":783,"props":13833,"children":13834},{"style":875},[13835],{"type":420,"value":12081},{"type":415,"tag":783,"props":13837,"children":13838},{"style":790},[13839],{"type":420,"value":6816},{"type":415,"tag":783,"props":13841,"children":13842},{"class":785,"line":893},[13843,13847,13851,13855,13860,13864,13869,13873,13877,13881,13885,13890,13894],{"type":415,"tag":783,"props":13844,"children":13845},{"style":790},[13846],{"type":420,"value":3314},{"type":415,"tag":783,"props":13848,"children":13849},{"style":1545},[13850],{"type":420,"value":6829},{"type":415,"tag":783,"props":13852,"children":13853},{"style":790},[13854],{"type":420,"value":1845},{"type":415,"tag":783,"props":13856,"children":13857},{"style":875},[13858],{"type":420,"value":13859},"c",{"type":415,"tag":783,"props":13861,"children":13862},{"style":790},[13863],{"type":420,"value":2827},{"type":415,"tag":783,"props":13865,"children":13866},{"style":1362},[13867],{"type":420,"value":13868}," c",{"type":415,"tag":783,"props":13870,"children":13871},{"style":790},[13872],{"type":420,"value":755},{"type":415,"tag":783,"props":13874,"children":13875},{"style":1362},[13876],{"type":420,"value":6941},{"type":415,"tag":783,"props":13878,"children":13879},{"style":790},[13880],{"type":420,"value":1984},{"type":415,"tag":783,"props":13882,"children":13883},{"style":790},[13884],{"type":420,"value":813},{"type":415,"tag":783,"props":13886,"children":13887},{"style":825},[13888],{"type":420,"value":13889},"http://urltotheuserapi.com",{"type":415,"tag":783,"props":13891,"children":13892},{"style":790},[13893],{"type":420,"value":813},{"type":415,"tag":783,"props":13895,"children":13896},{"style":790},[13897],{"type":420,"value":2552},{"type":415,"tag":783,"props":13899,"children":13900},{"class":785,"line":920},[13901],{"type":415,"tag":783,"props":13902,"children":13903},{"style":1362},[13904],{"type":420,"value":5167},{"type":415,"tag":783,"props":13906,"children":13907},{"class":785,"line":959},[13908,13912,13916,13920,13924,13929],{"type":415,"tag":783,"props":13909,"children":13910},{"style":1362},[13911],{"type":420,"value":13790},{"type":415,"tag":783,"props":13913,"children":13914},{"style":790},[13915],{"type":420,"value":755},{"type":415,"tag":783,"props":13917,"children":13918},{"style":1545},[13919],{"type":420,"value":6766},{"type":415,"tag":783,"props":13921,"children":13922},{"style":790},[13923],{"type":420,"value":2112},{"type":415,"tag":783,"props":13925,"children":13926},{"style":875},[13927],{"type":420,"value":13928},"UserApiAuthenticationHandler",{"type":415,"tag":783,"props":13930,"children":13931},{"style":790},[13932],{"type":420,"value":6735},{"type":415,"tag":783,"props":13934,"children":13935},{"class":785,"line":997},[13936,13940,13944,13948,13952,13956,13960,13964],{"type":415,"tag":783,"props":13937,"children":13938},{"style":1362},[13939],{"type":420,"value":13790},{"type":415,"tag":783,"props":13941,"children":13942},{"style":790},[13943],{"type":420,"value":755},{"type":415,"tag":783,"props":13945,"children":13946},{"style":1545},[13947],{"type":420,"value":13819},{"type":415,"tag":783,"props":13949,"children":13950},{"style":790},[13951],{"type":420,"value":2112},{"type":415,"tag":783,"props":13953,"children":13954},{"style":875},[13955],{"type":420,"value":10849},{"type":415,"tag":783,"props":13957,"children":13958},{"style":790},[13959],{"type":420,"value":2501},{"type":415,"tag":783,"props":13961,"children":13962},{"style":875},[13963],{"type":420,"value":10887},{"type":415,"tag":783,"props":13965,"children":13966},{"style":790},[13967],{"type":420,"value":6816},{"type":415,"tag":783,"props":13969,"children":13970},{"class":785,"line":1023},[13971,13975,13979,13983,13987,13991,13995,13999,14003,14007,14011,14015,14019],{"type":415,"tag":783,"props":13972,"children":13973},{"style":790},[13974],{"type":420,"value":3314},{"type":415,"tag":783,"props":13976,"children":13977},{"style":1545},[13978],{"type":420,"value":6829},{"type":415,"tag":783,"props":13980,"children":13981},{"style":790},[13982],{"type":420,"value":1845},{"type":415,"tag":783,"props":13984,"children":13985},{"style":875},[13986],{"type":420,"value":13859},{"type":415,"tag":783,"props":13988,"children":13989},{"style":790},[13990],{"type":420,"value":2827},{"type":415,"tag":783,"props":13992,"children":13993},{"style":1362},[13994],{"type":420,"value":13868},{"type":415,"tag":783,"props":13996,"children":13997},{"style":790},[13998],{"type":420,"value":755},{"type":415,"tag":783,"props":14000,"children":14001},{"style":1362},[14002],{"type":420,"value":6941},{"type":415,"tag":783,"props":14004,"children":14005},{"style":790},[14006],{"type":420,"value":1984},{"type":415,"tag":783,"props":14008,"children":14009},{"style":790},[14010],{"type":420,"value":813},{"type":415,"tag":783,"props":14012,"children":14013},{"style":825},[14014],{"type":420,"value":13889},{"type":415,"tag":783,"props":14016,"children":14017},{"style":790},[14018],{"type":420,"value":813},{"type":415,"tag":783,"props":14020,"children":14021},{"style":790},[14022],{"type":420,"value":1963},{"type":415,"tag":783,"props":14024,"children":14025},{"class":785,"line":1061},[14026,14030,14034,14038,14043],{"type":415,"tag":783,"props":14027,"children":14028},{"style":790},[14029],{"type":420,"value":3314},{"type":415,"tag":783,"props":14031,"children":14032},{"style":1545},[14033],{"type":420,"value":6994},{"type":415,"tag":783,"props":14035,"children":14036},{"style":790},[14037],{"type":420,"value":2112},{"type":415,"tag":783,"props":14039,"children":14040},{"style":875},[14041],{"type":420,"value":14042},"UserApiAuthenticationHanler",{"type":415,"tag":783,"props":14044,"children":14045},{"style":790},[14046],{"type":420,"value":6735},{"type":415,"tag":783,"props":14048,"children":14049},{"class":785,"line":1099},[14050],{"type":415,"tag":783,"props":14051,"children":14052},{"style":790},[14053],{"type":420,"value":1272},{"type":415,"tag":443,"props":14055,"children":14056},{"id":10191},[14057],{"type":420,"value":10194},{"type":415,"tag":416,"props":14059,"children":14060},{},[14061],{"type":420,"value":14062},"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":1420,"props":14064,"children":14065},{},[14066],{"type":420,"value":1424},{"title":401,"searchDepth":796,"depth":796,"links":14068},[14069,14070,14071,14072,14073],{"id":445,"depth":796,"text":448},{"id":10835,"depth":796,"text":10838},{"id":12014,"depth":796,"text":12017},{"id":12736,"depth":796,"text":12739},{"id":10191,"depth":796,"text":10194},"content:1.posts:5.delegating-handler.md","1.posts/5.delegating-handler.md",{"_path":10,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":9,"description":14077,"lead":14078,"date":14079,"image":14080,"badge":14082,"tags":14083,"body":14084,"_type":1435,"_id":14951,"_source":1437,"_file":14952,"_extension":1439},"Let's talk about tooling and testing an API!","Why using the vscode extension \"REST Client\" instead of Postman?","2019-03-05T00:00:00.000Z",{"src":14081},"/images/swiss_knifes.jpg",{"label":408},[206,208,210,213],{"type":412,"children":14085,"toc":14944},[14086,14090,14096,14101,14110,14115,14126,14132,14141,14172,14177,14191,14220,14231,14237,14271,14280,14285,14524,14569,14578,14584,14589,14594,14599,14605,14610,14622,14627,14940],{"type":415,"tag":416,"props":14087,"children":14088},{},[14089],{"type":420,"value":14077},{"type":415,"tag":443,"props":14091,"children":14093},{"id":14092},"gui-tools-and-their-limits",[14094],{"type":420,"value":14095},"GUI Tools and their limits",{"type":415,"tag":416,"props":14097,"children":14098},{},[14099],{"type":420,"value":14100},"Like most developers I guess, I often use GUI tools like Fiddler or Postman to query an API.\nOnce you get used to the HMI of Postman with all its tabs, it's quite easy to create GET / POST / PUT / ... requests, save them in a collection, and visualize the answers. Postman offers a lot of other features, but a very handy one is the possibility to use environment variables in your requests.",{"type":415,"tag":416,"props":14102,"children":14103},{},[14104],{"type":415,"tag":1322,"props":14105,"children":14109},{"alt":14106,"className":14107,"src":14108},"Postman UI",[1326,1327],"/posts/images/restclient_postman_1.png",[],{"type":415,"tag":416,"props":14111,"children":14112},{},[14113],{"type":420,"value":14114},"Seems to be the perfect tool you would say. Well, that's true if you want to quickly test an API on your own, and to be honest I use it a lot for that. But when you are collaborating on a real project with other developers, there might be some things you will miss. For me, it's a way to edit, version, and share requests with other developers.",{"type":415,"tag":416,"props":14116,"children":14117},{},[14118,14120,14125],{"type":420,"value":14119},"Okay, I know that Postman paid plan allows you to share requests with other people of your team. And I am aware of the collection export feature on the free plan, but that's not enough. I don't really like to be too tied to a proprietary software and its GUI to do things. As a developer what I want is to be able to edit my requests in simple text files that I can put in version control. And here's come ",{"type":415,"tag":423,"props":14121,"children":14123},{"href":1672,"rel":14122},[427],[14124],{"type":420,"value":7309},{"type":420,"value":755},{"type":415,"tag":443,"props":14127,"children":14129},{"id":14128},"what-is-rest-client",[14130],{"type":420,"value":14131},"What is REST Client?",{"type":415,"tag":416,"props":14133,"children":14134},{},[14135],{"type":415,"tag":1322,"props":14136,"children":14140},{"alt":14137,"className":14138,"src":14139},"REST Client extension in vscode marketplace",[1326,1327],"/posts/images/restclient_vscode_1.png",[],{"type":415,"tag":416,"props":14142,"children":14143},{},[14144,14146,14153,14155,14162,14164,14171],{"type":420,"value":14145},"The REST Client extension is an open source vs code extension developed by ",{"type":415,"tag":423,"props":14147,"children":14150},{"href":14148,"rel":14149},"https://github.com/Huachao",[427],[14151],{"type":420,"value":14152},"Huachao Mao",{"type":420,"value":14154},". If I quote the README of its ",{"type":415,"tag":423,"props":14156,"children":14159},{"href":14157,"rel":14158},"https://github.com/Huachao/vscode-restclient",[427],[14160],{"type":420,"value":14161},"GitHub repository",{"type":420,"value":14163},": REST Client allows you to send HTTP request and view the response in Visual Studio Code directly.\nLet's see that with a simple GET request to ",{"type":415,"tag":423,"props":14165,"children":14168},{"href":14166,"rel":14167},"https://swapi.co/",[427],[14169],{"type":420,"value":14170},"The Start Wars API",{"type":420,"value":635},{"type":415,"tag":416,"props":14173,"children":14174},{},[14175],{"type":420,"value":14176},"05578273",{"type":415,"tag":416,"props":14178,"children":14179},{},[14180,14182,14189],{"type":420,"value":14181},"Nothing new or complicated here, just the request you would have written intuitively. Like this, you can write any kind of request you want simply following the standard RFC 2616. Even if you don't know the standard, it's pretty straightforward and you often find samples with this format on the documentation of the API you are querying, like on the ",{"type":415,"tag":423,"props":14183,"children":14186},{"href":14184,"rel":14185},"https://docs.microsoft.com/en-us/graph/api/user-list-memberof?view=graph-rest-1.0#example",[427],[14187],{"type":420,"value":14188},"Microsoft Graph API documentation",{"type":420,"value":14190}," for instance.",{"type":415,"tag":416,"props":14192,"children":14193},{},[14194,14196,14200,14202,14206,14207,14211,14213,14218],{"type":420,"value":14195},"REST Client works on text files in vscode by selecting ",{"type":415,"tag":7543,"props":14197,"children":14198},{},[14199],{"type":420,"value":213},{"type":420,"value":14201}," as the Language Mode (by default this language mode is associated with files having the ",{"type":415,"tag":7543,"props":14203,"children":14204},{},[14205],{"type":420,"value":7547},{"type":420,"value":7549},{"type":415,"tag":7543,"props":14208,"children":14209},{},[14210],{"type":420,"value":7554},{"type":420,"value":14212}," extension). It provides you with some autocompletion and a few snippets to help you write your queries. You can write multiple requests on the same file in vscode just by separating them with ###. Above each request an actionable ",{"type":415,"tag":7543,"props":14214,"children":14215},{},[14216],{"type":420,"value":14217},"Send Request",{"type":420,"value":14219}," link allows you to run the request and see the response in a response panel.",{"type":415,"tag":416,"props":14221,"children":14222},{},[14223],{"type":415,"tag":1322,"props":14224,"children":14230},{"alt":14225,"className":14226,"src":14227,"height":14228,"width":14229},"Intellisense in HTTP files in vscode",[1326,1327],"/posts/images/restclient_swapi_3.png",400,800,[],{"type":415,"tag":443,"props":14232,"children":14234},{"id":14233},"using-variables-in-rest-client",[14235],{"type":420,"value":14236},"Using variables in REST Client",{"type":415,"tag":416,"props":14238,"children":14239},{},[14240,14242,14248,14250,14261,14263,14269],{"type":420,"value":14241},"As you can see below, it is possible to use variables with REST Client. A variable ",{"type":415,"tag":550,"props":14243,"children":14245},{"className":14244},[],[14246],{"type":420,"value":14247},"planetName",{"type":420,"value":14249}," is defined in the file and reused in 2 requests. A variable is also used to name the request ",{"type":415,"tag":7543,"props":14251,"children":14252},{},[14253,14255],{"type":420,"value":14254},"GET ",{"type":415,"tag":423,"props":14256,"children":14259},{"href":14257,"rel":14258},"https://swapi.co/api/people/?search=Luke",[427],[14260],{"type":420,"value":14257},{"type":420,"value":14262}," and makes it possible to use elements from the response (that you can see on the right). Here we are using the ",{"type":415,"tag":550,"props":14264,"children":14266},{"className":14265},[],[14267],{"type":420,"value":14268},"homeworld",{"type":420,"value":14270}," property of the response to retrieve the planet from which Luke was from in the following GET request. With the help of variables you can easily combine and chain requests for the scenario you need to realize.",{"type":415,"tag":416,"props":14272,"children":14273},{},[14274],{"type":415,"tag":1322,"props":14275,"children":14279},{"alt":14276,"className":14277,"src":14278},"Execution of an HTTP request in vscode",[1326,1327],"/posts/images/restclient_swapi_2.png",[],{"type":415,"tag":416,"props":14281,"children":14282},{},[14283],{"type":420,"value":14284},"REST Client allows you to define environments and their associated variables in the user settings file of vscode. For instance, let's say I want to query the Microsoft Graph API (both the V1 version and the beta version of the API), I will add the following JSON to my  settings file:",{"type":415,"tag":773,"props":14286,"children":14288},{"className":775,"code":14287,"language":777,"meta":401,"style":401},"\"rest-client.environmentVariables\": {\n    \"$shared\": {\n        \"host\": \"https://graph.microsoft.com/\",\n    },\n    \"graphV1\": {\n        \"version\": \"v1.0\",\n    },\n    \"graphBeta\": {\n        \"version\": \"beta\"\n    },\n}\n",[14289],{"type":415,"tag":550,"props":14290,"children":14291},{"__ignoreMap":401},[14292,14317,14341,14378,14386,14410,14447,14454,14478,14510,14517],{"type":415,"tag":783,"props":14293,"children":14294},{"class":785,"line":786},[14295,14299,14304,14308,14313],{"type":415,"tag":783,"props":14296,"children":14297},{"style":790},[14298],{"type":420,"value":813},{"type":415,"tag":783,"props":14300,"children":14301},{"style":825},[14302],{"type":420,"value":14303},"rest-client.environmentVariables",{"type":415,"tag":783,"props":14305,"children":14306},{"style":790},[14307],{"type":420,"value":813},{"type":415,"tag":783,"props":14309,"children":14310},{"style":1362},[14311],{"type":420,"value":14312},": ",{"type":415,"tag":783,"props":14314,"children":14315},{"style":790},[14316],{"type":420,"value":793},{"type":415,"tag":783,"props":14318,"children":14319},{"class":785,"line":796},[14320,14324,14329,14333,14337],{"type":415,"tag":783,"props":14321,"children":14322},{"style":790},[14323],{"type":420,"value":872},{"type":415,"tag":783,"props":14325,"children":14326},{"style":805},[14327],{"type":420,"value":14328},"$shared",{"type":415,"tag":783,"props":14330,"children":14331},{"style":790},[14332],{"type":420,"value":813},{"type":415,"tag":783,"props":14334,"children":14335},{"style":790},[14336],{"type":420,"value":635},{"type":415,"tag":783,"props":14338,"children":14339},{"style":790},[14340],{"type":420,"value":863},{"type":415,"tag":783,"props":14342,"children":14343},{"class":785,"line":840},[14344,14348,14353,14357,14361,14365,14370,14374],{"type":415,"tag":783,"props":14345,"children":14346},{"style":790},[14347],{"type":420,"value":926},{"type":415,"tag":783,"props":14349,"children":14350},{"style":875},[14351],{"type":420,"value":14352},"host",{"type":415,"tag":783,"props":14354,"children":14355},{"style":790},[14356],{"type":420,"value":813},{"type":415,"tag":783,"props":14358,"children":14359},{"style":790},[14360],{"type":420,"value":635},{"type":415,"tag":783,"props":14362,"children":14363},{"style":790},[14364],{"type":420,"value":822},{"type":415,"tag":783,"props":14366,"children":14367},{"style":825},[14368],{"type":420,"value":14369},"https://graph.microsoft.com/",{"type":415,"tag":783,"props":14371,"children":14372},{"style":790},[14373],{"type":420,"value":813},{"type":415,"tag":783,"props":14375,"children":14376},{"style":790},[14377],{"type":420,"value":837},{"type":415,"tag":783,"props":14379,"children":14380},{"class":785,"line":866},[14381],{"type":415,"tag":783,"props":14382,"children":14383},{"style":790},[14384],{"type":420,"value":14385},"    },\n",{"type":415,"tag":783,"props":14387,"children":14388},{"class":785,"line":893},[14389,14393,14398,14402,14406],{"type":415,"tag":783,"props":14390,"children":14391},{"style":790},[14392],{"type":420,"value":872},{"type":415,"tag":783,"props":14394,"children":14395},{"style":805},[14396],{"type":420,"value":14397},"graphV1",{"type":415,"tag":783,"props":14399,"children":14400},{"style":790},[14401],{"type":420,"value":813},{"type":415,"tag":783,"props":14403,"children":14404},{"style":790},[14405],{"type":420,"value":635},{"type":415,"tag":783,"props":14407,"children":14408},{"style":790},[14409],{"type":420,"value":863},{"type":415,"tag":783,"props":14411,"children":14412},{"class":785,"line":920},[14413,14417,14422,14426,14430,14434,14439,14443],{"type":415,"tag":783,"props":14414,"children":14415},{"style":790},[14416],{"type":420,"value":926},{"type":415,"tag":783,"props":14418,"children":14419},{"style":875},[14420],{"type":420,"value":14421},"version",{"type":415,"tag":783,"props":14423,"children":14424},{"style":790},[14425],{"type":420,"value":813},{"type":415,"tag":783,"props":14427,"children":14428},{"style":790},[14429],{"type":420,"value":635},{"type":415,"tag":783,"props":14431,"children":14432},{"style":790},[14433],{"type":420,"value":822},{"type":415,"tag":783,"props":14435,"children":14436},{"style":825},[14437],{"type":420,"value":14438},"v1.0",{"type":415,"tag":783,"props":14440,"children":14441},{"style":790},[14442],{"type":420,"value":813},{"type":415,"tag":783,"props":14444,"children":14445},{"style":790},[14446],{"type":420,"value":837},{"type":415,"tag":783,"props":14448,"children":14449},{"class":785,"line":959},[14450],{"type":415,"tag":783,"props":14451,"children":14452},{"style":790},[14453],{"type":420,"value":14385},{"type":415,"tag":783,"props":14455,"children":14456},{"class":785,"line":997},[14457,14461,14466,14470,14474],{"type":415,"tag":783,"props":14458,"children":14459},{"style":790},[14460],{"type":420,"value":872},{"type":415,"tag":783,"props":14462,"children":14463},{"style":805},[14464],{"type":420,"value":14465},"graphBeta",{"type":415,"tag":783,"props":14467,"children":14468},{"style":790},[14469],{"type":420,"value":813},{"type":415,"tag":783,"props":14471,"children":14472},{"style":790},[14473],{"type":420,"value":635},{"type":415,"tag":783,"props":14475,"children":14476},{"style":790},[14477],{"type":420,"value":863},{"type":415,"tag":783,"props":14479,"children":14480},{"class":785,"line":1023},[14481,14485,14489,14493,14497,14501,14506],{"type":415,"tag":783,"props":14482,"children":14483},{"style":790},[14484],{"type":420,"value":926},{"type":415,"tag":783,"props":14486,"children":14487},{"style":875},[14488],{"type":420,"value":14421},{"type":415,"tag":783,"props":14490,"children":14491},{"style":790},[14492],{"type":420,"value":813},{"type":415,"tag":783,"props":14494,"children":14495},{"style":790},[14496],{"type":420,"value":635},{"type":415,"tag":783,"props":14498,"children":14499},{"style":790},[14500],{"type":420,"value":822},{"type":415,"tag":783,"props":14502,"children":14503},{"style":825},[14504],{"type":420,"value":14505},"beta",{"type":415,"tag":783,"props":14507,"children":14508},{"style":790},[14509],{"type":420,"value":3275},{"type":415,"tag":783,"props":14511,"children":14512},{"class":785,"line":1061},[14513],{"type":415,"tag":783,"props":14514,"children":14515},{"style":790},[14516],{"type":420,"value":14385},{"type":415,"tag":783,"props":14518,"children":14519},{"class":785,"line":1099},[14520],{"type":415,"tag":783,"props":14521,"children":14522},{"style":790},[14523],{"type":420,"value":1272},{"type":415,"tag":416,"props":14525,"children":14526},{},[14527,14529,14533,14534,14538,14540,14544,14546,14550,14552,14556,14558,14562,14563,14567],{"type":420,"value":14528},"I have defined 2 environments ",{"type":415,"tag":7543,"props":14530,"children":14531},{},[14532],{"type":420,"value":14397},{"type":420,"value":7950},{"type":415,"tag":7543,"props":14535,"children":14536},{},[14537],{"type":420,"value":14465},{"type":420,"value":14539}," with a specific value for the ",{"type":415,"tag":7543,"props":14541,"children":14542},{},[14543],{"type":420,"value":14421},{"type":420,"value":14545}," variable. These environments share the ",{"type":415,"tag":7543,"props":14547,"children":14548},{},[14549],{"type":420,"value":14352},{"type":420,"value":14551}," as a common variable which is contained in the shared environment ",{"type":415,"tag":7543,"props":14553,"children":14554},{},[14555],{"type":420,"value":14328},{"type":420,"value":14557},". From my request file, I can now switch between environments and use the variables ",{"type":415,"tag":7543,"props":14559,"children":14560},{},[14561],{"type":420,"value":14421},{"type":420,"value":7950},{"type":415,"tag":7543,"props":14564,"children":14565},{},[14566],{"type":420,"value":14352},{"type":420,"value":14568}," to request the Microsoft Graph API.",{"type":415,"tag":416,"props":14570,"children":14571},{},[14572],{"type":415,"tag":1322,"props":14573,"children":14577},{"alt":14574,"className":14575,"src":14576},"Environment selection in vscode.",[1326,1327],"/posts/images/restclient_msgraph_1.png",[],{"type":415,"tag":443,"props":14579,"children":14581},{"id":14580},"what-i-like-about-rest-client",[14582],{"type":420,"value":14583},"What I like about REST Client?",{"type":415,"tag":416,"props":14585,"children":14586},{},[14587],{"type":420,"value":14588},"REST Client is a nice alternative to Postman as it allows to easily write requests and query APIs from Visual Studio Code. I am already a vscode user so I appreciate staying in the same environment I know and like for testing an API. REST Client may not offer as many functionalities as Postman but for the usage I have, it is quite enough.",{"type":415,"tag":416,"props":14590,"children":14591},{},[14592],{"type":420,"value":14593},"What I like about this tool is that you treat your requests as code: you can commit the files containing your requests, keep track of their modifications and share the requests with your colleagues in your Git project repository.",{"type":415,"tag":416,"props":14595,"children":14596},{},[14597],{"type":420,"value":14598},"I have seen quite a few people using it recently in video tutorials and if you have a look at the number of downloads it seems I am not the only one to find it useful.",{"type":415,"tag":443,"props":14600,"children":14602},{"id":14601},"getting-started",[14603],{"type":420,"value":14604},"Getting started",{"type":415,"tag":416,"props":14606,"children":14607},{},[14608],{"type":420,"value":14609},"There are a lot of other features in REST Client that I didn't talk about (generate code snippet, request history ...) so don't hesitate to give it a try. You can use it on any API you like (there is even basic support for SOAP) the same way you would use Postman or other tools.",{"type":415,"tag":416,"props":14611,"children":14612},{},[14613,14615,14620],{"type":420,"value":14614},"If you quickly want to convert some of your Postman queries, there is a ",{"type":415,"tag":7543,"props":14616,"children":14617},{},[14618],{"type":420,"value":14619},"Code",{"type":420,"value":14621}," button in Postman that allows you to see the HTTP request code that you can just copy and paste in vscode to use it with REST Client.",{"type":415,"tag":416,"props":14623,"children":14624},{},[14625],{"type":420,"value":14626},"Or if you prefer you can get started by testing the Star Wars API, you will find below the requests I used. Enjoy :)",{"type":415,"tag":773,"props":14628,"children":14631},{"className":1345,"code":14629,"filename":14630,"language":212,"meta":401,"style":401},"#### List of start wars planets\nGET https://swapi.co/api/planets/ HTTP/1.1\n\n### Get Luke Skywalker\n# @name lukeRequest\nGET https://swapi.co/api/people/?search=Luke HTTP/1.1\n\n### Get Luke Skywalker home planet\nGET {{lukeRequest.response.body.results[0].homeworld}} HTTP/1.1\n\n### List available resources\nGET https://swapi.co/api/ HTTP/1.1\n\n### Search planet with a specific name \n@planetName = Naboo\nGET https://swapi.co/api/planets/?search={{planetName}} HTTP/1.1\n\n### Search planet with a specific name in wookie encoding\nGET https://swapi.co/api/planets/?search={{planetName}}&format=wookiee HTTP/1.1\n\n### List starships\nGET https://swapi.co/api/starships HTTP/1.1\n","swapi.http",[14632],{"type":415,"tag":550,"props":14633,"children":14634},{"__ignoreMap":401},[14635,14643,14667,14674,14681,14705,14728,14735,14743,14767,14774,14782,14806,14813,14821,14838,14862,14869,14877,14901,14908,14916],{"type":415,"tag":783,"props":14636,"children":14637},{"class":785,"line":786},[14638],{"type":415,"tag":783,"props":14639,"children":14640},{"style":8009},[14641],{"type":420,"value":14642},"#### List of start wars planets\n",{"type":415,"tag":783,"props":14644,"children":14645},{"class":785,"line":796},[14646,14650,14655,14659,14663],{"type":415,"tag":783,"props":14647,"children":14648},{"style":1356},[14649],{"type":420,"value":1359},{"type":415,"tag":783,"props":14651,"children":14652},{"style":1362},[14653],{"type":420,"value":14654}," https://swapi.co/api/planets/ ",{"type":415,"tag":783,"props":14656,"children":14657},{"style":902},[14658],{"type":420,"value":213},{"type":415,"tag":783,"props":14660,"children":14661},{"style":1362},[14662],{"type":420,"value":5318},{"type":415,"tag":783,"props":14664,"children":14665},{"style":902},[14666],{"type":420,"value":8037},{"type":415,"tag":783,"props":14668,"children":14669},{"class":785,"line":840},[14670],{"type":415,"tag":783,"props":14671,"children":14672},{"emptyLinePlaceholder":1624},[14673],{"type":420,"value":1627},{"type":415,"tag":783,"props":14675,"children":14676},{"class":785,"line":866},[14677],{"type":415,"tag":783,"props":14678,"children":14679},{"style":8009},[14680],{"type":420,"value":8012},{"type":415,"tag":783,"props":14682,"children":14683},{"class":785,"line":893},[14684,14689,14693,14699],{"type":415,"tag":783,"props":14685,"children":14686},{"style":8009},[14687],{"type":420,"value":14688},"# ",{"type":415,"tag":783,"props":14690,"children":14691},{"style":1356},[14692],{"type":420,"value":1608},{"type":415,"tag":783,"props":14694,"children":14696},{"style":14695},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[14697],{"type":420,"value":14698},"name",{"type":415,"tag":783,"props":14700,"children":14702},{"style":14701},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[14703],{"type":420,"value":14704}," lukeRequest\n",{"type":415,"tag":783,"props":14706,"children":14707},{"class":785,"line":920},[14708,14712,14716,14720,14724],{"type":415,"tag":783,"props":14709,"children":14710},{"style":1356},[14711],{"type":420,"value":1359},{"type":415,"tag":783,"props":14713,"children":14714},{"style":1362},[14715],{"type":420,"value":8024},{"type":415,"tag":783,"props":14717,"children":14718},{"style":902},[14719],{"type":420,"value":213},{"type":415,"tag":783,"props":14721,"children":14722},{"style":1362},[14723],{"type":420,"value":5318},{"type":415,"tag":783,"props":14725,"children":14726},{"style":902},[14727],{"type":420,"value":8037},{"type":415,"tag":783,"props":14729,"children":14730},{"class":785,"line":959},[14731],{"type":415,"tag":783,"props":14732,"children":14733},{"emptyLinePlaceholder":1624},[14734],{"type":420,"value":1627},{"type":415,"tag":783,"props":14736,"children":14737},{"class":785,"line":997},[14738],{"type":415,"tag":783,"props":14739,"children":14740},{"style":8009},[14741],{"type":420,"value":14742},"### Get Luke Skywalker home planet\n",{"type":415,"tag":783,"props":14744,"children":14745},{"class":785,"line":1023},[14746,14750,14755,14759,14763],{"type":415,"tag":783,"props":14747,"children":14748},{"style":1356},[14749],{"type":420,"value":1359},{"type":415,"tag":783,"props":14751,"children":14752},{"style":1362},[14753],{"type":420,"value":14754}," {{lukeRequest.response.body.results[0].homeworld}} ",{"type":415,"tag":783,"props":14756,"children":14757},{"style":902},[14758],{"type":420,"value":213},{"type":415,"tag":783,"props":14760,"children":14761},{"style":1362},[14762],{"type":420,"value":5318},{"type":415,"tag":783,"props":14764,"children":14765},{"style":902},[14766],{"type":420,"value":8037},{"type":415,"tag":783,"props":14768,"children":14769},{"class":785,"line":1061},[14770],{"type":415,"tag":783,"props":14771,"children":14772},{"emptyLinePlaceholder":1624},[14773],{"type":420,"value":1627},{"type":415,"tag":783,"props":14775,"children":14776},{"class":785,"line":1099},[14777],{"type":415,"tag":783,"props":14778,"children":14779},{"style":8009},[14780],{"type":420,"value":14781},"### List available resources\n",{"type":415,"tag":783,"props":14783,"children":14784},{"class":785,"line":1137},[14785,14789,14794,14798,14802],{"type":415,"tag":783,"props":14786,"children":14787},{"style":1356},[14788],{"type":420,"value":1359},{"type":415,"tag":783,"props":14790,"children":14791},{"style":1362},[14792],{"type":420,"value":14793}," https://swapi.co/api/ ",{"type":415,"tag":783,"props":14795,"children":14796},{"style":902},[14797],{"type":420,"value":213},{"type":415,"tag":783,"props":14799,"children":14800},{"style":1362},[14801],{"type":420,"value":5318},{"type":415,"tag":783,"props":14803,"children":14804},{"style":902},[14805],{"type":420,"value":8037},{"type":415,"tag":783,"props":14807,"children":14808},{"class":785,"line":1175},[14809],{"type":415,"tag":783,"props":14810,"children":14811},{"emptyLinePlaceholder":1624},[14812],{"type":420,"value":1627},{"type":415,"tag":783,"props":14814,"children":14815},{"class":785,"line":1213},[14816],{"type":415,"tag":783,"props":14817,"children":14818},{"style":8009},[14819],{"type":420,"value":14820},"### Search planet with a specific name \n",{"type":415,"tag":783,"props":14822,"children":14823},{"class":785,"line":1239},[14824,14828,14833],{"type":415,"tag":783,"props":14825,"children":14826},{"style":902},[14827],{"type":420,"value":1608},{"type":415,"tag":783,"props":14829,"children":14830},{"style":1362},[14831],{"type":420,"value":14832},"planetName = ",{"type":415,"tag":783,"props":14834,"children":14835},{"style":825},[14836],{"type":420,"value":14837},"Naboo\n",{"type":415,"tag":783,"props":14839,"children":14840},{"class":785,"line":1248},[14841,14845,14850,14854,14858],{"type":415,"tag":783,"props":14842,"children":14843},{"style":1356},[14844],{"type":420,"value":1359},{"type":415,"tag":783,"props":14846,"children":14847},{"style":1362},[14848],{"type":420,"value":14849}," https://swapi.co/api/planets/?search={{planetName}} ",{"type":415,"tag":783,"props":14851,"children":14852},{"style":902},[14853],{"type":420,"value":213},{"type":415,"tag":783,"props":14855,"children":14856},{"style":1362},[14857],{"type":420,"value":5318},{"type":415,"tag":783,"props":14859,"children":14860},{"style":902},[14861],{"type":420,"value":8037},{"type":415,"tag":783,"props":14863,"children":14864},{"class":785,"line":1257},[14865],{"type":415,"tag":783,"props":14866,"children":14867},{"emptyLinePlaceholder":1624},[14868],{"type":420,"value":1627},{"type":415,"tag":783,"props":14870,"children":14871},{"class":785,"line":1266},[14872],{"type":415,"tag":783,"props":14873,"children":14874},{"style":8009},[14875],{"type":420,"value":14876},"### Search planet with a specific name in wookie encoding\n",{"type":415,"tag":783,"props":14878,"children":14879},{"class":785,"line":2847},[14880,14884,14889,14893,14897],{"type":415,"tag":783,"props":14881,"children":14882},{"style":1356},[14883],{"type":420,"value":1359},{"type":415,"tag":783,"props":14885,"children":14886},{"style":1362},[14887],{"type":420,"value":14888}," https://swapi.co/api/planets/?search={{planetName}}&format=wookiee ",{"type":415,"tag":783,"props":14890,"children":14891},{"style":902},[14892],{"type":420,"value":213},{"type":415,"tag":783,"props":14894,"children":14895},{"style":1362},[14896],{"type":420,"value":5318},{"type":415,"tag":783,"props":14898,"children":14899},{"style":902},[14900],{"type":420,"value":8037},{"type":415,"tag":783,"props":14902,"children":14903},{"class":785,"line":2896},[14904],{"type":415,"tag":783,"props":14905,"children":14906},{"emptyLinePlaceholder":1624},[14907],{"type":420,"value":1627},{"type":415,"tag":783,"props":14909,"children":14910},{"class":785,"line":2942},[14911],{"type":415,"tag":783,"props":14912,"children":14913},{"style":8009},[14914],{"type":420,"value":14915},"### List starships\n",{"type":415,"tag":783,"props":14917,"children":14918},{"class":785,"line":2988},[14919,14923,14928,14932,14936],{"type":415,"tag":783,"props":14920,"children":14921},{"style":1356},[14922],{"type":420,"value":1359},{"type":415,"tag":783,"props":14924,"children":14925},{"style":1362},[14926],{"type":420,"value":14927}," https://swapi.co/api/starships ",{"type":415,"tag":783,"props":14929,"children":14930},{"style":902},[14931],{"type":420,"value":213},{"type":415,"tag":783,"props":14933,"children":14934},{"style":1362},[14935],{"type":420,"value":5318},{"type":415,"tag":783,"props":14937,"children":14938},{"style":902},[14939],{"type":420,"value":8037},{"type":415,"tag":1420,"props":14941,"children":14942},{},[14943],{"type":420,"value":1424},{"title":401,"searchDepth":796,"depth":796,"links":14945},[14946,14947,14948,14949,14950],{"id":14092,"depth":796,"text":14095},{"id":14128,"depth":796,"text":14131},{"id":14233,"depth":796,"text":14236},{"id":14580,"depth":796,"text":14583},{"id":14601,"depth":796,"text":14604},"content:1.posts:1.testing-your-api-with-rest-client.md","1.posts/1.testing-your-api-with-rest-client.md",1716749600607]