[{"data":1,"prerenderedAt":7244},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-rest":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,1082,2432,6352],{"_path":136,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":135,"description":402,"lead":403,"date":404,"image":405,"badge":407,"tags":409,"body":410,"_type":1077,"_id":1078,"_source":1079,"_file":1080,"_extension":1081},"posts",false,"","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":406},"/images/tools_1.jpg",{"label":408},"Tooling",[206,213,360,210],{"type":411,"children":412,"toc":1057},"root",[413,420,427,443,515,545,550,556,561,573,580,585,590,599,604,622,627,633,638,651,657,662,667,689,698,718,763,769,774,783,789,811,816,822,827,832,841,847,852,857,875,884,896,901,907,913,918,923,928,933,938,944,957,962,975,1003,1017,1029,1046,1052],{"type":414,"tag":415,"props":416,"children":417},"element","p",{},[418],{"type":419,"value":402},"text",{"type":414,"tag":421,"props":422,"children":424},"h2",{"id":423},"some-context",[425],{"type":419,"value":426},"Some context",{"type":414,"tag":415,"props":428,"children":429},{},[430,432,441],{"type":419,"value":431},"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":414,"tag":433,"props":434,"children":438},"a",{"href":435,"rel":436},"https://www.techwatching.dev/posts/testing-your-api-with-rest-client",[437],"nofollow",[439],{"type":419,"value":440},"This article",{"type":419,"value":442}," 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":414,"tag":415,"props":444,"children":445},{},[446,448,455,457,464,465,472,473,480,481,488,489,496,497,504,506,513],{"type":419,"value":447},"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":414,"tag":433,"props":449,"children":452},{"href":450,"rel":451},"https://www.postman.com",[437],[453],{"type":419,"value":454},"Postman",{"type":419,"value":456},", ",{"type":414,"tag":433,"props":458,"children":461},{"href":459,"rel":460},"https://marketplace.visualstudio.com/items?itemName=humao.rest-client",[437],[462],{"type":419,"value":463},"REST Client",{"type":419,"value":456},{"type":414,"tag":433,"props":466,"children":469},{"href":467,"rel":468},"https://www.thunderclient.com/",[437],[470],{"type":419,"value":471},"Thunder Client",{"type":419,"value":456},{"type":414,"tag":433,"props":474,"children":477},{"href":475,"rel":476},"https://nightingale.rest/",[437],[478],{"type":419,"value":479},"Nightingale",{"type":419,"value":456},{"type":414,"tag":433,"props":482,"children":485},{"href":483,"rel":484},"https://insomnia.rest/",[437],[486],{"type":419,"value":487},"Insomnia",{"type":419,"value":456},{"type":414,"tag":433,"props":490,"children":493},{"href":491,"rel":492},"https://rapidapi.com/products/api-design/",[437],[494],{"type":419,"value":495},"RapidAPI Client",{"type":419,"value":456},{"type":414,"tag":433,"props":498,"children":501},{"href":499,"rel":500},"https://hoppscotch.io/fr/",[437],[502],{"type":419,"value":503},"Hoppscotch",{"type":419,"value":505},", and ",{"type":414,"tag":433,"props":507,"children":510},{"href":508,"rel":509},"https://httpie.io/",[437],[511],{"type":419,"value":512},"HTTPie",{"type":419,"value":514}," just to name a few. There are many reasons why people choose one tool over another:",{"type":414,"tag":516,"props":517,"children":518},"ul",{},[519,525,530,535,540],{"type":414,"tag":520,"props":521,"children":522},"li",{},[523],{"type":419,"value":524},"it has more features than others",{"type":414,"tag":520,"props":526,"children":527},{},[528],{"type":419,"value":529},"some colleagues suggested it",{"type":414,"tag":520,"props":531,"children":532},{},[533],{"type":419,"value":534},"it's the latest tool featured on ProductHunt",{"type":414,"tag":520,"props":536,"children":537},{},[538],{"type":419,"value":539},"everyone in the company uses this API client",{"type":414,"tag":520,"props":541,"children":542},{},[543],{"type":419,"value":544},"it would be time-consuming to learn how to use another API Client",{"type":414,"tag":415,"props":546,"children":547},{},[548],{"type":419,"value":549},"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":414,"tag":421,"props":551,"children":553},{"id":552},"ease-of-use",[554],{"type":419,"value":555},"Ease of use",{"type":414,"tag":415,"props":557,"children":558},{},[559],{"type":419,"value":560},"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":414,"tag":415,"props":562,"children":563},{},[564],{"type":414,"tag":565,"props":566,"children":572},"img",{"alt":567,"className":568,"src":571},"A scrabble tile that says keep things simple.",[569,570],"rounded-lg","mx-auto","/posts/images/httpclients_1.jpg",[],{"type":414,"tag":574,"props":575,"children":577},"h3",{"id":576},"all-conceivable-functionalities-vs-essentials-features",[578],{"type":419,"value":579},"All conceivable functionalities vs. essentials features",{"type":414,"tag":415,"props":581,"children":582},{},[583],{"type":419,"value":584},"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":414,"tag":415,"props":586,"children":587},{},[588],{"type":419,"value":589},"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":414,"tag":415,"props":591,"children":592},{},[593],{"type":414,"tag":565,"props":594,"children":598},{"alt":595,"className":596,"src":597},"Logo of Postman.",[569,570],"/posts/images/httpclients_2.jpg",[],{"type":414,"tag":415,"props":600,"children":601},{},[602],{"type":419,"value":603},"So what are the essentials features an API Client should have besides sending requests to an API and displaying the response?",{"type":414,"tag":516,"props":605,"children":606},{},[607,612,617],{"type":414,"tag":520,"props":608,"children":609},{},[610],{"type":419,"value":611},"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":414,"tag":520,"props":613,"children":614},{},[615],{"type":419,"value":616},"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":414,"tag":520,"props":618,"children":619},{},[620],{"type":419,"value":621},"Third, it should allow version control of your request (we will come back to this later).",{"type":414,"tag":415,"props":623,"children":624},{},[625],{"type":419,"value":626},"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":414,"tag":574,"props":628,"children":630},{"id":629},"integrated-tools-vs-standalone-tools",[631],{"type":419,"value":632},"Integrated tools vs. standalone tools",{"type":414,"tag":415,"props":634,"children":635},{},[636],{"type":419,"value":637},"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":414,"tag":415,"props":639,"children":640},{},[641,643,649],{"type":419,"value":642},"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":414,"tag":433,"props":644,"children":647},{"href":645,"rel":646},"https://marketplace.visualstudio.com/items?itemName=MadsKristensen.RestClient",[437],[648],{"type":419,"value":463},{"type":419,"value":650}," 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":414,"tag":574,"props":652,"children":654},{"id":653},"gui-tools-vs-text-based-tools",[655],{"type":419,"value":656},"GUI tools vs. text-based tools",{"type":414,"tag":415,"props":658,"children":659},{},[660],{"type":419,"value":661},"There are 2 types of tools: GUI tools and text-based tools.",{"type":414,"tag":415,"props":663,"children":664},{},[665],{"type":419,"value":666},"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":414,"tag":415,"props":668,"children":669},{},[670,672,678,680,687],{"type":419,"value":671},"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":414,"tag":673,"props":674,"children":676},"code",{"className":675},[],[677],{"type":419,"value":463},{"type":419,"value":679}," you write your request following the standard ",{"type":414,"tag":433,"props":681,"children":684},{"href":682,"rel":683},"https://www.rfc-editor.org/rfc/rfc7230#section-3",[437],[685],{"type":419,"value":686},"RFC 2730",{"type":419,"value":688},". 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":414,"tag":415,"props":690,"children":691},{},[692],{"type":414,"tag":565,"props":693,"children":697},{"alt":694,"className":695,"src":696},"REST Client in vscode.",[569,570],"/posts/images/httpclients_3.png",[],{"type":414,"tag":415,"props":699,"children":700},{},[701,703,709,711,716],{"type":419,"value":702},"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":414,"tag":704,"props":705,"children":706},"em",{},[707],{"type":419,"value":708},".rest",{"type":419,"value":710}," or ",{"type":414,"tag":704,"props":712,"children":713},{},[714],{"type":419,"value":715},".http",{"type":419,"value":717}," 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":414,"tag":719,"props":720,"children":722},"callout",{"icon":721},"i-heroicons-light-bulb",[723,728],{"type":414,"tag":415,"props":724,"children":725},{},[726],{"type":419,"value":727},"I already mentioned them before but examples of such text-based tools are:",{"type":414,"tag":516,"props":729,"children":730},{},[731,741,751],{"type":414,"tag":520,"props":732,"children":733},{},[734,739],{"type":414,"tag":433,"props":735,"children":737},{"href":459,"rel":736},[437],[738],{"type":419,"value":463},{"type":419,"value":740}," in vscode",{"type":414,"tag":520,"props":742,"children":743},{},[744,749],{"type":414,"tag":433,"props":745,"children":747},{"href":645,"rel":746},[437],[748],{"type":419,"value":463},{"type":419,"value":750}," in Visual Studio",{"type":414,"tag":520,"props":752,"children":753},{},[754,761],{"type":414,"tag":433,"props":755,"children":758},{"href":756,"rel":757},"https://www.jetbrains.com/help/rider/Http_client_in__product__code_editor.html",[437],[759],{"type":419,"value":760},"HTTP Client",{"type":419,"value":762}," in Rider or any other JetBrains IDE",{"type":414,"tag":421,"props":764,"children":766},{"id":765},"collaboration",[767],{"type":419,"value":768},"Collaboration",{"type":414,"tag":415,"props":770,"children":771},{},[772],{"type":419,"value":773},"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":414,"tag":415,"props":775,"children":776},{},[777],{"type":414,"tag":565,"props":778,"children":782},{"alt":779,"className":780,"src":781},"A scrabble board with words spelling teamwork.",[569,570],"/posts/images/httpclients_4.jpg",[],{"type":414,"tag":574,"props":784,"children":786},{"id":785},"are-you-ready-to-pay-the-price-for-team-collaboration",[787],{"type":419,"value":788},"Are you ready to pay the price for team collaboration?",{"type":414,"tag":415,"props":790,"children":791},{},[792,794,800,802,809],{"type":419,"value":793},"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":414,"tag":433,"props":795,"children":798},{"href":796,"rel":797},"https://www.postman.com/pricing/",[437],[799],{"type":419,"value":454},{"type":419,"value":801}," or the one from ",{"type":414,"tag":433,"props":803,"children":806},{"href":804,"rel":805},"https://rapidapi.com/products/api-design",[437],[807],{"type":419,"value":808},"RapidAPI",{"type":419,"value":810},". 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":414,"tag":415,"props":812,"children":813},{},[814],{"type":419,"value":815},"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":414,"tag":574,"props":817,"children":819},{"id":818},"version-control-is-the-key",[820],{"type":419,"value":821},"Version control is the key",{"type":414,"tag":415,"props":823,"children":824},{},[825],{"type":419,"value":826},"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":414,"tag":415,"props":828,"children":829},{},[830],{"type":419,"value":831},"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":414,"tag":719,"props":833,"children":835},{"icon":834},"i-heroicons-chat-bubble-left-20-solid",[836],{"type":414,"tag":415,"props":837,"children":838},{},[839],{"type":419,"value":840},"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":414,"tag":574,"props":842,"children":844},{"id":843},"how-requests-are-stored-is-important",[845],{"type":419,"value":846},"How requests are stored is important",{"type":414,"tag":415,"props":848,"children":849},{},[850],{"type":419,"value":851},"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":414,"tag":415,"props":853,"children":854},{},[855],{"type":419,"value":856},"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":414,"tag":516,"props":858,"children":859},{},[860,865,870],{"type":414,"tag":520,"props":861,"children":862},{},[863],{"type":419,"value":864},"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":414,"tag":520,"props":866,"children":867},{},[868],{"type":419,"value":869},"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":414,"tag":520,"props":871,"children":872},{},[873],{"type":419,"value":874},"the environment files versioned were containing secrets so secrets were committed in clear text in the git repository 😱",{"type":414,"tag":415,"props":876,"children":877},{},[878],{"type":414,"tag":565,"props":879,"children":883},{"alt":880,"className":881,"src":882},"A silhouette of a man.",[569,570],"/posts/images/httpclients_5.jpg",[],{"type":414,"tag":415,"props":885,"children":886},{},[887,889,894],{"type":419,"value":888},"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":414,"tag":433,"props":890,"children":892},{"href":682,"rel":891},[437],[893],{"type":419,"value":686},{"type":419,"value":895},". 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":414,"tag":415,"props":897,"children":898},{},[899],{"type":419,"value":900},"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":414,"tag":421,"props":902,"children":904},{"id":903},"final-thoughts",[905],{"type":419,"value":906},"Final thoughts",{"type":414,"tag":574,"props":908,"children":910},{"id":909},"using-the-right-tool-for-a-given-context",[911],{"type":419,"value":912},"Using the right tool for a given context",{"type":414,"tag":415,"props":914,"children":915},{},[916],{"type":419,"value":917},"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":414,"tag":415,"props":919,"children":920},{},[921],{"type":419,"value":922},"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":414,"tag":415,"props":924,"children":925},{},[926],{"type":419,"value":927},"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":414,"tag":415,"props":929,"children":930},{},[931],{"type":419,"value":932},"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":414,"tag":415,"props":934,"children":935},{},[936],{"type":419,"value":937},"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":414,"tag":574,"props":939,"children":941},{"id":940},"what-am-i-currently-using",[942],{"type":419,"value":943},"What am I currently using?",{"type":414,"tag":415,"props":945,"children":946},{},[947,949,955],{"type":419,"value":948},"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":414,"tag":673,"props":950,"children":952},{"className":951},[],[953],{"type":419,"value":954},"git pull",{"type":419,"value":956}," 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":414,"tag":415,"props":958,"children":959},{},[960],{"type":419,"value":961},"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":414,"tag":415,"props":963,"children":964},{},[965,967,973],{"type":419,"value":966},"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":414,"tag":433,"props":968,"children":970},{"href":756,"rel":969},[437],[971],{"type":419,"value":972},"built-in HTTP Client",{"type":419,"value":974}," because:",{"type":414,"tag":516,"props":976,"children":977},{},[978,983,988,993,998],{"type":414,"tag":520,"props":979,"children":980},{},[981],{"type":419,"value":982},"you don't have to leave your favorite IDE to make HTTP requests to an API",{"type":414,"tag":520,"props":984,"children":985},{},[986],{"type":419,"value":987},"it supports HTTP requests, gRPC requests, WebSocket requests, GraphQL",{"type":414,"tag":520,"props":989,"children":990},{},[991],{"type":419,"value":992},"it has many features to help you write the requests like converting cURL requests to the HTTP request format",{"type":414,"tag":520,"props":994,"children":995},{},[996],{"type":419,"value":997},"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":414,"tag":520,"props":999,"children":1000},{},[1001],{"type":419,"value":1002},"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":414,"tag":415,"props":1004,"children":1005},{},[1006,1008,1015],{"type":419,"value":1007},"And the icing on the cake, as you see on the tweet below there is a ",{"type":414,"tag":433,"props":1009,"children":1012},{"href":1010,"rel":1011},"https://github.com/restcli/restcli",[437],[1013],{"type":419,"value":1014},"CLI",{"type":419,"value":1016}," 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":414,"tag":1018,"props":1019,"children":1023},"div",{"className":1020},[1021,1022],"flex","justify-center",[1024],{"type":414,"tag":1025,"props":1026,"children":1028},"tweet",{"id":1027},"1546831245274931201",[],{"type":414,"tag":719,"props":1030,"children":1031},{"icon":721},[1032],{"type":414,"tag":415,"props":1033,"children":1034},{},[1035,1037,1044],{"type":419,"value":1036},"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":414,"tag":433,"props":1038,"children":1041},{"href":1039,"rel":1040},"https://www.techwatching.dev/posts/http-clients-secrets",[437],[1042],{"type":419,"value":1043},"an article",{"type":419,"value":1045}," 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":414,"tag":574,"props":1047,"children":1049},{"id":1048},"in-summary",[1050],{"type":419,"value":1051},"In summary",{"type":414,"tag":415,"props":1053,"children":1054},{},[1055],{"type":419,"value":1056},"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":1058,"depth":1058,"links":1059},2,[1060,1061,1067,1072],{"id":423,"depth":1058,"text":426},{"id":552,"depth":1058,"text":555,"children":1062},[1063,1065,1066],{"id":576,"depth":1064,"text":579},3,{"id":629,"depth":1064,"text":632},{"id":653,"depth":1064,"text":656},{"id":765,"depth":1058,"text":768,"children":1068},[1069,1070,1071],{"id":785,"depth":1064,"text":788},{"id":818,"depth":1064,"text":821},{"id":843,"depth":1064,"text":846},{"id":903,"depth":1058,"text":906,"children":1073},[1074,1075,1076],{"id":909,"depth":1064,"text":912},{"id":940,"depth":1064,"text":943},{"id":1048,"depth":1064,"text":1051},"markdown","content:1.posts:43.http-clients.md","content","1.posts/43.http-clients.md","md",{"_path":55,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":54,"description":1083,"lead":1084,"date":1085,"image":1086,"badge":1088,"tags":1090,"body":1091,"_type":1077,"_id":2430,"_source":1079,"_file":2431,"_extension":1081},"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":1087},"/images/western_1.jpg",{"label":1089},"Development",[236,213,286,210,288],{"type":411,"children":1092,"toc":2416},[1093,1097,1103,1134,1231,1237,1250,1264,1359,1379,1827,1853,1862,1875,1884,1933,1942,1955,1980,1989,1994,2000,2028,2037,2051,2056,2065,2098,2106,2141,2149,2161,2166,2177,2183,2212,2221,2233,2247,2252,2272,2281,2292,2306,2329,2338,2358,2367,2379,2388,2399,2405,2410],{"type":414,"tag":415,"props":1094,"children":1095},{},[1096],{"type":419,"value":1083},{"type":414,"tag":421,"props":1098,"children":1100},{"id":1099},"introducing-the-case-study",[1101],{"type":419,"value":1102},"Introducing the case study",{"type":414,"tag":415,"props":1104,"children":1105},{},[1106,1108,1119,1121,1132],{"type":419,"value":1107},"I wrote a very basic ASP.NET Core API ",{"type":414,"tag":433,"props":1109,"children":1112},{"href":1110,"rel":1111},"https://github.com/TechWatching/MyLotrApi/tree/a70b6f91fcbcc30a3c3a3616799e3e85817b7906",[437],[1113],{"type":414,"tag":673,"props":1114,"children":1116},{"className":1115},[],[1117],{"type":419,"value":1118},"MyLotrApi",{"type":419,"value":1120}," that exposes some data from the \"Lord of the Rings\" universe. This API calls another existing API ",{"type":414,"tag":433,"props":1122,"children":1125},{"href":1123,"rel":1124},"https://the-one-api.dev/",[437],[1126],{"type":414,"tag":673,"props":1127,"children":1129},{"className":1128},[],[1130],{"type":419,"value":1131},"The One API",{"type":419,"value":1133}," to retrieve this data. The code is quite simple:",{"type":414,"tag":516,"props":1135,"children":1136},{},[1137,1175,1218],{"type":414,"tag":520,"props":1138,"children":1139},{},[1140,1142,1148,1150],{"type":419,"value":1141},"a controller ",{"type":414,"tag":673,"props":1143,"children":1145},{"className":1144},[],[1146],{"type":419,"value":1147},"LotrController",{"type":419,"value":1149}," with 2 routes\n",{"type":414,"tag":516,"props":1151,"children":1152},{},[1153,1164],{"type":414,"tag":520,"props":1154,"children":1155},{},[1156,1162],{"type":414,"tag":673,"props":1157,"children":1159},{"className":1158},[],[1160],{"type":419,"value":1161},"GET /popularmovies",{"type":419,"value":1163}," that returns the movies in the \"Lord of the Rings\" universe with a rotten tomatoes score above 80",{"type":414,"tag":520,"props":1165,"children":1166},{},[1167,1173],{"type":414,"tag":673,"props":1168,"children":1170},{"className":1169},[],[1171],{"type":419,"value":1172},"GET /famousorcs",{"type":419,"value":1174}," that returns orc characters from the \"Lord of the Rings\" universe",{"type":414,"tag":520,"props":1176,"children":1177},{},[1178,1180,1186,1188],{"type":419,"value":1179},"a service ",{"type":414,"tag":673,"props":1181,"children":1183},{"className":1182},[],[1184],{"type":419,"value":1185},"TheOneApiService",{"type":419,"value":1187}," that\n",{"type":414,"tag":516,"props":1189,"children":1190},{},[1191,1201,1213],{"type":414,"tag":520,"props":1192,"children":1193},{},[1194,1196],{"type":419,"value":1195},"makes the HTTP calls to the API ",{"type":414,"tag":673,"props":1197,"children":1199},{"className":1198},[],[1200],{"type":419,"value":1131},{"type":414,"tag":520,"props":1202,"children":1203},{},[1204,1206,1211],{"type":419,"value":1205},"has one method for each endpoint of the API ",{"type":414,"tag":673,"props":1207,"children":1209},{"className":1208},[],[1210],{"type":419,"value":1131},{"type":419,"value":1212}," that is used",{"type":414,"tag":520,"props":1214,"children":1215},{},[1216],{"type":419,"value":1217},"uses NewtonSoft for deserializing responses",{"type":414,"tag":520,"props":1219,"children":1220},{},[1221,1223,1229],{"type":419,"value":1222},"a ",{"type":414,"tag":673,"props":1224,"children":1226},{"className":1225},[],[1227],{"type":419,"value":1228},"Models",{"type":419,"value":1230}," class that contains the different data models used by the API",{"type":414,"tag":421,"props":1232,"children":1234},{"id":1233},"about-using-records",[1235],{"type":419,"value":1236},"About using records",{"type":414,"tag":415,"props":1238,"children":1239},{},[1240,1242,1248],{"type":419,"value":1241},"Instead of using basic C# classes for the models in this API, I used ",{"type":414,"tag":433,"props":1243,"children":1246},{"href":1244,"rel":1245},"https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#record-types",[437],[1247],{"type":419,"value":286},{"type":419,"value":1249},". 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":414,"tag":415,"props":1251,"children":1252},{},[1253,1255,1262],{"type":419,"value":1254},"In my sample, I declared my models with the ",{"type":414,"tag":433,"props":1256,"children":1259},{"href":1257,"rel":1258},"https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#positional-syntax-for-property-definition",[437],[1260],{"type":419,"value":1261},"positional syntax for property definition",{"type":419,"value":1263}," 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":414,"tag":1265,"props":1266,"children":1269},"pre",{"className":1267,"code":1268,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","public record Movie(string Name, int RuntimeInMinutes, int BudgetInMillions, float RottenTomatesScore);\n",[1270],{"type":414,"tag":673,"props":1271,"children":1272},{"__ignoreMap":401},[1273],{"type":414,"tag":1274,"props":1275,"children":1278},"span",{"class":1276,"line":1277},"line",1,[1279,1285,1291,1296,1302,1307,1312,1317,1322,1327,1331,1335,1340,1344,1349,1354],{"type":414,"tag":1274,"props":1280,"children":1282},{"style":1281},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[1283],{"type":419,"value":1284},"public",{"type":414,"tag":1274,"props":1286,"children":1288},{"style":1287},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1289],{"type":419,"value":1290}," record",{"type":414,"tag":1274,"props":1292,"children":1293},{"style":1287},[1294],{"type":419,"value":1295}," Movie",{"type":414,"tag":1274,"props":1297,"children":1299},{"style":1298},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1300],{"type":419,"value":1301},"(",{"type":414,"tag":1274,"props":1303,"children":1304},{"style":1298},[1305],{"type":419,"value":1306},"string",{"type":414,"tag":1274,"props":1308,"children":1309},{"style":1287},[1310],{"type":419,"value":1311}," Name",{"type":414,"tag":1274,"props":1313,"children":1314},{"style":1298},[1315],{"type":419,"value":1316},",",{"type":414,"tag":1274,"props":1318,"children":1319},{"style":1298},[1320],{"type":419,"value":1321}," int",{"type":414,"tag":1274,"props":1323,"children":1324},{"style":1287},[1325],{"type":419,"value":1326}," RuntimeInMinutes",{"type":414,"tag":1274,"props":1328,"children":1329},{"style":1298},[1330],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1332,"children":1333},{"style":1298},[1334],{"type":419,"value":1321},{"type":414,"tag":1274,"props":1336,"children":1337},{"style":1287},[1338],{"type":419,"value":1339}," BudgetInMillions",{"type":414,"tag":1274,"props":1341,"children":1342},{"style":1298},[1343],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1345,"children":1346},{"style":1298},[1347],{"type":419,"value":1348}," float",{"type":414,"tag":1274,"props":1350,"children":1351},{"style":1287},[1352],{"type":419,"value":1353}," RottenTomatesScore",{"type":414,"tag":1274,"props":1355,"children":1356},{"style":1298},[1357],{"type":419,"value":1358},");\n",{"type":414,"tag":415,"props":1360,"children":1361},{},[1362,1364,1370,1372,1377],{"type":419,"value":1363},"You can notice that I put my records in one place (the ",{"type":414,"tag":673,"props":1365,"children":1367},{"className":1366},[],[1368],{"type":419,"value":1369},"Models.cs",{"type":419,"value":1371}," 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":414,"tag":673,"props":1373,"children":1375},{"className":1374},[],[1376],{"type":419,"value":1228},{"type":419,"value":1378},". But I think the convention of using one file by class is not completely relevant in the case of records.",{"type":414,"tag":1265,"props":1380,"children":1382},{"className":1267,"code":1381,"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",[1383],{"type":414,"tag":673,"props":1384,"children":1385},{"__ignoreMap":401},[1386,1406,1440,1464,1489,1523,1533,1547,1556,1625,1634,1697,1705,1752,1760,1818],{"type":414,"tag":1274,"props":1387,"children":1388},{"class":1276,"line":1277},[1389,1395,1401],{"type":414,"tag":1274,"props":1390,"children":1392},{"style":1391},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1393],{"type":419,"value":1394},"using",{"type":414,"tag":1274,"props":1396,"children":1398},{"style":1397},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1399],{"type":419,"value":1400}," System",{"type":414,"tag":1274,"props":1402,"children":1403},{"style":1298},[1404],{"type":419,"value":1405},";\n",{"type":414,"tag":1274,"props":1407,"children":1408},{"class":1276,"line":1058},[1409,1413,1417,1422,1427,1431,1436],{"type":414,"tag":1274,"props":1410,"children":1411},{"style":1391},[1412],{"type":419,"value":1394},{"type":414,"tag":1274,"props":1414,"children":1415},{"style":1397},[1416],{"type":419,"value":1400},{"type":414,"tag":1274,"props":1418,"children":1419},{"style":1298},[1420],{"type":419,"value":1421},".",{"type":414,"tag":1274,"props":1423,"children":1424},{"style":1397},[1425],{"type":419,"value":1426},"Collections",{"type":414,"tag":1274,"props":1428,"children":1429},{"style":1298},[1430],{"type":419,"value":1421},{"type":414,"tag":1274,"props":1432,"children":1433},{"style":1397},[1434],{"type":419,"value":1435},"Generic",{"type":414,"tag":1274,"props":1437,"children":1438},{"style":1298},[1439],{"type":419,"value":1405},{"type":414,"tag":1274,"props":1441,"children":1442},{"class":1276,"line":1064},[1443,1447,1451,1455,1460],{"type":414,"tag":1274,"props":1444,"children":1445},{"style":1391},[1446],{"type":419,"value":1394},{"type":414,"tag":1274,"props":1448,"children":1449},{"style":1397},[1450],{"type":419,"value":1400},{"type":414,"tag":1274,"props":1452,"children":1453},{"style":1298},[1454],{"type":419,"value":1421},{"type":414,"tag":1274,"props":1456,"children":1457},{"style":1397},[1458],{"type":419,"value":1459},"Linq",{"type":414,"tag":1274,"props":1461,"children":1462},{"style":1298},[1463],{"type":419,"value":1405},{"type":414,"tag":1274,"props":1465,"children":1467},{"class":1276,"line":1466},4,[1468,1472,1476,1480,1485],{"type":414,"tag":1274,"props":1469,"children":1470},{"style":1391},[1471],{"type":419,"value":1394},{"type":414,"tag":1274,"props":1473,"children":1474},{"style":1397},[1475],{"type":419,"value":1400},{"type":414,"tag":1274,"props":1477,"children":1478},{"style":1298},[1479],{"type":419,"value":1421},{"type":414,"tag":1274,"props":1481,"children":1482},{"style":1397},[1483],{"type":419,"value":1484},"Text",{"type":414,"tag":1274,"props":1486,"children":1487},{"style":1298},[1488],{"type":419,"value":1405},{"type":414,"tag":1274,"props":1490,"children":1492},{"class":1276,"line":1491},5,[1493,1497,1501,1505,1510,1514,1519],{"type":414,"tag":1274,"props":1494,"children":1495},{"style":1391},[1496],{"type":419,"value":1394},{"type":414,"tag":1274,"props":1498,"children":1499},{"style":1397},[1500],{"type":419,"value":1400},{"type":414,"tag":1274,"props":1502,"children":1503},{"style":1298},[1504],{"type":419,"value":1421},{"type":414,"tag":1274,"props":1506,"children":1507},{"style":1397},[1508],{"type":419,"value":1509},"Threading",{"type":414,"tag":1274,"props":1511,"children":1512},{"style":1298},[1513],{"type":419,"value":1421},{"type":414,"tag":1274,"props":1515,"children":1516},{"style":1397},[1517],{"type":419,"value":1518},"Tasks",{"type":414,"tag":1274,"props":1520,"children":1521},{"style":1298},[1522],{"type":419,"value":1405},{"type":414,"tag":1274,"props":1524,"children":1526},{"class":1276,"line":1525},6,[1527],{"type":414,"tag":1274,"props":1528,"children":1530},{"emptyLinePlaceholder":1529},true,[1531],{"type":419,"value":1532},"\n",{"type":414,"tag":1274,"props":1534,"children":1536},{"class":1276,"line":1535},7,[1537,1542],{"type":414,"tag":1274,"props":1538,"children":1539},{"style":1287},[1540],{"type":419,"value":1541},"namespace",{"type":414,"tag":1274,"props":1543,"children":1544},{"style":1397},[1545],{"type":419,"value":1546}," MyLotrApi\n",{"type":414,"tag":1274,"props":1548,"children":1550},{"class":1276,"line":1549},8,[1551],{"type":414,"tag":1274,"props":1552,"children":1553},{"style":1298},[1554],{"type":419,"value":1555},"{\n",{"type":414,"tag":1274,"props":1557,"children":1559},{"class":1276,"line":1558},9,[1560,1565,1569,1573,1577,1581,1585,1589,1593,1597,1601,1605,1609,1613,1617,1621],{"type":414,"tag":1274,"props":1561,"children":1562},{"style":1281},[1563],{"type":419,"value":1564},"    public",{"type":414,"tag":1274,"props":1566,"children":1567},{"style":1287},[1568],{"type":419,"value":1290},{"type":414,"tag":1274,"props":1570,"children":1571},{"style":1287},[1572],{"type":419,"value":1295},{"type":414,"tag":1274,"props":1574,"children":1575},{"style":1298},[1576],{"type":419,"value":1301},{"type":414,"tag":1274,"props":1578,"children":1579},{"style":1298},[1580],{"type":419,"value":1306},{"type":414,"tag":1274,"props":1582,"children":1583},{"style":1287},[1584],{"type":419,"value":1311},{"type":414,"tag":1274,"props":1586,"children":1587},{"style":1298},[1588],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1590,"children":1591},{"style":1298},[1592],{"type":419,"value":1321},{"type":414,"tag":1274,"props":1594,"children":1595},{"style":1287},[1596],{"type":419,"value":1326},{"type":414,"tag":1274,"props":1598,"children":1599},{"style":1298},[1600],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1602,"children":1603},{"style":1298},[1604],{"type":419,"value":1321},{"type":414,"tag":1274,"props":1606,"children":1607},{"style":1287},[1608],{"type":419,"value":1339},{"type":414,"tag":1274,"props":1610,"children":1611},{"style":1298},[1612],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1614,"children":1615},{"style":1298},[1616],{"type":419,"value":1348},{"type":414,"tag":1274,"props":1618,"children":1619},{"style":1287},[1620],{"type":419,"value":1353},{"type":414,"tag":1274,"props":1622,"children":1623},{"style":1298},[1624],{"type":419,"value":1358},{"type":414,"tag":1274,"props":1626,"children":1628},{"class":1276,"line":1627},10,[1629],{"type":414,"tag":1274,"props":1630,"children":1631},{"style":1397},[1632],{"type":419,"value":1633},"    \n",{"type":414,"tag":1274,"props":1635,"children":1637},{"class":1276,"line":1636},11,[1638,1642,1646,1651,1655,1660,1665,1670,1675,1680,1684,1688,1693],{"type":414,"tag":1274,"props":1639,"children":1640},{"style":1281},[1641],{"type":419,"value":1564},{"type":414,"tag":1274,"props":1643,"children":1644},{"style":1287},[1645],{"type":419,"value":1290},{"type":414,"tag":1274,"props":1647,"children":1648},{"style":1287},[1649],{"type":419,"value":1650}," MovieResponse",{"type":414,"tag":1274,"props":1652,"children":1653},{"style":1298},[1654],{"type":419,"value":1301},{"type":414,"tag":1274,"props":1656,"children":1657},{"style":1287},[1658],{"type":419,"value":1659},"IList",{"type":414,"tag":1274,"props":1661,"children":1662},{"style":1298},[1663],{"type":419,"value":1664},"\u003C",{"type":414,"tag":1274,"props":1666,"children":1667},{"style":1287},[1668],{"type":419,"value":1669},"Movie",{"type":414,"tag":1274,"props":1671,"children":1672},{"style":1298},[1673],{"type":419,"value":1674},">",{"type":414,"tag":1274,"props":1676,"children":1677},{"style":1287},[1678],{"type":419,"value":1679}," Docs",{"type":414,"tag":1274,"props":1681,"children":1682},{"style":1298},[1683],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1685,"children":1686},{"style":1298},[1687],{"type":419,"value":1321},{"type":414,"tag":1274,"props":1689,"children":1690},{"style":1287},[1691],{"type":419,"value":1692}," Total",{"type":414,"tag":1274,"props":1694,"children":1695},{"style":1298},[1696],{"type":419,"value":1358},{"type":414,"tag":1274,"props":1698,"children":1700},{"class":1276,"line":1699},12,[1701],{"type":414,"tag":1274,"props":1702,"children":1703},{"emptyLinePlaceholder":1529},[1704],{"type":419,"value":1532},{"type":414,"tag":1274,"props":1706,"children":1708},{"class":1276,"line":1707},13,[1709,1713,1717,1722,1726,1730,1734,1738,1743,1748],{"type":414,"tag":1274,"props":1710,"children":1711},{"style":1281},[1712],{"type":419,"value":1564},{"type":414,"tag":1274,"props":1714,"children":1715},{"style":1287},[1716],{"type":419,"value":1290},{"type":414,"tag":1274,"props":1718,"children":1719},{"style":1287},[1720],{"type":419,"value":1721}," Character",{"type":414,"tag":1274,"props":1723,"children":1724},{"style":1298},[1725],{"type":419,"value":1301},{"type":414,"tag":1274,"props":1727,"children":1728},{"style":1298},[1729],{"type":419,"value":1306},{"type":414,"tag":1274,"props":1731,"children":1732},{"style":1287},[1733],{"type":419,"value":1311},{"type":414,"tag":1274,"props":1735,"children":1736},{"style":1298},[1737],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1739,"children":1740},{"style":1298},[1741],{"type":419,"value":1742}," string",{"type":414,"tag":1274,"props":1744,"children":1745},{"style":1287},[1746],{"type":419,"value":1747}," Realm",{"type":414,"tag":1274,"props":1749,"children":1750},{"style":1298},[1751],{"type":419,"value":1358},{"type":414,"tag":1274,"props":1753,"children":1755},{"class":1276,"line":1754},14,[1756],{"type":414,"tag":1274,"props":1757,"children":1758},{"emptyLinePlaceholder":1529},[1759],{"type":419,"value":1532},{"type":414,"tag":1274,"props":1761,"children":1763},{"class":1276,"line":1762},15,[1764,1768,1772,1777,1781,1785,1789,1794,1798,1802,1806,1810,1814],{"type":414,"tag":1274,"props":1765,"children":1766},{"style":1281},[1767],{"type":419,"value":1564},{"type":414,"tag":1274,"props":1769,"children":1770},{"style":1287},[1771],{"type":419,"value":1290},{"type":414,"tag":1274,"props":1773,"children":1774},{"style":1287},[1775],{"type":419,"value":1776}," CharacterResponse",{"type":414,"tag":1274,"props":1778,"children":1779},{"style":1298},[1780],{"type":419,"value":1301},{"type":414,"tag":1274,"props":1782,"children":1783},{"style":1287},[1784],{"type":419,"value":1659},{"type":414,"tag":1274,"props":1786,"children":1787},{"style":1298},[1788],{"type":419,"value":1664},{"type":414,"tag":1274,"props":1790,"children":1791},{"style":1287},[1792],{"type":419,"value":1793},"Character",{"type":414,"tag":1274,"props":1795,"children":1796},{"style":1298},[1797],{"type":419,"value":1674},{"type":414,"tag":1274,"props":1799,"children":1800},{"style":1287},[1801],{"type":419,"value":1679},{"type":414,"tag":1274,"props":1803,"children":1804},{"style":1298},[1805],{"type":419,"value":1316},{"type":414,"tag":1274,"props":1807,"children":1808},{"style":1298},[1809],{"type":419,"value":1321},{"type":414,"tag":1274,"props":1811,"children":1812},{"style":1287},[1813],{"type":419,"value":1692},{"type":414,"tag":1274,"props":1815,"children":1816},{"style":1298},[1817],{"type":419,"value":1358},{"type":414,"tag":1274,"props":1819,"children":1821},{"class":1276,"line":1820},16,[1822],{"type":414,"tag":1274,"props":1823,"children":1824},{"style":1298},[1825],{"type":419,"value":1826},"}\n",{"type":414,"tag":415,"props":1828,"children":1829},{},[1830,1832,1837,1839,1844,1846,1851],{"type":419,"value":1831},"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":414,"tag":673,"props":1833,"children":1835},{"className":1834},[],[1836],{"type":419,"value":1131},{"type":419,"value":1838},". Indeed it makes perfect sense in this context where my API queries ",{"type":414,"tag":673,"props":1840,"children":1842},{"className":1841},[],[1843],{"type":419,"value":1131},{"type":419,"value":1845},", 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":414,"tag":673,"props":1847,"children":1849},{"className":1848},[],[1850],{"type":419,"value":1131},{"type":419,"value":1852}," and immutable records can easily guarantee that: if the code tries to change something it won't compile.",{"type":414,"tag":415,"props":1854,"children":1855},{},[1856],{"type":414,"tag":565,"props":1857,"children":1861},{"alt":1858,"className":1859,"src":1860},"Code showing immutability of records.",[569,570],"/posts/images/onceuponatime_records_1.png",[],{"type":414,"tag":415,"props":1863,"children":1864},{},[1865,1867,1873],{"type":419,"value":1866},"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":414,"tag":673,"props":1868,"children":1870},{"className":1869},[],[1871],{"type":419,"value":1872},"Assert.AreEqual",{"type":419,"value":1874}," 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":414,"tag":415,"props":1876,"children":1877},{},[1878],{"type":414,"tag":565,"props":1879,"children":1883},{"alt":1880,"className":1881,"src":1882},"Code showing classes not having value equality",[569,570],"onceuponatime_records_3.png",[],{"type":414,"tag":415,"props":1885,"children":1886},{},[1887,1889,1900,1902,1908,1910,1916,1918,1924,1926,1931],{"type":419,"value":1888},"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":414,"tag":433,"props":1890,"children":1893},{"href":1891,"rel":1892},"https://github.com/fluentassertions/fluentassertions",[437],[1894],{"type":414,"tag":673,"props":1895,"children":1897},{"className":1896},[],[1898],{"type":419,"value":1899},"FluentAssertions",{"type":419,"value":1901}," for your asserts. But the real solution to make your asserts work is to implement ",{"type":414,"tag":673,"props":1903,"children":1905},{"className":1904},[],[1906],{"type":419,"value":1907},"IEquatable\u003CT>",{"type":419,"value":1909},", and overrides ",{"type":414,"tag":673,"props":1911,"children":1913},{"className":1912},[],[1914],{"type":419,"value":1915},"Object.Equals(Object)",{"type":419,"value":1917}," and ",{"type":414,"tag":673,"props":1919,"children":1921},{"className":1920},[],[1922],{"type":419,"value":1923},"Object.GetHashCode()",{"type":419,"value":1925}," 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":414,"tag":673,"props":1927,"children":1929},{"className":1928},[],[1930],{"type":419,"value":1872},{"type":419,"value":1932}," between two variables of a record type will work if all the property and field values match.",{"type":414,"tag":415,"props":1934,"children":1935},{},[1936],{"type":414,"tag":565,"props":1937,"children":1941},{"alt":1938,"className":1939,"src":1940},"Code showing value equality of records",[569,570],"/posts/images/onceuponatime_records_2.png",[],{"type":414,"tag":421,"props":1943,"children":1945},{"id":1944},"what-can-be-improved-in-theoneapiservice",[1946,1948,1953],{"type":419,"value":1947},"What can be improved in ",{"type":414,"tag":673,"props":1949,"children":1951},{"className":1950},[],[1952],{"type":419,"value":1185},{"type":419,"value":1954},"?",{"type":414,"tag":415,"props":1956,"children":1957},{},[1958,1960,1970,1972,1978],{"type":419,"value":1959},"Enough talking about records, let's have a closer look at ",{"type":414,"tag":433,"props":1961,"children":1964},{"href":1962,"rel":1963},"https://github.com/TechWatching/MyLotrApi/blob/a70b6f91fcbcc30a3c3a3616799e3e85817b7906/src/MyLotrApi/TheOneApiService.cs",[437],[1965],{"type":414,"tag":673,"props":1966,"children":1968},{"className":1967},[],[1969],{"type":419,"value":1185},{"type":419,"value":1971}," and see what we can improve. At first sight, the code looks fine, just 2 methods that use an ",{"type":414,"tag":673,"props":1973,"children":1975},{"className":1974},[],[1976],{"type":419,"value":1977},"HttpClient",{"type":419,"value":1979}," 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":414,"tag":415,"props":1981,"children":1982},{},[1983],{"type":414,"tag":565,"props":1984,"children":1988},{"alt":1985,"className":1986,"src":1987},"The OneApiService first code version.",[569,570],"/posts/images/onceuponatime_theoneapiservice_1.png",[],{"type":414,"tag":415,"props":1990,"children":1991},{},[1992],{"type":419,"value":1993},"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":414,"tag":574,"props":1995,"children":1997},{"id":1996},"adding-a-private-method-that-factorizes-the-code",[1998],{"type":419,"value":1999},"Adding a private method that factorizes the code",{"type":414,"tag":415,"props":2001,"children":2002},{},[2003,2005,2011,2013,2019,2020,2026],{"type":419,"value":2004},"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":414,"tag":673,"props":2006,"children":2008},{"className":2007},[],[2009],{"type":419,"value":2010},"Send",{"type":419,"value":2012}," that does all the job (request, response handling, deserialization ...), and our 2 methods ",{"type":414,"tag":673,"props":2014,"children":2016},{"className":2015},[],[2017],{"type":419,"value":2018},"GetMovies",{"type":419,"value":1917},{"type":414,"tag":673,"props":2021,"children":2023},{"className":2022},[],[2024],{"type":419,"value":2025},"GetCharacters",{"type":419,"value":2027}," that have become quite trivial.",{"type":414,"tag":415,"props":2029,"children":2030},{},[2031],{"type":414,"tag":565,"props":2032,"children":2036},{"alt":2033,"className":2034,"src":2035},"The OneApiService factorizing code in a private method.",[569,570],"/posts/images/onceuponatime_theoneapiservice_2.png",[],{"type":414,"tag":415,"props":2038,"children":2039},{},[2040,2042,2049],{"type":419,"value":2041},"(this code can be found ",{"type":414,"tag":433,"props":2043,"children":2046},{"href":2044,"rel":2045},"https://github.com/TechWatching/MyLotrApi/blob/3e5561cb71678e432e970edcac6509581e3aaecd/src/MyLotrApi/TheOneApiService.cs",[437],[2047],{"type":419,"value":2048},"here",{"type":419,"value":2050},")",{"type":414,"tag":415,"props":2052,"children":2053},{},[2054],{"type":419,"value":2055},"Well, the code is fine, nothing to say about that but I don't like this solution at all 😁. And here is why:",{"type":414,"tag":2057,"props":2058,"children":2059},"ol",{},[2060],{"type":414,"tag":520,"props":2061,"children":2062},{},[2063],{"type":419,"value":2064},"It adds complexity and makes the code more difficult to read",{"type":414,"tag":415,"props":2066,"children":2067},{},[2068,2070,2075,2076,2081,2083,2088,2090,2096],{"type":419,"value":2069},"When I look at the ",{"type":414,"tag":673,"props":2071,"children":2073},{"className":2072},[],[2074],{"type":419,"value":2018},{"type":419,"value":710},{"type":414,"tag":673,"props":2077,"children":2079},{"className":2078},[],[2080],{"type":419,"value":2025},{"type":419,"value":2082}," I don't know exactly what they do, the business logic is hidden in the private ",{"type":414,"tag":673,"props":2084,"children":2086},{"className":2085},[],[2087],{"type":419,"value":2010},{"type":419,"value":2089}," 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":414,"tag":673,"props":2091,"children":2093},{"className":2092},[],[2094],{"type":419,"value":2095},"HttpRequestMessage",{"type":419,"value":2097}," with the potential content to send in the request. In fact, it's quite clear that this method does too many different things.",{"type":414,"tag":2057,"props":2099,"children":2100},{"start":1058},[2101],{"type":414,"tag":520,"props":2102,"children":2103},{},[2104],{"type":419,"value":2105},"It abstracts the use of the HttpClient",{"type":414,"tag":415,"props":2107,"children":2108},{},[2109,2111,2117,2119,2124,2126,2132,2134,2139],{"type":419,"value":2110},"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":414,"tag":673,"props":2112,"children":2114},{"className":2113},[],[2115],{"type":419,"value":2116},"GET",{"type":419,"value":2118}," request on the \"character\" route for instance. Of course, we can find part of that information in the parameters provided to the ",{"type":414,"tag":673,"props":2120,"children":2122},{"className":2121},[],[2123],{"type":419,"value":2010},{"type":419,"value":2125}," method but it is not as clear as calling the ",{"type":414,"tag":673,"props":2127,"children":2129},{"className":2128},[],[2130],{"type":419,"value":2131},"Get",{"type":419,"value":2133}," method of the ",{"type":414,"tag":673,"props":2135,"children":2137},{"className":2136},[],[2138],{"type":419,"value":1977},{"type":419,"value":2140}," 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":414,"tag":2057,"props":2142,"children":2143},{"start":1064},[2144],{"type":414,"tag":520,"props":2145,"children":2146},{},[2147],{"type":419,"value":2148},"It makes the code hard to maintain",{"type":414,"tag":415,"props":2150,"children":2151},{},[2152,2154,2159],{"type":419,"value":2153},"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":414,"tag":673,"props":2155,"children":2157},{"className":2156},[],[2158],{"type":419,"value":2010},{"type":419,"value":2160}," 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":414,"tag":415,"props":2162,"children":2163},{},[2164],{"type":419,"value":2165},"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":414,"tag":415,"props":2167,"children":2168},{},[2169,2171,2176],{"type":419,"value":2170},"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":414,"tag":673,"props":2172,"children":2174},{"className":2173},[],[2175],{"type":419,"value":1185},{"type":419,"value":1421},{"type":414,"tag":574,"props":2178,"children":2180},{"id":2179},"implementing-an-http-message-handler-to-simplify-the-code",[2181],{"type":419,"value":2182},"Implementing an HTTP message handler to simplify the code",{"type":414,"tag":415,"props":2184,"children":2185},{},[2186,2188,2195,2197,2202,2204,2210],{"type":419,"value":2187},"I already talked about using an HTTP message handler / delegating handler in ",{"type":414,"tag":433,"props":2189,"children":2192},{"href":2190,"rel":2191},"https://www.techwatching.dev/posts/delegating-handler",[437],[2193],{"type":419,"value":2194},"a previous article",{"type":419,"value":2196},". 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":414,"tag":673,"props":2198,"children":2200},{"className":2199},[],[2201],{"type":419,"value":1131},{"type":419,"value":2203}," like the fact of throwing the ",{"type":414,"tag":673,"props":2205,"children":2207},{"className":2206},[],[2208],{"type":419,"value":2209},"TheOneApiException",{"type":419,"value":2211}," when the HTTP responses are not successful.",{"type":414,"tag":415,"props":2213,"children":2214},{},[2215],{"type":414,"tag":565,"props":2216,"children":2220},{"alt":2217,"className":2218,"src":2219},"The code the OneApiErrorDelegatingHandler.",[569,570],"/posts/images/onceuponatime_handler_1.png",[],{"type":414,"tag":415,"props":2222,"children":2223},{},[2224,2226,2232],{"type":419,"value":2225},"(This code can be found ",{"type":414,"tag":433,"props":2227,"children":2230},{"href":2228,"rel":2229},"https://github.com/TechWatching/MyLotrApi/blob/9dfd9966044560d6e13c71d93eeba775e02bd18d/src/MyLotrApi/Services/HttpMessageHandlers/TheOneApiErrorDelegatingHandler.cs",[437],[2231],{"type":419,"value":2048},{"type":419,"value":2050},{"type":414,"tag":574,"props":2234,"children":2236},{"id":2235},"using-httpclientjsonextensions-to-get-rid-of-the-deserialization-code",[2237,2239,2245],{"type":419,"value":2238},"Using ",{"type":414,"tag":673,"props":2240,"children":2242},{"className":2241},[],[2243],{"type":419,"value":2244},"HttpClientJsonExtensions",{"type":419,"value":2246}," to get rid of the deserialization code",{"type":414,"tag":415,"props":2248,"children":2249},{},[2250],{"type":419,"value":2251},"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":414,"tag":415,"props":2253,"children":2254},{},[2255,2257,2270],{"type":419,"value":2256},"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":414,"tag":433,"props":2258,"children":2261},{"href":2259,"rel":2260},"https://www.nuget.org/packages/System.Net.Http.Json",[437],[2262,2268],{"type":414,"tag":673,"props":2263,"children":2265},{"className":2264},[],[2266],{"type":419,"value":2267},"System.Net.Http.Json",{"type":419,"value":2269}," NuGet package",{"type":419,"value":2271}," and the code becomes simpler.",{"type":414,"tag":415,"props":2273,"children":2274},{},[2275],{"type":414,"tag":565,"props":2276,"children":2280},{"alt":2277,"className":2278,"src":2279},"The code of GetCharacters method without manual deserialization.",[569,570],"/posts/images/onceuponatime_theoneapiservice_3.png",[],{"type":414,"tag":415,"props":2282,"children":2283},{},[2284,2285,2291],{"type":419,"value":2225},{"type":414,"tag":433,"props":2286,"children":2289},{"href":2287,"rel":2288},"https://github.com/TechWatching/MyLotrApi/blob/4ceca01826a0de4cca593c731f812ace874924a8/src/MyLotrApi/Services/TheOneApiService.cs",[437],[2290],{"type":419,"value":2048},{"type":419,"value":2050},{"type":414,"tag":574,"props":2293,"children":2295},{"id":2294},"exploring-an-alternative-to-implementing-the-interface-itheoneapiservice-with-refit",[2296,2298,2304],{"type":419,"value":2297},"Exploring an alternative to implementing the interface ",{"type":414,"tag":673,"props":2299,"children":2301},{"className":2300},[],[2302],{"type":419,"value":2303},"ITheOneApiService",{"type":419,"value":2305}," with Refit",{"type":414,"tag":415,"props":2307,"children":2308},{},[2309,2311,2318,2320,2327],{"type":419,"value":2310},"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":414,"tag":433,"props":2312,"children":2315},{"href":2313,"rel":2314},"https://github.com/reactiveui/refit",[437],[2316],{"type":419,"value":2317},"Refit",{"type":419,"value":2319},": the automatic type-safe REST library for .NET. The idea behind this ",{"type":414,"tag":433,"props":2321,"children":2324},{"href":2322,"rel":2323},"https://reactiveui.github.io/refit/",[437],[2325],{"type":419,"value":2326},"library",{"type":419,"value":2328}," 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":414,"tag":415,"props":2330,"children":2331},{},[2332],{"type":414,"tag":565,"props":2333,"children":2337},{"alt":2334,"className":2335,"src":2336},"The code of the IOneApiService interface using Refit.",[569,570],"/posts/images/onceuponatime_refit_2.png",[],{"type":414,"tag":415,"props":2339,"children":2340},{},[2341,2343,2348,2350,2356],{"type":419,"value":2342},"Refit even automatically handles query parameters by mapping them to the public properties of the object in parameter of a ",{"type":414,"tag":673,"props":2344,"children":2346},{"className":2345},[],[2347],{"type":419,"value":2116},{"type":419,"value":2349}," method in the interface. To name differently your property from the query parameter you can simply add an ",{"type":414,"tag":673,"props":2351,"children":2353},{"className":2352},[],[2354],{"type":419,"value":2355},"AliasAs",{"type":419,"value":2357}," attribute as I did here.",{"type":414,"tag":415,"props":2359,"children":2360},{},[2361],{"type":414,"tag":565,"props":2362,"children":2366},{"alt":2363,"className":2364,"src":2365},"The code of CharacterQueryParam.",[569,570],"/posts/images/onceuponatime_refit_3.png",[],{"type":414,"tag":415,"props":2368,"children":2369},{},[2370,2372,2377],{"type":419,"value":2371},"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":414,"tag":673,"props":2373,"children":2375},{"className":2374},[],[2376],{"type":419,"value":1185},{"type":419,"value":2378},", 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":414,"tag":415,"props":2380,"children":2381},{},[2382],{"type":414,"tag":565,"props":2383,"children":2387},{"alt":2384,"className":2385,"src":2386},"The code for registering the services using Refit.",[569,570],"/posts/images/onceuponatime_refit_1.png",[],{"type":414,"tag":415,"props":2389,"children":2390},{},[2391,2392,2398],{"type":419,"value":2225},{"type":414,"tag":433,"props":2393,"children":2396},{"href":2394,"rel":2395},"https://github.com/TechWatching/MyLotrApi/blob/76f85099bdb8c747717bf3e61007c276d5055e6f/src/MyLotrApi/Startup.cs",[437],[2397],{"type":419,"value":2048},{"type":419,"value":2050},{"type":414,"tag":421,"props":2400,"children":2402},{"id":2401},"to-conclude",[2403],{"type":419,"value":2404},"To conclude",{"type":414,"tag":415,"props":2406,"children":2407},{},[2408],{"type":419,"value":2409},"In this article, we have seen how we can improve some .NET code while talking about records, delegating handlers, refit...",{"type":414,"tag":2411,"props":2412,"children":2413},"style",{},[2414],{"type":419,"value":2415},"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":1058,"depth":1058,"links":2417},[2418,2419,2420,2429],{"id":1099,"depth":1058,"text":1102},{"id":1233,"depth":1058,"text":1236},{"id":1944,"depth":1058,"text":2421,"children":2422},"What can be improved in TheOneApiService?",[2423,2424,2425,2427],{"id":1996,"depth":1064,"text":1999},{"id":2179,"depth":1064,"text":2182},{"id":2235,"depth":1064,"text":2426},"Using HttpClientJsonExtensions to get rid of the deserialization code",{"id":2294,"depth":1064,"text":2428},"Exploring an alternative to implementing the interface ITheOneApiService with Refit",{"id":2401,"depth":1058,"text":2404},"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":2433,"lead":2434,"date":2435,"image":2436,"badge":2438,"tags":2439,"body":2440,"_type":1077,"_id":6350,"_source":1079,"_file":6351,"_extension":1081},"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":2437},"/images/keyboard_1.jpg",{"label":1089},[213,210,236,239],{"type":411,"children":2441,"toc":6343},[2442,2446,2452,2457,2466,2501,2506,2544,2653,2665,2670,2913,2931,3055,3067,3073,3099,4240,4245,4280,4286,4327,4982,5002,5008,5047,5081,5093,5462,5467,5995,6008,6330,6334,6339],{"type":414,"tag":415,"props":2443,"children":2444},{},[2445],{"type":419,"value":2433},{"type":414,"tag":421,"props":2447,"children":2449},{"id":2448},"context",[2450],{"type":419,"value":2451},"Context",{"type":414,"tag":415,"props":2453,"children":2454},{},[2455],{"type":419,"value":2456},"Let's imagine we have a very simple API that contains the following routes :",{"type":414,"tag":415,"props":2458,"children":2459},{},[2460],{"type":414,"tag":565,"props":2461,"children":2465},{"alt":2462,"className":2463,"src":2464},"Open API specifications of the Users API",[569,570],"/posts/images/delegatinghandler_api_1.png",[],{"type":414,"tag":415,"props":2467,"children":2468},{},[2469,2471,2477,2479,2485,2487,2493,2494,2500],{"type":419,"value":2470},"The ",{"type":414,"tag":673,"props":2472,"children":2474},{"className":2473},[],[2475],{"type":419,"value":2476},"POST /login",{"type":419,"value":2478}," route returns an ",{"type":414,"tag":673,"props":2480,"children":2482},{"className":2481},[],[2483],{"type":419,"value":2484},"AuthResponse",{"type":419,"value":2486}," that contains the necessary Bearer token to call the 2 protected routes ",{"type":414,"tag":673,"props":2488,"children":2490},{"className":2489},[],[2491],{"type":419,"value":2492},"GET /users",{"type":419,"value":1917},{"type":414,"tag":673,"props":2495,"children":2497},{"className":2496},[],[2498],{"type":419,"value":2499},"PUT /users/{username}",{"type":419,"value":1421},{"type":414,"tag":415,"props":2502,"children":2503},{},[2504],{"type":419,"value":2505},"We want to implement an IUserService that has 2 methods:",{"type":414,"tag":516,"props":2507,"children":2508},{},[2509,2527],{"type":414,"tag":520,"props":2510,"children":2511},{},[2512,2518,2520,2525],{"type":414,"tag":673,"props":2513,"children":2515},{"className":2514},[],[2516],{"type":419,"value":2517},"GetAllUsers",{"type":419,"value":2519}," to retrieve the list of users that will use the ",{"type":414,"tag":673,"props":2521,"children":2523},{"className":2522},[],[2524],{"type":419,"value":2492},{"type":419,"value":2526}," route",{"type":414,"tag":520,"props":2528,"children":2529},{},[2530,2536,2538,2543],{"type":414,"tag":673,"props":2531,"children":2533},{"className":2532},[],[2534],{"type":419,"value":2535},"UpdateUser",{"type":419,"value":2537}," to update a user that will use the ",{"type":414,"tag":673,"props":2539,"children":2541},{"className":2540},[],[2542],{"type":419,"value":2499},{"type":419,"value":2526},{"type":414,"tag":1265,"props":2545,"children":2547},{"className":1267,"code":2546,"language":326,"meta":401,"style":401},"public interface IUserService\n{\n    Task\u003CIReadOnlyCollection\u003CUser>> GetAllUsers();\n    Task UpdateUser(User userToUpdate);\n}\n",[2548],{"type":414,"tag":673,"props":2549,"children":2550},{"__ignoreMap":401},[2551,2568,2575,2617,2646],{"type":414,"tag":1274,"props":2552,"children":2553},{"class":1276,"line":1277},[2554,2558,2563],{"type":414,"tag":1274,"props":2555,"children":2556},{"style":1281},[2557],{"type":419,"value":1284},{"type":414,"tag":1274,"props":2559,"children":2560},{"style":1287},[2561],{"type":419,"value":2562}," interface",{"type":414,"tag":1274,"props":2564,"children":2565},{"style":1287},[2566],{"type":419,"value":2567}," IUserService\n",{"type":414,"tag":1274,"props":2569,"children":2570},{"class":1276,"line":1058},[2571],{"type":414,"tag":1274,"props":2572,"children":2573},{"style":1298},[2574],{"type":419,"value":1555},{"type":414,"tag":1274,"props":2576,"children":2577},{"class":1276,"line":1064},[2578,2583,2587,2592,2596,2601,2606,2612],{"type":414,"tag":1274,"props":2579,"children":2580},{"style":1287},[2581],{"type":419,"value":2582},"    Task",{"type":414,"tag":1274,"props":2584,"children":2585},{"style":1298},[2586],{"type":419,"value":1664},{"type":414,"tag":1274,"props":2588,"children":2589},{"style":1287},[2590],{"type":419,"value":2591},"IReadOnlyCollection",{"type":414,"tag":1274,"props":2593,"children":2594},{"style":1298},[2595],{"type":419,"value":1664},{"type":414,"tag":1274,"props":2597,"children":2598},{"style":1287},[2599],{"type":419,"value":2600},"User",{"type":414,"tag":1274,"props":2602,"children":2603},{"style":1298},[2604],{"type":419,"value":2605},">>",{"type":414,"tag":1274,"props":2607,"children":2609},{"style":2608},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[2610],{"type":419,"value":2611}," GetAllUsers",{"type":414,"tag":1274,"props":2613,"children":2614},{"style":1298},[2615],{"type":419,"value":2616},"();\n",{"type":414,"tag":1274,"props":2618,"children":2619},{"class":1276,"line":1466},[2620,2624,2629,2633,2637,2642],{"type":414,"tag":1274,"props":2621,"children":2622},{"style":1287},[2623],{"type":419,"value":2582},{"type":414,"tag":1274,"props":2625,"children":2626},{"style":2608},[2627],{"type":419,"value":2628}," UpdateUser",{"type":414,"tag":1274,"props":2630,"children":2631},{"style":1298},[2632],{"type":419,"value":1301},{"type":414,"tag":1274,"props":2634,"children":2635},{"style":1287},[2636],{"type":419,"value":2600},{"type":414,"tag":1274,"props":2638,"children":2639},{"style":1287},[2640],{"type":419,"value":2641}," userToUpdate",{"type":414,"tag":1274,"props":2643,"children":2644},{"style":1298},[2645],{"type":419,"value":1358},{"type":414,"tag":1274,"props":2647,"children":2648},{"class":1276,"line":1491},[2649],{"type":414,"tag":1274,"props":2650,"children":2651},{"style":1298},[2652],{"type":419,"value":1826},{"type":414,"tag":415,"props":2654,"children":2655},{},[2656,2658,2663],{"type":419,"value":2657},"Each of these methods needs to retrieve a valid token from the ",{"type":414,"tag":673,"props":2659,"children":2661},{"className":2660},[],[2662],{"type":419,"value":2476},{"type":419,"value":2664}," route and set the Authorization header with this token in the HTTP request to each of the protected routes.",{"type":414,"tag":415,"props":2666,"children":2667},{},[2668],{"type":419,"value":2669},"The following code shows how to retrieve the token:",{"type":414,"tag":1265,"props":2671,"children":2673},{"className":1267,"code":2672,"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",[2674],{"type":414,"tag":673,"props":2675,"children":2676},{"__ignoreMap":401},[2677,2762,2858],{"type":414,"tag":1274,"props":2678,"children":2679},{"class":1276,"line":1277},[2680,2685,2690,2695,2700,2705,2710,2715,2720,2726,2731,2735,2740,2744,2748,2753,2757],{"type":414,"tag":1274,"props":2681,"children":2682},{"style":1287},[2683],{"type":419,"value":2684},"var",{"type":414,"tag":1274,"props":2686,"children":2687},{"style":1287},[2688],{"type":419,"value":2689}," body",{"type":414,"tag":1274,"props":2691,"children":2692},{"style":1298},[2693],{"type":419,"value":2694}," =",{"type":414,"tag":1274,"props":2696,"children":2697},{"style":1298},[2698],{"type":419,"value":2699}," new",{"type":414,"tag":1274,"props":2701,"children":2702},{"style":1298},[2703],{"type":419,"value":2704}," {",{"type":414,"tag":1274,"props":2706,"children":2707},{"style":1397},[2708],{"type":419,"value":2709}," login ",{"type":414,"tag":1274,"props":2711,"children":2712},{"style":1298},[2713],{"type":419,"value":2714},"=",{"type":414,"tag":1274,"props":2716,"children":2717},{"style":1298},[2718],{"type":419,"value":2719}," \"",{"type":414,"tag":1274,"props":2721,"children":2723},{"style":2722},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[2724],{"type":419,"value":2725},"login",{"type":414,"tag":1274,"props":2727,"children":2728},{"style":1298},[2729],{"type":419,"value":2730},"\"",{"type":414,"tag":1274,"props":2732,"children":2733},{"style":1298},[2734],{"type":419,"value":1316},{"type":414,"tag":1274,"props":2736,"children":2737},{"style":1397},[2738],{"type":419,"value":2739}," password ",{"type":414,"tag":1274,"props":2741,"children":2742},{"style":1298},[2743],{"type":419,"value":2714},{"type":414,"tag":1274,"props":2745,"children":2746},{"style":1298},[2747],{"type":419,"value":2719},{"type":414,"tag":1274,"props":2749,"children":2750},{"style":2722},[2751],{"type":419,"value":2752},"password",{"type":414,"tag":1274,"props":2754,"children":2755},{"style":1298},[2756],{"type":419,"value":2730},{"type":414,"tag":1274,"props":2758,"children":2759},{"style":1298},[2760],{"type":419,"value":2761}," };\n",{"type":414,"tag":1274,"props":2763,"children":2764},{"class":1276,"line":1058},[2765,2769,2774,2778,2783,2788,2792,2797,2801,2805,2809,2813,2817,2821,2826,2830,2835,2839,2844,2848,2853],{"type":414,"tag":1274,"props":2766,"children":2767},{"style":1287},[2768],{"type":419,"value":2684},{"type":414,"tag":1274,"props":2770,"children":2771},{"style":1287},[2772],{"type":419,"value":2773}," response",{"type":414,"tag":1274,"props":2775,"children":2776},{"style":1298},[2777],{"type":419,"value":2694},{"type":414,"tag":1274,"props":2779,"children":2780},{"style":1298},[2781],{"type":419,"value":2782}," await",{"type":414,"tag":1274,"props":2784,"children":2785},{"style":1397},[2786],{"type":419,"value":2787}," _httpClient",{"type":414,"tag":1274,"props":2789,"children":2790},{"style":1298},[2791],{"type":419,"value":1421},{"type":414,"tag":1274,"props":2793,"children":2794},{"style":2608},[2795],{"type":419,"value":2796},"PostAsync",{"type":414,"tag":1274,"props":2798,"children":2799},{"style":1298},[2800],{"type":419,"value":1301},{"type":414,"tag":1274,"props":2802,"children":2803},{"style":1298},[2804],{"type":419,"value":2730},{"type":414,"tag":1274,"props":2806,"children":2807},{"style":2722},[2808],{"type":419,"value":2725},{"type":414,"tag":1274,"props":2810,"children":2811},{"style":1298},[2812],{"type":419,"value":2730},{"type":414,"tag":1274,"props":2814,"children":2815},{"style":1298},[2816],{"type":419,"value":1316},{"type":414,"tag":1274,"props":2818,"children":2819},{"style":1298},[2820],{"type":419,"value":2699},{"type":414,"tag":1274,"props":2822,"children":2823},{"style":1287},[2824],{"type":419,"value":2825}," StringContent",{"type":414,"tag":1274,"props":2827,"children":2828},{"style":1298},[2829],{"type":419,"value":1301},{"type":414,"tag":1274,"props":2831,"children":2832},{"style":1397},[2833],{"type":419,"value":2834},"JsonConvert",{"type":414,"tag":1274,"props":2836,"children":2837},{"style":1298},[2838],{"type":419,"value":1421},{"type":414,"tag":1274,"props":2840,"children":2841},{"style":2608},[2842],{"type":419,"value":2843},"SerializeObject",{"type":414,"tag":1274,"props":2845,"children":2846},{"style":1298},[2847],{"type":419,"value":1301},{"type":414,"tag":1274,"props":2849,"children":2850},{"style":1397},[2851],{"type":419,"value":2852},"body",{"type":414,"tag":1274,"props":2854,"children":2855},{"style":1298},[2856],{"type":419,"value":2857},")));\n",{"type":414,"tag":1274,"props":2859,"children":2860},{"class":1276,"line":1064},[2861,2865,2870,2874,2878,2882,2886,2891,2895,2900,2904,2908],{"type":414,"tag":1274,"props":2862,"children":2863},{"style":1287},[2864],{"type":419,"value":2684},{"type":414,"tag":1274,"props":2866,"children":2867},{"style":1287},[2868],{"type":419,"value":2869}," authResponse",{"type":414,"tag":1274,"props":2871,"children":2872},{"style":1298},[2873],{"type":419,"value":2694},{"type":414,"tag":1274,"props":2875,"children":2876},{"style":1298},[2877],{"type":419,"value":2782},{"type":414,"tag":1274,"props":2879,"children":2880},{"style":1397},[2881],{"type":419,"value":2773},{"type":414,"tag":1274,"props":2883,"children":2884},{"style":1298},[2885],{"type":419,"value":1421},{"type":414,"tag":1274,"props":2887,"children":2888},{"style":1397},[2889],{"type":419,"value":2890},"Content",{"type":414,"tag":1274,"props":2892,"children":2893},{"style":1298},[2894],{"type":419,"value":1421},{"type":414,"tag":1274,"props":2896,"children":2897},{"style":2608},[2898],{"type":419,"value":2899},"ReadAsAsync",{"type":414,"tag":1274,"props":2901,"children":2902},{"style":1298},[2903],{"type":419,"value":1664},{"type":414,"tag":1274,"props":2905,"children":2906},{"style":1287},[2907],{"type":419,"value":2484},{"type":414,"tag":1274,"props":2909,"children":2910},{"style":1298},[2911],{"type":419,"value":2912},">();\n",{"type":414,"tag":415,"props":2914,"children":2915},{},[2916,2918,2923,2925,2930],{"type":419,"value":2917},"where ",{"type":414,"tag":673,"props":2919,"children":2921},{"className":2920},[],[2922],{"type":419,"value":2484},{"type":419,"value":2924}," is a class we defined to map the response of the ",{"type":414,"tag":673,"props":2926,"children":2928},{"className":2927},[],[2929],{"type":419,"value":2476},{"type":419,"value":2526},{"type":414,"tag":1265,"props":2932,"children":2934},{"className":1267,"code":2933,"language":326,"meta":401,"style":401},"public class AuthResponse\n{\n  public string Token { get; set; }\n  public DateTime Expiration { get; set; }\n}\n",[2935],{"type":414,"tag":673,"props":2936,"children":2937},{"__ignoreMap":401},[2938,2955,2962,3007,3048],{"type":414,"tag":1274,"props":2939,"children":2940},{"class":1276,"line":1277},[2941,2945,2950],{"type":414,"tag":1274,"props":2942,"children":2943},{"style":1281},[2944],{"type":419,"value":1284},{"type":414,"tag":1274,"props":2946,"children":2947},{"style":1287},[2948],{"type":419,"value":2949}," class",{"type":414,"tag":1274,"props":2951,"children":2952},{"style":1287},[2953],{"type":419,"value":2954}," AuthResponse\n",{"type":414,"tag":1274,"props":2956,"children":2957},{"class":1276,"line":1058},[2958],{"type":414,"tag":1274,"props":2959,"children":2960},{"style":1298},[2961],{"type":419,"value":1555},{"type":414,"tag":1274,"props":2963,"children":2964},{"class":1276,"line":1064},[2965,2970,2974,2979,2983,2988,2993,2998,3002],{"type":414,"tag":1274,"props":2966,"children":2967},{"style":1281},[2968],{"type":419,"value":2969},"  public",{"type":414,"tag":1274,"props":2971,"children":2972},{"style":1298},[2973],{"type":419,"value":1742},{"type":414,"tag":1274,"props":2975,"children":2976},{"style":1287},[2977],{"type":419,"value":2978}," Token",{"type":414,"tag":1274,"props":2980,"children":2981},{"style":1298},[2982],{"type":419,"value":2704},{"type":414,"tag":1274,"props":2984,"children":2985},{"style":1287},[2986],{"type":419,"value":2987}," get",{"type":414,"tag":1274,"props":2989,"children":2990},{"style":1298},[2991],{"type":419,"value":2992},";",{"type":414,"tag":1274,"props":2994,"children":2995},{"style":1287},[2996],{"type":419,"value":2997}," set",{"type":414,"tag":1274,"props":2999,"children":3000},{"style":1298},[3001],{"type":419,"value":2992},{"type":414,"tag":1274,"props":3003,"children":3004},{"style":1298},[3005],{"type":419,"value":3006}," }\n",{"type":414,"tag":1274,"props":3008,"children":3009},{"class":1276,"line":1466},[3010,3014,3019,3024,3028,3032,3036,3040,3044],{"type":414,"tag":1274,"props":3011,"children":3012},{"style":1281},[3013],{"type":419,"value":2969},{"type":414,"tag":1274,"props":3015,"children":3016},{"style":1287},[3017],{"type":419,"value":3018}," DateTime",{"type":414,"tag":1274,"props":3020,"children":3021},{"style":1287},[3022],{"type":419,"value":3023}," Expiration",{"type":414,"tag":1274,"props":3025,"children":3026},{"style":1298},[3027],{"type":419,"value":2704},{"type":414,"tag":1274,"props":3029,"children":3030},{"style":1287},[3031],{"type":419,"value":2987},{"type":414,"tag":1274,"props":3033,"children":3034},{"style":1298},[3035],{"type":419,"value":2992},{"type":414,"tag":1274,"props":3037,"children":3038},{"style":1287},[3039],{"type":419,"value":2997},{"type":414,"tag":1274,"props":3041,"children":3042},{"style":1298},[3043],{"type":419,"value":2992},{"type":414,"tag":1274,"props":3045,"children":3046},{"style":1298},[3047],{"type":419,"value":3006},{"type":414,"tag":1274,"props":3049,"children":3050},{"class":1276,"line":1491},[3051],{"type":414,"tag":1274,"props":3052,"children":3053},{"style":1298},[3054],{"type":419,"value":1826},{"type":414,"tag":415,"props":3056,"children":3057},{},[3058,3060,3066],{"type":419,"value":3059},"So now we have the code to retrieve the token, how do we use it to implement our ",{"type":414,"tag":673,"props":3061,"children":3063},{"className":3062},[],[3064],{"type":419,"value":3065},"IUserService",{"type":419,"value":1954},{"type":414,"tag":421,"props":3068,"children":3070},{"id":3069},"retrieve-the-token-from-a-private-method",[3071],{"type":419,"value":3072},"Retrieve the token from a private method",{"type":414,"tag":415,"props":3074,"children":3075},{},[3076,3078,3084,3086,3091,3092,3097],{"type":419,"value":3077},"The easiest way to do that is to create a private method in ",{"type":414,"tag":673,"props":3079,"children":3081},{"className":3080},[],[3082],{"type":419,"value":3083},"UserService",{"type":419,"value":3085}," that returns this token and to call it from ",{"type":414,"tag":673,"props":3087,"children":3089},{"className":3088},[],[3090],{"type":419,"value":2517},{"type":419,"value":1917},{"type":414,"tag":673,"props":3093,"children":3095},{"className":3094},[],[3096],{"type":419,"value":2535},{"type":419,"value":3098},". That would give us something like that :",{"type":414,"tag":1265,"props":3100,"children":3102},{"className":1267,"code":3101,"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",[3103],{"type":414,"tag":673,"props":3104,"children":3105},{"__ignoreMap":401},[3106,3131,3138,3164,3193,3201,3221,3229,3236,3282,3289,3319,3382,3450,3495,3516,3570,3578,3586,3622,3630,3658,3741,3805,3863,3907,3927,3935,3943,3979,3987,4059,4147,4199,4224,4232],{"type":414,"tag":1274,"props":3107,"children":3108},{"class":1276,"line":1277},[3109,3113,3117,3122,3127],{"type":414,"tag":1274,"props":3110,"children":3111},{"style":1281},[3112],{"type":419,"value":1284},{"type":414,"tag":1274,"props":3114,"children":3115},{"style":1287},[3116],{"type":419,"value":2949},{"type":414,"tag":1274,"props":3118,"children":3119},{"style":1287},[3120],{"type":419,"value":3121}," UserService",{"type":414,"tag":1274,"props":3123,"children":3124},{"style":1298},[3125],{"type":419,"value":3126}," :",{"type":414,"tag":1274,"props":3128,"children":3129},{"style":1287},[3130],{"type":419,"value":2567},{"type":414,"tag":1274,"props":3132,"children":3133},{"class":1276,"line":1058},[3134],{"type":414,"tag":1274,"props":3135,"children":3136},{"style":1298},[3137],{"type":419,"value":1555},{"type":414,"tag":1274,"props":3139,"children":3140},{"class":1276,"line":1064},[3141,3146,3151,3156,3160],{"type":414,"tag":1274,"props":3142,"children":3143},{"style":1281},[3144],{"type":419,"value":3145},"    private",{"type":414,"tag":1274,"props":3147,"children":3148},{"style":1281},[3149],{"type":419,"value":3150}," readonly",{"type":414,"tag":1274,"props":3152,"children":3153},{"style":1287},[3154],{"type":419,"value":3155}," HttpClient",{"type":414,"tag":1274,"props":3157,"children":3158},{"style":1287},[3159],{"type":419,"value":2787},{"type":414,"tag":1274,"props":3161,"children":3162},{"style":1298},[3163],{"type":419,"value":1405},{"type":414,"tag":1274,"props":3165,"children":3166},{"class":1276,"line":1466},[3167,3171,3175,3179,3183,3188],{"type":414,"tag":1274,"props":3168,"children":3169},{"style":1281},[3170],{"type":419,"value":1564},{"type":414,"tag":1274,"props":3172,"children":3173},{"style":2608},[3174],{"type":419,"value":3121},{"type":414,"tag":1274,"props":3176,"children":3177},{"style":1298},[3178],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3180,"children":3181},{"style":1287},[3182],{"type":419,"value":1977},{"type":414,"tag":1274,"props":3184,"children":3185},{"style":1287},[3186],{"type":419,"value":3187}," httpClient",{"type":414,"tag":1274,"props":3189,"children":3190},{"style":1298},[3191],{"type":419,"value":3192},")\n",{"type":414,"tag":1274,"props":3194,"children":3195},{"class":1276,"line":1491},[3196],{"type":414,"tag":1274,"props":3197,"children":3198},{"style":1298},[3199],{"type":419,"value":3200},"    {\n",{"type":414,"tag":1274,"props":3202,"children":3203},{"class":1276,"line":1525},[3204,3209,3213,3217],{"type":414,"tag":1274,"props":3205,"children":3206},{"style":1397},[3207],{"type":419,"value":3208},"        _httpClient ",{"type":414,"tag":1274,"props":3210,"children":3211},{"style":1298},[3212],{"type":419,"value":2714},{"type":414,"tag":1274,"props":3214,"children":3215},{"style":1397},[3216],{"type":419,"value":3187},{"type":414,"tag":1274,"props":3218,"children":3219},{"style":1298},[3220],{"type":419,"value":1405},{"type":414,"tag":1274,"props":3222,"children":3223},{"class":1276,"line":1535},[3224],{"type":414,"tag":1274,"props":3225,"children":3226},{"style":1298},[3227],{"type":419,"value":3228},"    }\n",{"type":414,"tag":1274,"props":3230,"children":3231},{"class":1276,"line":1549},[3232],{"type":414,"tag":1274,"props":3233,"children":3234},{"emptyLinePlaceholder":1529},[3235],{"type":419,"value":1532},{"type":414,"tag":1274,"props":3237,"children":3238},{"class":1276,"line":1558},[3239,3243,3248,3253,3257,3261,3265,3269,3273,3277],{"type":414,"tag":1274,"props":3240,"children":3241},{"style":1281},[3242],{"type":419,"value":1564},{"type":414,"tag":1274,"props":3244,"children":3245},{"style":1281},[3246],{"type":419,"value":3247}," async",{"type":414,"tag":1274,"props":3249,"children":3250},{"style":1287},[3251],{"type":419,"value":3252}," Task",{"type":414,"tag":1274,"props":3254,"children":3255},{"style":1298},[3256],{"type":419,"value":1664},{"type":414,"tag":1274,"props":3258,"children":3259},{"style":1287},[3260],{"type":419,"value":2591},{"type":414,"tag":1274,"props":3262,"children":3263},{"style":1298},[3264],{"type":419,"value":1664},{"type":414,"tag":1274,"props":3266,"children":3267},{"style":1287},[3268],{"type":419,"value":2600},{"type":414,"tag":1274,"props":3270,"children":3271},{"style":1298},[3272],{"type":419,"value":2605},{"type":414,"tag":1274,"props":3274,"children":3275},{"style":2608},[3276],{"type":419,"value":2611},{"type":414,"tag":1274,"props":3278,"children":3279},{"style":1298},[3280],{"type":419,"value":3281},"()\n",{"type":414,"tag":1274,"props":3283,"children":3284},{"class":1276,"line":1627},[3285],{"type":414,"tag":1274,"props":3286,"children":3287},{"style":1298},[3288],{"type":419,"value":3200},{"type":414,"tag":1274,"props":3290,"children":3291},{"class":1276,"line":1636},[3292,3297,3302,3306,3310,3315],{"type":414,"tag":1274,"props":3293,"children":3294},{"style":1287},[3295],{"type":419,"value":3296},"        var",{"type":414,"tag":1274,"props":3298,"children":3299},{"style":1287},[3300],{"type":419,"value":3301}," token",{"type":414,"tag":1274,"props":3303,"children":3304},{"style":1298},[3305],{"type":419,"value":2694},{"type":414,"tag":1274,"props":3307,"children":3308},{"style":1298},[3309],{"type":419,"value":2782},{"type":414,"tag":1274,"props":3311,"children":3312},{"style":2608},[3313],{"type":419,"value":3314}," RetrieveToken",{"type":414,"tag":1274,"props":3316,"children":3317},{"style":1298},[3318],{"type":419,"value":2616},{"type":414,"tag":1274,"props":3320,"children":3321},{"class":1276,"line":1699},[3322,3326,3331,3335,3339,3344,3348,3353,3357,3361,3365,3369,3374,3378],{"type":414,"tag":1274,"props":3323,"children":3324},{"style":1287},[3325],{"type":419,"value":3296},{"type":414,"tag":1274,"props":3327,"children":3328},{"style":1287},[3329],{"type":419,"value":3330}," request",{"type":414,"tag":1274,"props":3332,"children":3333},{"style":1298},[3334],{"type":419,"value":2694},{"type":414,"tag":1274,"props":3336,"children":3337},{"style":1298},[3338],{"type":419,"value":2699},{"type":414,"tag":1274,"props":3340,"children":3341},{"style":1287},[3342],{"type":419,"value":3343}," HttpRequestMessage",{"type":414,"tag":1274,"props":3345,"children":3346},{"style":1298},[3347],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3349,"children":3350},{"style":1397},[3351],{"type":419,"value":3352},"HttpMethod",{"type":414,"tag":1274,"props":3354,"children":3355},{"style":1298},[3356],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3358,"children":3359},{"style":1397},[3360],{"type":419,"value":2131},{"type":414,"tag":1274,"props":3362,"children":3363},{"style":1298},[3364],{"type":419,"value":1316},{"type":414,"tag":1274,"props":3366,"children":3367},{"style":1298},[3368],{"type":419,"value":2719},{"type":414,"tag":1274,"props":3370,"children":3371},{"style":2722},[3372],{"type":419,"value":3373},"user",{"type":414,"tag":1274,"props":3375,"children":3376},{"style":1298},[3377],{"type":419,"value":2730},{"type":414,"tag":1274,"props":3379,"children":3380},{"style":1298},[3381],{"type":419,"value":1358},{"type":414,"tag":1274,"props":3383,"children":3384},{"class":1276,"line":1707},[3385,3390,3394,3399,3403,3408,3412,3416,3421,3425,3429,3434,3438,3442,3446],{"type":414,"tag":1274,"props":3386,"children":3387},{"style":1397},[3388],{"type":419,"value":3389},"        request",{"type":414,"tag":1274,"props":3391,"children":3392},{"style":1298},[3393],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3395,"children":3396},{"style":1397},[3397],{"type":419,"value":3398},"Headers",{"type":414,"tag":1274,"props":3400,"children":3401},{"style":1298},[3402],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3404,"children":3405},{"style":1397},[3406],{"type":419,"value":3407},"Authorization ",{"type":414,"tag":1274,"props":3409,"children":3410},{"style":1298},[3411],{"type":419,"value":2714},{"type":414,"tag":1274,"props":3413,"children":3414},{"style":1298},[3415],{"type":419,"value":2699},{"type":414,"tag":1274,"props":3417,"children":3418},{"style":1287},[3419],{"type":419,"value":3420}," AuthenticationHeaderValue",{"type":414,"tag":1274,"props":3422,"children":3423},{"style":1298},[3424],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3426,"children":3427},{"style":1298},[3428],{"type":419,"value":2730},{"type":414,"tag":1274,"props":3430,"children":3431},{"style":2722},[3432],{"type":419,"value":3433},"Bearer",{"type":414,"tag":1274,"props":3435,"children":3436},{"style":1298},[3437],{"type":419,"value":2730},{"type":414,"tag":1274,"props":3439,"children":3440},{"style":1298},[3441],{"type":419,"value":1316},{"type":414,"tag":1274,"props":3443,"children":3444},{"style":1397},[3445],{"type":419,"value":3301},{"type":414,"tag":1274,"props":3447,"children":3448},{"style":1298},[3449],{"type":419,"value":1358},{"type":414,"tag":1274,"props":3451,"children":3452},{"class":1276,"line":1754},[3453,3457,3461,3465,3469,3473,3477,3482,3486,3491],{"type":414,"tag":1274,"props":3454,"children":3455},{"style":1287},[3456],{"type":419,"value":3296},{"type":414,"tag":1274,"props":3458,"children":3459},{"style":1287},[3460],{"type":419,"value":2773},{"type":414,"tag":1274,"props":3462,"children":3463},{"style":1298},[3464],{"type":419,"value":2694},{"type":414,"tag":1274,"props":3466,"children":3467},{"style":1298},[3468],{"type":419,"value":2782},{"type":414,"tag":1274,"props":3470,"children":3471},{"style":1397},[3472],{"type":419,"value":2787},{"type":414,"tag":1274,"props":3474,"children":3475},{"style":1298},[3476],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3478,"children":3479},{"style":2608},[3480],{"type":419,"value":3481},"SendAsync",{"type":414,"tag":1274,"props":3483,"children":3484},{"style":1298},[3485],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3487,"children":3488},{"style":1397},[3489],{"type":419,"value":3490},"request",{"type":414,"tag":1274,"props":3492,"children":3493},{"style":1298},[3494],{"type":419,"value":1358},{"type":414,"tag":1274,"props":3496,"children":3497},{"class":1276,"line":1762},[3498,3503,3507,3512],{"type":414,"tag":1274,"props":3499,"children":3500},{"style":1397},[3501],{"type":419,"value":3502},"        response",{"type":414,"tag":1274,"props":3504,"children":3505},{"style":1298},[3506],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3508,"children":3509},{"style":2608},[3510],{"type":419,"value":3511},"EnsureSuccessStatusCode",{"type":414,"tag":1274,"props":3513,"children":3514},{"style":1298},[3515],{"type":419,"value":2616},{"type":414,"tag":1274,"props":3517,"children":3518},{"class":1276,"line":1820},[3519,3525,3529,3533,3537,3541,3545,3549,3553,3557,3561,3565],{"type":414,"tag":1274,"props":3520,"children":3522},{"style":3521},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[3523],{"type":419,"value":3524},"        return",{"type":414,"tag":1274,"props":3526,"children":3527},{"style":1298},[3528],{"type":419,"value":2782},{"type":414,"tag":1274,"props":3530,"children":3531},{"style":1397},[3532],{"type":419,"value":2773},{"type":414,"tag":1274,"props":3534,"children":3535},{"style":1298},[3536],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3538,"children":3539},{"style":1397},[3540],{"type":419,"value":2890},{"type":414,"tag":1274,"props":3542,"children":3543},{"style":1298},[3544],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3546,"children":3547},{"style":2608},[3548],{"type":419,"value":2899},{"type":414,"tag":1274,"props":3550,"children":3551},{"style":1298},[3552],{"type":419,"value":1664},{"type":414,"tag":1274,"props":3554,"children":3555},{"style":1287},[3556],{"type":419,"value":2591},{"type":414,"tag":1274,"props":3558,"children":3559},{"style":1298},[3560],{"type":419,"value":1664},{"type":414,"tag":1274,"props":3562,"children":3563},{"style":1287},[3564],{"type":419,"value":2600},{"type":414,"tag":1274,"props":3566,"children":3567},{"style":1298},[3568],{"type":419,"value":3569},">>();\n",{"type":414,"tag":1274,"props":3571,"children":3573},{"class":1276,"line":3572},17,[3574],{"type":414,"tag":1274,"props":3575,"children":3576},{"style":1298},[3577],{"type":419,"value":3228},{"type":414,"tag":1274,"props":3579,"children":3581},{"class":1276,"line":3580},18,[3582],{"type":414,"tag":1274,"props":3583,"children":3584},{"emptyLinePlaceholder":1529},[3585],{"type":419,"value":1532},{"type":414,"tag":1274,"props":3587,"children":3589},{"class":1276,"line":3588},19,[3590,3594,3598,3602,3606,3610,3614,3618],{"type":414,"tag":1274,"props":3591,"children":3592},{"style":1281},[3593],{"type":419,"value":1564},{"type":414,"tag":1274,"props":3595,"children":3596},{"style":1281},[3597],{"type":419,"value":3247},{"type":414,"tag":1274,"props":3599,"children":3600},{"style":1287},[3601],{"type":419,"value":3252},{"type":414,"tag":1274,"props":3603,"children":3604},{"style":2608},[3605],{"type":419,"value":2628},{"type":414,"tag":1274,"props":3607,"children":3608},{"style":1298},[3609],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3611,"children":3612},{"style":1287},[3613],{"type":419,"value":2600},{"type":414,"tag":1274,"props":3615,"children":3616},{"style":1287},[3617],{"type":419,"value":2641},{"type":414,"tag":1274,"props":3619,"children":3620},{"style":1298},[3621],{"type":419,"value":3192},{"type":414,"tag":1274,"props":3623,"children":3625},{"class":1276,"line":3624},20,[3626],{"type":414,"tag":1274,"props":3627,"children":3628},{"style":1298},[3629],{"type":419,"value":3200},{"type":414,"tag":1274,"props":3631,"children":3633},{"class":1276,"line":3632},21,[3634,3638,3642,3646,3650,3654],{"type":414,"tag":1274,"props":3635,"children":3636},{"style":1287},[3637],{"type":419,"value":3296},{"type":414,"tag":1274,"props":3639,"children":3640},{"style":1287},[3641],{"type":419,"value":3301},{"type":414,"tag":1274,"props":3643,"children":3644},{"style":1298},[3645],{"type":419,"value":2694},{"type":414,"tag":1274,"props":3647,"children":3648},{"style":1298},[3649],{"type":419,"value":2782},{"type":414,"tag":1274,"props":3651,"children":3652},{"style":2608},[3653],{"type":419,"value":3314},{"type":414,"tag":1274,"props":3655,"children":3656},{"style":1298},[3657],{"type":419,"value":2616},{"type":414,"tag":1274,"props":3659,"children":3661},{"class":1276,"line":3660},22,[3662,3666,3670,3674,3678,3682,3686,3690,3694,3699,3703,3708,3713,3718,3723,3727,3732,3737],{"type":414,"tag":1274,"props":3663,"children":3664},{"style":1287},[3665],{"type":419,"value":3296},{"type":414,"tag":1274,"props":3667,"children":3668},{"style":1287},[3669],{"type":419,"value":3330},{"type":414,"tag":1274,"props":3671,"children":3672},{"style":1298},[3673],{"type":419,"value":2694},{"type":414,"tag":1274,"props":3675,"children":3676},{"style":1298},[3677],{"type":419,"value":2699},{"type":414,"tag":1274,"props":3679,"children":3680},{"style":1287},[3681],{"type":419,"value":3343},{"type":414,"tag":1274,"props":3683,"children":3684},{"style":1298},[3685],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3687,"children":3688},{"style":1397},[3689],{"type":419,"value":3352},{"type":414,"tag":1274,"props":3691,"children":3692},{"style":1298},[3693],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3695,"children":3696},{"style":1397},[3697],{"type":419,"value":3698},"Put",{"type":414,"tag":1274,"props":3700,"children":3701},{"style":1298},[3702],{"type":419,"value":1316},{"type":414,"tag":1274,"props":3704,"children":3705},{"style":1298},[3706],{"type":419,"value":3707}," $\"",{"type":414,"tag":1274,"props":3709,"children":3710},{"style":2722},[3711],{"type":419,"value":3712},"user/",{"type":414,"tag":1274,"props":3714,"children":3715},{"style":1298},[3716],{"type":419,"value":3717},"{",{"type":414,"tag":1274,"props":3719,"children":3720},{"style":1397},[3721],{"type":419,"value":3722},"userToUpdate",{"type":414,"tag":1274,"props":3724,"children":3725},{"style":1298},[3726],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3728,"children":3729},{"style":1397},[3730],{"type":419,"value":3731},"Name",{"type":414,"tag":1274,"props":3733,"children":3734},{"style":1298},[3735],{"type":419,"value":3736},"}\"",{"type":414,"tag":1274,"props":3738,"children":3739},{"style":1298},[3740],{"type":419,"value":1358},{"type":414,"tag":1274,"props":3742,"children":3744},{"class":1276,"line":3743},23,[3745,3749,3753,3757,3761,3765,3769,3773,3777,3781,3785,3789,3793,3797,3801],{"type":414,"tag":1274,"props":3746,"children":3747},{"style":1397},[3748],{"type":419,"value":3389},{"type":414,"tag":1274,"props":3750,"children":3751},{"style":1298},[3752],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3754,"children":3755},{"style":1397},[3756],{"type":419,"value":3398},{"type":414,"tag":1274,"props":3758,"children":3759},{"style":1298},[3760],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3762,"children":3763},{"style":1397},[3764],{"type":419,"value":3407},{"type":414,"tag":1274,"props":3766,"children":3767},{"style":1298},[3768],{"type":419,"value":2714},{"type":414,"tag":1274,"props":3770,"children":3771},{"style":1298},[3772],{"type":419,"value":2699},{"type":414,"tag":1274,"props":3774,"children":3775},{"style":1287},[3776],{"type":419,"value":3420},{"type":414,"tag":1274,"props":3778,"children":3779},{"style":1298},[3780],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3782,"children":3783},{"style":1298},[3784],{"type":419,"value":2730},{"type":414,"tag":1274,"props":3786,"children":3787},{"style":2722},[3788],{"type":419,"value":3433},{"type":414,"tag":1274,"props":3790,"children":3791},{"style":1298},[3792],{"type":419,"value":2730},{"type":414,"tag":1274,"props":3794,"children":3795},{"style":1298},[3796],{"type":419,"value":1316},{"type":414,"tag":1274,"props":3798,"children":3799},{"style":1397},[3800],{"type":419,"value":3301},{"type":414,"tag":1274,"props":3802,"children":3803},{"style":1298},[3804],{"type":419,"value":1358},{"type":414,"tag":1274,"props":3806,"children":3808},{"class":1276,"line":3807},24,[3809,3813,3817,3822,3826,3830,3834,3838,3842,3846,3850,3854,3858],{"type":414,"tag":1274,"props":3810,"children":3811},{"style":1397},[3812],{"type":419,"value":3389},{"type":414,"tag":1274,"props":3814,"children":3815},{"style":1298},[3816],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3818,"children":3819},{"style":1397},[3820],{"type":419,"value":3821},"Content ",{"type":414,"tag":1274,"props":3823,"children":3824},{"style":1298},[3825],{"type":419,"value":2714},{"type":414,"tag":1274,"props":3827,"children":3828},{"style":1298},[3829],{"type":419,"value":2699},{"type":414,"tag":1274,"props":3831,"children":3832},{"style":1287},[3833],{"type":419,"value":2825},{"type":414,"tag":1274,"props":3835,"children":3836},{"style":1298},[3837],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3839,"children":3840},{"style":1397},[3841],{"type":419,"value":2834},{"type":414,"tag":1274,"props":3843,"children":3844},{"style":1298},[3845],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3847,"children":3848},{"style":2608},[3849],{"type":419,"value":2843},{"type":414,"tag":1274,"props":3851,"children":3852},{"style":1298},[3853],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3855,"children":3856},{"style":1397},[3857],{"type":419,"value":3722},{"type":414,"tag":1274,"props":3859,"children":3860},{"style":1298},[3861],{"type":419,"value":3862},"));\n",{"type":414,"tag":1274,"props":3864,"children":3866},{"class":1276,"line":3865},25,[3867,3871,3875,3879,3883,3887,3891,3895,3899,3903],{"type":414,"tag":1274,"props":3868,"children":3869},{"style":1287},[3870],{"type":419,"value":3296},{"type":414,"tag":1274,"props":3872,"children":3873},{"style":1287},[3874],{"type":419,"value":2773},{"type":414,"tag":1274,"props":3876,"children":3877},{"style":1298},[3878],{"type":419,"value":2694},{"type":414,"tag":1274,"props":3880,"children":3881},{"style":1298},[3882],{"type":419,"value":2782},{"type":414,"tag":1274,"props":3884,"children":3885},{"style":1397},[3886],{"type":419,"value":2787},{"type":414,"tag":1274,"props":3888,"children":3889},{"style":1298},[3890],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3892,"children":3893},{"style":2608},[3894],{"type":419,"value":3481},{"type":414,"tag":1274,"props":3896,"children":3897},{"style":1298},[3898],{"type":419,"value":1301},{"type":414,"tag":1274,"props":3900,"children":3901},{"style":1397},[3902],{"type":419,"value":3490},{"type":414,"tag":1274,"props":3904,"children":3905},{"style":1298},[3906],{"type":419,"value":1358},{"type":414,"tag":1274,"props":3908,"children":3910},{"class":1276,"line":3909},26,[3911,3915,3919,3923],{"type":414,"tag":1274,"props":3912,"children":3913},{"style":1397},[3914],{"type":419,"value":3502},{"type":414,"tag":1274,"props":3916,"children":3917},{"style":1298},[3918],{"type":419,"value":1421},{"type":414,"tag":1274,"props":3920,"children":3921},{"style":2608},[3922],{"type":419,"value":3511},{"type":414,"tag":1274,"props":3924,"children":3925},{"style":1298},[3926],{"type":419,"value":2616},{"type":414,"tag":1274,"props":3928,"children":3930},{"class":1276,"line":3929},27,[3931],{"type":414,"tag":1274,"props":3932,"children":3933},{"style":1298},[3934],{"type":419,"value":3228},{"type":414,"tag":1274,"props":3936,"children":3938},{"class":1276,"line":3937},28,[3939],{"type":414,"tag":1274,"props":3940,"children":3941},{"emptyLinePlaceholder":1529},[3942],{"type":419,"value":1532},{"type":414,"tag":1274,"props":3944,"children":3946},{"class":1276,"line":3945},29,[3947,3951,3955,3959,3963,3967,3971,3975],{"type":414,"tag":1274,"props":3948,"children":3949},{"style":1281},[3950],{"type":419,"value":3145},{"type":414,"tag":1274,"props":3952,"children":3953},{"style":1281},[3954],{"type":419,"value":3247},{"type":414,"tag":1274,"props":3956,"children":3957},{"style":1287},[3958],{"type":419,"value":3252},{"type":414,"tag":1274,"props":3960,"children":3961},{"style":1298},[3962],{"type":419,"value":1664},{"type":414,"tag":1274,"props":3964,"children":3965},{"style":1298},[3966],{"type":419,"value":1306},{"type":414,"tag":1274,"props":3968,"children":3969},{"style":1298},[3970],{"type":419,"value":1674},{"type":414,"tag":1274,"props":3972,"children":3973},{"style":2608},[3974],{"type":419,"value":3314},{"type":414,"tag":1274,"props":3976,"children":3977},{"style":1298},[3978],{"type":419,"value":3281},{"type":414,"tag":1274,"props":3980,"children":3982},{"class":1276,"line":3981},30,[3983],{"type":414,"tag":1274,"props":3984,"children":3985},{"style":1298},[3986],{"type":419,"value":3200},{"type":414,"tag":1274,"props":3988,"children":3990},{"class":1276,"line":3989},31,[3991,3995,3999,4003,4007,4011,4015,4019,4023,4027,4031,4035,4039,4043,4047,4051,4055],{"type":414,"tag":1274,"props":3992,"children":3993},{"style":1287},[3994],{"type":419,"value":3296},{"type":414,"tag":1274,"props":3996,"children":3997},{"style":1287},[3998],{"type":419,"value":2689},{"type":414,"tag":1274,"props":4000,"children":4001},{"style":1298},[4002],{"type":419,"value":2694},{"type":414,"tag":1274,"props":4004,"children":4005},{"style":1298},[4006],{"type":419,"value":2699},{"type":414,"tag":1274,"props":4008,"children":4009},{"style":1298},[4010],{"type":419,"value":2704},{"type":414,"tag":1274,"props":4012,"children":4013},{"style":1397},[4014],{"type":419,"value":2709},{"type":414,"tag":1274,"props":4016,"children":4017},{"style":1298},[4018],{"type":419,"value":2714},{"type":414,"tag":1274,"props":4020,"children":4021},{"style":1298},[4022],{"type":419,"value":2719},{"type":414,"tag":1274,"props":4024,"children":4025},{"style":2722},[4026],{"type":419,"value":2725},{"type":414,"tag":1274,"props":4028,"children":4029},{"style":1298},[4030],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4032,"children":4033},{"style":1298},[4034],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4036,"children":4037},{"style":1397},[4038],{"type":419,"value":2739},{"type":414,"tag":1274,"props":4040,"children":4041},{"style":1298},[4042],{"type":419,"value":2714},{"type":414,"tag":1274,"props":4044,"children":4045},{"style":1298},[4046],{"type":419,"value":2719},{"type":414,"tag":1274,"props":4048,"children":4049},{"style":2722},[4050],{"type":419,"value":2752},{"type":414,"tag":1274,"props":4052,"children":4053},{"style":1298},[4054],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4056,"children":4057},{"style":1298},[4058],{"type":419,"value":2761},{"type":414,"tag":1274,"props":4060,"children":4062},{"class":1276,"line":4061},32,[4063,4067,4071,4075,4079,4083,4087,4091,4095,4099,4103,4107,4111,4115,4119,4123,4127,4131,4135,4139,4143],{"type":414,"tag":1274,"props":4064,"children":4065},{"style":1287},[4066],{"type":419,"value":3296},{"type":414,"tag":1274,"props":4068,"children":4069},{"style":1287},[4070],{"type":419,"value":2773},{"type":414,"tag":1274,"props":4072,"children":4073},{"style":1298},[4074],{"type":419,"value":2694},{"type":414,"tag":1274,"props":4076,"children":4077},{"style":1298},[4078],{"type":419,"value":2782},{"type":414,"tag":1274,"props":4080,"children":4081},{"style":1397},[4082],{"type":419,"value":2787},{"type":414,"tag":1274,"props":4084,"children":4085},{"style":1298},[4086],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4088,"children":4089},{"style":2608},[4090],{"type":419,"value":2796},{"type":414,"tag":1274,"props":4092,"children":4093},{"style":1298},[4094],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4096,"children":4097},{"style":1298},[4098],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4100,"children":4101},{"style":2722},[4102],{"type":419,"value":2725},{"type":414,"tag":1274,"props":4104,"children":4105},{"style":1298},[4106],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4108,"children":4109},{"style":1298},[4110],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4112,"children":4113},{"style":1298},[4114],{"type":419,"value":2699},{"type":414,"tag":1274,"props":4116,"children":4117},{"style":1287},[4118],{"type":419,"value":2825},{"type":414,"tag":1274,"props":4120,"children":4121},{"style":1298},[4122],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4124,"children":4125},{"style":1397},[4126],{"type":419,"value":2834},{"type":414,"tag":1274,"props":4128,"children":4129},{"style":1298},[4130],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4132,"children":4133},{"style":2608},[4134],{"type":419,"value":2843},{"type":414,"tag":1274,"props":4136,"children":4137},{"style":1298},[4138],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4140,"children":4141},{"style":1397},[4142],{"type":419,"value":2852},{"type":414,"tag":1274,"props":4144,"children":4145},{"style":1298},[4146],{"type":419,"value":2857},{"type":414,"tag":1274,"props":4148,"children":4150},{"class":1276,"line":4149},33,[4151,4155,4159,4163,4167,4171,4175,4179,4183,4187,4191,4195],{"type":414,"tag":1274,"props":4152,"children":4153},{"style":1287},[4154],{"type":419,"value":3296},{"type":414,"tag":1274,"props":4156,"children":4157},{"style":1287},[4158],{"type":419,"value":2869},{"type":414,"tag":1274,"props":4160,"children":4161},{"style":1298},[4162],{"type":419,"value":2694},{"type":414,"tag":1274,"props":4164,"children":4165},{"style":1298},[4166],{"type":419,"value":2782},{"type":414,"tag":1274,"props":4168,"children":4169},{"style":1397},[4170],{"type":419,"value":2773},{"type":414,"tag":1274,"props":4172,"children":4173},{"style":1298},[4174],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4176,"children":4177},{"style":1397},[4178],{"type":419,"value":2890},{"type":414,"tag":1274,"props":4180,"children":4181},{"style":1298},[4182],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4184,"children":4185},{"style":2608},[4186],{"type":419,"value":2899},{"type":414,"tag":1274,"props":4188,"children":4189},{"style":1298},[4190],{"type":419,"value":1664},{"type":414,"tag":1274,"props":4192,"children":4193},{"style":1287},[4194],{"type":419,"value":2484},{"type":414,"tag":1274,"props":4196,"children":4197},{"style":1298},[4198],{"type":419,"value":2912},{"type":414,"tag":1274,"props":4200,"children":4202},{"class":1276,"line":4201},34,[4203,4207,4211,4215,4220],{"type":414,"tag":1274,"props":4204,"children":4205},{"style":3521},[4206],{"type":419,"value":3524},{"type":414,"tag":1274,"props":4208,"children":4209},{"style":1397},[4210],{"type":419,"value":2869},{"type":414,"tag":1274,"props":4212,"children":4213},{"style":1298},[4214],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4216,"children":4217},{"style":1397},[4218],{"type":419,"value":4219},"Token",{"type":414,"tag":1274,"props":4221,"children":4222},{"style":1298},[4223],{"type":419,"value":1405},{"type":414,"tag":1274,"props":4225,"children":4227},{"class":1276,"line":4226},35,[4228],{"type":414,"tag":1274,"props":4229,"children":4230},{"style":1298},[4231],{"type":419,"value":3228},{"type":414,"tag":1274,"props":4233,"children":4235},{"class":1276,"line":4234},36,[4236],{"type":414,"tag":1274,"props":4237,"children":4238},{"style":1298},[4239],{"type":419,"value":1826},{"type":414,"tag":415,"props":4241,"children":4242},{},[4243],{"type":419,"value":4244},"There are two main problems with this way of doing things:",{"type":414,"tag":516,"props":4246,"children":4247},{},[4248,4268],{"type":414,"tag":520,"props":4249,"children":4250},{},[4251,4253,4259,4261,4266],{"type":419,"value":4252},"We have some code duplication as we are calling the ",{"type":414,"tag":673,"props":4254,"children":4256},{"className":4255},[],[4257],{"type":419,"value":4258},"RetrieveToken",{"type":419,"value":4260}," 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":414,"tag":673,"props":4262,"children":4264},{"className":4263},[],[4265],{"type":419,"value":4258},{"type":419,"value":4267},"in each method.",{"type":414,"tag":520,"props":4269,"children":4270},{},[4271,4273,4278],{"type":419,"value":4272},"For each call to an authenticated route of the API, we are making a call to the ",{"type":414,"tag":673,"props":4274,"children":4276},{"className":4275},[],[4277],{"type":419,"value":2725},{"type":419,"value":4279}," route even if our token from a previous call is probably still valid.",{"type":414,"tag":421,"props":4281,"children":4283},{"id":4282},"use-a-dedicated-service-to-retrieve-the-token-and-save-it-for-future-calls",[4284],{"type":419,"value":4285},"Use a dedicated service to retrieve the token and save it for future calls",{"type":414,"tag":415,"props":4287,"children":4288},{},[4289,4291,4296,4298,4304,4306,4311,4313,4318,4320,4325],{"type":419,"value":4290},"Although it's not necessary at this point, it can be interesting to move the code of our private method ",{"type":414,"tag":673,"props":4292,"children":4294},{"className":4293},[],[4295],{"type":419,"value":4258},{"type":419,"value":4297}," into a separate service ",{"type":414,"tag":673,"props":4299,"children":4301},{"className":4300},[],[4302],{"type":419,"value":4303},"UserApiAuthenticationService",{"type":419,"value":4305}," that will be injected in ",{"type":414,"tag":673,"props":4307,"children":4309},{"className":4308},[],[4310],{"type":419,"value":3083},{"type":419,"value":4312},". That way, if the authentication method changes someday, ",{"type":414,"tag":673,"props":4314,"children":4316},{"className":4315},[],[4317],{"type":419,"value":3083},{"type":419,"value":4319}," implementation won't change. Moreover, we won't mess with the same ",{"type":414,"tag":673,"props":4321,"children":4323},{"className":4322},[],[4324],{"type":419,"value":1977},{"type":419,"value":4326}," for authentication and other calls.",{"type":414,"tag":1265,"props":4328,"children":4330},{"className":1267,"code":4329,"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",[4331],{"type":414,"tag":673,"props":4332,"children":4333},{"__ignoreMap":401},[4334,4359,4366,4391,4414,4421,4461,4468,4487,4507,4514,4521,4556,4563,4580,4645,4653,4725,4812,4878,4945,4953,4968,4975],{"type":414,"tag":1274,"props":4335,"children":4336},{"class":1276,"line":1277},[4337,4341,4345,4350,4354],{"type":414,"tag":1274,"props":4338,"children":4339},{"style":1281},[4340],{"type":419,"value":1284},{"type":414,"tag":1274,"props":4342,"children":4343},{"style":1287},[4344],{"type":419,"value":2949},{"type":414,"tag":1274,"props":4346,"children":4347},{"style":1287},[4348],{"type":419,"value":4349}," UserApiAuthenticationService",{"type":414,"tag":1274,"props":4351,"children":4352},{"style":1298},[4353],{"type":419,"value":3126},{"type":414,"tag":1274,"props":4355,"children":4356},{"style":1287},[4357],{"type":419,"value":4358}," IUserApiAuthenticationService\n",{"type":414,"tag":1274,"props":4360,"children":4361},{"class":1276,"line":1058},[4362],{"type":414,"tag":1274,"props":4363,"children":4364},{"style":1298},[4365],{"type":419,"value":1555},{"type":414,"tag":1274,"props":4367,"children":4368},{"class":1276,"line":1064},[4369,4373,4377,4382,4387],{"type":414,"tag":1274,"props":4370,"children":4371},{"style":1281},[4372],{"type":419,"value":3145},{"type":414,"tag":1274,"props":4374,"children":4375},{"style":1281},[4376],{"type":419,"value":3150},{"type":414,"tag":1274,"props":4378,"children":4379},{"style":1287},[4380],{"type":419,"value":4381}," IMemoryCache",{"type":414,"tag":1274,"props":4383,"children":4384},{"style":1287},[4385],{"type":419,"value":4386}," _memoryCache",{"type":414,"tag":1274,"props":4388,"children":4389},{"style":1298},[4390],{"type":419,"value":1405},{"type":414,"tag":1274,"props":4392,"children":4393},{"class":1276,"line":1466},[4394,4398,4402,4406,4410],{"type":414,"tag":1274,"props":4395,"children":4396},{"style":1281},[4397],{"type":419,"value":3145},{"type":414,"tag":1274,"props":4399,"children":4400},{"style":1281},[4401],{"type":419,"value":3150},{"type":414,"tag":1274,"props":4403,"children":4404},{"style":1287},[4405],{"type":419,"value":3155},{"type":414,"tag":1274,"props":4407,"children":4408},{"style":1287},[4409],{"type":419,"value":2787},{"type":414,"tag":1274,"props":4411,"children":4412},{"style":1298},[4413],{"type":419,"value":1405},{"type":414,"tag":1274,"props":4415,"children":4416},{"class":1276,"line":1491},[4417],{"type":414,"tag":1274,"props":4418,"children":4419},{"emptyLinePlaceholder":1529},[4420],{"type":419,"value":1532},{"type":414,"tag":1274,"props":4422,"children":4423},{"class":1276,"line":1525},[4424,4428,4432,4436,4440,4444,4448,4452,4457],{"type":414,"tag":1274,"props":4425,"children":4426},{"style":1281},[4427],{"type":419,"value":1564},{"type":414,"tag":1274,"props":4429,"children":4430},{"style":2608},[4431],{"type":419,"value":4349},{"type":414,"tag":1274,"props":4433,"children":4434},{"style":1298},[4435],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4437,"children":4438},{"style":1287},[4439],{"type":419,"value":1977},{"type":414,"tag":1274,"props":4441,"children":4442},{"style":1287},[4443],{"type":419,"value":3187},{"type":414,"tag":1274,"props":4445,"children":4446},{"style":1298},[4447],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4449,"children":4450},{"style":1287},[4451],{"type":419,"value":4381},{"type":414,"tag":1274,"props":4453,"children":4454},{"style":1287},[4455],{"type":419,"value":4456}," memoryCache",{"type":414,"tag":1274,"props":4458,"children":4459},{"style":1298},[4460],{"type":419,"value":3192},{"type":414,"tag":1274,"props":4462,"children":4463},{"class":1276,"line":1535},[4464],{"type":414,"tag":1274,"props":4465,"children":4466},{"style":1298},[4467],{"type":419,"value":3200},{"type":414,"tag":1274,"props":4469,"children":4470},{"class":1276,"line":1549},[4471,4475,4479,4483],{"type":414,"tag":1274,"props":4472,"children":4473},{"style":1397},[4474],{"type":419,"value":3208},{"type":414,"tag":1274,"props":4476,"children":4477},{"style":1298},[4478],{"type":419,"value":2714},{"type":414,"tag":1274,"props":4480,"children":4481},{"style":1397},[4482],{"type":419,"value":3187},{"type":414,"tag":1274,"props":4484,"children":4485},{"style":1298},[4486],{"type":419,"value":1405},{"type":414,"tag":1274,"props":4488,"children":4489},{"class":1276,"line":1558},[4490,4495,4499,4503],{"type":414,"tag":1274,"props":4491,"children":4492},{"style":1397},[4493],{"type":419,"value":4494},"        _memoryCache ",{"type":414,"tag":1274,"props":4496,"children":4497},{"style":1298},[4498],{"type":419,"value":2714},{"type":414,"tag":1274,"props":4500,"children":4501},{"style":1397},[4502],{"type":419,"value":4456},{"type":414,"tag":1274,"props":4504,"children":4505},{"style":1298},[4506],{"type":419,"value":1405},{"type":414,"tag":1274,"props":4508,"children":4509},{"class":1276,"line":1627},[4510],{"type":414,"tag":1274,"props":4511,"children":4512},{"style":1298},[4513],{"type":419,"value":3228},{"type":414,"tag":1274,"props":4515,"children":4516},{"class":1276,"line":1636},[4517],{"type":414,"tag":1274,"props":4518,"children":4519},{"emptyLinePlaceholder":1529},[4520],{"type":419,"value":1532},{"type":414,"tag":1274,"props":4522,"children":4523},{"class":1276,"line":1699},[4524,4528,4532,4536,4540,4544,4548,4552],{"type":414,"tag":1274,"props":4525,"children":4526},{"style":1281},[4527],{"type":419,"value":1564},{"type":414,"tag":1274,"props":4529,"children":4530},{"style":1281},[4531],{"type":419,"value":3247},{"type":414,"tag":1274,"props":4533,"children":4534},{"style":1287},[4535],{"type":419,"value":3252},{"type":414,"tag":1274,"props":4537,"children":4538},{"style":1298},[4539],{"type":419,"value":1664},{"type":414,"tag":1274,"props":4541,"children":4542},{"style":1298},[4543],{"type":419,"value":1306},{"type":414,"tag":1274,"props":4545,"children":4546},{"style":1298},[4547],{"type":419,"value":1674},{"type":414,"tag":1274,"props":4549,"children":4550},{"style":2608},[4551],{"type":419,"value":3314},{"type":414,"tag":1274,"props":4553,"children":4554},{"style":1298},[4555],{"type":419,"value":3281},{"type":414,"tag":1274,"props":4557,"children":4558},{"class":1276,"line":1707},[4559],{"type":414,"tag":1274,"props":4560,"children":4561},{"style":1298},[4562],{"type":419,"value":3200},{"type":414,"tag":1274,"props":4564,"children":4565},{"class":1276,"line":1754},[4566,4571,4576],{"type":414,"tag":1274,"props":4567,"children":4568},{"style":1287},[4569],{"type":419,"value":4570},"        DateTime",{"type":414,"tag":1274,"props":4572,"children":4573},{"style":1287},[4574],{"type":419,"value":4575}," expirationDate",{"type":414,"tag":1274,"props":4577,"children":4578},{"style":1298},[4579],{"type":419,"value":1405},{"type":414,"tag":1274,"props":4581,"children":4582},{"class":1276,"line":1762},[4583,4588,4593,4598,4602,4607,4611,4615,4619,4623,4627,4632,4636,4640],{"type":414,"tag":1274,"props":4584,"children":4585},{"style":3521},[4586],{"type":419,"value":4587},"        if",{"type":414,"tag":1274,"props":4589,"children":4590},{"style":1298},[4591],{"type":419,"value":4592}," (!",{"type":414,"tag":1274,"props":4594,"children":4595},{"style":1397},[4596],{"type":419,"value":4597},"_memoryCache",{"type":414,"tag":1274,"props":4599,"children":4600},{"style":1298},[4601],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4603,"children":4604},{"style":2608},[4605],{"type":419,"value":4606},"TryGetValue",{"type":414,"tag":1274,"props":4608,"children":4609},{"style":1298},[4610],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4612,"children":4613},{"style":1298},[4614],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4616,"children":4617},{"style":2722},[4618],{"type":419,"value":4219},{"type":414,"tag":1274,"props":4620,"children":4621},{"style":1298},[4622],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4624,"children":4625},{"style":1298},[4626],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4628,"children":4629},{"style":1281},[4630],{"type":419,"value":4631}," out",{"type":414,"tag":1274,"props":4633,"children":4634},{"style":1298},[4635],{"type":419,"value":1742},{"type":414,"tag":1274,"props":4637,"children":4638},{"style":1287},[4639],{"type":419,"value":3301},{"type":414,"tag":1274,"props":4641,"children":4642},{"style":1298},[4643],{"type":419,"value":4644},"))\n",{"type":414,"tag":1274,"props":4646,"children":4647},{"class":1276,"line":1820},[4648],{"type":414,"tag":1274,"props":4649,"children":4650},{"style":1298},[4651],{"type":419,"value":4652},"        {\n",{"type":414,"tag":1274,"props":4654,"children":4655},{"class":1276,"line":3572},[4656,4661,4665,4669,4673,4677,4681,4685,4689,4693,4697,4701,4705,4709,4713,4717,4721],{"type":414,"tag":1274,"props":4657,"children":4658},{"style":1287},[4659],{"type":419,"value":4660},"            var",{"type":414,"tag":1274,"props":4662,"children":4663},{"style":1287},[4664],{"type":419,"value":2689},{"type":414,"tag":1274,"props":4666,"children":4667},{"style":1298},[4668],{"type":419,"value":2694},{"type":414,"tag":1274,"props":4670,"children":4671},{"style":1298},[4672],{"type":419,"value":2699},{"type":414,"tag":1274,"props":4674,"children":4675},{"style":1298},[4676],{"type":419,"value":2704},{"type":414,"tag":1274,"props":4678,"children":4679},{"style":1397},[4680],{"type":419,"value":2709},{"type":414,"tag":1274,"props":4682,"children":4683},{"style":1298},[4684],{"type":419,"value":2714},{"type":414,"tag":1274,"props":4686,"children":4687},{"style":1298},[4688],{"type":419,"value":2719},{"type":414,"tag":1274,"props":4690,"children":4691},{"style":2722},[4692],{"type":419,"value":2725},{"type":414,"tag":1274,"props":4694,"children":4695},{"style":1298},[4696],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4698,"children":4699},{"style":1298},[4700],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4702,"children":4703},{"style":1397},[4704],{"type":419,"value":2739},{"type":414,"tag":1274,"props":4706,"children":4707},{"style":1298},[4708],{"type":419,"value":2714},{"type":414,"tag":1274,"props":4710,"children":4711},{"style":1298},[4712],{"type":419,"value":2719},{"type":414,"tag":1274,"props":4714,"children":4715},{"style":2722},[4716],{"type":419,"value":2752},{"type":414,"tag":1274,"props":4718,"children":4719},{"style":1298},[4720],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4722,"children":4723},{"style":1298},[4724],{"type":419,"value":2761},{"type":414,"tag":1274,"props":4726,"children":4727},{"class":1276,"line":3580},[4728,4732,4736,4740,4744,4748,4752,4756,4760,4764,4768,4772,4776,4780,4784,4788,4792,4796,4800,4804,4808],{"type":414,"tag":1274,"props":4729,"children":4730},{"style":1287},[4731],{"type":419,"value":4660},{"type":414,"tag":1274,"props":4733,"children":4734},{"style":1287},[4735],{"type":419,"value":2773},{"type":414,"tag":1274,"props":4737,"children":4738},{"style":1298},[4739],{"type":419,"value":2694},{"type":414,"tag":1274,"props":4741,"children":4742},{"style":1298},[4743],{"type":419,"value":2782},{"type":414,"tag":1274,"props":4745,"children":4746},{"style":1397},[4747],{"type":419,"value":2787},{"type":414,"tag":1274,"props":4749,"children":4750},{"style":1298},[4751],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4753,"children":4754},{"style":2608},[4755],{"type":419,"value":2796},{"type":414,"tag":1274,"props":4757,"children":4758},{"style":1298},[4759],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4761,"children":4762},{"style":1298},[4763],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4765,"children":4766},{"style":2722},[4767],{"type":419,"value":2725},{"type":414,"tag":1274,"props":4769,"children":4770},{"style":1298},[4771],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4773,"children":4774},{"style":1298},[4775],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4777,"children":4778},{"style":1298},[4779],{"type":419,"value":2699},{"type":414,"tag":1274,"props":4781,"children":4782},{"style":1287},[4783],{"type":419,"value":2825},{"type":414,"tag":1274,"props":4785,"children":4786},{"style":1298},[4787],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4789,"children":4790},{"style":1397},[4791],{"type":419,"value":2834},{"type":414,"tag":1274,"props":4793,"children":4794},{"style":1298},[4795],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4797,"children":4798},{"style":2608},[4799],{"type":419,"value":2843},{"type":414,"tag":1274,"props":4801,"children":4802},{"style":1298},[4803],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4805,"children":4806},{"style":1397},[4807],{"type":419,"value":2852},{"type":414,"tag":1274,"props":4809,"children":4810},{"style":1298},[4811],{"type":419,"value":2857},{"type":414,"tag":1274,"props":4813,"children":4814},{"class":1276,"line":3588},[4815,4820,4825,4829,4834,4838,4842,4846,4850,4854,4858,4862,4866,4870,4874],{"type":414,"tag":1274,"props":4816,"children":4817},{"style":1298},[4818],{"type":419,"value":4819},"            (",{"type":414,"tag":1274,"props":4821,"children":4822},{"style":1397},[4823],{"type":419,"value":4824},"token",{"type":414,"tag":1274,"props":4826,"children":4827},{"style":1298},[4828],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4830,"children":4831},{"style":1397},[4832],{"type":419,"value":4833},"  expirationDate",{"type":414,"tag":1274,"props":4835,"children":4836},{"style":1298},[4837],{"type":419,"value":2050},{"type":414,"tag":1274,"props":4839,"children":4840},{"style":1298},[4841],{"type":419,"value":2694},{"type":414,"tag":1274,"props":4843,"children":4844},{"style":1298},[4845],{"type":419,"value":2782},{"type":414,"tag":1274,"props":4847,"children":4848},{"style":1397},[4849],{"type":419,"value":2773},{"type":414,"tag":1274,"props":4851,"children":4852},{"style":1298},[4853],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4855,"children":4856},{"style":1397},[4857],{"type":419,"value":2890},{"type":414,"tag":1274,"props":4859,"children":4860},{"style":1298},[4861],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4863,"children":4864},{"style":2608},[4865],{"type":419,"value":2899},{"type":414,"tag":1274,"props":4867,"children":4868},{"style":1298},[4869],{"type":419,"value":1664},{"type":414,"tag":1274,"props":4871,"children":4872},{"style":1287},[4873],{"type":419,"value":2484},{"type":414,"tag":1274,"props":4875,"children":4876},{"style":1298},[4877],{"type":419,"value":2912},{"type":414,"tag":1274,"props":4879,"children":4880},{"class":1276,"line":3624},[4881,4886,4890,4895,4899,4903,4907,4911,4915,4919,4923,4927,4932,4936,4941],{"type":414,"tag":1274,"props":4882,"children":4883},{"style":1397},[4884],{"type":419,"value":4885},"            _memoryCache",{"type":414,"tag":1274,"props":4887,"children":4888},{"style":1298},[4889],{"type":419,"value":1421},{"type":414,"tag":1274,"props":4891,"children":4892},{"style":2608},[4893],{"type":419,"value":4894},"Set",{"type":414,"tag":1274,"props":4896,"children":4897},{"style":1298},[4898],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4900,"children":4901},{"style":1298},[4902],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4904,"children":4905},{"style":2722},[4906],{"type":419,"value":4219},{"type":414,"tag":1274,"props":4908,"children":4909},{"style":1298},[4910],{"type":419,"value":2730},{"type":414,"tag":1274,"props":4912,"children":4913},{"style":1298},[4914],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4916,"children":4917},{"style":1397},[4918],{"type":419,"value":3301},{"type":414,"tag":1274,"props":4920,"children":4921},{"style":1298},[4922],{"type":419,"value":1316},{"type":414,"tag":1274,"props":4924,"children":4925},{"style":1298},[4926],{"type":419,"value":2699},{"type":414,"tag":1274,"props":4928,"children":4929},{"style":1287},[4930],{"type":419,"value":4931}," DateTimeOffset",{"type":414,"tag":1274,"props":4933,"children":4934},{"style":1298},[4935],{"type":419,"value":1301},{"type":414,"tag":1274,"props":4937,"children":4938},{"style":1397},[4939],{"type":419,"value":4940},"expirationDate",{"type":414,"tag":1274,"props":4942,"children":4943},{"style":1298},[4944],{"type":419,"value":3862},{"type":414,"tag":1274,"props":4946,"children":4947},{"class":1276,"line":3632},[4948],{"type":414,"tag":1274,"props":4949,"children":4950},{"style":1298},[4951],{"type":419,"value":4952},"        }\n",{"type":414,"tag":1274,"props":4954,"children":4955},{"class":1276,"line":3660},[4956,4960,4964],{"type":414,"tag":1274,"props":4957,"children":4958},{"style":3521},[4959],{"type":419,"value":3524},{"type":414,"tag":1274,"props":4961,"children":4962},{"style":1397},[4963],{"type":419,"value":3301},{"type":414,"tag":1274,"props":4965,"children":4966},{"style":1298},[4967],{"type":419,"value":1405},{"type":414,"tag":1274,"props":4969,"children":4970},{"class":1276,"line":3743},[4971],{"type":414,"tag":1274,"props":4972,"children":4973},{"style":1298},[4974],{"type":419,"value":3228},{"type":414,"tag":1274,"props":4976,"children":4977},{"class":1276,"line":3807},[4978],{"type":414,"tag":1274,"props":4979,"children":4980},{"style":1298},[4981],{"type":419,"value":1826},{"type":414,"tag":415,"props":4983,"children":4984},{},[4985,4987,4993,4995,5001],{"type":419,"value":4986},"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":414,"tag":673,"props":4988,"children":4990},{"className":4989},[],[4991],{"type":419,"value":4992},"IMemoryCache",{"type":419,"value":4994}," 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":414,"tag":433,"props":4996,"children":4999},{"href":4997,"rel":4998},"https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-3.1",[437],[5000],{"type":419,"value":2048},{"type":419,"value":1421},{"type":414,"tag":421,"props":5003,"children":5005},{"id":5004},"use-a-delegating-handler-to-directly-set-the-token-in-the-httpclient-request",[5006],{"type":419,"value":5007},"Use a Delegating handler to directly set the token in the HttpClient request",{"type":414,"tag":415,"props":5009,"children":5010},{},[5011,5013,5018,5020,5025,5027,5032,5034,5039,5041,5046],{"type":419,"value":5012},"Handling the token retrieval in a separate service is nice but that does not solve the issue of duplicated code. Even if the ",{"type":414,"tag":673,"props":5014,"children":5016},{"className":5015},[],[5017],{"type":419,"value":4258},{"type":419,"value":5019}," method is now part of ",{"type":414,"tag":673,"props":5021,"children":5023},{"className":5022},[],[5024],{"type":419,"value":4303},{"type":419,"value":5026},", each method of ",{"type":414,"tag":673,"props":5028,"children":5030},{"className":5029},[],[5031],{"type":419,"value":3083},{"type":419,"value":5033}," will still call ",{"type":414,"tag":673,"props":5035,"children":5037},{"className":5036},[],[5038],{"type":419,"value":4258},{"type":419,"value":5040},". Moreover setting the token on each request should not be a concern of ",{"type":414,"tag":673,"props":5042,"children":5044},{"className":5043},[],[5045],{"type":419,"value":3083},{"type":419,"value":1421},{"type":414,"tag":415,"props":5048,"children":5049},{},[5050,5052,5057,5059,5064,5066,5070,5072,5079],{"type":419,"value":5051},"That's where come ",{"type":414,"tag":704,"props":5053,"children":5054},{},[5055],{"type":419,"value":5056},"delegating handlers",{"type":419,"value":5058},". 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":414,"tag":673,"props":5060,"children":5062},{"className":5061},[],[5063],{"type":419,"value":1977},{"type":419,"value":5065},". To learn more about ",{"type":414,"tag":704,"props":5067,"children":5068},{},[5069],{"type":419,"value":5056},{"type":419,"value":5071}," there is a nice ",{"type":414,"tag":433,"props":5073,"children":5076},{"href":5074,"rel":5075},"https://www.stevejgordon.co.uk/httpclientfactory-aspnetcore-outgoing-request-middleware-pipeline-delegatinghandlers",[437],[5077],{"type":419,"value":5078},"article",{"type":419,"value":5080}," from Steve Gordon on the topic.",{"type":414,"tag":415,"props":5082,"children":5083},{},[5084,5086,5091],{"type":419,"value":5085},"A custom delegating handler is exactly what we need: a piece of code that all our HTTP requests from ",{"type":414,"tag":673,"props":5087,"children":5089},{"className":5088},[],[5090],{"type":419,"value":3083},{"type":419,"value":5092}," 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":414,"tag":1265,"props":5094,"children":5096},{"className":1267,"code":5095,"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",[5097],{"type":414,"tag":673,"props":5098,"children":5099},{"__ignoreMap":401},[5100,5125,5132,5157,5164,5193,5200,5220,5227,5234,5298,5305,5340,5403,5448,5455],{"type":414,"tag":1274,"props":5101,"children":5102},{"class":1276,"line":1277},[5103,5107,5111,5116,5120],{"type":414,"tag":1274,"props":5104,"children":5105},{"style":1281},[5106],{"type":419,"value":1284},{"type":414,"tag":1274,"props":5108,"children":5109},{"style":1287},[5110],{"type":419,"value":2949},{"type":414,"tag":1274,"props":5112,"children":5113},{"style":1287},[5114],{"type":419,"value":5115}," UserApiAuthenticationHandler",{"type":414,"tag":1274,"props":5117,"children":5118},{"style":1298},[5119],{"type":419,"value":3126},{"type":414,"tag":1274,"props":5121,"children":5122},{"style":1287},[5123],{"type":419,"value":5124}," DelegatingHandler\n",{"type":414,"tag":1274,"props":5126,"children":5127},{"class":1276,"line":1058},[5128],{"type":414,"tag":1274,"props":5129,"children":5130},{"style":1298},[5131],{"type":419,"value":1555},{"type":414,"tag":1274,"props":5133,"children":5134},{"class":1276,"line":1064},[5135,5139,5143,5148,5153],{"type":414,"tag":1274,"props":5136,"children":5137},{"style":1281},[5138],{"type":419,"value":3145},{"type":414,"tag":1274,"props":5140,"children":5141},{"style":1281},[5142],{"type":419,"value":3150},{"type":414,"tag":1274,"props":5144,"children":5145},{"style":1287},[5146],{"type":419,"value":5147}," IUserApiAuthenticationService",{"type":414,"tag":1274,"props":5149,"children":5150},{"style":1287},[5151],{"type":419,"value":5152}," _authenticationService",{"type":414,"tag":1274,"props":5154,"children":5155},{"style":1298},[5156],{"type":419,"value":1405},{"type":414,"tag":1274,"props":5158,"children":5159},{"class":1276,"line":1466},[5160],{"type":414,"tag":1274,"props":5161,"children":5162},{"emptyLinePlaceholder":1529},[5163],{"type":419,"value":1532},{"type":414,"tag":1274,"props":5165,"children":5166},{"class":1276,"line":1491},[5167,5171,5175,5179,5184,5189],{"type":414,"tag":1274,"props":5168,"children":5169},{"style":1281},[5170],{"type":419,"value":1564},{"type":414,"tag":1274,"props":5172,"children":5173},{"style":2608},[5174],{"type":419,"value":5115},{"type":414,"tag":1274,"props":5176,"children":5177},{"style":1298},[5178],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5180,"children":5181},{"style":1287},[5182],{"type":419,"value":5183},"IUserApiAuthenticationService",{"type":414,"tag":1274,"props":5185,"children":5186},{"style":1287},[5187],{"type":419,"value":5188}," authenticationService",{"type":414,"tag":1274,"props":5190,"children":5191},{"style":1298},[5192],{"type":419,"value":3192},{"type":414,"tag":1274,"props":5194,"children":5195},{"class":1276,"line":1525},[5196],{"type":414,"tag":1274,"props":5197,"children":5198},{"style":1298},[5199],{"type":419,"value":3200},{"type":414,"tag":1274,"props":5201,"children":5202},{"class":1276,"line":1535},[5203,5208,5212,5216],{"type":414,"tag":1274,"props":5204,"children":5205},{"style":1397},[5206],{"type":419,"value":5207},"        _authenticationService ",{"type":414,"tag":1274,"props":5209,"children":5210},{"style":1298},[5211],{"type":419,"value":2714},{"type":414,"tag":1274,"props":5213,"children":5214},{"style":1397},[5215],{"type":419,"value":5188},{"type":414,"tag":1274,"props":5217,"children":5218},{"style":1298},[5219],{"type":419,"value":1405},{"type":414,"tag":1274,"props":5221,"children":5222},{"class":1276,"line":1549},[5223],{"type":414,"tag":1274,"props":5224,"children":5225},{"style":1298},[5226],{"type":419,"value":3228},{"type":414,"tag":1274,"props":5228,"children":5229},{"class":1276,"line":1558},[5230],{"type":414,"tag":1274,"props":5231,"children":5232},{"style":1397},[5233],{"type":419,"value":1633},{"type":414,"tag":1274,"props":5235,"children":5236},{"class":1276,"line":1627},[5237,5242,5246,5251,5255,5259,5264,5268,5273,5277,5281,5285,5289,5294],{"type":414,"tag":1274,"props":5238,"children":5239},{"style":1281},[5240],{"type":419,"value":5241},"    protected",{"type":414,"tag":1274,"props":5243,"children":5244},{"style":1281},[5245],{"type":419,"value":3247},{"type":414,"tag":1274,"props":5247,"children":5248},{"style":1281},[5249],{"type":419,"value":5250}," override",{"type":414,"tag":1274,"props":5252,"children":5253},{"style":1287},[5254],{"type":419,"value":3252},{"type":414,"tag":1274,"props":5256,"children":5257},{"style":1298},[5258],{"type":419,"value":1664},{"type":414,"tag":1274,"props":5260,"children":5261},{"style":1287},[5262],{"type":419,"value":5263},"HttpResponseMessage",{"type":414,"tag":1274,"props":5265,"children":5266},{"style":1298},[5267],{"type":419,"value":1674},{"type":414,"tag":1274,"props":5269,"children":5270},{"style":2608},[5271],{"type":419,"value":5272}," SendAsync",{"type":414,"tag":1274,"props":5274,"children":5275},{"style":1298},[5276],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5278,"children":5279},{"style":1287},[5280],{"type":419,"value":2095},{"type":414,"tag":1274,"props":5282,"children":5283},{"style":1287},[5284],{"type":419,"value":3330},{"type":414,"tag":1274,"props":5286,"children":5287},{"style":1298},[5288],{"type":419,"value":1316},{"type":414,"tag":1274,"props":5290,"children":5291},{"style":1397},[5292],{"type":419,"value":5293}," CancellationTokencancellationToken",{"type":414,"tag":1274,"props":5295,"children":5296},{"style":1298},[5297],{"type":419,"value":3192},{"type":414,"tag":1274,"props":5299,"children":5300},{"class":1276,"line":1636},[5301],{"type":414,"tag":1274,"props":5302,"children":5303},{"style":1298},[5304],{"type":419,"value":3200},{"type":414,"tag":1274,"props":5306,"children":5307},{"class":1276,"line":1699},[5308,5312,5316,5320,5324,5328,5332,5336],{"type":414,"tag":1274,"props":5309,"children":5310},{"style":1287},[5311],{"type":419,"value":3296},{"type":414,"tag":1274,"props":5313,"children":5314},{"style":1287},[5315],{"type":419,"value":3301},{"type":414,"tag":1274,"props":5317,"children":5318},{"style":1298},[5319],{"type":419,"value":2694},{"type":414,"tag":1274,"props":5321,"children":5322},{"style":1298},[5323],{"type":419,"value":2782},{"type":414,"tag":1274,"props":5325,"children":5326},{"style":1397},[5327],{"type":419,"value":5152},{"type":414,"tag":1274,"props":5329,"children":5330},{"style":1298},[5331],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5333,"children":5334},{"style":2608},[5335],{"type":419,"value":4258},{"type":414,"tag":1274,"props":5337,"children":5338},{"style":1298},[5339],{"type":419,"value":2616},{"type":414,"tag":1274,"props":5341,"children":5342},{"class":1276,"line":1707},[5343,5347,5351,5355,5359,5363,5367,5371,5375,5379,5383,5387,5391,5395,5399],{"type":414,"tag":1274,"props":5344,"children":5345},{"style":1397},[5346],{"type":419,"value":3389},{"type":414,"tag":1274,"props":5348,"children":5349},{"style":1298},[5350],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5352,"children":5353},{"style":1397},[5354],{"type":419,"value":3398},{"type":414,"tag":1274,"props":5356,"children":5357},{"style":1298},[5358],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5360,"children":5361},{"style":1397},[5362],{"type":419,"value":3407},{"type":414,"tag":1274,"props":5364,"children":5365},{"style":1298},[5366],{"type":419,"value":2714},{"type":414,"tag":1274,"props":5368,"children":5369},{"style":1298},[5370],{"type":419,"value":2699},{"type":414,"tag":1274,"props":5372,"children":5373},{"style":1287},[5374],{"type":419,"value":3420},{"type":414,"tag":1274,"props":5376,"children":5377},{"style":1298},[5378],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5380,"children":5381},{"style":1298},[5382],{"type":419,"value":2730},{"type":414,"tag":1274,"props":5384,"children":5385},{"style":2722},[5386],{"type":419,"value":3433},{"type":414,"tag":1274,"props":5388,"children":5389},{"style":1298},[5390],{"type":419,"value":2730},{"type":414,"tag":1274,"props":5392,"children":5393},{"style":1298},[5394],{"type":419,"value":1316},{"type":414,"tag":1274,"props":5396,"children":5397},{"style":1397},[5398],{"type":419,"value":3301},{"type":414,"tag":1274,"props":5400,"children":5401},{"style":1298},[5402],{"type":419,"value":1358},{"type":414,"tag":1274,"props":5404,"children":5405},{"class":1276,"line":1754},[5406,5410,5414,5419,5423,5427,5431,5435,5439,5444],{"type":414,"tag":1274,"props":5407,"children":5408},{"style":3521},[5409],{"type":419,"value":3524},{"type":414,"tag":1274,"props":5411,"children":5412},{"style":1298},[5413],{"type":419,"value":2782},{"type":414,"tag":1274,"props":5415,"children":5416},{"style":1397},[5417],{"type":419,"value":5418}," base",{"type":414,"tag":1274,"props":5420,"children":5421},{"style":1298},[5422],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5424,"children":5425},{"style":2608},[5426],{"type":419,"value":3481},{"type":414,"tag":1274,"props":5428,"children":5429},{"style":1298},[5430],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5432,"children":5433},{"style":1397},[5434],{"type":419,"value":3490},{"type":414,"tag":1274,"props":5436,"children":5437},{"style":1298},[5438],{"type":419,"value":1316},{"type":414,"tag":1274,"props":5440,"children":5441},{"style":1397},[5442],{"type":419,"value":5443}," cancellationToken",{"type":414,"tag":1274,"props":5445,"children":5446},{"style":1298},[5447],{"type":419,"value":1358},{"type":414,"tag":1274,"props":5449,"children":5450},{"class":1276,"line":1762},[5451],{"type":414,"tag":1274,"props":5452,"children":5453},{"style":1298},[5454],{"type":419,"value":3228},{"type":414,"tag":1274,"props":5456,"children":5457},{"class":1276,"line":1820},[5458],{"type":414,"tag":1274,"props":5459,"children":5460},{"style":1298},[5461],{"type":419,"value":1826},{"type":414,"tag":415,"props":5463,"children":5464},{},[5465],{"type":419,"value":5466},"That's it, we don't need anymore to handle token retrieval on UserService which becomes simpler:",{"type":414,"tag":1265,"props":5468,"children":5470},{"className":1267,"code":5469,"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",[5471],{"type":414,"tag":673,"props":5472,"children":5473},{"__ignoreMap":401},[5474,5498,5505,5528,5555,5562,5581,5588,5595,5638,5645,5707,5726,5777,5784,5791,5826,5833,5885,5962,5981,5988],{"type":414,"tag":1274,"props":5475,"children":5476},{"class":1276,"line":1277},[5477,5481,5485,5489,5493],{"type":414,"tag":1274,"props":5478,"children":5479},{"style":1281},[5480],{"type":419,"value":1284},{"type":414,"tag":1274,"props":5482,"children":5483},{"style":1287},[5484],{"type":419,"value":2949},{"type":414,"tag":1274,"props":5486,"children":5487},{"style":1287},[5488],{"type":419,"value":3121},{"type":414,"tag":1274,"props":5490,"children":5491},{"style":1298},[5492],{"type":419,"value":3126},{"type":414,"tag":1274,"props":5494,"children":5495},{"style":1397},[5496],{"type":419,"value":5497}," \n",{"type":414,"tag":1274,"props":5499,"children":5500},{"class":1276,"line":1058},[5501],{"type":414,"tag":1274,"props":5502,"children":5503},{"style":1298},[5504],{"type":419,"value":1555},{"type":414,"tag":1274,"props":5506,"children":5507},{"class":1276,"line":1064},[5508,5512,5516,5520,5524],{"type":414,"tag":1274,"props":5509,"children":5510},{"style":1281},[5511],{"type":419,"value":3145},{"type":414,"tag":1274,"props":5513,"children":5514},{"style":1281},[5515],{"type":419,"value":3150},{"type":414,"tag":1274,"props":5517,"children":5518},{"style":1287},[5519],{"type":419,"value":3155},{"type":414,"tag":1274,"props":5521,"children":5522},{"style":1287},[5523],{"type":419,"value":2787},{"type":414,"tag":1274,"props":5525,"children":5526},{"style":1298},[5527],{"type":419,"value":1405},{"type":414,"tag":1274,"props":5529,"children":5530},{"class":1276,"line":1466},[5531,5535,5539,5543,5547,5551],{"type":414,"tag":1274,"props":5532,"children":5533},{"style":1281},[5534],{"type":419,"value":1564},{"type":414,"tag":1274,"props":5536,"children":5537},{"style":2608},[5538],{"type":419,"value":3121},{"type":414,"tag":1274,"props":5540,"children":5541},{"style":1298},[5542],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5544,"children":5545},{"style":1287},[5546],{"type":419,"value":1977},{"type":414,"tag":1274,"props":5548,"children":5549},{"style":1287},[5550],{"type":419,"value":3187},{"type":414,"tag":1274,"props":5552,"children":5553},{"style":1298},[5554],{"type":419,"value":3192},{"type":414,"tag":1274,"props":5556,"children":5557},{"class":1276,"line":1491},[5558],{"type":414,"tag":1274,"props":5559,"children":5560},{"style":1298},[5561],{"type":419,"value":3200},{"type":414,"tag":1274,"props":5563,"children":5564},{"class":1276,"line":1525},[5565,5569,5573,5577],{"type":414,"tag":1274,"props":5566,"children":5567},{"style":1397},[5568],{"type":419,"value":3208},{"type":414,"tag":1274,"props":5570,"children":5571},{"style":1298},[5572],{"type":419,"value":2714},{"type":414,"tag":1274,"props":5574,"children":5575},{"style":1397},[5576],{"type":419,"value":3187},{"type":414,"tag":1274,"props":5578,"children":5579},{"style":1298},[5580],{"type":419,"value":1405},{"type":414,"tag":1274,"props":5582,"children":5583},{"class":1276,"line":1535},[5584],{"type":414,"tag":1274,"props":5585,"children":5586},{"style":1298},[5587],{"type":419,"value":3228},{"type":414,"tag":1274,"props":5589,"children":5590},{"class":1276,"line":1549},[5591],{"type":414,"tag":1274,"props":5592,"children":5593},{"emptyLinePlaceholder":1529},[5594],{"type":419,"value":1532},{"type":414,"tag":1274,"props":5596,"children":5597},{"class":1276,"line":1558},[5598,5602,5606,5610,5614,5618,5622,5626,5630,5634],{"type":414,"tag":1274,"props":5599,"children":5600},{"style":1281},[5601],{"type":419,"value":1564},{"type":414,"tag":1274,"props":5603,"children":5604},{"style":1281},[5605],{"type":419,"value":3247},{"type":414,"tag":1274,"props":5607,"children":5608},{"style":1287},[5609],{"type":419,"value":3252},{"type":414,"tag":1274,"props":5611,"children":5612},{"style":1298},[5613],{"type":419,"value":1664},{"type":414,"tag":1274,"props":5615,"children":5616},{"style":1287},[5617],{"type":419,"value":2591},{"type":414,"tag":1274,"props":5619,"children":5620},{"style":1298},[5621],{"type":419,"value":1664},{"type":414,"tag":1274,"props":5623,"children":5624},{"style":1287},[5625],{"type":419,"value":2600},{"type":414,"tag":1274,"props":5627,"children":5628},{"style":1298},[5629],{"type":419,"value":2605},{"type":414,"tag":1274,"props":5631,"children":5632},{"style":2608},[5633],{"type":419,"value":2611},{"type":414,"tag":1274,"props":5635,"children":5636},{"style":1298},[5637],{"type":419,"value":3281},{"type":414,"tag":1274,"props":5639,"children":5640},{"class":1276,"line":1627},[5641],{"type":414,"tag":1274,"props":5642,"children":5643},{"style":1298},[5644],{"type":419,"value":3200},{"type":414,"tag":1274,"props":5646,"children":5647},{"class":1276,"line":1636},[5648,5652,5656,5660,5664,5668,5672,5677,5682,5687,5691,5695,5699,5703],{"type":414,"tag":1274,"props":5649,"children":5650},{"style":1287},[5651],{"type":419,"value":3296},{"type":414,"tag":1274,"props":5653,"children":5654},{"style":1287},[5655],{"type":419,"value":2773},{"type":414,"tag":1274,"props":5657,"children":5658},{"style":1298},[5659],{"type":419,"value":2694},{"type":414,"tag":1274,"props":5661,"children":5662},{"style":1298},[5663],{"type":419,"value":2782},{"type":414,"tag":1274,"props":5665,"children":5666},{"style":1397},[5667],{"type":419,"value":2787},{"type":414,"tag":1274,"props":5669,"children":5670},{"style":1298},[5671],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5673,"children":5674},{"style":2608},[5675],{"type":419,"value":5676},"GetAsync",{"type":414,"tag":1274,"props":5678,"children":5679},{"style":1298},[5680],{"type":419,"value":5681},"(new",{"type":414,"tag":1274,"props":5683,"children":5684},{"style":1287},[5685],{"type":419,"value":5686}," Uri",{"type":414,"tag":1274,"props":5688,"children":5689},{"style":1298},[5690],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5692,"children":5693},{"style":1298},[5694],{"type":419,"value":2730},{"type":414,"tag":1274,"props":5696,"children":5697},{"style":2722},[5698],{"type":419,"value":3373},{"type":414,"tag":1274,"props":5700,"children":5701},{"style":1298},[5702],{"type":419,"value":2730},{"type":414,"tag":1274,"props":5704,"children":5705},{"style":1298},[5706],{"type":419,"value":3862},{"type":414,"tag":1274,"props":5708,"children":5709},{"class":1276,"line":1699},[5710,5714,5718,5722],{"type":414,"tag":1274,"props":5711,"children":5712},{"style":1397},[5713],{"type":419,"value":3502},{"type":414,"tag":1274,"props":5715,"children":5716},{"style":1298},[5717],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5719,"children":5720},{"style":2608},[5721],{"type":419,"value":3511},{"type":414,"tag":1274,"props":5723,"children":5724},{"style":1298},[5725],{"type":419,"value":2616},{"type":414,"tag":1274,"props":5727,"children":5728},{"class":1276,"line":1707},[5729,5733,5737,5741,5745,5749,5753,5757,5761,5765,5769,5773],{"type":414,"tag":1274,"props":5730,"children":5731},{"style":3521},[5732],{"type":419,"value":3524},{"type":414,"tag":1274,"props":5734,"children":5735},{"style":1298},[5736],{"type":419,"value":2782},{"type":414,"tag":1274,"props":5738,"children":5739},{"style":1397},[5740],{"type":419,"value":2773},{"type":414,"tag":1274,"props":5742,"children":5743},{"style":1298},[5744],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5746,"children":5747},{"style":1397},[5748],{"type":419,"value":2890},{"type":414,"tag":1274,"props":5750,"children":5751},{"style":1298},[5752],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5754,"children":5755},{"style":2608},[5756],{"type":419,"value":2899},{"type":414,"tag":1274,"props":5758,"children":5759},{"style":1298},[5760],{"type":419,"value":1664},{"type":414,"tag":1274,"props":5762,"children":5763},{"style":1287},[5764],{"type":419,"value":2591},{"type":414,"tag":1274,"props":5766,"children":5767},{"style":1298},[5768],{"type":419,"value":1664},{"type":414,"tag":1274,"props":5770,"children":5771},{"style":1287},[5772],{"type":419,"value":2600},{"type":414,"tag":1274,"props":5774,"children":5775},{"style":1298},[5776],{"type":419,"value":3569},{"type":414,"tag":1274,"props":5778,"children":5779},{"class":1276,"line":1754},[5780],{"type":414,"tag":1274,"props":5781,"children":5782},{"style":1298},[5783],{"type":419,"value":3228},{"type":414,"tag":1274,"props":5785,"children":5786},{"class":1276,"line":1762},[5787],{"type":414,"tag":1274,"props":5788,"children":5789},{"emptyLinePlaceholder":1529},[5790],{"type":419,"value":1532},{"type":414,"tag":1274,"props":5792,"children":5793},{"class":1276,"line":1820},[5794,5798,5802,5806,5810,5814,5818,5822],{"type":414,"tag":1274,"props":5795,"children":5796},{"style":1281},[5797],{"type":419,"value":1564},{"type":414,"tag":1274,"props":5799,"children":5800},{"style":1281},[5801],{"type":419,"value":3247},{"type":414,"tag":1274,"props":5803,"children":5804},{"style":1287},[5805],{"type":419,"value":3252},{"type":414,"tag":1274,"props":5807,"children":5808},{"style":2608},[5809],{"type":419,"value":2628},{"type":414,"tag":1274,"props":5811,"children":5812},{"style":1298},[5813],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5815,"children":5816},{"style":1287},[5817],{"type":419,"value":2600},{"type":414,"tag":1274,"props":5819,"children":5820},{"style":1287},[5821],{"type":419,"value":2641},{"type":414,"tag":1274,"props":5823,"children":5824},{"style":1298},[5825],{"type":419,"value":3192},{"type":414,"tag":1274,"props":5827,"children":5828},{"class":1276,"line":3572},[5829],{"type":414,"tag":1274,"props":5830,"children":5831},{"style":1298},[5832],{"type":419,"value":3200},{"type":414,"tag":1274,"props":5834,"children":5835},{"class":1276,"line":3580},[5836,5840,5845,5849,5853,5857,5861,5865,5869,5873,5877,5881],{"type":414,"tag":1274,"props":5837,"children":5838},{"style":1287},[5839],{"type":419,"value":3296},{"type":414,"tag":1274,"props":5841,"children":5842},{"style":1287},[5843],{"type":419,"value":5844}," content",{"type":414,"tag":1274,"props":5846,"children":5847},{"style":1298},[5848],{"type":419,"value":2694},{"type":414,"tag":1274,"props":5850,"children":5851},{"style":1298},[5852],{"type":419,"value":2699},{"type":414,"tag":1274,"props":5854,"children":5855},{"style":1287},[5856],{"type":419,"value":2825},{"type":414,"tag":1274,"props":5858,"children":5859},{"style":1298},[5860],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5862,"children":5863},{"style":1397},[5864],{"type":419,"value":2834},{"type":414,"tag":1274,"props":5866,"children":5867},{"style":1298},[5868],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5870,"children":5871},{"style":2608},[5872],{"type":419,"value":2843},{"type":414,"tag":1274,"props":5874,"children":5875},{"style":1298},[5876],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5878,"children":5879},{"style":1397},[5880],{"type":419,"value":3722},{"type":414,"tag":1274,"props":5882,"children":5883},{"style":1298},[5884],{"type":419,"value":3862},{"type":414,"tag":1274,"props":5886,"children":5887},{"class":1276,"line":3588},[5888,5892,5896,5900,5904,5908,5912,5917,5921,5926,5930,5934,5938,5942,5946,5950,5954,5958],{"type":414,"tag":1274,"props":5889,"children":5890},{"style":1287},[5891],{"type":419,"value":3296},{"type":414,"tag":1274,"props":5893,"children":5894},{"style":1287},[5895],{"type":419,"value":2773},{"type":414,"tag":1274,"props":5897,"children":5898},{"style":1298},[5899],{"type":419,"value":2694},{"type":414,"tag":1274,"props":5901,"children":5902},{"style":1298},[5903],{"type":419,"value":2782},{"type":414,"tag":1274,"props":5905,"children":5906},{"style":1397},[5907],{"type":419,"value":2787},{"type":414,"tag":1274,"props":5909,"children":5910},{"style":1298},[5911],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5913,"children":5914},{"style":2608},[5915],{"type":419,"value":5916},"PutAsync",{"type":414,"tag":1274,"props":5918,"children":5919},{"style":1298},[5920],{"type":419,"value":1301},{"type":414,"tag":1274,"props":5922,"children":5923},{"style":1298},[5924],{"type":419,"value":5925},"$\"",{"type":414,"tag":1274,"props":5927,"children":5928},{"style":2722},[5929],{"type":419,"value":3712},{"type":414,"tag":1274,"props":5931,"children":5932},{"style":1298},[5933],{"type":419,"value":3717},{"type":414,"tag":1274,"props":5935,"children":5936},{"style":1397},[5937],{"type":419,"value":3722},{"type":414,"tag":1274,"props":5939,"children":5940},{"style":1298},[5941],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5943,"children":5944},{"style":1397},[5945],{"type":419,"value":3731},{"type":414,"tag":1274,"props":5947,"children":5948},{"style":1298},[5949],{"type":419,"value":3736},{"type":414,"tag":1274,"props":5951,"children":5952},{"style":1298},[5953],{"type":419,"value":1316},{"type":414,"tag":1274,"props":5955,"children":5956},{"style":1397},[5957],{"type":419,"value":5844},{"type":414,"tag":1274,"props":5959,"children":5960},{"style":1298},[5961],{"type":419,"value":1358},{"type":414,"tag":1274,"props":5963,"children":5964},{"class":1276,"line":3624},[5965,5969,5973,5977],{"type":414,"tag":1274,"props":5966,"children":5967},{"style":1397},[5968],{"type":419,"value":3502},{"type":414,"tag":1274,"props":5970,"children":5971},{"style":1298},[5972],{"type":419,"value":1421},{"type":414,"tag":1274,"props":5974,"children":5975},{"style":2608},[5976],{"type":419,"value":3511},{"type":414,"tag":1274,"props":5978,"children":5979},{"style":1298},[5980],{"type":419,"value":2616},{"type":414,"tag":1274,"props":5982,"children":5983},{"class":1276,"line":3632},[5984],{"type":414,"tag":1274,"props":5985,"children":5986},{"style":1298},[5987],{"type":419,"value":3228},{"type":414,"tag":1274,"props":5989,"children":5990},{"class":1276,"line":3660},[5991],{"type":414,"tag":1274,"props":5992,"children":5993},{"style":1298},[5994],{"type":419,"value":1826},{"type":414,"tag":415,"props":5996,"children":5997},{},[5998,6000,6006],{"type":419,"value":5999},"To finish we just have to specify in the ",{"type":414,"tag":673,"props":6001,"children":6003},{"className":6002},[],[6004],{"type":419,"value":6005},"Startup.cs",{"type":419,"value":6007}," on which HttpClient to apply the delegating handler we have just created.",{"type":414,"tag":1265,"props":6009,"children":6011},{"className":1267,"code":6010,"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",[6012],{"type":414,"tag":673,"props":6013,"children":6014},{"__ignoreMap":401},[6015,6045,6052,6073,6110,6172,6179,6208,6243,6298,6323],{"type":414,"tag":1274,"props":6016,"children":6017},{"class":1276,"line":1277},[6018,6022,6027,6032,6036,6041],{"type":414,"tag":1274,"props":6019,"children":6020},{"style":1281},[6021],{"type":419,"value":1284},{"type":414,"tag":1274,"props":6023,"children":6024},{"style":1298},[6025],{"type":419,"value":6026}," void",{"type":414,"tag":1274,"props":6028,"children":6029},{"style":2608},[6030],{"type":419,"value":6031}," ConfigureServices",{"type":414,"tag":1274,"props":6033,"children":6034},{"style":1298},[6035],{"type":419,"value":1301},{"type":414,"tag":1274,"props":6037,"children":6038},{"style":1397},[6039],{"type":419,"value":6040},"IServiceCollectionservices",{"type":414,"tag":1274,"props":6042,"children":6043},{"style":1298},[6044],{"type":419,"value":3192},{"type":414,"tag":1274,"props":6046,"children":6047},{"class":1276,"line":1058},[6048],{"type":414,"tag":1274,"props":6049,"children":6050},{"style":1298},[6051],{"type":419,"value":1555},{"type":414,"tag":1274,"props":6053,"children":6054},{"class":1276,"line":1064},[6055,6060,6064,6069],{"type":414,"tag":1274,"props":6056,"children":6057},{"style":1397},[6058],{"type":419,"value":6059},"    services",{"type":414,"tag":1274,"props":6061,"children":6062},{"style":1298},[6063],{"type":419,"value":1421},{"type":414,"tag":1274,"props":6065,"children":6066},{"style":2608},[6067],{"type":419,"value":6068},"AddMemoryCache",{"type":414,"tag":1274,"props":6070,"children":6071},{"style":1298},[6072],{"type":419,"value":2616},{"type":414,"tag":1274,"props":6074,"children":6075},{"class":1276,"line":1466},[6076,6080,6084,6089,6093,6097,6101,6105],{"type":414,"tag":1274,"props":6077,"children":6078},{"style":1397},[6079],{"type":419,"value":6059},{"type":414,"tag":1274,"props":6081,"children":6082},{"style":1298},[6083],{"type":419,"value":1421},{"type":414,"tag":1274,"props":6085,"children":6086},{"style":2608},[6087],{"type":419,"value":6088},"AddHttpClient",{"type":414,"tag":1274,"props":6090,"children":6091},{"style":1298},[6092],{"type":419,"value":1664},{"type":414,"tag":1274,"props":6094,"children":6095},{"style":1287},[6096],{"type":419,"value":5183},{"type":414,"tag":1274,"props":6098,"children":6099},{"style":1298},[6100],{"type":419,"value":1316},{"type":414,"tag":1274,"props":6102,"children":6103},{"style":1287},[6104],{"type":419,"value":4349},{"type":414,"tag":1274,"props":6106,"children":6107},{"style":1298},[6108],{"type":419,"value":6109},">()\n",{"type":414,"tag":1274,"props":6111,"children":6112},{"class":1276,"line":1491},[6113,6118,6123,6127,6132,6137,6142,6146,6151,6155,6159,6164,6168],{"type":414,"tag":1274,"props":6114,"children":6115},{"style":1298},[6116],{"type":419,"value":6117},"            .",{"type":414,"tag":1274,"props":6119,"children":6120},{"style":2608},[6121],{"type":419,"value":6122},"ConfigureHttpClient",{"type":414,"tag":1274,"props":6124,"children":6125},{"style":1298},[6126],{"type":419,"value":1301},{"type":414,"tag":1274,"props":6128,"children":6129},{"style":1287},[6130],{"type":419,"value":6131},"c",{"type":414,"tag":1274,"props":6133,"children":6134},{"style":1298},[6135],{"type":419,"value":6136}," =>",{"type":414,"tag":1274,"props":6138,"children":6139},{"style":1397},[6140],{"type":419,"value":6141}," c",{"type":414,"tag":1274,"props":6143,"children":6144},{"style":1298},[6145],{"type":419,"value":1421},{"type":414,"tag":1274,"props":6147,"children":6148},{"style":1397},[6149],{"type":419,"value":6150},"BaseAddress ",{"type":414,"tag":1274,"props":6152,"children":6153},{"style":1298},[6154],{"type":419,"value":2714},{"type":414,"tag":1274,"props":6156,"children":6157},{"style":1298},[6158],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6160,"children":6161},{"style":2722},[6162],{"type":419,"value":6163},"http://urltotheuserapi.com",{"type":414,"tag":1274,"props":6165,"children":6166},{"style":1298},[6167],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6169,"children":6170},{"style":1298},[6171],{"type":419,"value":1358},{"type":414,"tag":1274,"props":6173,"children":6174},{"class":1276,"line":1525},[6175],{"type":414,"tag":1274,"props":6176,"children":6177},{"style":1397},[6178],{"type":419,"value":1633},{"type":414,"tag":1274,"props":6180,"children":6181},{"class":1276,"line":1535},[6182,6186,6190,6195,6199,6204],{"type":414,"tag":1274,"props":6183,"children":6184},{"style":1397},[6185],{"type":419,"value":6059},{"type":414,"tag":1274,"props":6187,"children":6188},{"style":1298},[6189],{"type":419,"value":1421},{"type":414,"tag":1274,"props":6191,"children":6192},{"style":2608},[6193],{"type":419,"value":6194},"AddTransient",{"type":414,"tag":1274,"props":6196,"children":6197},{"style":1298},[6198],{"type":419,"value":1664},{"type":414,"tag":1274,"props":6200,"children":6201},{"style":1287},[6202],{"type":419,"value":6203},"UserApiAuthenticationHandler",{"type":414,"tag":1274,"props":6205,"children":6206},{"style":1298},[6207],{"type":419,"value":2912},{"type":414,"tag":1274,"props":6209,"children":6210},{"class":1276,"line":1549},[6211,6215,6219,6223,6227,6231,6235,6239],{"type":414,"tag":1274,"props":6212,"children":6213},{"style":1397},[6214],{"type":419,"value":6059},{"type":414,"tag":1274,"props":6216,"children":6217},{"style":1298},[6218],{"type":419,"value":1421},{"type":414,"tag":1274,"props":6220,"children":6221},{"style":2608},[6222],{"type":419,"value":6088},{"type":414,"tag":1274,"props":6224,"children":6225},{"style":1298},[6226],{"type":419,"value":1664},{"type":414,"tag":1274,"props":6228,"children":6229},{"style":1287},[6230],{"type":419,"value":3083},{"type":414,"tag":1274,"props":6232,"children":6233},{"style":1298},[6234],{"type":419,"value":1316},{"type":414,"tag":1274,"props":6236,"children":6237},{"style":1287},[6238],{"type":419,"value":3121},{"type":414,"tag":1274,"props":6240,"children":6241},{"style":1298},[6242],{"type":419,"value":6109},{"type":414,"tag":1274,"props":6244,"children":6245},{"class":1276,"line":1558},[6246,6250,6254,6258,6262,6266,6270,6274,6278,6282,6286,6290,6294],{"type":414,"tag":1274,"props":6247,"children":6248},{"style":1298},[6249],{"type":419,"value":6117},{"type":414,"tag":1274,"props":6251,"children":6252},{"style":2608},[6253],{"type":419,"value":6122},{"type":414,"tag":1274,"props":6255,"children":6256},{"style":1298},[6257],{"type":419,"value":1301},{"type":414,"tag":1274,"props":6259,"children":6260},{"style":1287},[6261],{"type":419,"value":6131},{"type":414,"tag":1274,"props":6263,"children":6264},{"style":1298},[6265],{"type":419,"value":6136},{"type":414,"tag":1274,"props":6267,"children":6268},{"style":1397},[6269],{"type":419,"value":6141},{"type":414,"tag":1274,"props":6271,"children":6272},{"style":1298},[6273],{"type":419,"value":1421},{"type":414,"tag":1274,"props":6275,"children":6276},{"style":1397},[6277],{"type":419,"value":6150},{"type":414,"tag":1274,"props":6279,"children":6280},{"style":1298},[6281],{"type":419,"value":2714},{"type":414,"tag":1274,"props":6283,"children":6284},{"style":1298},[6285],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6287,"children":6288},{"style":2722},[6289],{"type":419,"value":6163},{"type":414,"tag":1274,"props":6291,"children":6292},{"style":1298},[6293],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6295,"children":6296},{"style":1298},[6297],{"type":419,"value":3192},{"type":414,"tag":1274,"props":6299,"children":6300},{"class":1276,"line":1627},[6301,6305,6310,6314,6319],{"type":414,"tag":1274,"props":6302,"children":6303},{"style":1298},[6304],{"type":419,"value":6117},{"type":414,"tag":1274,"props":6306,"children":6307},{"style":2608},[6308],{"type":419,"value":6309},"AddHttpMessageHandler",{"type":414,"tag":1274,"props":6311,"children":6312},{"style":1298},[6313],{"type":419,"value":1664},{"type":414,"tag":1274,"props":6315,"children":6316},{"style":1287},[6317],{"type":419,"value":6318},"UserApiAuthenticationHanler",{"type":414,"tag":1274,"props":6320,"children":6321},{"style":1298},[6322],{"type":419,"value":2912},{"type":414,"tag":1274,"props":6324,"children":6325},{"class":1276,"line":1636},[6326],{"type":414,"tag":1274,"props":6327,"children":6328},{"style":1298},[6329],{"type":419,"value":1826},{"type":414,"tag":421,"props":6331,"children":6332},{"id":2401},[6333],{"type":419,"value":2404},{"type":414,"tag":415,"props":6335,"children":6336},{},[6337],{"type":419,"value":6338},"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":414,"tag":2411,"props":6340,"children":6341},{},[6342],{"type":419,"value":2415},{"title":401,"searchDepth":1058,"depth":1058,"links":6344},[6345,6346,6347,6348,6349],{"id":2448,"depth":1058,"text":2451},{"id":3069,"depth":1058,"text":3072},{"id":4282,"depth":1058,"text":4285},{"id":5004,"depth":1058,"text":5007},{"id":2401,"depth":1058,"text":2404},"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":6353,"lead":6354,"date":6355,"image":6356,"badge":6358,"tags":6359,"body":6360,"_type":1077,"_id":7242,"_source":1079,"_file":7243,"_extension":1081},"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":6357},"/images/swiss_knifes.jpg",{"label":408},[206,208,210,213],{"type":411,"children":6361,"toc":7235},[6362,6366,6372,6377,6386,6391,6402,6408,6417,6449,6454,6468,6497,6508,6514,6548,6557,6562,6808,6853,6862,6868,6873,6878,6883,6889,6894,6906,6911,7231],{"type":414,"tag":415,"props":6363,"children":6364},{},[6365],{"type":419,"value":6353},{"type":414,"tag":421,"props":6367,"children":6369},{"id":6368},"gui-tools-and-their-limits",[6370],{"type":419,"value":6371},"GUI Tools and their limits",{"type":414,"tag":415,"props":6373,"children":6374},{},[6375],{"type":419,"value":6376},"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":414,"tag":415,"props":6378,"children":6379},{},[6380],{"type":414,"tag":565,"props":6381,"children":6385},{"alt":6382,"className":6383,"src":6384},"Postman UI",[569,570],"/posts/images/restclient_postman_1.png",[],{"type":414,"tag":415,"props":6387,"children":6388},{},[6389],{"type":419,"value":6390},"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":414,"tag":415,"props":6392,"children":6393},{},[6394,6396,6401],{"type":419,"value":6395},"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":414,"tag":433,"props":6397,"children":6399},{"href":459,"rel":6398},[437],[6400],{"type":419,"value":463},{"type":419,"value":1421},{"type":414,"tag":421,"props":6403,"children":6405},{"id":6404},"what-is-rest-client",[6406],{"type":419,"value":6407},"What is REST Client?",{"type":414,"tag":415,"props":6409,"children":6410},{},[6411],{"type":414,"tag":565,"props":6412,"children":6416},{"alt":6413,"className":6414,"src":6415},"REST Client extension in vscode marketplace",[569,570],"/posts/images/restclient_vscode_1.png",[],{"type":414,"tag":415,"props":6418,"children":6419},{},[6420,6422,6429,6431,6438,6440,6447],{"type":419,"value":6421},"The REST Client extension is an open source vs code extension developed by ",{"type":414,"tag":433,"props":6423,"children":6426},{"href":6424,"rel":6425},"https://github.com/Huachao",[437],[6427],{"type":419,"value":6428},"Huachao Mao",{"type":419,"value":6430},". If I quote the README of its ",{"type":414,"tag":433,"props":6432,"children":6435},{"href":6433,"rel":6434},"https://github.com/Huachao/vscode-restclient",[437],[6436],{"type":419,"value":6437},"GitHub repository",{"type":419,"value":6439},": 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":414,"tag":433,"props":6441,"children":6444},{"href":6442,"rel":6443},"https://swapi.co/",[437],[6445],{"type":419,"value":6446},"The Start Wars API",{"type":419,"value":6448},":",{"type":414,"tag":415,"props":6450,"children":6451},{},[6452],{"type":419,"value":6453},"05578273",{"type":414,"tag":415,"props":6455,"children":6456},{},[6457,6459,6466],{"type":419,"value":6458},"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":414,"tag":433,"props":6460,"children":6463},{"href":6461,"rel":6462},"https://docs.microsoft.com/en-us/graph/api/user-list-memberof?view=graph-rest-1.0#example",[437],[6464],{"type":419,"value":6465},"Microsoft Graph API documentation",{"type":419,"value":6467}," for instance.",{"type":414,"tag":415,"props":6469,"children":6470},{},[6471,6473,6477,6479,6483,6484,6488,6490,6495],{"type":419,"value":6472},"REST Client works on text files in vscode by selecting ",{"type":414,"tag":704,"props":6474,"children":6475},{},[6476],{"type":419,"value":213},{"type":419,"value":6478}," as the Language Mode (by default this language mode is associated with files having the ",{"type":414,"tag":704,"props":6480,"children":6481},{},[6482],{"type":419,"value":708},{"type":419,"value":710},{"type":414,"tag":704,"props":6485,"children":6486},{},[6487],{"type":419,"value":715},{"type":419,"value":6489}," 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":414,"tag":704,"props":6491,"children":6492},{},[6493],{"type":419,"value":6494},"Send Request",{"type":419,"value":6496}," link allows you to run the request and see the response in a response panel.",{"type":414,"tag":415,"props":6498,"children":6499},{},[6500],{"type":414,"tag":565,"props":6501,"children":6507},{"alt":6502,"className":6503,"src":6504,"height":6505,"width":6506},"Intellisense in HTTP files in vscode",[569,570],"/posts/images/restclient_swapi_3.png",400,800,[],{"type":414,"tag":421,"props":6509,"children":6511},{"id":6510},"using-variables-in-rest-client",[6512],{"type":419,"value":6513},"Using variables in REST Client",{"type":414,"tag":415,"props":6515,"children":6516},{},[6517,6519,6525,6527,6538,6540,6546],{"type":419,"value":6518},"As you can see below, it is possible to use variables with REST Client. A variable ",{"type":414,"tag":673,"props":6520,"children":6522},{"className":6521},[],[6523],{"type":419,"value":6524},"planetName",{"type":419,"value":6526}," is defined in the file and reused in 2 requests. A variable is also used to name the request ",{"type":414,"tag":704,"props":6528,"children":6529},{},[6530,6532],{"type":419,"value":6531},"GET ",{"type":414,"tag":433,"props":6533,"children":6536},{"href":6534,"rel":6535},"https://swapi.co/api/people/?search=Luke",[437],[6537],{"type":419,"value":6534},{"type":419,"value":6539}," and makes it possible to use elements from the response (that you can see on the right). Here we are using the ",{"type":414,"tag":673,"props":6541,"children":6543},{"className":6542},[],[6544],{"type":419,"value":6545},"homeworld",{"type":419,"value":6547}," 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":414,"tag":415,"props":6549,"children":6550},{},[6551],{"type":414,"tag":565,"props":6552,"children":6556},{"alt":6553,"className":6554,"src":6555},"Execution of an HTTP request in vscode",[569,570],"/posts/images/restclient_swapi_2.png",[],{"type":414,"tag":415,"props":6558,"children":6559},{},[6560],{"type":419,"value":6561},"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":414,"tag":1265,"props":6563,"children":6567},{"className":6564,"code":6565,"language":6566,"meta":401,"style":401},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\"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","json",[6568],{"type":414,"tag":673,"props":6569,"children":6570},{"__ignoreMap":401},[6571,6596,6622,6661,6669,6693,6730,6737,6761,6794,6801],{"type":414,"tag":1274,"props":6572,"children":6573},{"class":1276,"line":1277},[6574,6578,6583,6587,6592],{"type":414,"tag":1274,"props":6575,"children":6576},{"style":1298},[6577],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6579,"children":6580},{"style":2722},[6581],{"type":419,"value":6582},"rest-client.environmentVariables",{"type":414,"tag":1274,"props":6584,"children":6585},{"style":1298},[6586],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6588,"children":6589},{"style":1397},[6590],{"type":419,"value":6591},": ",{"type":414,"tag":1274,"props":6593,"children":6594},{"style":1298},[6595],{"type":419,"value":1555},{"type":414,"tag":1274,"props":6597,"children":6598},{"class":1276,"line":1058},[6599,6604,6609,6613,6617],{"type":414,"tag":1274,"props":6600,"children":6601},{"style":1298},[6602],{"type":419,"value":6603},"    \"",{"type":414,"tag":1274,"props":6605,"children":6606},{"style":1281},[6607],{"type":419,"value":6608},"$shared",{"type":414,"tag":1274,"props":6610,"children":6611},{"style":1298},[6612],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6614,"children":6615},{"style":1298},[6616],{"type":419,"value":6448},{"type":414,"tag":1274,"props":6618,"children":6619},{"style":1298},[6620],{"type":419,"value":6621}," {\n",{"type":414,"tag":1274,"props":6623,"children":6624},{"class":1276,"line":1064},[6625,6630,6635,6639,6643,6647,6652,6656],{"type":414,"tag":1274,"props":6626,"children":6627},{"style":1298},[6628],{"type":419,"value":6629},"        \"",{"type":414,"tag":1274,"props":6631,"children":6632},{"style":1287},[6633],{"type":419,"value":6634},"host",{"type":414,"tag":1274,"props":6636,"children":6637},{"style":1298},[6638],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6640,"children":6641},{"style":1298},[6642],{"type":419,"value":6448},{"type":414,"tag":1274,"props":6644,"children":6645},{"style":1298},[6646],{"type":419,"value":2719},{"type":414,"tag":1274,"props":6648,"children":6649},{"style":2722},[6650],{"type":419,"value":6651},"https://graph.microsoft.com/",{"type":414,"tag":1274,"props":6653,"children":6654},{"style":1298},[6655],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6657,"children":6658},{"style":1298},[6659],{"type":419,"value":6660},",\n",{"type":414,"tag":1274,"props":6662,"children":6663},{"class":1276,"line":1466},[6664],{"type":414,"tag":1274,"props":6665,"children":6666},{"style":1298},[6667],{"type":419,"value":6668},"    },\n",{"type":414,"tag":1274,"props":6670,"children":6671},{"class":1276,"line":1491},[6672,6676,6681,6685,6689],{"type":414,"tag":1274,"props":6673,"children":6674},{"style":1298},[6675],{"type":419,"value":6603},{"type":414,"tag":1274,"props":6677,"children":6678},{"style":1281},[6679],{"type":419,"value":6680},"graphV1",{"type":414,"tag":1274,"props":6682,"children":6683},{"style":1298},[6684],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6686,"children":6687},{"style":1298},[6688],{"type":419,"value":6448},{"type":414,"tag":1274,"props":6690,"children":6691},{"style":1298},[6692],{"type":419,"value":6621},{"type":414,"tag":1274,"props":6694,"children":6695},{"class":1276,"line":1525},[6696,6700,6705,6709,6713,6717,6722,6726],{"type":414,"tag":1274,"props":6697,"children":6698},{"style":1298},[6699],{"type":419,"value":6629},{"type":414,"tag":1274,"props":6701,"children":6702},{"style":1287},[6703],{"type":419,"value":6704},"version",{"type":414,"tag":1274,"props":6706,"children":6707},{"style":1298},[6708],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6710,"children":6711},{"style":1298},[6712],{"type":419,"value":6448},{"type":414,"tag":1274,"props":6714,"children":6715},{"style":1298},[6716],{"type":419,"value":2719},{"type":414,"tag":1274,"props":6718,"children":6719},{"style":2722},[6720],{"type":419,"value":6721},"v1.0",{"type":414,"tag":1274,"props":6723,"children":6724},{"style":1298},[6725],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6727,"children":6728},{"style":1298},[6729],{"type":419,"value":6660},{"type":414,"tag":1274,"props":6731,"children":6732},{"class":1276,"line":1535},[6733],{"type":414,"tag":1274,"props":6734,"children":6735},{"style":1298},[6736],{"type":419,"value":6668},{"type":414,"tag":1274,"props":6738,"children":6739},{"class":1276,"line":1549},[6740,6744,6749,6753,6757],{"type":414,"tag":1274,"props":6741,"children":6742},{"style":1298},[6743],{"type":419,"value":6603},{"type":414,"tag":1274,"props":6745,"children":6746},{"style":1281},[6747],{"type":419,"value":6748},"graphBeta",{"type":414,"tag":1274,"props":6750,"children":6751},{"style":1298},[6752],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6754,"children":6755},{"style":1298},[6756],{"type":419,"value":6448},{"type":414,"tag":1274,"props":6758,"children":6759},{"style":1298},[6760],{"type":419,"value":6621},{"type":414,"tag":1274,"props":6762,"children":6763},{"class":1276,"line":1558},[6764,6768,6772,6776,6780,6784,6789],{"type":414,"tag":1274,"props":6765,"children":6766},{"style":1298},[6767],{"type":419,"value":6629},{"type":414,"tag":1274,"props":6769,"children":6770},{"style":1287},[6771],{"type":419,"value":6704},{"type":414,"tag":1274,"props":6773,"children":6774},{"style":1298},[6775],{"type":419,"value":2730},{"type":414,"tag":1274,"props":6777,"children":6778},{"style":1298},[6779],{"type":419,"value":6448},{"type":414,"tag":1274,"props":6781,"children":6782},{"style":1298},[6783],{"type":419,"value":2719},{"type":414,"tag":1274,"props":6785,"children":6786},{"style":2722},[6787],{"type":419,"value":6788},"beta",{"type":414,"tag":1274,"props":6790,"children":6791},{"style":1298},[6792],{"type":419,"value":6793},"\"\n",{"type":414,"tag":1274,"props":6795,"children":6796},{"class":1276,"line":1627},[6797],{"type":414,"tag":1274,"props":6798,"children":6799},{"style":1298},[6800],{"type":419,"value":6668},{"type":414,"tag":1274,"props":6802,"children":6803},{"class":1276,"line":1636},[6804],{"type":414,"tag":1274,"props":6805,"children":6806},{"style":1298},[6807],{"type":419,"value":1826},{"type":414,"tag":415,"props":6809,"children":6810},{},[6811,6813,6817,6818,6822,6824,6828,6830,6834,6836,6840,6842,6846,6847,6851],{"type":419,"value":6812},"I have defined 2 environments ",{"type":414,"tag":704,"props":6814,"children":6815},{},[6816],{"type":419,"value":6680},{"type":419,"value":1917},{"type":414,"tag":704,"props":6819,"children":6820},{},[6821],{"type":419,"value":6748},{"type":419,"value":6823}," with a specific value for the ",{"type":414,"tag":704,"props":6825,"children":6826},{},[6827],{"type":419,"value":6704},{"type":419,"value":6829}," variable. These environments share the ",{"type":414,"tag":704,"props":6831,"children":6832},{},[6833],{"type":419,"value":6634},{"type":419,"value":6835}," as a common variable which is contained in the shared environment ",{"type":414,"tag":704,"props":6837,"children":6838},{},[6839],{"type":419,"value":6608},{"type":419,"value":6841},". From my request file, I can now switch between environments and use the variables ",{"type":414,"tag":704,"props":6843,"children":6844},{},[6845],{"type":419,"value":6704},{"type":419,"value":1917},{"type":414,"tag":704,"props":6848,"children":6849},{},[6850],{"type":419,"value":6634},{"type":419,"value":6852}," to request the Microsoft Graph API.",{"type":414,"tag":415,"props":6854,"children":6855},{},[6856],{"type":414,"tag":565,"props":6857,"children":6861},{"alt":6858,"className":6859,"src":6860},"Environment selection in vscode.",[569,570],"/posts/images/restclient_msgraph_1.png",[],{"type":414,"tag":421,"props":6863,"children":6865},{"id":6864},"what-i-like-about-rest-client",[6866],{"type":419,"value":6867},"What I like about REST Client?",{"type":414,"tag":415,"props":6869,"children":6870},{},[6871],{"type":419,"value":6872},"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":414,"tag":415,"props":6874,"children":6875},{},[6876],{"type":419,"value":6877},"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":414,"tag":415,"props":6879,"children":6880},{},[6881],{"type":419,"value":6882},"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":414,"tag":421,"props":6884,"children":6886},{"id":6885},"getting-started",[6887],{"type":419,"value":6888},"Getting started",{"type":414,"tag":415,"props":6890,"children":6891},{},[6892],{"type":419,"value":6893},"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":414,"tag":415,"props":6895,"children":6896},{},[6897,6899,6904],{"type":419,"value":6898},"If you quickly want to convert some of your Postman queries, there is a ",{"type":414,"tag":704,"props":6900,"children":6901},{},[6902],{"type":419,"value":6903},"Code",{"type":419,"value":6905}," 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":414,"tag":415,"props":6907,"children":6908},{},[6909],{"type":419,"value":6910},"Or if you prefer you can get started by testing the Star Wars API, you will find below the requests I used. Enjoy :)",{"type":414,"tag":1265,"props":6912,"children":6916},{"className":6913,"code":6914,"filename":6915,"language":212,"meta":401,"style":401},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","#### List of start wars planets\nGET https://swapi.co/api/planets/ HTTP/1.1\n\n### Get Luke Skywalker\n# @name lukeRequest\nGET https://swapi.co/api/people/?search=Luke HTTP/1.1\n\n### Get Luke Skywalker home planet\nGET {{lukeRequest.response.body.results[0].homeworld}} HTTP/1.1\n\n### List available resources\nGET https://swapi.co/api/ HTTP/1.1\n\n### Search planet with a specific name \n@planetName = Naboo\nGET https://swapi.co/api/planets/?search={{planetName}} HTTP/1.1\n\n### Search planet with a specific name in wookie encoding\nGET https://swapi.co/api/planets/?search={{planetName}}&format=wookiee HTTP/1.1\n\n### List starships\nGET https://swapi.co/api/starships HTTP/1.1\n","swapi.http",[6917],{"type":414,"tag":673,"props":6918,"children":6919},{"__ignoreMap":401},[6920,6929,6955,6962,6970,6995,7019,7026,7034,7058,7065,7073,7097,7104,7112,7129,7153,7160,7168,7192,7199,7207],{"type":414,"tag":1274,"props":6921,"children":6922},{"class":1276,"line":1277},[6923],{"type":414,"tag":1274,"props":6924,"children":6926},{"style":6925},"--shiki-light:#90A4AE;--shiki-default:#546E7A;--shiki-dark:#676E95;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[6927],{"type":419,"value":6928},"#### List of start wars planets\n",{"type":414,"tag":1274,"props":6930,"children":6931},{"class":1276,"line":1058},[6932,6936,6941,6945,6950],{"type":414,"tag":1274,"props":6933,"children":6934},{"style":3521},[6935],{"type":419,"value":2116},{"type":414,"tag":1274,"props":6937,"children":6938},{"style":1397},[6939],{"type":419,"value":6940}," https://swapi.co/api/planets/ ",{"type":414,"tag":1274,"props":6942,"children":6943},{"style":1391},[6944],{"type":419,"value":213},{"type":414,"tag":1274,"props":6946,"children":6947},{"style":1397},[6948],{"type":419,"value":6949},"/",{"type":414,"tag":1274,"props":6951,"children":6952},{"style":1391},[6953],{"type":419,"value":6954},"1.1\n",{"type":414,"tag":1274,"props":6956,"children":6957},{"class":1276,"line":1064},[6958],{"type":414,"tag":1274,"props":6959,"children":6960},{"emptyLinePlaceholder":1529},[6961],{"type":419,"value":1532},{"type":414,"tag":1274,"props":6963,"children":6964},{"class":1276,"line":1466},[6965],{"type":414,"tag":1274,"props":6966,"children":6967},{"style":6925},[6968],{"type":419,"value":6969},"### Get Luke Skywalker\n",{"type":414,"tag":1274,"props":6971,"children":6972},{"class":1276,"line":1491},[6973,6978,6983,6989],{"type":414,"tag":1274,"props":6974,"children":6975},{"style":6925},[6976],{"type":419,"value":6977},"# ",{"type":414,"tag":1274,"props":6979,"children":6980},{"style":3521},[6981],{"type":419,"value":6982},"@",{"type":414,"tag":1274,"props":6984,"children":6986},{"style":6985},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[6987],{"type":419,"value":6988},"name",{"type":414,"tag":1274,"props":6990,"children":6992},{"style":6991},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[6993],{"type":419,"value":6994}," lukeRequest\n",{"type":414,"tag":1274,"props":6996,"children":6997},{"class":1276,"line":1525},[6998,7002,7007,7011,7015],{"type":414,"tag":1274,"props":6999,"children":7000},{"style":3521},[7001],{"type":419,"value":2116},{"type":414,"tag":1274,"props":7003,"children":7004},{"style":1397},[7005],{"type":419,"value":7006}," https://swapi.co/api/people/?search=Luke ",{"type":414,"tag":1274,"props":7008,"children":7009},{"style":1391},[7010],{"type":419,"value":213},{"type":414,"tag":1274,"props":7012,"children":7013},{"style":1397},[7014],{"type":419,"value":6949},{"type":414,"tag":1274,"props":7016,"children":7017},{"style":1391},[7018],{"type":419,"value":6954},{"type":414,"tag":1274,"props":7020,"children":7021},{"class":1276,"line":1535},[7022],{"type":414,"tag":1274,"props":7023,"children":7024},{"emptyLinePlaceholder":1529},[7025],{"type":419,"value":1532},{"type":414,"tag":1274,"props":7027,"children":7028},{"class":1276,"line":1549},[7029],{"type":414,"tag":1274,"props":7030,"children":7031},{"style":6925},[7032],{"type":419,"value":7033},"### Get Luke Skywalker home planet\n",{"type":414,"tag":1274,"props":7035,"children":7036},{"class":1276,"line":1558},[7037,7041,7046,7050,7054],{"type":414,"tag":1274,"props":7038,"children":7039},{"style":3521},[7040],{"type":419,"value":2116},{"type":414,"tag":1274,"props":7042,"children":7043},{"style":1397},[7044],{"type":419,"value":7045}," {{lukeRequest.response.body.results[0].homeworld}} ",{"type":414,"tag":1274,"props":7047,"children":7048},{"style":1391},[7049],{"type":419,"value":213},{"type":414,"tag":1274,"props":7051,"children":7052},{"style":1397},[7053],{"type":419,"value":6949},{"type":414,"tag":1274,"props":7055,"children":7056},{"style":1391},[7057],{"type":419,"value":6954},{"type":414,"tag":1274,"props":7059,"children":7060},{"class":1276,"line":1627},[7061],{"type":414,"tag":1274,"props":7062,"children":7063},{"emptyLinePlaceholder":1529},[7064],{"type":419,"value":1532},{"type":414,"tag":1274,"props":7066,"children":7067},{"class":1276,"line":1636},[7068],{"type":414,"tag":1274,"props":7069,"children":7070},{"style":6925},[7071],{"type":419,"value":7072},"### List available resources\n",{"type":414,"tag":1274,"props":7074,"children":7075},{"class":1276,"line":1699},[7076,7080,7085,7089,7093],{"type":414,"tag":1274,"props":7077,"children":7078},{"style":3521},[7079],{"type":419,"value":2116},{"type":414,"tag":1274,"props":7081,"children":7082},{"style":1397},[7083],{"type":419,"value":7084}," https://swapi.co/api/ ",{"type":414,"tag":1274,"props":7086,"children":7087},{"style":1391},[7088],{"type":419,"value":213},{"type":414,"tag":1274,"props":7090,"children":7091},{"style":1397},[7092],{"type":419,"value":6949},{"type":414,"tag":1274,"props":7094,"children":7095},{"style":1391},[7096],{"type":419,"value":6954},{"type":414,"tag":1274,"props":7098,"children":7099},{"class":1276,"line":1707},[7100],{"type":414,"tag":1274,"props":7101,"children":7102},{"emptyLinePlaceholder":1529},[7103],{"type":419,"value":1532},{"type":414,"tag":1274,"props":7105,"children":7106},{"class":1276,"line":1754},[7107],{"type":414,"tag":1274,"props":7108,"children":7109},{"style":6925},[7110],{"type":419,"value":7111},"### Search planet with a specific name \n",{"type":414,"tag":1274,"props":7113,"children":7114},{"class":1276,"line":1762},[7115,7119,7124],{"type":414,"tag":1274,"props":7116,"children":7117},{"style":1391},[7118],{"type":419,"value":6982},{"type":414,"tag":1274,"props":7120,"children":7121},{"style":1397},[7122],{"type":419,"value":7123},"planetName = ",{"type":414,"tag":1274,"props":7125,"children":7126},{"style":2722},[7127],{"type":419,"value":7128},"Naboo\n",{"type":414,"tag":1274,"props":7130,"children":7131},{"class":1276,"line":1820},[7132,7136,7141,7145,7149],{"type":414,"tag":1274,"props":7133,"children":7134},{"style":3521},[7135],{"type":419,"value":2116},{"type":414,"tag":1274,"props":7137,"children":7138},{"style":1397},[7139],{"type":419,"value":7140}," https://swapi.co/api/planets/?search={{planetName}} ",{"type":414,"tag":1274,"props":7142,"children":7143},{"style":1391},[7144],{"type":419,"value":213},{"type":414,"tag":1274,"props":7146,"children":7147},{"style":1397},[7148],{"type":419,"value":6949},{"type":414,"tag":1274,"props":7150,"children":7151},{"style":1391},[7152],{"type":419,"value":6954},{"type":414,"tag":1274,"props":7154,"children":7155},{"class":1276,"line":3572},[7156],{"type":414,"tag":1274,"props":7157,"children":7158},{"emptyLinePlaceholder":1529},[7159],{"type":419,"value":1532},{"type":414,"tag":1274,"props":7161,"children":7162},{"class":1276,"line":3580},[7163],{"type":414,"tag":1274,"props":7164,"children":7165},{"style":6925},[7166],{"type":419,"value":7167},"### Search planet with a specific name in wookie encoding\n",{"type":414,"tag":1274,"props":7169,"children":7170},{"class":1276,"line":3588},[7171,7175,7180,7184,7188],{"type":414,"tag":1274,"props":7172,"children":7173},{"style":3521},[7174],{"type":419,"value":2116},{"type":414,"tag":1274,"props":7176,"children":7177},{"style":1397},[7178],{"type":419,"value":7179}," https://swapi.co/api/planets/?search={{planetName}}&format=wookiee ",{"type":414,"tag":1274,"props":7181,"children":7182},{"style":1391},[7183],{"type":419,"value":213},{"type":414,"tag":1274,"props":7185,"children":7186},{"style":1397},[7187],{"type":419,"value":6949},{"type":414,"tag":1274,"props":7189,"children":7190},{"style":1391},[7191],{"type":419,"value":6954},{"type":414,"tag":1274,"props":7193,"children":7194},{"class":1276,"line":3624},[7195],{"type":414,"tag":1274,"props":7196,"children":7197},{"emptyLinePlaceholder":1529},[7198],{"type":419,"value":1532},{"type":414,"tag":1274,"props":7200,"children":7201},{"class":1276,"line":3632},[7202],{"type":414,"tag":1274,"props":7203,"children":7204},{"style":6925},[7205],{"type":419,"value":7206},"### List starships\n",{"type":414,"tag":1274,"props":7208,"children":7209},{"class":1276,"line":3660},[7210,7214,7219,7223,7227],{"type":414,"tag":1274,"props":7211,"children":7212},{"style":3521},[7213],{"type":419,"value":2116},{"type":414,"tag":1274,"props":7215,"children":7216},{"style":1397},[7217],{"type":419,"value":7218}," https://swapi.co/api/starships ",{"type":414,"tag":1274,"props":7220,"children":7221},{"style":1391},[7222],{"type":419,"value":213},{"type":414,"tag":1274,"props":7224,"children":7225},{"style":1397},[7226],{"type":419,"value":6949},{"type":414,"tag":1274,"props":7228,"children":7229},{"style":1391},[7230],{"type":419,"value":6954},{"type":414,"tag":2411,"props":7232,"children":7233},{},[7234],{"type":419,"value":2415},{"title":401,"searchDepth":1058,"depth":1058,"links":7236},[7237,7238,7239,7240,7241],{"id":6368,"depth":1058,"text":6371},{"id":6404,"depth":1058,"text":6407},{"id":6510,"depth":1058,"text":6513},{"id":6864,"depth":1058,"text":6867},{"id":6885,"depth":1058,"text":6888},"content:1.posts:1.testing-your-api-with-rest-client.md","1.posts/1.testing-your-api-with-rest-client.md",1716749600660]