tag:blogger.com,1999:blog-63930511148131144432024-02-19T11:10:41.448-05:00Lee's BlogLee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.comBlogger117125tag:blogger.com,1999:blog-6393051114813114443.post-64871844835596129042023-05-25T16:53:00.001-05:002023-05-25T17:09:05.954-05:00How To Decrease ABP's Azure Costs by An Order of Magnitude<p><span style="font-size: large;"><i>The Azure SQL Serverless SKU can save you a lot of money, but only if you know how to take advantage of it. This post will show you how to minimize costs, particularly if you use the ABP Framework.</i> </span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_wR60ynIxZR08iUyKQIAFIclf0e51xtzZmCxgrgl5I_HkPxfwMIEthjda8c91LHWAFprUYIdXcPiBrHUOrrXjUNLHvak3BSGKVZoTJ665-tPDtSgTqSOlQVIe5hV6mMUD3D6cn-SnpTDqJsgf2CyyCkXLA-zenwa7hf-0XGMx1UHv3QPZ3sRUqhIm/s1024/dollarsign.jpeg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="1024" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_wR60ynIxZR08iUyKQIAFIclf0e51xtzZmCxgrgl5I_HkPxfwMIEthjda8c91LHWAFprUYIdXcPiBrHUOrrXjUNLHvak3BSGKVZoTJ665-tPDtSgTqSOlQVIe5hV6mMUD3D6cn-SnpTDqJsgf2CyyCkXLA-zenwa7hf-0XGMx1UHv3QPZ3sRUqhIm/w640-h640/dollarsign.jpeg" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">As I may have mentioned <a href="https://youtu.be/ea0Zx9DLcGA" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">once</a> or <a href="https://blog.infernored.com/be-a-superhero-on-day-1-with-abp-io/" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">twice</a>, <a href="https://abp.io/" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">ABP Framework</a> is an excellent way to jump start ASP.NET web projects. It can propel you to production faster in the short term while improving maintainability and scalability and setting you up for success in the long term.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">However, if you're deploying to Azure, you may discover that the out of the box settings are optimized more for convenience, security, and an on-premise deployment – they are definitely not optimized to reduce Azure spend.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">In this post I'll share a couple minor tweaks you can implement to reduce your ABP Azure Costs by an order of magnitude. Even if you don't use ABP, this article will help you understand how to minimize spend generally with the Azure SQL Serverless SKU.</span></p><h1 style="text-align: left;">Settings.BurnMoney = true</h1><div><span style="background-color: white; color: #15171a;"><span style="font-size: large;">If you deploy ABP Framework as an App Service and an Azure SQL serverless database you're liable to see this after a few weeks:</span></span></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPC110r6hdShKF68h3uy6OJRvORB2ncLYPfvlO3Ke9hmlaeVb35DNVlVv3a-J-YaNIk27NaPvYs0j50R_sy2kHHULS2dHLWDn7Kb8ONKD71Y04GTEpErMZH5bAk-GaesJnsy7x37gO-jj61tTcsTFsYDW-bEoal_hThkz-wKGtDNnjUuJxNfgPmPvb/s1600/1-expensive.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="920" data-original-width="1600" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPC110r6hdShKF68h3uy6OJRvORB2ncLYPfvlO3Ke9hmlaeVb35DNVlVv3a-J-YaNIk27NaPvYs0j50R_sy2kHHULS2dHLWDn7Kb8ONKD71Y04GTEpErMZH5bAk-GaesJnsy7x37gO-jj61tTcsTFsYDW-bEoal_hThkz-wKGtDNnjUuJxNfgPmPvb/w640-h368/1-expensive.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">In just 16 days, this deployment racked up $151 dollars of cost with 88% of that cost from the database alone. That's $9.41 per day, $8.37 of which is for the database! That's extremely high for a dev environment that contains virtually no data and was barely touched.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">That wasn't for especially expensive Azure resources either. For instance, I picked the lowest cost database SKU I could find: a General Purpose Serverless database with every setting cranked to the lowest cost position.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpQFE3tek1UKUwNJgMqOQB6JenEkw4iG4wb5VdeOzXcc898XV04cyWq_RSePaI7gYt_sq2ZJUqwfWyt9MxHcJ_YcjaPEnaXJZIM5Nbe1dJ5uGn2IsRHLalYS43Ob95HjGmip1V9703fDKmUexbHjZl_jUD7kYTaAFaqnRHMl4ZwOpo1X8ZzFy5aMXF/s1710/2-auto-pause.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1611" data-original-width="1710" height="602" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpQFE3tek1UKUwNJgMqOQB6JenEkw4iG4wb5VdeOzXcc898XV04cyWq_RSePaI7gYt_sq2ZJUqwfWyt9MxHcJ_YcjaPEnaXJZIM5Nbe1dJ5uGn2IsRHLalYS43Ob95HjGmip1V9703fDKmUexbHjZl_jUD7kYTaAFaqnRHMl4ZwOpo1X8ZzFy5aMXF/w640-h602/2-auto-pause.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">That looked promising when I set it up, especially that $4.78 / month estimate on the right.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"><span style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: 700; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">MISLEADING AZURE UI ALERT</span>: The estimate cost box when selecting a SKU is unhelpful at best. To begin with my actual storage costs were closer to $32 per month not $4.78. Worse, it mentions but doesn't include an estimate of compute costs. As it turns out, my storage costs were virtually insignificant compared to my actual ~$259 / month of compute costs!</span></p><h1 style="text-align: left;">The Hidden Cost: SQL Compute</h1></div><div><span face="var(--font-serif)" style="background-color: white; color: #15171a; font-size: large;">Serverless with auto-pause is supposed to be the perfect SKU for a low utilized deployment like a dev environment. It should also be good for a production internal site that won't be used much on weekends and after-hours.</span></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">The general idea of serverless SQL is that if the database isn't used for an hour (unfortunately 1 hour is the minimum), then the database will pause itself to reduce compute costs.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">However, auto pause only works if there are literally zero requests hitting the database for an entire hour. A single request, even at minute 59 will restart the timer for another hour.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Diagnosing why your database doesn't auto-pause can be challenging. One way you can tell if your app has successfully stopped hitting the database when not in use by going to the Database -> Monitoring -> Metrics panel and pulling up "App CPU Billed".</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">The "CPU Billed" for my ABP Framework with nearly out of the box settings my looked like this:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmiCpyT4ThThCsDgd3GWfIlxQvJjth4rkv3vY0aB_jC0Kz4jo7UIKj_pvLLgcRipPP0DJv_TvAiQHEM1x7EQkvfj7olbXU7Wj6mkryj1H9ObsYVYL9Cc2ITNaTLL-Vwh-zhm4FPm61suNmSVuzPOgyGAakyQzluQE33xE3L_rZ-y2rvSEXsBetS7t_/s3215/3-cpu-billed.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1345" data-original-width="3215" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmiCpyT4ThThCsDgd3GWfIlxQvJjth4rkv3vY0aB_jC0Kz4jo7UIKj_pvLLgcRipPP0DJv_TvAiQHEM1x7EQkvfj7olbXU7Wj6mkryj1H9ObsYVYL9Cc2ITNaTLL-Vwh-zhm4FPm61suNmSVuzPOgyGAakyQzluQE33xE3L_rZ-y2rvSEXsBetS7t_/w640-h268/3-cpu-billed.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">While my CPU percentage looked like this:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjmS37jg1LJmaHONugTpAZP-rretZY5S9JWSDeUR63EUhYJGN-J6DrC1FArUt_0XuFywj_LJb6hL6W6gjkoZ-5oRcRrk-IzjtR4ZuOuLF1lA5r9iQq1mLiNQt3pXnmWGhx2ROQYTUtE3kx0kTLdbkijsU-ZrQ2smATdmu-k6FKsPy2p-5qq1EbzlaR/s3207/4-cpu-billed.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1359" data-original-width="3207" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjmS37jg1LJmaHONugTpAZP-rretZY5S9JWSDeUR63EUhYJGN-J6DrC1FArUt_0XuFywj_LJb6hL6W6gjkoZ-5oRcRrk-IzjtR4ZuOuLF1lA5r9iQq1mLiNQt3pXnmWGhx2ROQYTUtE3kx0kTLdbkijsU-ZrQ2smATdmu-k6FKsPy2p-5qq1EbzlaR/w640-h272/4-cpu-billed.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Translation: my CPU Utilized was near zero while CPU billed was pegged. That meant something was frequently and very lightly hitting the database. To track the culprit down I turned to a familiar tool.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Running SQL server Query Analyzer in my local environment was the best way I found to determine what's going on. </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic6W-dNTnEXVA6MUBx7UEVjj3iYSeXFm81S8g5b2zrK4motroj7xhaZD0vXlx0NNGbBL6sQR8_bB0bmXVetEhsu3z4DtEpHErq-RHe8MAft7jboVVgaigd4oi_BJwrL8O6x2Dg6LDEZSjjRuWiqORGWIKUcX8b7M8olJugDnbWIgjLDaCZFCfVfbHI/s1165/5-profiler.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="795" data-original-width="1165" height="436" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic6W-dNTnEXVA6MUBx7UEVjj3iYSeXFm81S8g5b2zrK4motroj7xhaZD0vXlx0NNGbBL6sQR8_bB0bmXVetEhsu3z4DtEpHErq-RHe8MAft7jboVVgaigd4oi_BJwrL8O6x2Dg6LDEZSjjRuWiqORGWIKUcX8b7M8olJugDnbWIgjLDaCZFCfVfbHI/w640-h436/5-profiler.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">With that open it was clear that every 3-5 seconds ABP was polling the AbpBackgroundJobs table.</span></p><pre class="language-sql" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-sql" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SELECT</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">TOP</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FROM</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>AbpBackgroundJobs<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AS</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>a<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">WHERE</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ORDER</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BY</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span></code></pre></div><br /><h1 style="text-align: left;">Culprit #1: Background Jobs</h1><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"><a href="https://docs.abp.io/en/abp/latest/Background-Jobs" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">Background Jobs</a> are a wonderful ABP feature that allow you to offload run long running jobs like e-mailing or report creation to a queue for execution on a dedicated background thread. They have a lot of great features I could extol, but it's not strictly relevant, so I'll just encourage you to skim over the documentation.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">On my project I'm not using background jobs yet so I just <a href="https://docs.abp.io/en/abp/latest/Background-Jobs#disable-job-execution" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">disabled</a> them per the documentation like this:</span></p><pre class="language-c" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="# language-c" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">private <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ConfigureBackgroundJobs</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
Configure<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>AbpBackgroundJobOptions<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>options <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// background jobs constantly poll the DB and run up Azure costs, so disable until we need this feature</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>IsJobExecutionEnabled <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> false<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">If you wanted to decrease the polling period you could alternately do something like this:</span></p><pre class="language-c" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="# language-c" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">Configure<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>AbpBackgroundJobWorkerOptions<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>options <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// background jobs normally poll the database every 5 seconds, this</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// updates it to every 6 hours</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>JobPollPeriod <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">21</span>_600_000<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>#</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Unfortunately, after I deployed that it didn't exactly solve all the cost problems. After I let it run for several days, the costs decreased, but in odd, chunky, ways:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Z8iN68mEo7VSNpM8HxFEITKJ0m26_mlKKXY4v91vcxWUgfAQ6RYmD-Tf3FsLodBwQk0wE6mMJNq4WMjf3h2L6PTP3dqJb-Yu1X6o-_BFvgleWden61jrDK6uBRKr5QQjNR-_9Xq-mLpZ8tdF2vuJsZ13br-HyR-NstVXxrrKjFPBxB_jzY6itlRu/s3197/6-chunky.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1362" data-original-width="3197" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Z8iN68mEo7VSNpM8HxFEITKJ0m26_mlKKXY4v91vcxWUgfAQ6RYmD-Tf3FsLodBwQk0wE6mMJNq4WMjf3h2L6PTP3dqJb-Yu1X6o-_BFvgleWden61jrDK6uBRKr5QQjNR-_9Xq-mLpZ8tdF2vuJsZ13br-HyR-NstVXxrrKjFPBxB_jzY6itlRu/w640-h272/6-chunky.png" width="640" /></a></div><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Here you can see it was now able to pause correctly sometimes, but after a hit to the site it would turn back on for days at a time.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Turning back to SQL Server Profiler, and running it for a long time, I eventually saw this:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeklTqJbE2UKELvpE_Pawtuqpj5bcprwMzoovWQnMNdyd4OK0c6OsJmDkI_fcKeXf4MelGviOqtlKBKLhYbgQPCBsBzW1w5sxUaeDsg71TTd19FX_XPzmL-ppHmBU7JO1OA3tCjLn0cJHlRDELQN_tj7mk21ZossuxzyWEIPWPrfpTik-TSRwZs_qc/s829/7-profiler.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="478" data-original-width="829" height="370" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeklTqJbE2UKELvpE_Pawtuqpj5bcprwMzoovWQnMNdyd4OK0c6OsJmDkI_fcKeXf4MelGviOqtlKBKLhYbgQPCBsBzW1w5sxUaeDsg71TTd19FX_XPzmL-ppHmBU7JO1OA3tCjLn0cJHlRDELQN_tj7mk21ZossuxzyWEIPWPrfpTik-TSRwZs_qc/w640-h370/7-profiler.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">The following SQL was hitting the database at 60 minute intervals, right when my database was about to take a well deserved nap.</span></p><pre class="language-sql" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-sql" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SELECT</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">TOP</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FROM</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>OpenIddictAuthorizations<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AS</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>o<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LEFT</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">JOIN</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SELECT</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FROM</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>OpenIddictTokens<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AS</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>oO<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">WHERE</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span></code></pre></div><div><code class="language-sql" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 1em; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><br /></span></code></div><h1 style="text-align: left;">Culprit #2 OpenIdDict</h1><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Even though I disabled general purpose background workers, this OpenIddict background job was still running. Digging into it further, it turned out the offending class is <a href="https://github.com/abpframework/abp/blob/e499f40fc1e7f041def67b6bf8d30d5b337c4b54/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/TokenCleanupService.cs" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">TokenCleanupService</a>, which has the following description:</span></p><pre class="language-c" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="# language-c" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span style="font-size: x-small;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// Note: this background task is responsible of automatically removing orphaned tokens/authorizations</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// (i.e tokens that are no longer valid and ad-hoc authorizations that have no valid tokens associated).</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// Import: since tokens associated to ad-hoc authorizations are not removed as part of the same operation,</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// the tokens MUST be deleted before removing the ad-hoc authorizations that no longer have any token.</span>
</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">The class gets run hourly by TokenCleanupBackgroundWorker, which is registered by the AbpOpenIddictDomainModule <a href="https://docs.abp.io/en/abp/latest/Module-Development-Basics" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">module</a>, which in turn is a dependency of the module [MyProject]DomainModule that was generated from the starter ABP template. </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Removing the AbpOpenIddictDomainModule dependency or disabling the job seems like a poor idea, since most projects, mine included, require oAuth authentication.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">However, by digging through the code one can see how to turn down the frequency. Because of ABP's excellent customizability it's actually quite easy. Just add this inside of your main module:</span></p><pre class="language-c" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="# language-c" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span style="font-size: x-small;">public override <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">PreConfigureServices</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>ServiceConfigurationContext context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
Configure<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>TokenCleanupOptions<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>options <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// The default OpenIdDict cleanup peariod is 3,600,000 ms aka 1 hr, however, this</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// is just short enough to disable the SQL Auto-pause delay and cause it to never shut down.</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// This changes it to every 6 hours or 4 times a day</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>CleanupPeriod <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">21</span>_600_000<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">And now, finally, auto-pause started working as expected. It fired back up 4 times a day to run the cleanup job:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnBMTUT3MJ7uYESj3s5GymMUQlaYBuPk8QVfG5zWQwkm96iuoV3YmL4U8bqdAcCyyT7wyCRdf7Q2vrF4qtsyft-MTKCa59-O6oNW-txrOp_S9bbkEyEK6hK3PK7N1NUJXT0WRCaE46wWvC3Nfc7d0cRx4RtrifpMtMSblGWLMti9xoVckAq7OSreSm/s1625/7-sleeping.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="688" data-original-width="1625" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnBMTUT3MJ7uYESj3s5GymMUQlaYBuPk8QVfG5zWQwkm96iuoV3YmL4U8bqdAcCyyT7wyCRdf7Q2vrF4qtsyft-MTKCa59-O6oNW-txrOp_S9bbkEyEK6hK3PK7N1NUJXT0WRCaE46wWvC3Nfc7d0cRx4RtrifpMtMSblGWLMti9xoVckAq7OSreSm/w640-h270/7-sleeping.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">To reduce costs further I tried reducing CleanupPeriod to <code style="background: rgb(240, 246, 249); border-radius: 0.25em; border: 1px solid rgb(225, 234, 239); box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0.15em 0.4em; vertical-align: middle;">86_400_000</code>, or once per day. That resulted in prices ranging from $1.33 all the way down to $0.50 for the database under light to no usage!</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"></span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">And for comparison purposes here's the cost of the deployment after running it for the same time period as earlier, but with the two configuration tweaks:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8WkX8loTI89EcttFkEh1SB858dnCtlV0ISFB817303-xuleYKxUMmgdOa8wLvdx2H050VqvhP41uMjDKPFG8cHU5yTnO1ED5xmfmfQAno_ZuQ_ao52awwQ9Ck0YIqWpi5bia1cgQUusF1XVLrpO_tin1qbD5lo6vy57n6E54YAHqDrJDCNfVj6IT6/s1956/8-decreased-cost.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1016" data-original-width="1956" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8WkX8loTI89EcttFkEh1SB858dnCtlV0ISFB817303-xuleYKxUMmgdOa8wLvdx2H050VqvhP41uMjDKPFG8cHU5yTnO1ED5xmfmfQAno_ZuQ_ao52awwQ9Ck0YIqWpi5bia1cgQUusF1XVLrpO_tin1qbD5lo6vy57n6E54YAHqDrJDCNfVj6IT6/w640-h332/8-decreased-cost.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"><span face="var(--font-serif)" style="color: #15171a;">That's an overall reduction from $151 down to $21. The majority of the savings were in the database costs, which went from $134 down to $7!</span></span></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"><span face="var(--font-serif)" style="color: #15171a;"></span></span></p><h1>Summary</h1><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"><span face="var(--font-serif)" style="color: #15171a;">Azure SQL serverless can be a great, inexpensive option for certain usage scenarios like dev environments or apps not used on weekends and evenings. If you've got one of those scenarios and you're using ABP though, you will need to adjust your background job and openiddict settings to maximize your cost savings. I hope this post helps you to massively reduce your Azure costs.</span></span></p></div>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-84362458113404781102023-04-14T08:35:00.004-05:002023-04-14T08:49:00.378-05:00MS Build 2023: Must-See Sessions<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjSIAvWsf4bUkh8PqTjBvYX_KXrD5luhZMMC6Ihv6JFIKtFImx9xjeB42kh8QGu7fhHmrMpk0Fw8sCwnrBZRd7dlLqEmxyYwM0jIzjEGqFgrdrmOIs4JDhQirnnPZGg2uYI8wUt_JQU3ZplbaHpChxXmXHKUK7RXXjPFD7iBAEWsDMWLO15Eu3BzkiL" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="651" data-original-width="1260" height="330" src="https://blogger.googleusercontent.com/img/a/AVvXsEjSIAvWsf4bUkh8PqTjBvYX_KXrD5luhZMMC6Ihv6JFIKtFImx9xjeB42kh8QGu7fhHmrMpk0Fw8sCwnrBZRd7dlLqEmxyYwM0jIzjEGqFgrdrmOIs4JDhQirnnPZGg2uYI8wUt_JQU3ZplbaHpChxXmXHKUK7RXXjPFD7iBAEWsDMWLO15Eu3BzkiL=w640-h330" width="640" /></a></div><br />I've been to every single Microsoft Build conference one save since it started in 2011. It's one of my favorite conferences, and I'm so excited that it will be in-person again this year after a two year break. <p></p><p>And now that they published the <a href="https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fstats.microsoft.regsvc.com%2Fls%2Fclick%3Fupn%3DvhfpwUiF7CHrYM7mOM1GER0I082qLC-2FIAqXUhF3iWZUQpzMuODZ0Qi-2FeaczEtUDz7iYeN5Aopm1LR1RGgOUoaA-3D-3DWekZ_mcczW1FTase9WdkG5xlGmlRJF9gLFNK4E0U-2FfJbr-2BYHf6K1Rjqh-2FSJ85lnhCdwGKeV7m5r-2BFTPN-2F-2FDVFUhDpbfQx9YroSb9-2FeRjKjpejCZMUwp0c4IpUaatEeZN8DaGx7ROV-2BcTDCW-2FGXaWVd24jUI66i2mxpEdy12DKuUVrqV4Z7wDmj2TdfxkgV4C5NMg8qU2AYK91UR0ToDiRvpNuuotEtrANx9xYz5c-2BK72hJ-2BbajfCgVMauW4E8O-2BUC461Bw3tIF77hHYJv8gry6RMc9UPRyOSfpL9ldgShJMUiAWCjbSE0e6VmCsGpsGJUCd9mIhdRQtepvY3fGR5HIjAbJjIK-2FnDh6fYLcHYbYdf962mRegk6oRBXrwTO6diuQogx4xuq4TBRxlXuUVUt6iFwsg-3D-3D&data=05%7C01%7C%7Ca0fd097a8e2948262bdc08db3ab604b0%7Cd675516581cb46c88525f0825ab33a2c%7C1%7C0%7C638168325674116118%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=O9cnb%2Bz74gkEiqpviQzezEGA%2FSy6I5SDKVoGDsgapaE%3D&reserved=0">session catalog</a> I have even more reason to be excited. I had a blast browsing through the sessions. There are so many that look amazing. In case you don't have time to browse the full catalog here are the sessions I'm most looking forward to, roughly grouped:</p><h2 style="text-align: left;">.NET</h2><div><ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/7bdbc522-10ed-4114-a0f1-afd45acbf7ee?source=sessions" target="_blank">What’s new in C# 12 and beyond (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/7bdbc522-10ed-4114-a0f1-afd45acbf7ee?source=sessions" target="_blank">)</a> - Dustin Campbell & Mads Torgersen<o:p></o:p></li>
<li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/e9568a77-7cf7-451e-a14b-a347313b2494?source=sessions" target="_blank">Pair programing with Mark Russinovich and Scott Hanselman
(</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/e9568a77-7cf7-451e-a14b-a347313b2494?source=sessions" target="_blank">)</a><o:p></o:p></li>
<li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/7ed9bb72-b4f4-4490-9b26-911d1ac263d1?source=sessions" target="_blank">Developer joy with Scott Hanselman and friends (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/7ed9bb72-b4f4-4490-9b26-911d1ac263d1?source=sessions" target="_blank">)</a><o:p></o:p></li>
<li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/5ee143d2-5336-4e2f-b345-7daf606e7629?source=sessions" target="_blank">Advanced developer tips and tricks in Visual Studio (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/5ee143d2-5336-4e2f-b345-7daf606e7629?source=sessions" target="_blank">)</a> - Mads Kristensen<o:p></o:p></li>
<li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/01f6a7ae-d371-43d5-9e6c-9ed2cf853d94?source=sessions" target="_blank">Inject the power of the cloud and AI into your development
workflow (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/01f6a7ae-d371-43d5-9e6c-9ed2cf853d94?source=sessions" target="_blank">)</a> - w Amanda Silver<o:p></o:p></li>
<li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/7a726a0f-5433-46a4-a91d-7d427ffb5b30?source=sessions" target="_blank">Pragmatic techniques to get the most out of GitHub Copilot
(</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/7a726a0f-5433-46a4-a91d-7d427ffb5b30?source=sessions" target="_blank">)</a><o:p></o:p></li>
</ul><div><h2>AI</h2></div><div><ul style="margin-top: 0in;" type="disc"><li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/852ccf38-b07d-4ddc-a9fe-2e57bdaeb613?source=sessions" target="_blank">Analytics in the Age of AI (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/852ccf38-b07d-4ddc-a9fe-2e57bdaeb613?source=sessions" target="_blank">)</a><o:p></o:p></li><li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/ac905dca-7801-4ad7-8cbd-51defeec1253?source=sessions" target="_blank">Azure-enabled vision AI with NVIDIA AI Enterprise and Jetson (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/ac905dca-7801-4ad7-8cbd-51defeec1253?source=sessions" target="_blank">)</a><o:p></o:p></li><li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/27c0f55d-9c02-4003-bfb3-7e077a12fea2?source=sessions" target="_blank">Getting started with generative AI using Azure OpenAI Service (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/27c0f55d-9c02-4003-bfb3-7e077a12fea2?source=sessions" target="_blank">)</a><o:p></o:p></li><li class="MsoNormal"><a href="https://build.microsoft.com/en-US/sessions/4fa46b40-5a7e-4a2e-8641-e9665b7da757?source=sessions" target="_blank">Integrating Azure OpenAI Service into your intelligent apps (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/4fa46b40-5a7e-4a2e-8641-e9665b7da757?source=sessions" target="_blank">)</a><o:p></o:p></li></ul></div><h2 style="text-align: left;">Mobile</h2></div><p></p><ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/52f77215-c8fa-49eb-844b-46ad4b006987?source=sessions" target="_blank">All things client and mobile app development with .NET (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/52f77215-c8fa-49eb-844b-46ad4b006987?source=sessions" target="_blank">)</a> - w David Ortinau & Maddy Montaquila<o:p></o:p></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/2215f254-3fc3-4529-aa2f-3578b3bfdac9?source=sessions" target="_blank">What's new in .NET Multi-platform App UI (MAUI), Q&A (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/2215f254-3fc3-4529-aa2f-3578b3bfdac9?source=sessions" target="_blank">)</a><o:p></o:p></li>
</ul><h2 style="text-align: left;">Cloud</h2><div><ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/8d95ec32-05e5-4c07-84c9-260148a7578d?source=sessions" target="_blank">The future of the cloud platform (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/8d95ec32-05e5-4c07-84c9-260148a7578d?source=sessions" target="_blank">)</a> - discussion with David Fowler, Chris Gillum,
Hanselman<o:p></o:p></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/836e93ad-72b1-49d4-9430-d6277051aba7?source=sessions" target="_blank">Inside Azure innovations with Mark Russinovich (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/836e93ad-72b1-49d4-9430-d6277051aba7?source=sessions" target="_blank">)</a><o:p></o:p></li>
</ul><h2 style="text-align: left;">Perf</h2></div><div><ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/28588f70-fb54-447a-b778-7ef02c8ffdf8?source=sessions" target="_blank">Deep dive into .NET performance and native AOT (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/28588f70-fb54-447a-b778-7ef02c8ffdf8?source=sessions" target="_blank">)</a> - David Fowler<o:p></o:p></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/d9af0a09-9967-47d2-b77d-7f283b149758?source=sessions" target="_blank">Engineering reliable AI systems at scale (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/d9af0a09-9967-47d2-b77d-7f283b149758?source=sessions" target="_blank">)</a><o:p></o:p></li>
</ul><h2 style="text-align: left;">Web</h2></div><div><ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="http://asp.net/" target="_blank">ASP.NET</a><a href="https://build.microsoft.com/en-US/sessions/4cfe374e-a9a0-4a82-a9b6-890bd90df931?source=sessions" target="_blank"> Core and Blazor futures, Q&A (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/4cfe374e-a9a0-4a82-a9b6-890bd90df931?source=sessions" target="_blank">)</a> - David Fowler, Jeremy Likness, Daniel Roth<o:p></o:p></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/7fc9a4e6-b9ca-42ef-b523-34335603e42c?source=sessions" target="_blank">Full stack Web in .NET 8 with Blazor (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/7fc9a4e6-b9ca-42ef-b523-34335603e42c?source=sessions" target="_blank">)</a><o:p></o:p></li>
</ul><h2 style="text-align: left;">DevOps</h2></div><div><ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/cd278f6c-9405-464e-9fe3-4d7f53bc18b8?source=sessions" target="_blank">CI/CD for the enterprise with GitHub Actions (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/cd278f6c-9405-464e-9fe3-4d7f53bc18b8?source=sessions" target="_blank">)</a><o:p></o:p></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/f62e22f4-8140-4122-91c6-c11e2f44bec4?source=sessions" target="_blank">Prioritize your most critical security findings with
Microsoft Defender for DevOps</a><o:p></o:p></li>
</ul><h2 style="text-align: left;">Misc</h2></div><div><ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/e3492a33-2601-4378-9ee8-a78d40b32df6?source=sessions" target="_blank">How GitHub builds GitHub with GitHub (</a><a href="http://microsoft.com/" target="_blank">microsoft.com</a><a href="https://build.microsoft.com/en-US/sessions/e3492a33-2601-4378-9ee8-a78d40b32df6?source=sessions" target="_blank">)</a><o:p></o:p></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><a href="https://build.microsoft.com/en-US/sessions/67d4a607-f4a1-460c-93d7-c80d94e965c8?source=sessions" target="_blank">Transform any Microsoft Teams app into a multiplayer
experience</a><o:p></o:p></li>
</ul><h2 style="text-align: left;">Summary</h2></div><div>These are the sessions I'm most excited about, which talks did I miss? Please share in the comments on social media.</div><p></p>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-45699695691988865442023-03-01T23:41:00.009-05:002023-03-03T17:44:35.376-05:00How To Deploy EF Database Migrations<p style="text-align: left;"><i>How to deploy Entity Framework Database Migrations across multiple environments, revert migrations, and support complex migrations, all while avoiding security flags.</i></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoUiVFORjpG9fIV3wJth5NnlcGqRicDKkqFGvokIogTv6LvoKV2SqgYfn_FFVEZQcT5VHDeQaggdHJ3tlcVQlYKi_E6YiLde2_ssuODuYFwpAP68N57tIX-IQfqrWbpvWudYSaYPPyZBjeVW28AT3YvMhoEsJDzJoGvbZ_LgscIcDQVMENykdvRSYd/s1024/DALL%C2%B7E%202023-02-08%2019.55.07%20-%20Arrows%20pointing%20between%20database%20tables.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="514" data-original-width="1024" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoUiVFORjpG9fIV3wJth5NnlcGqRicDKkqFGvokIogTv6LvoKV2SqgYfn_FFVEZQcT5VHDeQaggdHJ3tlcVQlYKi_E6YiLde2_ssuODuYFwpAP68N57tIX-IQfqrWbpvWudYSaYPPyZBjeVW28AT3YvMhoEsJDzJoGvbZ_LgscIcDQVMENykdvRSYd/s16000/DALL%C2%B7E%202023-02-08%2019.55.07%20-%20Arrows%20pointing%20between%20database%20tables.png" /></a></div><br /> <br /><span style="font-size: medium;">Managing stateful data is typically one of the tricker parts of a DevOps strategy. The migrations feature of Entity Framework can help immensely with its small, independently executable, PR friendly delta's. Theoretically it can even grant the ability to revert migrations if a deployment goes poorly. If used correctly the technology can be a huge help.<br /><br /></span><div><span style="font-size: medium;">However, in practice, there are a lot of different ways to automate the execution of those deltas. Each approach has pros and cons, and what may work for one project may not for another.<br /><br />In this post I'll show six ways to run EF Database Migrations, explain in which circumstances each would be most helpful, and then show how to set up Active Directory (AD) Authentication and set your connection string correctly when running migrations from a build server.<br /></span><div><h1>1. Migrating via App</h1></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZCTgIISfxrbBAFR9uyNAKTDW5nLtDuBt8I-5lE8A5ihEus9U_jd64JWdctCQ7wUICPfJXCqMylLfBbkYunfgvZnq6Gskh0WLY4uggR885GDHPX4A_DDAaX0ei2VbrJ4XKpQGIrWZuMmCH0aVEvFdcLhswxnrRLwIUXiod--FGJ4IJTGr7PHxLCfyJ/s1213/1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="111" data-original-width="1213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZCTgIISfxrbBAFR9uyNAKTDW5nLtDuBt8I-5lE8A5ihEus9U_jd64JWdctCQ7wUICPfJXCqMylLfBbkYunfgvZnq6Gskh0WLY4uggR885GDHPX4A_DDAaX0ei2VbrJ4XKpQGIrWZuMmCH0aVEvFdcLhswxnrRLwIUXiod--FGJ4IJTGr7PHxLCfyJ/s16000/1.png" /></a></div><br /><div><span face="var(--font-serif)" style="background-color: white; color: #15171a;"><span style="font-size: large;">The question of when to run migrations is ... interesting. The thing is, it's so easy to run the migrations when an app starts for the first time with the </span><span style="font-family: courier; font-size: medium;">DbContext.Database.MigrateAsync() </span><span style="font-size: large;"> </span></span><span face="var(--font-serif)" style="background-color: white; color: #15171a; font-size: large;">command.</span></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhupiEcPRk2ErLcwKBHsIpxuh-5xKoQwteityFMAGYv8T4D0axc0NheUU6ucRSpNSkD90Adt7jbX-jtLAx49pzBvA35SSCuiSJj54EXtt-n4AcIEKLPTbp7eumDRzt8KceKsLxeIcjUwTnsEY4MKaCfA6qQztkxrbJk5X9dVBDvZWCYXJJi6SrAd6OH/s1072/2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="575" data-original-width="1072" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhupiEcPRk2ErLcwKBHsIpxuh-5xKoQwteityFMAGYv8T4D0axc0NheUU6ucRSpNSkD90Adt7jbX-jtLAx49pzBvA35SSCuiSJj54EXtt-n4AcIEKLPTbp7eumDRzt8KceKsLxeIcjUwTnsEY4MKaCfA6qQztkxrbJk5X9dVBDvZWCYXJJi6SrAd6OH/s16000/2.png" /></a><br /><div style="text-align: left;"><span style="background-color: white; color: #15171a; font-size: large;">Running migrations on startup is convenient and a time saver because it piggybacks off of an existing database connection and firewall rule. But it offers some downsides:</span></div></div><div><ol style="text-align: left;"><li><span style="background-color: transparent; font-size: large;">Slows app startup</span></li><li><span style="font-size: large;">Hard to revert</span></li><li><span style="font-size: large;">Timeout problems for long-running migrations</span></li><li><span style="font-size: large;">Violates the principle of least privilege</span></li></ol><span style="font-size: large;">The last point bears explanation. It references the following security best practice:</span></div><div><p style="background-color: white; border-bottom: 0px; border-image: initial; border-left: rgb(218, 242, 253); border-right: 0px; border-top: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(4.8vmin, 32px) 0px 0px; padding: 0px; position: relative; quotes: none; text-align: left; vertical-align: baseline;"><span style="font-size: medium; font-style: italic;"><em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: 700; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">The principle of least privilege</span></em><br />In order to minimize the damage caused by security incidents, a system should be granted the minimum level of access required. </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; text-align: left; vertical-align: baseline;"><span style="font-size: medium;">In other words, don't grant a system any permissions it doesn't need.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; text-align: left; vertical-align: baseline;"><span style="font-size: medium;">For instance, as part of their day-to-day operations apps don't generally need to delete database tables, therefore they should not be granted that permission. However, that's exactly the type of permission an app needs if it is going to run database migrations. Thus, by having an app run database migrations we inadvertently grant attackers an ability to cause more mayhem than is necessary should they gain access to the database through an app.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; text-align: left; vertical-align: baseline;"><span style="font-size: medium;">To put it more concretely: if an app is connecting to a SQL Server, then it's ok to grant the account the app is running under <code style="background: rgb(240, 246, 249); border-radius: 0.25em; border: 1px solid rgb(225, 234, 239); box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0.15em 0.4em; vertical-align: middle;">db_datareader</code> and <code style="background: rgb(240, 246, 249); border-radius: 0.25em; border: 1px solid rgb(225, 234, 239); box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0.15em 0.4em; vertical-align: middle;">db_datawriter</code>, but not <code style="background: rgb(240, 246, 249); border-radius: 0.25em; border: 1px solid rgb(225, 234, 239); box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0.15em 0.4em; vertical-align: middle;">db_ddladmin</code>, and definitely not <code style="background: rgb(240, 246, 249); border-radius: 0.25em; border: 1px solid rgb(225, 234, 239); box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0.15em 0.4em; vertical-align: middle;">db_owner</code>. Doing so will generate a flag in a security center audit.</span></p><br /><h1 style="text-align: left;">Migrating via Build Server</h1></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;">Migrating via app may be good enough if you you're still in dev, intentionally deferring security risks, or are just generally comfortable with the risk. However, the alternative, when you're ready for it, is to have your build server run EF migrations. There are several ways to approach it, each with pros and cons.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNaUUMdoq8GiZfw-V5PjkWu0QERQ6jssDV2IdwcGKt_5zEGLIxD67C0f1t0mbhzEKpC7ewsc6TsXM5FZjAMvEwsPh_nvaO890hxaYzPeHfCtgukA8v9HIKkW95fVJRXkDzE0Z2O7NdATSF2grejQPcMyQRvt-YpqWgAcN3V5zVTbX_rkVFZBejHQY1/s581/3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="581" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNaUUMdoq8GiZfw-V5PjkWu0QERQ6jssDV2IdwcGKt_5zEGLIxD67C0f1t0mbhzEKpC7ewsc6TsXM5FZjAMvEwsPh_nvaO890hxaYzPeHfCtgukA8v9HIKkW95fVJRXkDzE0Z2O7NdATSF2grejQPcMyQRvt-YpqWgAcN3V5zVTbX_rkVFZBejHQY1/s16000/3.png" /></a></div><br /><div><br /></div><h2 style="text-align: left;">2. Command Line Tools</h2><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYQtQStwO-wkWsiJrR3o6QPOn6DAR6n0tnMrhM2T9FUDT76Gxsyg6tRtFHxs5GnGGEjP5o1RX_uvegAV_nd3KqSl_K5Xs8aasS6U3sqaJcB8d26RbM3nDyWuryFwmWX2aFrsnGDp9XNgeuw4D2wNvWK-c0NJwD2Fz28C5DQbwv0bIpEaF9GfCbWxnE/s1213/4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="111" data-original-width="1213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYQtQStwO-wkWsiJrR3o6QPOn6DAR6n0tnMrhM2T9FUDT76Gxsyg6tRtFHxs5GnGGEjP5o1RX_uvegAV_nd3KqSl_K5Xs8aasS6U3sqaJcB8d26RbM3nDyWuryFwmWX2aFrsnGDp9XNgeuw4D2wNvWK-c0NJwD2Fz28C5DQbwv0bIpEaF9GfCbWxnE/s16000/4.png" /></a></div><div><br /></div><span style="font-size: medium;">As a developer you're probably already familiar with the <span style="font-family: courier;">dotnet ef database update</span> command. This option is inconvenient in a DevOps world because it requires source code. Source code is a pain a variety of reasons, not the least of which is you'd need to get the exact version of code for the deployment you're trying to run. The other approaches below are usually preferable.</span></div><h2 style="text-align: left;">3. SQL Scripts</h2><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAQdL_KoHKj2WxQxM3V_RSfpcrKP-fpdYRbGObCD4_Yv0PfnNRi4PMGEnhukokywWTR0AvcHA4nseQp6BVcyUk_CFxm3M-aLU0fGBozlxB_mqxheDwXcFtVJrwiqQr1knFHl0-PJtqA7ilgDxvMA1riVVZOk98WQaIgIcrHkrHtq4oBDtO0UhzSzSJ/s1213/5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="111" data-original-width="1213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAQdL_KoHKj2WxQxM3V_RSfpcrKP-fpdYRbGObCD4_Yv0PfnNRi4PMGEnhukokywWTR0AvcHA4nseQp6BVcyUk_CFxm3M-aLU0fGBozlxB_mqxheDwXcFtVJrwiqQr1knFHl0-PJtqA7ilgDxvMA1riVVZOk98WQaIgIcrHkrHtq4oBDtO0UhzSzSJ/s16000/5.png" /></a></div><br /><div><span style="font-size: medium;">If you have your build server run the command <span style="font-family: courier;">dotnet ef migrations script [oldmigration] [newmigration]</span>, it'll produce a single file that you can save as an artifact in a build pipeline and then execute for each environment. Unlike some other options, this approach produces an asset that can be reviewed by a DBA. However, figuring out which values to use for oldmigration and newmigration would be tricky. Worse, if each environment is at a different version, as often happens when not every PR is deployed through to production, then it could be impossible to produce a single artifact that would work for all environments because those values would be different for every environment. Therefore, I wouldn't generally recommend this approach.</span></div><h2 style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; letter-spacing: -0.01em; line-height: 1.15; margin: 2em 0px 0px; padding: 0px; text-align: left; text-rendering: optimizelegibility; vertical-align: baseline;"><span style="font-size: large;">4. Idempotent SQL Scripts</span></h2><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWNccoRg_b3zyFiiF5S4YYwS14XI7vYHitoZcaOF_09IopZ_cldN568FQd1IOPS828MK0G2iSb5cqnHlsnSKlTn6FSSypm2m7FbJUdxs1K2l6pTs-_ydaZWnjVOSLZVrjytgo3EgMJhuRKQFG4Ex0WOu0TEIWXZmwfm5zOcoUHFu875NKT8C9_fqDn/s1213/4IdempotentSQLScripts.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="111" data-original-width="1213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWNccoRg_b3zyFiiF5S4YYwS14XI7vYHitoZcaOF_09IopZ_cldN568FQd1IOPS828MK0G2iSb5cqnHlsnSKlTn6FSSypm2m7FbJUdxs1K2l6pTs-_ydaZWnjVOSLZVrjytgo3EgMJhuRKQFG4Ex0WOu0TEIWXZmwfm5zOcoUHFu875NKT8C9_fqDn/s16000/4IdempotentSQLScripts.png" /></a></div><div><span style="font-size: medium;"><br /></span></div><div><span style="font-size: medium;">Fortunately, if you pass the <span style="font-family: courier;">--idempotent</span> parameter to the <span style="font-family: courier;">dotnet ef migrations script</span>, then it will generate a script that will only run those migrations that need to run. The resulting file looks like a bunch of if statements like this:</span></div><div><pre class="language-sql" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-sql" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IF</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">NOT</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EXISTS</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SELECT</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">*</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FROM</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>__EFMigrationsHistory<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">WHERE</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>MigrationId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> N<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'20230110143448_Initial'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BEGIN</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CREATE</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">INDEX</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>IX_AbpAuditLogActions_AuditLogId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ON</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>AbpAuditLogActions<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>AuditLogId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">END</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
GO</code></pre></div><span style="font-size: large;"><br /></span></div><div><span style="font-size: medium;">While this option doesn't grant the option to revert a bad deployment, it works great as a published build artifact, can be reviewed by a DBA, and works when each environment is at a different version. However, this approach isn't transactional, and so a failed migration could leave your database in an inconsistent state.</span></div><div><h3 id="5-bundles" style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; letter-spacing: -0.01em; line-height: 1.15; margin: 2em 0px 0px; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;"><span style="font-size: large;">5. Bundles</span></h3></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcomfROE3sTWxOiHre6snM1ICARwRdlbkJJyJKb71OZM_m5srQaR-ZuUytyQD-O1z9Z71jbP0aMVjkD7qfWG5RLpcTXbMonqBIlMVPq23juBg-nEgsAsAJp9nKoyNzEwEdBUrStqT4LrkuNpA6pXpPIafWd9Kh3ANtF3SmAA904EtL3VN4WH5e3IzJ/s1213/5-bundles.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="111" data-original-width="1213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcomfROE3sTWxOiHre6snM1ICARwRdlbkJJyJKb71OZM_m5srQaR-ZuUytyQD-O1z9Z71jbP0aMVjkD7qfWG5RLpcTXbMonqBIlMVPq23juBg-nEgsAsAJp9nKoyNzEwEdBUrStqT4LrkuNpA6pXpPIafWd9Kh3ANtF3SmAA904EtL3VN4WH5e3IzJ/s16000/5-bundles.png" /></a></div><br /><span><div><span style="font-size: medium;">Bundles are great. They solve the problem of applying transactions to your migrations. Simply have your build server run <span style="font-family: courier;">dotnet ef migrations bundle --self-contained -r [linux-x64|win-x64]</span> and you'll have a single file binary (called efbundle.exe by default) that you can publish as an artifact, that runs migrations within a transaction, and that will run only the migrations that need to be applied. You can even specify a specific migration, which allows you to revert migrations. The resulting file looks like this:</span></div><div><pre style="border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: var(--color-wash); font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.5em; margin-bottom: 0px; margin-top: max(3.2vmin, 24px); overflow: auto; padding: 16px 20px; vertical-align: baseline;"><code style="border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: medium;">.\efbundle.exe --help
Entity Framework Core Migrations Bundle 7.0.1
Usage: efbundle [arguments] [options] [[--] <arg>...]]
Arguments:
<MIGRATION> The target migration. If '0', all migrations will be reverted. Defaults to the last migration.
Options:
--connection <CONNECTION> The connection string to the database. Defaults to the one specified in AddDbContext or OnConfiguring.
--version Show version information
-h|--help Show help information
-v|--verbose Show verbose output.
--no-color Don't colorize output.
--prefix-output Prefix output with level.</span></code></pre></div></span></div><div><span><div><span style="font-size: medium;">This option is almost my favorite. The only thing it lacks is the ability to run custom code outside of a migration.</span></div><h1 style="text-align: left;"><span style="font-size: large;">6. Command Line App</span></h1><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijEpnxc9eVApAFUSLYvDwwCUIoEYHeZw5orTQyn6MPBs-135MJ_sWsIFMSWiyS1l5YCTPRbYiW4Ck0am3pLI_dOb4nUywNBDCdM1SXOv9T8DDykPMry8TvsOVTtpRoTGi1jTfKpfAXQAobKSvwmgRGwBJgauXul4DrIjiANbTmKhPfmh2ds4297Ql0/s1213/6-command-line-app.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="111" data-original-width="1213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijEpnxc9eVApAFUSLYvDwwCUIoEYHeZw5orTQyn6MPBs-135MJ_sWsIFMSWiyS1l5YCTPRbYiW4Ck0am3pLI_dOb4nUywNBDCdM1SXOv9T8DDykPMry8TvsOVTtpRoTGi1jTfKpfAXQAobKSvwmgRGwBJgauXul4DrIjiANbTmKhPfmh2ds4297Ql0/s16000/6-command-line-app.png" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: medium;">Once upon a time a project of mine was storing encrypted data in a field in a database. After we were in production (of course) we realized that the encryption algorithm was too strong and was causing performance problems. We needed to decrease the strength of the encryption, but that meant we needed to perform a complex data migration involving a method written in C#.<br /></span><span style="font-size: large;"><br />We would have to run a query to read every row, decrypted it with the old algorithm in C#, re-encrypted it with the new algorithm in C#, and update it back into the database. Should be easy enough for EF Migrations right?</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span face="var(--font-serif)" style="color: #15171a; font-size: medium;">Surprisingly, it turned out that EF migrations can't do that type of work. They're designed to run insert or update SQL statements or create or drop DDL statements, but not retrieve data. Check it out for yourself: see if you can find a single method to retrieve data on </span><span style="background-color: transparent;"><span style="color: #15171a; font-size: medium;"><a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.migrations.migrationbuilder?view=efcore-7.0#methods">MigrationBuilder</a></span></span><span face="var(--font-serif)" style="color: #15171a; font-size: large;">.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="background-color: transparent; color: #15171a; font-size: large;">So, since the algorithm was located in a C# method and since EF Migrations can't access it, we had to run code outside of EF Migrations.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="color: #15171a; font-size: large;">Fortunately, because we were using ASP.Net Boilerplate (the predecessor to the </span><a href="https://abp.io/" style="font-size: large;">ABP Framework</a><span style="color: #15171a; font-size: large;">), it contained a command line app that was running our migrations. That provided the flexibility to run code before or after the migration and thus solve our problem.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: medium;"><span face="var(--font-serif)" style="color: #15171a;">Command line apps (or main apps with a command line option) that run </span><span style="background-color: transparent;"><span style="color: #15171a;"> <span style="font-family: courier;">DbContext.Database.MigrateAsync()</span> </span></span><span face="var(--font-serif)" style="color: #15171a;">from the build server can run in transactions, and when compiled with </span><span style="background-color: transparent;"><span style="color: #15171a;"> <span style="font-family: courier;">--self-contained -r [linux-x64|win-x64]</span></span></span><span face="var(--font-serif)" style="color: #15171a;"> </span><span face="var(--font-serif)" style="color: #15171a;">are nearly single files (you do have to include Microsoft.Data.SqlClient.SNI.dll). The downside is they don't allow reverting migrations. However, they're my personal favorite because they offer the most flexibility when faced with tough migrations. Also, they work particularly well in database-per-tenant multi-tenant scenarios.</span></span></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="color: #15171a; font-size: medium;">If the details of this approach interest you, check out a <a href="https://sirenofshame.visualstudio.com/LeeStore-DbMigrator/">DbMigrator sample project</a> I created that compiles and publishes a command line app in one stage of a multi-stage build pipeline, then executes it in another.</span></p></div><h1 style="text-align: left;">Authentication</h1><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7F1RIF77LMk5oftJKIWQebgPV2fqS-82Wed9eejPbuoZgk7w8_HPlCVmZWAH_-I3Fx4xnny1Tw_Yu-LqIXSefF8aGAM5c2uk2XCbXJjdNZ-O4WAuBHZAgkA2aAGm0GSmhIpQIfkqegAlM8wQeG0H7QN0ptYALu1y0il4eXV2nr_sjFxDywAl3ltIE/s1000/elephant.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="1000" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7F1RIF77LMk5oftJKIWQebgPV2fqS-82Wed9eejPbuoZgk7w8_HPlCVmZWAH_-I3Fx4xnny1Tw_Yu-LqIXSefF8aGAM5c2uk2XCbXJjdNZ-O4WAuBHZAgkA2aAGm0GSmhIpQIfkqegAlM8wQeG0H7QN0ptYALu1y0il4eXV2nr_sjFxDywAl3ltIE/s16000/elephant.png" /></a></div><br /><div><br /></div><div><span style="font-size: medium;">It's time to acknowledge the elephant in the room. If you don't run migrations on app startup, how do you obtain a connection to your database from your build server? Also, assuming you're using SQL Server on Azure and following best practices of only using AD authentication, how do you authenticate in a headless environment with an Active Directory account? </span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZWUj650dzBQu9gZTW-xs0ZhMj-nodz1r_U-qq03Q2x4yre2kunz6a2ELOFmPebveUJp2YYv6_fbp3PMmheQrn8ag3FEDGhlD2iYEZ0_5EJS_AXm_MU-PDEC-4navhGEeSge4cBxpE3yt55IMt3GXUnseytQUV1mQH33P6pybs46I3R_HDG-xGVIY1/s994/authentication-method.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="153" data-original-width="994" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZWUj650dzBQu9gZTW-xs0ZhMj-nodz1r_U-qq03Q2x4yre2kunz6a2ELOFmPebveUJp2YYv6_fbp3PMmheQrn8ag3FEDGhlD2iYEZ0_5EJS_AXm_MU-PDEC-4navhGEeSge4cBxpE3yt55IMt3GXUnseytQUV1mQH33P6pybs46I3R_HDG-xGVIY1/s16000/authentication-method.png" /></a></div><br /><div a="" app="" create="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[],"markups":[["code"]],"sections":[[1,"p",[[0,[],0,"Generally speaking, there are four steps. First, create an App Registration. Second, add the App Registration to your database with "],[0,[0],1,"CREATE USER [{userName}] FROM EXTERNAL PROVIDER;"],[0,[],0," and grant it permissions to run DDL with "],[0,[0],1,"EXEC sp_addrolemember " ddl_admin="" for="" registration:="" secret="" the="" third="" username=""><p><span style="font-size: medium;">Generally speaking, there are four steps. First, create an App Registration. Second, add the App Registration to your database with <code>CREATE USER [{userName}] FROM EXTERNAL PROVIDER;</code> and grant it permissions to run DDL with <code>EXEC sp_addrolemember 'ddl_admin', '{userName}'</code>. Third, create a secret for the app registration:</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0yzdcKTVqORgDgzg4F2nw1T5fBokT2Yzyxz9KHQEiNa5A5n-Dyr2Zx35QFUJmw6DKNik3DEwQBNcNjfPghiVAyO6DlaK3_PMdViuMcLaFKbjSwtge9Z_elkefGYmvCeM3CrO8VeTPkUVTC38Xiv0NjjWcgvpT8iO0Bczu0WceAgPcVvJEj9B_ECFr/s1961/my-db-migrator.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="788" data-original-width="1961" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0yzdcKTVqORgDgzg4F2nw1T5fBokT2Yzyxz9KHQEiNa5A5n-Dyr2Zx35QFUJmw6DKNik3DEwQBNcNjfPghiVAyO6DlaK3_PMdViuMcLaFKbjSwtge9Z_elkefGYmvCeM3CrO8VeTPkUVTC38Xiv0NjjWcgvpT8iO0Bczu0WceAgPcVvJEj9B_ECFr/s16000/my-db-migrator.png" /></a></div><br /><p></p><div a="" access="" agent="" allow="" and="" azure="" bicep="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[],"markups":[],"sections":[[1,"p",[[0,[],0,"Finally, add a firewall rule to allow access to your database from your custom build agent, or if you" hosted="" in="" like="" looks="" re="" resources="" server="" services="" then="" this:="" this="" to="" using="" which=""><p><span style="font-size: medium;">Finally, add a firewall rule to allow access to your database from your custom build agent, or if you're using a Hosted Agent, then "Allow Azure services and resources to access this server", which in Bicep looks like this:</span></p><div allowazureips="" bicep="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[["code",{"code":"resource firewallRule_AzureIps " endipaddress:="" finally="" firewallrules="" language="" like="" markups="" microsoft.sql="" n="" name:="" p="" parent:="" properties:="" sections="" servers="" sql="" startipaddress:="" this:=""><pre class="language-bicep" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-bicep" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span style="font-size: medium;">resource firewallRule_AzureIps 'Microsoft.Sql/servers/firewallRules@2021-11-01' = {
name: 'AllowAzureIps'
parent: sql
properties: {
startIpAddress: '0.0.0.0'
endIpAddress: '0.0.0.0'
}
}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span face="var(--font-serif)" style="color: #15171a; font-size: medium;">Finally, you should be able to use a connection string like this: </span><span style="background-color: transparent;"><span style="color: #15171a; font-family: courier; font-size: medium;">"Server=tcp:{sqlServerName}.database.windows.net,1433; "Database={dbName}; Encrypt=True; User Id={servicePrincipalAppId}; Password={servicePrinicpalSecret}; Authentication='Active Directory Service Principal';"</span></span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span face="var(--font-serif)" style="font-size: large;">And that's all there is. Plunk in your app registration app id and the secret you generated, and you're off to the races.</span></p><div><br /></div></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh85qJUEtzXbkPe3oEv7oKyyFzH-6HlUdT2El4R1anX7452IkPKACQ9VwmaKj3pPNVfQPiK3wb8ZgGrkaygUw-gGSPp9_oFITLmJFaRSxqU4l5DabI11I6tQErdsfTuCa4e6twu0o84p1WFu2sxHVsj2ct2U8bOen4hKSnNciP78joBsrwE6qAmgCwh/s903/stages.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="552" data-original-width="903" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh85qJUEtzXbkPe3oEv7oKyyFzH-6HlUdT2El4R1anX7452IkPKACQ9VwmaKj3pPNVfQPiK3wb8ZgGrkaygUw-gGSPp9_oFITLmJFaRSxqU4l5DabI11I6tQErdsfTuCa4e6twu0o84p1WFu2sxHVsj2ct2U8bOen4hKSnNciP78joBsrwE6qAmgCwh/s16000/stages.png" /></a></div><br /><h1 style="text-align: left;">Summary</h1><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;">In this article I've discussed six ways to run migrations and followed it up with how to accomplish authentication. The following chart will help summarize the pros and cons:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;"><br /></p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPqn9Q-jqU6ITVKME5gTErPZawBNytLlf5mH4FQ2iio0OJecFM2dvbM54mbHtYbu7EQusGXzfYqXj0sP78gsWRfixoet3YO28MrS7_3_Hvr9PO6I5eWV5B-b6xUJE4Ef-2VDNzz-5VIOrbJ5ZATlfeYjcjNJeuvkPETTPwGyb_QRy3wZ11jzAU16Ob/s1506/ef-migration-strategies-chart.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="281" data-original-width="1506" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPqn9Q-jqU6ITVKME5gTErPZawBNytLlf5mH4FQ2iio0OJecFM2dvbM54mbHtYbu7EQusGXzfYqXj0sP78gsWRfixoet3YO28MrS7_3_Hvr9PO6I5eWV5B-b6xUJE4Ef-2VDNzz-5VIOrbJ5ZATlfeYjcjNJeuvkPETTPwGyb_QRy3wZ11jzAU16Ob/s16000/ef-migration-strategies-chart.png" /></a></div><div a="" access="" agent="" allow="" and="" azure="" bicep="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[],"markups":[],"sections":[[1,"p",[[0,[],0,"Finally, add a firewall rule to allow access to your database from your custom build agent, or if you" hosted="" in="" like="" looks="" re="" resources="" server="" services="" then="" this:="" this="" to="" using="" which=""><br /></div><div a="" access="" agent="" allow="" and="" azure="" bicep="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[],"markups":[],"sections":[[1,"p",[[0,[],0,"Finally, add a firewall rule to allow access to your database from your custom build agent, or if you" hosted="" in="" like="" looks="" re="" resources="" server="" services="" then="" this:="" this="" to="" using="" which=""><br /></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-style: inherit; font-variant: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: medium;">As I mentioned my personal favorite is the last, the command line app, because even though it doesn't support an automated revert, it'll run in transactions and it has the flexibility to perform complex migrations outside of EF.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-style: inherit; font-variant: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: medium;">What approaches have you tried? Did I miss anything? Feel free to chime in in the comments or hit me up on <a href="https://twitter.com/lprichar" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">twitter</a> or <a href="https://techhub.social/@lprichar" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">mastodon</a>.</span></p></div></div></div></span></div><a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com2tag:blogger.com,1999:blog-6393051114813114443.post-59379852109612818022023-01-26T23:09:00.000-05:002023-01-26T23:09:01.690-05:00Master ChatGPT Today or Risk Obsolescence Tomorrow<p><span style="background-color: white; color: #15171a; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;"><i><span style="font-size: medium;">As a dev I tried ChatGPT for a week instead of search engines, official docs, and Stack Overflow. Here's what I learned.</span></i></span></p><p><span style="font-size: medium;"> </span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJSvWfsBwc6iQ-v6TxjW2hQTUwvTFwNdYi3Jr-n1edoXUP7i7AIOTwjU3-2eRnHQISbfg18OuIOoGILuNnxYG3iMuvWMSalLJW-hSQEhW2qYPaa6KTYxxqCS02H2faq9R9IRVaMKbDxcE5H8CGX0pHQzUwgr5cFA7QMdUHkxYd354WAOohnrNRmJhx/s1024/DALL%C2%B7E%202023-01-26%2018.53.20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-size: medium;"><img border="0" data-original-height="1024" data-original-width="1024" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJSvWfsBwc6iQ-v6TxjW2hQTUwvTFwNdYi3Jr-n1edoXUP7i7AIOTwjU3-2eRnHQISbfg18OuIOoGILuNnxYG3iMuvWMSalLJW-hSQEhW2qYPaa6KTYxxqCS02H2faq9R9IRVaMKbDxcE5H8CGX0pHQzUwgr5cFA7QMdUHkxYd354WAOohnrNRmJhx/s16000/DALL%C2%B7E%202023-01-26%2018.53.20.png" /></span></a></div><span style="font-size: medium;"><br /></span><p></p><p><span style="background-color: white; color: #15171a; font-family: Georgia, Times, serif;"><span style="font-size: medium;">Since ChatGPT is all the rage I thought I'd try it for couple weeks instead of my existing dev workflow of search engines, Stack Overflow, and reading docs.</span></span></p><p><span style="background-color: white; color: #15171a; font-family: Georgia, Times, serif;"><span style="font-size: medium;"><br /></span></span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9_HgVmHvckqJI33Rhkrm_SubkxZcR_s2Y9pOZ43rLNRnp-irrA5OYzY5_lkNKy-E-pIYViYhSvDPILcjiIMaRAhMjZHfbtRe2RjrMqPnLnfnjMUZEl8akwJrn5EO9YlWwGx_WwpelMUcj0cUQeYpwAV32dbBmJWY5g-SLOkjcZmxmSDniAMjozvLY/s1679/chatgptworkflow1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-size: medium;"><img border="0" data-original-height="1144" data-original-width="1679" height="436" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9_HgVmHvckqJI33Rhkrm_SubkxZcR_s2Y9pOZ43rLNRnp-irrA5OYzY5_lkNKy-E-pIYViYhSvDPILcjiIMaRAhMjZHfbtRe2RjrMqPnLnfnjMUZEl8akwJrn5EO9YlWwGx_WwpelMUcj0cUQeYpwAV32dbBmJWY5g-SLOkjcZmxmSDniAMjozvLY/w640-h436/chatgptworkflow1.png" width="640" /></span></a></div><p style="text-align: left;"><br /><br /><span style="font-size: medium;">Even as it exists today, in beta, it has substantially increased my productivity, and I guarantee it will for you.</span></p><span style="font-size: medium;">In this article I'll break down six areas where ChatGPT can help increase your productivity as a developer. Of course, no tool is perfect and so I'll also list six areas where it fails, so you can avoid those pitfalls.<br /><br />However, there's something I can't easily convey here: its potential. While this article can help you understand some use cases, until you <a href="https://chat.openai.com/">try it</a>, it'll be hard to appreciate what it might be like in a year, two, or five. Large Language Models (LLM's) like ChatGPT will be the de facto way of working very soon, and once you try it, you'll realize that if you aren't on board, you're going to be left behind.<br /><br />And with that bold prediction out of the way I'll get started:</span><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#1 Pro: Find Information, Fast</h1></div><div><span style="font-size: medium;">ChatGPT is amazing at searching through all of humanity's knowledge to find an answer to very specific tech questions in a human readable way. For instance:<br /><br /><ul style="text-align: left;"><li><span style="font-size: medium;"><i>In bicep if I specify a system assigned identity, how can I get back the app id of that identity?</i></span></li><li><i>How do I set the AccessToken in order to connect to an Azure SQL Database using a service principal?</i></li><li><span style="font-size: medium;"><i>In Azure pipelines, what hosted options are there when setting the vmImage setting for a pool?</i></span></li><li><span style="font-size: medium;"><i>How do you convert an object to json using System.Text.Json?</i></span></li><li><span style="font-size: medium;"><i>In Bicep what are the pro's and con's of using an import statement vs using a module?</i></span></li></ul></span><div><span style="font-size: medium;"><br /></span></div><div><span style="font-size: medium;">ChatGPT answered all of the questions above perfectly. For instance:</span><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: max(4.8vmin, 32px) !important; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE7kM8xcikD2hZGmuyNQSyeYG-g3F02BSxZc1EOEAcWiC54jFNf7q1YUvvAVyDWuG6BHgcBjMxVCoSw_EKc2ANS-kG8NaDmFcUYwO4n6j2iNPrAthtIfzg7m8cf43VckIdEAGehsr_fkUe48B8tvkk-G71jAmD5nW5JxrjWmYoZsq8bbsl36dVsnAX/s1632/chatgptsession.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-size: medium;"><img border="0" data-original-height="1632" data-original-width="1406" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE7kM8xcikD2hZGmuyNQSyeYG-g3F02BSxZc1EOEAcWiC54jFNf7q1YUvvAVyDWuG6BHgcBjMxVCoSw_EKc2ANS-kG8NaDmFcUYwO4n6j2iNPrAthtIfzg7m8cf43VckIdEAGehsr_fkUe48B8tvkk-G71jAmD5nW5JxrjWmYoZsq8bbsl36dVsnAX/s16000/chatgptsession.png" /></span></a></div><span style="font-size: medium;"><br /></span><p></p><br /><br /><span style="font-size: medium;">It was able to surface the information I needed faster than I possibly could have with my existing workflow, and it always provided helpful code samples.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#2 Con: Over-Confidence</h1><span style="font-size: medium;">Do you have a friend or family member who answers questions with such conviction and precision that you can't help but believe them? Except that you've eventually learned that they're mostly full of crap? That's ChatGPT (today). It will dazzle you at the precision of the answers and the way it provides code samples that look runnable. Except they aren't. For instance:</span></div><div><span style="font-size: medium;"><br /><ul style="text-align: left;"><li><span style="font-size: medium;"><i>In a windows azure app service when you set the WEBSITE_LOAD_CERTIFICATES app setting, in what folder does the app service store certificates?</i></span></li></ul></span><span style="font-size: medium;"><br />ChatGPT provided a specific folder that looked like exactly what I was looking for. Except it was a complete lie.<br /><br />The same as with my <a href="https://blog.infernored.com/how-to-improve-speed-and-code-quality-with-copilot/">CoPilot suggestions</a>: don't make the mistake of trusting AI results at all. In many cases ChatGPT provides obsolete information, or provides answers that look perfect, except they just aren't valid.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#3 Pro: Conversational Follow-Ups</h1><br /><span style="font-size: medium;">When ChatGPT gives you a crappy answer or code that doesn't run, you can tell it that it was wrong, and why, and it can follow-up for a better answer. For instance:<br /><br /></span></div><div><ul style="text-align: left;"><li><span style="font-size: medium;"><i>There is no `group` parameter on the command `az role assignment create` did you maybe mean `--assignee`?</i></span></li><li><i>After executing that I got role "Directory Readers" doesn't exist. Why might that be?</i></li><li><span style="font-size: large;"><i>Your example didn't work, I got "Missing expression after unary operator '--'.". In your multi-line example do there need to be quotes around each argument?</i></span></li></ul></div><div><span style="font-size: medium;"><br />Each time ChatGPT corrected itself and helped get to a correct answer. For instance, to that last point ChatGPT responded:</span></div><div><span style="font-size: medium;"><br /><ul style="text-align: left;"><li><span style="font-size: medium;"><i>I apologize for the confusion caused. You are correct that the arguments field in the PowerShell@2 task should be a single string, and the arguments field should not span multiple lines…</i></span></li></ul><br />It then provided a valid example that was helpful. ChatGPT can even follow up with abstract concepts like theoretical reasoning about variable naming!</span><figure class="kg-card kg-embed-card" style="align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #15171a; display: flex; flex-direction: column; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: inherit; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline; width: 720px;"><blockquote class="twitter-tweet" style="border-bottom: 0px; border-image: initial; border-left: rgb(218, 242, 253); border-right: 0px; border-top: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 1.5em 0px; padding: 0px 1.6em; quotes: none; vertical-align: baseline;"><p dir="ltr" lang="en" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: medium;">Holy crap is ChatGPT amazing! I've started using it regularly instead of Internet searches. Faster and more accurate. Check out session below. Q1: obscure tech question (not in docs) answered correctly. Q2: follow-up discussion on best practices around naming, argued beautifully! <a href="https://t.co/5MczUPKMW2" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">pic.twitter.com/5MczUPKMW2</a></span></p><span style="font-size: medium;">— Lee (P )?Richardson 🚨 (@lprichar) <a href="https://twitter.com/lprichar/status/1614277675060715521?ref_src=twsrc%5Etfw" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">January 14, 2023</a></span></blockquote></figure><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtJ2q6_ejZbn6vyCIQ47iK6t-B83DDfGJULrspp99eb9bg30oMl2kNry21cN00N1aGqIB5p0DOF1o07COGvtq-cnwB_LAdoCyjxzOri6oD0OT9LHI1xI5L3DzrnGVeB0V7pQAoMq1k7-DcNtmbo_HbIV2Mf_VUmV-LzE3s3ImLxzD9raHFhK1x3AoP/s1182/chatgptsession.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="982" data-original-width="1182" height="532" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtJ2q6_ejZbn6vyCIQ47iK6t-B83DDfGJULrspp99eb9bg30oMl2kNry21cN00N1aGqIB5p0DOF1o07COGvtq-cnwB_LAdoCyjxzOri6oD0OT9LHI1xI5L3DzrnGVeB0V7pQAoMq1k7-DcNtmbo_HbIV2Mf_VUmV-LzE3s3ImLxzD9raHFhK1x3AoP/w640-h532/chatgptsession.jpg" width="640" /></a></div><br /><div>Incredible!</div><div><br /></div><h1 style="text-align: left;">#4 Con: Stale, Unprioritized Sources</h1><br /><span style="font-size: medium;">As the saying goes: bad data in bad data out. In this respect ChatGPT has some serious information shortcomings:</span></div><div><span style="font-size: medium;"><br /></span></div><div><ul style="text-align: left;"><li><span style="font-size: medium;">It fails to take authoritative sources into account (e.g. learn.microsoft.com will contain correct information about Azure content vs random discussion groups)</span></li><li><span style="font-size: large;">It also fails to take age of information into account (newer should be better)</span></li><li><span style="font-size: large;">Its model is over a year old, which is like 10 in dev years, so its information is often stale</span></li></ul></div><div><span style="font-size: medium;"><br />While it tends to be correct more often than not, it's information on how to do Open ID Connect authentication for example was repeatedly and frustratingly out of date and I wasted a ton of time trying to get information out of ChatGPT that it just couldn't provide.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#5 Pro: Help Debugging</h1><br /><span style="font-size: medium;">Chat GPT can help you troubleshoot issues too. For instance:<br /><br /></span></div><div><ul style="text-align: left;"><li><span style="font-size: medium;"><i>The command `.\build.ps1 --target=PublishDevopsArtifacts` appears to be freezing in DevOps. It produces the output "xyz", any idea why?</i></span></li></ul><span style="font-size: medium;"><br />ChatGPT provided three possible reasons and then presented six extremely helpful debugging techniques such as logging to a file and increasing the verbosity level.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#6 Con: ML That Doesn't Learn</h1><br /><span style="font-size: medium;">Sadly, when you point out areas where ChatGPT fails, it doesn't learn from its mistakes in subsequent sessions. Like an amnesiac, it forgets every single session. For someone who likes to give back to the community such as adding answers or clarifications to old questions in Stack Overflow this is a big disappointment.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#7 Pro: Writes Code</h1><br /><span style="font-size: medium;">In many cases ChatGPT can write small functions to allow you to work at a higher level of abstraction. For instance:<br /></span><ul style="text-align: left;"><li><span style="font-size: medium;"><i>Using Azure CLI can you please show me how to 1. create an Active Directory group called "DirectoryReadersGroup"; 2. assign the "Directory Readers" role to the group; then 3. Add a SQL Managed identity called "MyProj-dev-sql" to the group.</i></span></li></ul><span style="font-size: medium;"><br />Or even more complicated tasks like:<br /><br /></span></div><div><ul style="text-align: left;"><li><span style="font-size: medium;"><i>Please provide me a DevOps multi-stage build pipeline. It should run on `windows-latest`. It should trigger on merge to the `main` branch. The first stage should run the command `.\build.ps1 --target=PublishDevopsArtifacts`. The second stage should download build artifacts to a downloads directory, and then it should run the command `.\build.ps1 --target=RunDbMigratorDevOpsArtifact --environment=$environmentName --migratorZip='$(Pipeline.Workspace)/download/Migrator/Migrator.zip'`</i></span></li></ul><span style="font-size: medium;"><br />The results are sometimes immediately usable such as in the first case, or in other cases a guideline that you can follow as you hand write something more complicated, such as in the second case.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#8 Con: Writes Bad Code</h1><br /><span style="font-size: medium;">ChatGPT can't run or compile code at the moment, so it can't verify that any code it provides to you is correct. If a future version had a dev environment it would be substantially more helpful. <br /><br />However, like giving a toddler car keys, perhaps giving AI access to a development environment is a terrible idea. So, I guess just get used to bad AI code for the foreseeable future.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#9 Pro: Translate Paradigms and Languages</h1><br /><span style="font-size: medium;">Sometimes the docs you're reading provide a sample in a different language or paradigm. ChatGPT to the rescue:</span></div><div><span style="font-size: medium;"><br /><ul style="text-align: left;"><li><span style="font-size: medium;"><i>What is the equivalent of "Get-AzureADServicePrincipal -SearchString "Microsoft Graph";" in Azure CLI?</i></span></li></ul><br />Very helpful.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#10 Pro: Simplify laborious tasks</h1><br /><span style="font-size: medium;">Dev work has plenty of tasks that require a lot of typing. For instance:<br /><br /></span></div><div><ul style="text-align: left;"><li><span style="font-size: medium;"><i>Can you please create the C# records (or classes) that will allow me to deserialize the following json: `{ "student": [ { "id":"01", "name": "Tom", "lastname": "Price" }, { "id":"02", "name": "Nick", "lastname": "Thameson" } ] }`</i></span></li></ul><span style="font-size: medium;"><br />Pretty nice. Unfortunately, ChatGPT produced non-idiomatic lowercase C# and records whose properties weren't in the constructor. Nonetheless I was impressed and appreciate the potential.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">#11 Con: Doesn't list Sources</h1><br /><span style="font-size: medium;">As a dev I find it frustrating that ChatGPT answers so confidently but doesn't give any indication how it knows what it knows. The good news is you can kinda get sources if you ask. For instance:<br /><br /></span></div><div><ul style="text-align: left;"><li><span style="font-size: medium;"><i>Please provide the NuGet link to the Azure Active Directory Authentication Library (ADAL) you just mentioned</i></span></li><li><span style="font-size: medium;"><i>Can you please provide a link to the official docs for the Azure SQL database resource in your example?</i></span></li><li><span style="font-size: medium;"><i>Can you please point me to the documentation for that `PowerShell@2` command?</i></span></li></ul><span style="font-size: medium;"><br />With that type of query, you can quickly jump to the most up to date data about what you're attempting to accomplish.</span></div><div><span style="font-size: medium;"><br /></span><h1 style="text-align: left;">Summary</h1><br /><span style="font-size: medium;">After a week of using ChatGPT as my primary source of information, I have learned that it is sometimes, but not always the best first place to go. It is a powerful tool, but it doesn't entirely replace search engines or Stack Overflow just yet.</span></div><div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPpVmRsijex-Tp9QHj-caS_TTmWvVt_Wb1O-D7HhT8JyB9MtPBb44IzUSR8bg6vjok0XHuc51SnrPVJkf53q0WuVUy9ZIrp4ytujhhBNK71rbDJq3sxnTXMqIj5Q79imffjecVz6urVd_62OWUpBTDSnw2d70_KhtObYO2BdySpbjsZpEmQwAH0j9f/s1122/chatgptworkflow2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-size: medium;"><img border="0" data-original-height="839" data-original-width="1122" height="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPpVmRsijex-Tp9QHj-caS_TTmWvVt_Wb1O-D7HhT8JyB9MtPBb44IzUSR8bg6vjok0XHuc51SnrPVJkf53q0WuVUy9ZIrp4ytujhhBNK71rbDJq3sxnTXMqIj5Q79imffjecVz6urVd_62OWUpBTDSnw2d70_KhtObYO2BdySpbjsZpEmQwAH0j9f/w640-h478/chatgptworkflow2.png" width="640" /></span></a></div><span style="font-size: medium;"><br /></span><br /><span style="font-size: medium;">So, will AI eliminate the role of developers? Of course not. Until it can translate what users mean rather than what they say, navigate contradictory requirements, or grasp the bigger picture of a project, then it won't eliminate the role of software developers. Also, LLM's still need to solve some big problems like stale information, identification of authoritative sources, inability to validate code, and honestly just lack of ability to improve.<br /><br />However, as in any industry with big change comes both opportunity and risk. Those individuals that fail to adapt may well get left behind. However, ChatGPT is also a fantastic opportunity to get ahead of the curve, and prudent developers will start mastering this new tool ASAP.<br /><br /><i>Full disclosure: While ChatGPT didn't write this post, I did use it to help flesh out some of the ideas. Also, the header image was created by <a href="https://labs.openai.com/">DALL-E</a>.</i></span></div></div>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-56227896917552925962022-12-13T09:13:00.000-05:002022-12-13T09:13:11.133-05:00MAUI Sounds Amazing. Is It?<p class="article-excerpt" style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.45; margin: 20px 0px 0px; max-width: 720px; padding: 0px; vertical-align: baseline;"><i><span style="font-size: medium;">You're ready for .NET MAUI, but is it ready for you? In this post I share my real-world experience of Microsoft's latest write-once deploy-anywhere solution.</span></i></p><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-Rop1pfR2vWig17_iw5OOmxDzWiZXVv_a1hx06Uiw6CP3DEMGJIv7AvDqScuDqecaELSTjiz-dpns9HDF9Hrx7PwXy9D8Dqxxy2qKwrw_UviyCw3SKrNMiyREv_SEqvv9fw5tgCU2NtRPM732uQ7kqJJ6eogbD0QzPVHHfbYO055CLr2dgizPqxWU/s2000/MauiHero.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1295" data-original-width="2000" height="414" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-Rop1pfR2vWig17_iw5OOmxDzWiZXVv_a1hx06Uiw6CP3DEMGJIv7AvDqScuDqecaELSTjiz-dpns9HDF9Hrx7PwXy9D8Dqxxy2qKwrw_UviyCw3SKrNMiyREv_SEqvv9fw5tgCU2NtRPM732uQ7kqJJ6eogbD0QzPVHHfbYO055CLr2dgizPqxWU/w640-h414/MauiHero.jpg" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Technology vendors have promised write-once, deploy-everywhere solutions to developers since time immemorial. </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">It seems to be an especially hard problem for user interfaces, particularly when accounting for both mobile and desktop platforms.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">For instance, remember JavaFx? It was a Java-based solution that was supposed to deploy to Windows, Mac, Linux, Symbian, and Windows Mobile. I recall seeing that technology fail on virtually every platform in a live demo at a keynote at the JavaOne conference in 2009. Ouch.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Is MAUI any different?</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">For one thing the <a href="https://www.youtube.com/watch?v=Hh279ES_FNQ&list=PLdo4fOcmZ0oUBAdL2NwBpDs32zwGqb9DY&ab_channel=dotnet" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">MAUI demos</a> consistently look strong and the "File->New" experience works well. But I've long since learned to never trust even the best demo or File->New experiences.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Fortunately, over the last few weeks I've had the pleasure of working professionally on a .NET MAUI project and I think I've seen enough to help answer the question of whether .NET MAUI is ready for your next project.</span></p><h1 style="text-align: left;">What is MAUI?</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">First of all, in case you aren't familiar, the .NET Multi-platform App UI (<a href="https://dotnet.microsoft.com/en-us/learn/maui" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">MAUI</a>) is the successor to Xamarin that allows writing one UI that can deploy to Mac, Windows, Android, and IOS. There's no real Linux support yet (unless you count Tizen), but with Microsoft and Canonical being <a href="https://ubuntu.com/blog/install-dotnet-on-ubuntu" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">BFFs</a> I bet it won't be long.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">If MAUI sounds a bit like Electron so far: it isn't. Electron embeds a web browser in your app and provides an identical HTML based UI for desktop clients and a TypeScript or JavaScript back end.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">MAUI is much more. First of all, it natively deploys to both desktop and mobile. Even better, MAUI renders as native controls on each platform. That means your app looks and behaves like a native Mac app on Mac (via AppCatalyst), a native Android app on Android, a native Windows app on Windows, etc.</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtartOcvNtN4RAocJLRdyAr3Ff0L5JlSVGRDA4iJScRD36o-8MiXnCtCxi3tOk0v_Q0k6ot2N-GYfTNd56qE2U6bBkxYxYToKFuegcuOx7I3FE0Ib1QMSN3k3akcIo4pZSSSI61Kiwc-Wf1Dc7lZG7IuUMbnOLjUMOwHO-bFqe6NTzzWbKUJ-P_4Fc/s1024/MauiSample.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="715" data-original-width="1024" height="446" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtartOcvNtN4RAocJLRdyAr3Ff0L5JlSVGRDA4iJScRD36o-8MiXnCtCxi3tOk0v_Q0k6ot2N-GYfTNd56qE2U6bBkxYxYToKFuegcuOx7I3FE0Ib1QMSN3k3akcIo4pZSSSI61Kiwc-Wf1Dc7lZG7IuUMbnOLjUMOwHO-bFqe6NTzzWbKUJ-P_4Fc/w640-h446/MauiSample.png" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">But that's not all. While the native experience is the default option, MAUI also offers a Blazor control whereby you can embed some or all of your app in a web browser. Using that option you'd get an identical experience across iOS, Mac, PC, Android and could even deploy the same app <em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">to the web </em>too! </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Even cooler you can mix and match native controls with the Blazor control for hybrid UI solutions. A single UI and back-end codebase in C#, the best language ever: it sounds too good to be true. </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">What follows are three takeaways from the real world for how it actually stands up.</span></p><h1 style="text-align: left;">Takeaway #1: It Actually Works!</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Before I go any further, let me just say MAUI largely works as promised. Our project had a custom UI deploying to Mac and Windows. We had a dev team with a mix of Windows and Mac developers. Each app looked and felt pretty native with the exact same UI codebase.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Unfortunately, this app didn't need to target Android, iOS, or Web platforms, so I can't confidently comment on how well MAUI works on mobile just yet. But Xamarin has worked fine on mobile in the past, and the File->New experience works well, so I'm confident mobile works just as well as desktop.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">The fact that it works on both PC and Mac though is awesome enough that any subsequent griping feels like <a href="https://en.wiktionary.org/wiki/bikeshedding" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">bikeshedding</a> by comparison. That said I'm going to share some of my initial frustrations anyway, to hopefully help others avoid some of my pain.</span></p><h2 style="text-align: left;">Takeaway #2: Desktop UI Not Fully Baked</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">It's not just how a button looks that makes a native app native: it's also the little things like keyboard shortcuts, animations, and design paradigms. For instance, a material design UI with a big floating plus button just doesn't look right on iOS. MAUI solves some of these problems, but it also misses the mark some, particularly on its newer platforms: Windows and Mac.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">For one thing, I discovered it was <a href="https://stackoverflow.com/questions/73088203/mouse-hover-detection-in-net-maui" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">nearly impossible</a> to get the cursor to change to a hand on mouseover of selectable elements. Giving users a hint about interactive elements is important, but it didn't work on Mac or PC. That's probably because MAUI has its roots in mobile.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Another issue is I found it extremely challenging to fire off an animation when users click a button but before they navigate, particularly when using MVVM architecture (more on that later). These features would be easy or free in a native app (e.g., Win UI), but the desktop platforms just felt less fully baked in the current version (MAUI 7).</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">The solutions undoubtedly involve a custom renderer or <a href="https://github.com/dotnet/maui/wiki/Porting-Custom-Renderers-to-Handlers" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">handler</a>, but the problems weren't quite big enough to warrant that investment just yet. After all, a subsequent version of MAUI will probably fix these issues. But attempting to solve it did give me the opportunity to fiddle with platform specific code, which is a great strength.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">If you aren't familiar the location of the platform specific elements in MAUI is awesome and a huge improvement over Xamarin.</span></p><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUr_mPGlzYudWtwpWAgR04knwCMij4grRq0xXjB4_hHY_rP8pp0IIu8QauYigumqAOlVlixKVOC9Hv_eraB3G4Cc0yQlsjCSKXqyTQZQcyDgX0fYevkHWnI_s_84LjemEhPkWjX2p6W3_vzVEilLZCSYzrQyHTQk6o99hu5slU_PqEuiOemdIAYgq_/s588/SolutionExplorer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="588" data-original-width="554" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUr_mPGlzYudWtwpWAgR04knwCMij4grRq0xXjB4_hHY_rP8pp0IIu8QauYigumqAOlVlixKVOC9Hv_eraB3G4Cc0yQlsjCSKXqyTQZQcyDgX0fYevkHWnI_s_84LjemEhPkWjX2p6W3_vzVEilLZCSYzrQyHTQk6o99hu5slU_PqEuiOemdIAYgq_/w602-h640/SolutionExplorer.png" width="602" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">This folder-based approach to platform specific code is particularly awesome, because Xamarin used to require a separate project for each platform.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">While that approach is helpful, it wasn't enough to solve my problems easily. So, keep in mind if you're looking for a pixel perfect truly native app, it may be a large time investment, and you might even be better off writing your app from scratch for each platform. If you're ok with a good enough UI: MAUI (version 7) is for you.</span></p><h1 style="text-align: left;">Takeaway #3: Quirky</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">In my experience Xamarin was pretty quirky. MAUI is kinda green, so I expected it to be no less so. I wasn't disappointed. Here's a list of 3 quirks to be aware of if you're starting a new project.</span></p><h2 style="text-align: left;">Dependency Injection Helps, and Hurts</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">I love how dependency injection is a first-class citizen in MAUI. Unfortunately, if there are any problems with DI, MAUI falls over on startup without any warning of what went wrong. </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">On Mac it just fails. It looks like this in Visual Studio on Windows:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAtYcKJlqrK9bHUAiBfPy8IgZBfKCbPzIVcR73BlHILPl82LlE0kFeN_KKW092kSZ7XF4UGSqNC5NxJKAEud_ySPMijK2UB6svMm9dANYCVLP2430bZI7yNX54EaNPYkv85WaMoXRL8ovlkfq1MwTpdZLkzbsTO-Nm_wiF26_voOMDaJsobw45PUoU/s741/Error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="726" data-original-width="741" height="628" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAtYcKJlqrK9bHUAiBfPy8IgZBfKCbPzIVcR73BlHILPl82LlE0kFeN_KKW092kSZ7XF4UGSqNC5NxJKAEud_ySPMijK2UB6svMm9dANYCVLP2430bZI7yNX54EaNPYkv85WaMoXRL8ovlkfq1MwTpdZLkzbsTO-Nm_wiF26_voOMDaJsobw45PUoU/w640-h628/Error.png" width="640" /></a></div><br /><p style="border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="background-color: white; color: #15171a; font-family: var(--font-serif); font-size: large;">Along with </span><span style="font-family: courier; font-size: medium;">This program has exited with code 3221226107 (0xc000027b).</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">These can usually be quickly solved with something like:</span></p><pre class=" language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 6px -2px, rgba(0, 0, 0, 0.4) 0px 0px 1px; box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class=" language-csharp" style="background: 0px 0px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; hyphens: none; line-height: 1.5; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// don't forget to register both the page _and_ the ViewModel</span>
builder<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Services<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token generic-method" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AddTransient</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">MainPage</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
builder<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Services<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token generic-method" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AddTransient</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IMainPageViewModel</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">MainPageViewModel</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">In <code style="background: rgb(240, 246, 249); border-radius: 0.25em; border: 1px solid rgb(225, 234, 239); box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0.15em 0.4em; vertical-align: middle;">MauiProgram.cs</code>. That first line is a mild gotcha. It's because MAUI requires registering pages to get DI working, even though they worked fine prior to using DI. Unhelpful errors, but recognizable once you get used to them.</span></p><h2 style="text-align: left;">More Unhelpful Error Messages</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Continuing the trend of unhelpful error messages there's a checkbox on MAUI's file->new project dialog that if you click it will ruin your day. That button accidentally got clicked at some point and it started our project with the solution and the project in the same directory.</span></p><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZU7tpJ8xEzM8XSN5NZ4LdHgziFhpQZvV98xbeP_3BmpLPQLlYB33kb3BeUGyH0ujpX8Y1lLoCa8voHm30pjrLG-_cuYT59PP4L92c6W6A3IAawTaGcTWUVxjU8n2I3zqgaSNdtfa5rTRT0c69mJkW-UDYbNknG71SlQepwc3gQTGnkbhQXOWKOJQ-/s1135/SaveAs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="761" data-original-width="1135" height="430" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZU7tpJ8xEzM8XSN5NZ4LdHgziFhpQZvV98xbeP_3BmpLPQLlYB33kb3BeUGyH0ujpX8Y1lLoCa8voHm30pjrLG-_cuYT59PP4L92c6W6A3IAawTaGcTWUVxjU8n2I3zqgaSNdtfa5rTRT0c69mJkW-UDYbNknG71SlQepwc3gQTGnkbhQXOWKOJQ-/w640-h430/SaveAs.png" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: 6vmin 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Placing the solution and the project in the same directory worked out fine at first, but when we later went to add a library, we temporarily put that library in a child directory until the team got to a good stopping point for the big move refactor of the UI project. </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Except it failed. We got tons of unhelpful errors like this:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"><br /></span></p><span style="font-family: courier; font-size: large;">IDE1100 Error reading content of source file 'C:\dev\Lprichar.MyMauiApp\Lprichar.MyClassLibrary\obj\Debug\net7.0\Lprichar.MyClassLibrary.AssemblyInfo.cs' -- 'Could not find file 'C:\dev\Lprichar.MyMauiApp\Lprichar.MyClassLibrary\obj\Debug\net7.0\Lprichar.MyClassLibrary.AssemblyInfo.cs'.'.</span><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Eventually, we figured out the problem and sucked it up and immediately moved the MAUI and class library projects into sibling folders.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">You probably won't run into this exact problem but just remember MAUI is a new platform with some sharp and painful edge cases, so reserve plenty of time to solve inexplicable and unhelpfully worded errors.</span></p><h2 style="text-align: left;"><span style="font-size: large;">CommunityToolkit.Mvvm + Testing</span></h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">If your project will have any complexity, I strongly recommend the MVVM (Model View ViewModel) pattern and the <a href="https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/introduction" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">MVVM Community Toolkit</a> (big thank you to <a href="https://twitter.com/stevemaier3" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">Steve Maier</a> for introducing the Community Toolkit to our project and putting up with my initial grumbling about it 🙃). </span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">Without getting into too much detail, MVVM will allow a cleaner architecture and a better separation of responsibilities, and the MVVM Community Toolkit will significantly simplify the work required to accomplish that cleaner architecture.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">However, if you have a both a Maui App and a Library project, and you want to test elements from both in a unit test project then you're liable to end up with a ton of warnings like this:</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;"><br /></span></p><span style="font-size: medium;">Warning CS0436 The type 'ColorAnimationExtensions_Button' in 'CommunityToolkit.Maui.SourceGenerators\CommunityToolkit.Maui.SourceGenerators.Generators.TextColorToGenerator\ButtonTextColorTo.g.shared.cs' conflicts with the imported type 'ColorAnimationExtensions_Button' in 'Lee.MyMauiApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'CommunityToolkit.Maui.SourceGenerators\CommunityToolkit.Maui.SourceGenerators.Generators.TextColorToGenerator\ButtonTextColorTo.g.shared.cs'.</span><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">If that happens, I'd recommend taking the approach recommended by <a href="https://twitter.com/edsnider" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;">Ed Snider</a> in his book <a href="https://www.amazon.com/Mastering-Xamarin-Forms-architecture-techniques-multi-platform-ebook/dp/B082Y9G9SJ/ref=sr_1_1?crid=XRYNWMLB8DXG&keywords=mastering+xamarin+forms&qid=1670697174&sprefix=mastering+xamarin+forms%2Caps%2C64&sr=8-1" style="background-color: transparent; border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; word-break: break-word;"><em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Mastering Xamarin.Forms</em></a>, and move the ViewModels into the library. Any UI or platform specific code can be implemented in the UI project and dependency injected by interface into the library. Then you can remove the reference to the UI project entirely from the test project. That removes warnings, simplifies the architecture, and keeps business logic separate from user interface code.</span></p><h1 style="text-align: left;">Summary</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">So, is .NET MAUI ready for the real world on your next project? If you need a cross-platform UI solution that can run on any or all of Android, iOS, Mac, Windows, and potentially the Web, and you're prepared for a bit of a bumpy ride then I would say absolutely yes.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin: max(3.2vmin, 24px) 0px 0px; padding: 0px; vertical-align: baseline;"><span style="font-size: large;">I'd keep a sharp eye on the next release, but I can confidently say that the fundamentals of MAUI are strong, and it actually solves an extremely hard problem. Once you get used to the quirks, you'll appreciate that it does what it promises. Ultimately, it's ready for you, if you're ready for it.</span></p>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com7tag:blogger.com,1999:blog-6393051114813114443.post-48382412617366701982022-08-09T17:04:00.003-05:002022-08-09T17:05:51.901-05:005 Ways to Supercharge Your Productivity with GitHub Copilot<p><span face="-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif" style="background-color: white; color: #15171a; font-size: 20px;"><i>The new AI coding assistant from GitHub can help increase your speed, quality, and efficiency. Here's 5 tips to get you started.</i></span></p><p><span face="-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif" style="background-color: white; color: #15171a; font-size: 20px;"></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL047bk8Gwf8el6MI0sUlMiUw4j0fCJet9ctHAwHr_448HOXPWoi9Afe2oAcJW_8lxqflVZ3QrTCgPrbysLu0hbHZgjn4jTZyyNrfzRL-lcMWprEVW2Rmm3bfpeEbYvUxfaxIcCj6p2RRj_4AGQNzNIi7Q1w_WjJ3rVjUVGhvSpeaHMMvJBkSNm00t/s2361/CopilotHero.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2361" data-original-width="2000" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL047bk8Gwf8el6MI0sUlMiUw4j0fCJet9ctHAwHr_448HOXPWoi9Afe2oAcJW_8lxqflVZ3QrTCgPrbysLu0hbHZgjn4jTZyyNrfzRL-lcMWprEVW2Rmm3bfpeEbYvUxfaxIcCj6p2RRj_4AGQNzNIi7Q1w_WjJ3rVjUVGhvSpeaHMMvJBkSNm00t/w542-h640/CopilotHero.png" width="542" /></a></div><br /><p></p><br />Copilot recently saved my bacon. I had a tight three-week deadline and a lot of code to write. <a href="https://github.com/features/copilot/">Copilot</a>, the new AI coding assistant from GitHub, allowed me to meet my deadline with enhanced quality and at a rate substantially faster than I normally travel. It felt like being pulled along a moving walkway at an airport.<br /><br />But while I highly recommend Copilot, it's still just a tool, and one that works better in some situations than others. Below is what I learned about it on my recent project organized as five tips to help you learn Copilot fast and increase your speed, quality, and efficiency.<br /><br />Let's get right to where Copilot it fails before covering where it shines.<div><br /></div><div><h1 style="text-align: left;">🐛 Write More Bugs, Faster</h1><br />I imagine everyone knows copy-paste bugs. Someone writes a section of code, later someone copies and pastes that section wholesale into another part of the application. However, some part of that section required a modification for the new context, or maybe the original had a bug in it that was just duplicated. The result is at least one subtle bug that looks reasonable at first glance.<br /><br />Copilot elevates copy-paste bugs to a whole new level. Consider this:<div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPYCt4x3w5cwmtUk05dU-_jzx1bjUt6pJ10Fb6D50Kz8z8r1UCI_tWfSKd4iVMg0R9rRicWmOTE5zArkqVVc_I5V_f7x9ZQkPdgjbBB6E2YT_zUGRvlkIWrxvCmc3JnerhuSx7UdkuZmBMYp2q7-g2NtWgw3PvEyGYL_Z_eTUgWnxAi7dNhD_F3Zav/s930/CopilotFail.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="306" data-original-width="930" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPYCt4x3w5cwmtUk05dU-_jzx1bjUt6pJ10Fb6D50Kz8z8r1UCI_tWfSKd4iVMg0R9rRicWmOTE5zArkqVVc_I5V_f7x9ZQkPdgjbBB6E2YT_zUGRvlkIWrxvCmc3JnerhuSx7UdkuZmBMYp2q7-g2NtWgw3PvEyGYL_Z_eTUgWnxAi7dNhD_F3Zav/w640-h210/CopilotFail.png" width="640" /></a></div><p></p>I wrote this shortly after starting with Copilot. I was so impressed that after I converted just one hex string to binary in comments Copilot figured out what I was doing for the second and subsequent lines and auto suggested the binary conversions.<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgji_3uW-ejybbdBTJyoXTK6D91dKeTWq52zGq0XywzhojSjwIe-L8iGemFCUbNUTpSgeMKh2lkzkvtM5W8EiZPDE-DJH5AlbczevHyUyGd594-fbffcK-j5jLsjpSFg9YdzEmByf2IPu7EiYYKihfkk_3LaR_SV1vP7rtDnUIAE7ckZUrUc7u7pjJ6/s1331/CopilotTwitter.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="746" data-original-width="1331" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgji_3uW-ejybbdBTJyoXTK6D91dKeTWq52zGq0XywzhojSjwIe-L8iGemFCUbNUTpSgeMKh2lkzkvtM5W8EiZPDE-DJH5AlbczevHyUyGd594-fbffcK-j5jLsjpSFg9YdzEmByf2IPu7EiYYKihfkk_3LaR_SV1vP7rtDnUIAE7ckZUrUc7u7pjJ6/w640-h358/CopilotTwitter.png" width="640" /></a></div><br /><br /><br />The 2nd and 3rd lines were correct, and the 4th looked right, and all too quickly I developed a false sense of security. I stopped double checking.<br /><br />BIG MISTAKE. New AI Enhanced Bug (nearly) introduced.</div><div><h3 style="text-align: left;">ProTip #1 - Double Check All Output</h3><div><br /></div>Copilot is not infallible, and everything it proposes must be double-checked. Like fertilizer on a garden, it can supercharge weeds as well as vegetables and flowers. So be careful, and never trust what it auto-suggests.</div><div><br /></div><div><h1 style="text-align: left;">🪤 The Distraction Trap</h1><br />I find there are different phases of the software development process that require different mindsets. For instance, both testing and self-reviewing PR's requires a dispassionate, critical mindset. Working new problems requires creativity. And following existing patterns to build out CRUD functionality allows you turn up the jams, turn down the creativity, and give your frontal cortex a break. Copilot works amazingly in that latter modality. <br /><br />But I've identified two other development modes where Copilot is extremely unhelpful. The first is when you're establishing a new pattern in your code, such as introducing dependency injection when you didn't start with it from day one. The second is when you need to solve a hard problem specific to your domain for which there are necessarily no existing patterns to follow.<br /><br />In both of these cases Copilot will attempt to throw code up at you as you type. It's so very tempting to want to look at that code and see if just maybe Copilot has some magic that can short circuit you having to think.<br /><br />IT'S A TRAP! That flash of code leads to distraction and losing the thread of thought right when you need thought continuity the most.</div><div><br /></div><div><h3 style="text-align: left;">ProTip #2 - Turn it Off</h3><div><br /></div>When you know you're doing something unique, turn off Copilot or just hit the escape key as fast as you can to force yourself to do the hard thinking that only an actively engaged, fully focused human mind can ever accomplish.</div><div><br /></div><div><h1 style="text-align: left;">🤘 Rocking Boilerplate</h1><br />In my experience software development requires quite a bit of boilerplate coding. Copilot rocks boilerplate coding. When you're just repeating a pattern, Copilot will accelerate you up to dizzying speeds. Just remember that speed doesn't always happen on day one. It takes a few days until Copilot learns your codebase and coding style.<br /><br />Once you're up to speed though take the extra time it gives you back to fit in some refactoring time to implement the Boy Scout rule and continuously leave the codebase cleaner than you found it.<h3 style="text-align: left;">ProTip #3 - Give It Time</h3><div>Give Copilot a few days to warm up. Then enjoy superspeed, but use some of the time saved to improve, not just expand, your codebase.</div><h1 style="text-align: left;">🏆 Get Specific Solutions, Fast</h1><div>At some point in this three week sprint I spent hours trying to convert a UTC date into the local time zone in Python. Exasperated and getting nowhere fast, I eventually recalled that Copilot would read the name of a method and auto-suggest an implementation. Maybe it could kind of search though all of GitHub for me and find what I needed? I wrote this:</div><div style="background-color: white; font-family: Consolas, "Courier New", monospace; line-height: 19px; white-space: pre;"><span style="color: blue;"><span style="font-size: 14px;">
</span><span style="font-size: medium;">def</span></span><span style="font-size: medium;"> <span style="color: #795e26;">convert_utc_to_local</span>(<span style="color: #001080;">utc_dt</span>: <span style="color: #267f99;">datetime</span>) -> <span style="color: #267f99;">datetime</span>:</span></div><div><br /></div>And as if by magic Copilot instantly found the alternate universe in which there existed an answer:<p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-size: 2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEits9drtWkpgKb27ifJtf6we2qiB0IvuYPgr-dLe7oJOxjZdf3jMDkNimz0U55bV6Vyb1k29pz0PiXCyy5R06KfyVRJeyLPp1x70iLBg6m7f4H6EV1WngQ0VHYawAk4PuC6PDJdtXIUZCC1AygOjM5ypv1LW7X2XJUGePafv3yAsvNc6JXVIx3VjMY_/s1112/CopilotSolution.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="121" data-original-width="1112" height="70" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEits9drtWkpgKb27ifJtf6we2qiB0IvuYPgr-dLe7oJOxjZdf3jMDkNimz0U55bV6Vyb1k29pz0PiXCyy5R06KfyVRJeyLPp1x70iLBg6m7f4H6EV1WngQ0VHYawAk4PuC6PDJdtXIUZCC1AygOjM5ypv1LW7X2XJUGePafv3yAsvNc6JXVIx3VjMY_/w640-h70/CopilotSolution.png" width="640" /></a></div><p></p>It worked beautifully and might have saved me hours if I'd only thought to do that up front.</div><div><br /></div><div><h3 style="text-align: left;">ProTip #4 - Write Small Well Named Functions</h3><div><br /></div>If you have a very specific problem to solve that has undoubtedly been solved before, write up a small well named function (which hopefully you're doing already anyway) and delegate that job to Copilot, and save yourself hours of frustration.<h1 style="text-align: left;">➿ Improve Consistency</h1><br />Occasionally I discovered that Copilot would provide a suggestion that didn't match what I was expecting. It was tempting to accept that answer if it's good enough, but I also found it's extremely helpful to ask why.<br /><br />Asking why Copilot suggests code different than expected often produces the answer that you aren't consistently following a pattern in your codebase. That's because Copilot looks at both what you just typed and also at all of the code written thus far in the solution, and if your new code deviates from the prior pattern the autosuggestion will also deviate.<br /><br />Sometimes that's ok but being alert to it can actually help you improve consistency within your codebase.<h3 style="text-align: left;">ProTip #5 - Use Copilot as a Heuristic</h3><div>If Copilot suggests something you don't expect, use that as a heuristic to improve consistency.</div><div><br /></div><h1 style="text-align: left;">Conclusion</h1><br /></div><div>In my mind Copilot is worth every penny. It allows developers to write faster boilerplate, find solutions to specific problems faster, and be more consistent. It comes with drawbacks too, but if you know the drawbacks and prepare for them, then overall it will boost your productivity to new heights. I would be shocked if AI assisted coding isn't the expected mode of working within the next few years.<br /><br />So what do you think of AI enhanced coding? Please share in the comments your thoughts along with any tips and tricks you've discovered.<p style="background-color: white; border: 0px; box-sizing: inherit; color: #15171a; font-family: var(--font-serif); font-size: 2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; grid-column: main-start / main-end; line-height: 1.6em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5rem !important; margin: 1.5rem 0px 0px; padding: 0px; vertical-align: baseline;"><span face="var(--font-serif)" style="font-size: 2rem;"><br /></span></p></div></div>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com1tag:blogger.com,1999:blog-6393051114813114443.post-74398358748224461452022-01-07T13:51:00.005-05:002022-01-10T13:58:03.526-05:006 Ways I'm Improving Mental Health in 2022<p><i>I sincerely hope you'll find some inspiration here. I'm temporarily veering away from my traditional topics of .NET, OSS, and Maker content. I share a personal story related to mental health. I want to thank <a href="https://twitter.com/sinclairinat0r">Jeremy Sinclair</a> for breaking the ice on this topic for me.</i></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiB-PCR4_cUw7FPauEAMkYxBOqoQuQGxO7oBbA-_Ud8jFaonFVv8Ko5dq3MKKdZ26F_MoKcXEMJLSoQhzUy8Tt7lX7pMM980UfDuL8n-aI7Ue0wc5phsnFZRhIrRLSHttSdFhjRRuTzMJGTIH9Ty3OnDuJpQSckU_g0vU_i09jkqM4I2Vio0I3NGsZq=s4806" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3124" data-original-width="4806" height="416" src="https://blogger.googleusercontent.com/img/a/AVvXsEiB-PCR4_cUw7FPauEAMkYxBOqoQuQGxO7oBbA-_Ud8jFaonFVv8Ko5dq3MKKdZ26F_MoKcXEMJLSoQhzUy8Tt7lX7pMM980UfDuL8n-aI7Ue0wc5phsnFZRhIrRLSHttSdFhjRRuTzMJGTIH9Ty3OnDuJpQSckU_g0vU_i09jkqM4I2Vio0I3NGsZq=w640-h416" width="640" /></a></div><br /><i><br /></i><p></p><p>I'm ready for a better 2022.</p><p>It wouldn't take much. 2021 pretty much sucked, right? Even for introverts like me who were gifted the best excuse ever to just stay home and code.</p><p>I mean, it's possible 2021 rocked for one or two people (per billion). Like remember that time your tech startup went public, you effectively won the lottery, and you bought a Maserati? You then quit your job only to find that true happiness was inside you all along and so you went back to work part time for the pure pleasure of it? Doesn't ring a bell? Oh yea, that was actually my roommate from college I recently met up with. I appreciate and am genuinely happy for him, but I suspect even he's had a tough year.</p><p>The point is 2022 is ripe for improvement. And tops on my areas for improvement: health. Here are some areas in which I hope to improve.</p><h2 style="text-align: left;">1. Be More Compassionate</h2><div>When Jeremy Sinclair spent a sizable segment of his <a href="https://youtu.be/M6uhtfijANc">Keynote at NoVA Code Camp</a> last year on mental health, I was amazed at his bravery. I've been struggling with why that is. I suppose as an industry, and maybe as a culture generally, we tuck this topic away and don't discuss it because it's hard and it's personal. But when we remain silent, we lose the opportunity to learn from each other.</div><div><br /></div><div>Following Jeremy's lead, I'm going to try to be brave too. Hopefully you can find something useful here. Please stop skimming and either compassionately read or skip this paragraph. You see this has been the hardest year I've had in a long time. My younger brother died this year. Please know that I share this out of love for his memory and my sincere hope that my honesty will help others. Sharing will at least help me. See, my brother struggled with Schizophrenia. He was the kindest, sweetest, quirkiest, most honest, trusting, most genuine, most loving person. But he struggled with these inner demons that no one should ever have to face. Once he discovered the right medication, and the right professional help, and after a lot of hard work, he was virtually indistinguishable from any other quirky person you've ever known. With the help of family and friends he lifted himself out of a mental health facility. By 2021 he had accomplished his three main life goals: he had a driver's license and a car, a condo where he lived on his own, and a job delivering food. I was so proud of him. Long story short COVID disrupted the medication he needed, and things went south.</div><div><br /></div><div>My brother's situation may seem foreign, but I bet you know folks that are a little different like he was. There were many people that picked on or took advantage of my brother, especially in the work world because he didn't fit the mold. That sucks. I can't change others but going into 2022 I'm going to try harder to be compassionate to those around me.</div><div><br /></div><div>Schizophrenia is one thing, but mental health challenges come in all shapes and sizes, and many aren't so visible. Jeremy described his challenges with ADHD. I know several folks that struggle with depression, some with addiction, and others that struggle with Asperger's.</div><div><br /></div><div>Personally, I struggle with anxiety. I've had two anxiety attacks in my life. I'm also currently struggling with mourning. I haven't blogged or done a video in 6 months. I'll get back to blogging regularly when I'm ready. But I'm striving to be more compassionate to myself too in the coming year.</div><div><br /></div><h2 style="text-align: left;">2. Improve Physical Health</h2><div>I firmly believe that there is a strong correlation between physical and mental health. For me there is anyway.</div><div><br /></div><div>For instance, today crowds don't bother me at all, but when I was younger, I couldn't stand them. Large groups of people caused such anxiety that I routinely had to literally run away. When someone asked recently, I estimated it improved about 10 years ago.</div><div><br /></div><div>I don't believe it's a coincidence that almost exactly 10 years ago in August of 2012 I got a Garmin Watch, and it <a href="http://www.leerichardson.com/2015/11/garmin-vs-microsoft-band-2-lifechanging.html">changed my life</a>. I started running daily in order to get 10,000 steps. My physical health improved, and my mental health along with it. My doctor confirmed that running helps with anxiety and indeed my overall anxiety decreased. I feel that this one daily habit has additionally improved my mental acuity, reduced stress, improved my sleep, and allowed me to manage my mental health challenges without medication.</div><div><br /></div><div>So, in 2022 I will continue to prioritize physical health because it improves my mental health. If that sounds good to you, I highly recommend a step counter. I particularly love my Apple Watch because it tracks calories not steps, and thus accounts for swimming and biking activities, and the achievements make it fun.</div><h2 style="text-align: left;">3. Track Mental Health</h2><div>Ask any software developer and the first step of improving performance is collecting data. There are many folks I work with and respect that might collect mental health data with pen and paper. However, for the last month I've been using the <a href="https://daylio.net/">daylio</a> app. It's produced a number of personalized insights for both preventative and reactive triggers for anxiety and mental wellbeing generally. For instance, I've started my day with meditation (with the <a href="https://insighttimer.com/">Insight Timer</a> app) for the last two weeks and I've discovered it improves my mood and reduces anxiety. Also music, comedy, hobbies, me time, cleaning (seriously), and getting to sleep early seem to make a big difference. I will continue tracking my moods in 2022 to gain additional insights to improve my mental health.</div><div><br /></div><h2 style="text-align: left;">4. Manage Psychic Weight</h2><div>I receive an enormous amount of anxiety from unfinished, and especially unenumerated tasks. I believe Scott Hanselman refers to this as psychic weight.</div><div><br /></div><div><blockquote>I was really stressed out ten years ago. I felt that familiar pressure between my eyes and felt like all the things that remained undone were pressing on me. I called it "<a href="https://www.hanselman.com/blog/psychic-weight-dealing-with-the-things-that-press-on-your-mind">psychic weight</a>." I have since then collected my <a href="https://www.hanselman.com/blog/scott-hanselmans-complete-list-of-productivity-tips">Productivity Tips</a> and written extensively on the topic of productivity and getting things done. I'm going to continue to remind YOU that <a href="https://www.hanselman.com/blog/selfcare-matters-pay-yourself-first">Self-Care Matters</a> in between my technical and coding topics.</blockquote></div><div><br /></div><div>I'll never be as productive as Scott, but I recently discovered <a href="https://todo.microsoft.com/tasks/">Microsoft ToDo</a>. I feel like I've tried just about all the other task management systems but solving daily task enumeration has helped me reduce stress immensely. The one feature I love most about it is the "My Day" list. This feature is a list that clears out every single day to help force you to reconstruct what's important to you on any given day. It forces good daily habits and doesn't hit you over the head with uncompleted tasks. Using this software I start each day with a fresh perspective and less psychic weight. I will keep this up daily in 2022, and that will make it a much better year for me.</div><div><br /></div><h2 style="text-align: left;">5. Consume Carefully</h2><div>Thanks to daylio I've discovered that the content I consume affects my mental health: comedy makes me happier, music inspires me, news results in fear and sadness, and politics make me angry. I don't want to be angry. So for 2022 I've removed political podcasts from my feed and reduced news consumption.</div><div><br /></div><div>I'm also trying to alternate reading inspiring non-fiction books that can improve my mental health with pleasurable fiction just for fun. If this sounds like something that might appeal to you, I would like to suggest some of the following books in which I have found inspiration:</div><div><div><ul style="text-align: left;"><li>Speaker for the Dead (Orsen Scott Card)</li><li>So You Want to Talk About Race (Ijeoma Oluo)</li><li>Celestine Prophecy (James Redfield)</li><li>How to Win Friends and Influence People (Dale Carnegie)</li><li>7 Habits of Highly Effective People (Sean Covey)</li><li>10% Happier (Dan Harris)</li><li>Altered Traits Science Reveals How Meditation Changes Your Mind, Brain and Body (Daniel Goleman, Richard Davidson)</li><li>The Power of Positive Thinking (Dr. Norman Vincent Peale)</li><li>How to Fail at Almost Everything and Still Win Big (Scott Adams)</li><li>The Road Less Traveled (M. Scott Peck M.D.)</li><li>Quiet: The Power of Introverts in a World That Can't Stop Talking (Susan Cain)</li><li>Zen and the Art of Motorcycle Maintenance (Robert M Pirsig)</li><li>The Paradox of Choice (Barry Schwartz)</li><li>The 4 Hour Workweek (Timothy Ferriss)</li></ul></div><div><br /></div><div>Please post additional inspirational reading suggestions for me and readers in the comments or message me on Twitter with them and I'll RT.</div></div><div><br /></div><h2 style="text-align: left;">6. Value Creativity</h2><div><div>Consuming (e.g. books, video games, podcasts, movies) can be helpful or a nice distraction, but for me they rarely bring joy the way creating does. I find my life is happier when I spend time creating things or solving problems. For me that includes coding, natural language writing (e.g. this post), woodworking, 3D Printing, electronics, cooking, playing guitar, and smoking meats. I don't know if it's technically creativity but also on that list is spending time in nature and quality time with family and close friends. These are the types of creative, non-consumption activities that produce joy for me that I will do more of in the coming year.</div><div><br /></div><h2 style="text-align: left;">Summary</h2><div><br /></div><div>2021 was hard, but 2022 will be better. What activities will you do more of to improve mental health? Is compassion a part of your New Year's resolutions? What will you do more of in 2022 to reduce stress and feel more balanced? Please share.</div><div><br /></div><div>If this post was helpful in any way, please say so on Twitter or in the comments. I've branched out by doing a personal, non-tech post and would be happy to do more if it struck a chord.</div></div><div><br /></div><div><br /></div><p></p>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-41353116558503408002021-07-01T16:13:00.008-05:002021-07-02T12:31:19.642-05:00Stop Saving to Disk with C# Asynchronous Streams<p><span style="background-color: white; color: #738a94; font-family: Georgia, serif; font-size: 23px;">My journey to solve a hard performance problem with a newish language feature: asynchronous streams. Explains what asynchrnous streams are, and shows a real world problem they can solve.</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ6EVQTWc4kU-C2QcMQjgF6It3lBnZYsF19bx4rW-cDVKJiQajmSMS_dSYTWNJOJx1eFG03VSzy5FiZaYq9wqMsoUV2mkaSUm4ldE9olKmZWeAOtwKostb2ht8SLkiQ3qdJhWLrZZ2Ydw/s868/Wireshark4.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="520" data-original-width="868" height="383" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ6EVQTWc4kU-C2QcMQjgF6It3lBnZYsF19bx4rW-cDVKJiQajmSMS_dSYTWNJOJx1eFG03VSzy5FiZaYq9wqMsoUV2mkaSUm4ldE9olKmZWeAOtwKostb2ht8SLkiQ3qdJhWLrZZ2Ydw/w640-h383/Wireshark4.gif" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Recently I faced a fun performance challenge and ended up <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">reducing a 3 hour job to 1.5 hours</em>, thanks to an awesome recent C# language enhancement: <a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/generate-consume-asynchronous-stream">Asynchronous Streams</a>. Whoa, so 2019 I hear you say. I'm sure you've read some headlines and skimmed some blog posts, but have you really grokked this technology and what it means? I hadn't. In this post I'll quickly explain what asynchronous streams are, describe what real world problem they helped me solve, and show some common pitfalls just in case you're in a similar situation.</p><h2 style="text-align: left;">What Are They?</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In short asynchronous streams are a language feature introduced in C# 8 that allow you to process a stream of data ... asynchronously. Right, obviously. An example will help.</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">IAsyncEnumerable<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> numbers <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> Producer<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetNumbersAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">foreach</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> number <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">in</span> numbers<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>number <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">10</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">break</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Above we're retrieving a set of numbers of type IAsyncEnumerable (an interface introduced in C# 8) and iterating over the first 10 of them with <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">await foreach</code> (a new language feature also introduced in C# 8). </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">What's fancy here is that each iteration of the loop has a hidden await that creates a continuation and returns control to the caller, until such a time as the data provider has a new number to provide. That returning of control to the caller is generally what await, introduced in C# 5 does. It frees the host up to refresh the UI of mobile apps or perhaps respond to HTTP requests. What's new with IAsyncEnumerable is that await is a first class citizen now when it comes to enumerables.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">You can see how it works if you open up the code from the prior example in <a href="https://www.microsoft.com/en-us/p/ilspy/9mxfbkfvsq13?activetab=pivot:overviewtab" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ILSpy</a>. If you decompile and view it as a release prior to C# 8 (ILSpy is <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">awesome </em>that way). </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5x3WPhHItQlZpQqyYvxsLiQki054_3zGqX9pqHNTcR1j5Pk-OaIbT8kNkwaVOQv-Vi0FtqIZ_IU-6TgB8410PgnkkiR1k_L8M1qOtxyI8H8qPpEd9PK9VfuqRhnfmpbIz9TDLhH_ZGwY/s1880/ILSpy.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1102" data-original-width="1880" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5x3WPhHItQlZpQqyYvxsLiQki054_3zGqX9pqHNTcR1j5Pk-OaIbT8kNkwaVOQv-Vi0FtqIZ_IU-6TgB8410PgnkkiR1k_L8M1qOtxyI8H8qPpEd9PK9VfuqRhnfmpbIz9TDLhH_ZGwY/w640-h376/ILSpy.jpg" width="640" /></a></div><span style="background-color: white; color: #313b3f; font-family: Georgia, serif; font-size: 20px;"><div><span style="background-color: white; color: #313b3f; font-family: Georgia, serif; font-size: 20px;"><br /></span></div>Then you end up with this:</span><div><span style="color: #313b3f; font-family: Georgia, serif;"><span style="font-size: 20px;"><br /></span></span></div><div><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">IAsyncEnumerable<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> numbers <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> Producer<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetNumbersAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
IAsyncEnumerator<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> asyncEnumerator <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> numbers<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetAsyncEnumerator</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">try</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">while</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> asyncEnumerator<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">MoveNextAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span> number <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> asyncEnumerator<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Current<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>number <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">10</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">break</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">finally</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>asyncEnumerator <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">!=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> asyncEnumerator<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DisposeAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre></div><div><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><br /></span></code></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now you can clearly see that IAsyncEnumerable works almost exactly like IEnumerable did with it's <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">.MoveNext</code> and <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">.Current</code> methods. Except three things: </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">1. The method names are suffixed with the word Async</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">2. Everything is task based</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">3. There's some extra cleanup going on</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Interesting, but how useful remains to be seen.</p><h2 style="text-align: left;">Obscure Language Feature: Meet Real World</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">On my project we need to download and process large files daily. Think 60 Gig CSV files. Technically they're 60 Gig BSON files. If they were CSV they'd be even larger. Whatever, the point is that we need to read and process a lot of data, and it's slow. It takes hours. And that's a problem because the data needs to be ready by a certain time of day and if something goes wrong we have to start over. So we only get a couple shots, and worse: the data is going to get even bigger in the future for this customer. We needed to find performance optimizations.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now historically we'd treated this process in several steps like:</p><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Download file</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Read and process file (using <a href="https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/dataflow-task-parallel-library" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">DataFlow</a> from the Task Parallel Library, which if you aren't familiar you should go drop everything and learn about)</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Insert results (only about 90 megs) into database</li></ol><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That's simplified but overall those three steps took over 2 hours. Downloading: ~40 minutes. Reading and processing: ~1.5 hours. Inserting: ~10 minutes.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The team spent a lot of time brainstorming solutions to performance. But there was one thing that was bugging me about that process. Maybe reread the the bullet points and see if anything stands up. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Answer: Why were we saving to disk and reading from disk at all?! Theoretically this is why streams exist. We should be able to download the data and process it down into 90 megs and never hit the disk at all. Right?! </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Also, that IO sounds slow, but that's a different story.</p><h2 style="text-align: left;">Capture Content As Stream?</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">But I didn't know if asynchronous streams could be applied to downloading large files over HTTP. First of all, the team had been downloading zip files in BSON. I needed the data to be consumable as a stream, so zipping was right out. Consuming BSON as a stream eventually turned out to be doable, but that came later and is beyond the scope of this post. Thus unzipped CSV for the first pass.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Fortunately, there was a way to specify in the data provider's API that we wanted unzipped CSV content. That was going to increase the download time, but I was betting we'd make it up during processing, since the disk appeared to be such a bottleneck.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Next I was curious if the TCP packets started immediately upon request and broke at newline boundaries. Important? Not sure, although it does make a good picture for a blog post.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYeQ4te2vBMU8C1HGSvmLPl5M06mFd0B-WNVjdXeOuOGZwWec2MgTXh06Q9SJ2AYSbyzIn34m27ni-sBg4BUF1CDqBmFd0-Og-JiyERMg0p8vy5dYPj2FhFcdRnk-a8eTbRrol0qx-rsQ/s868/Wireshark4.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="520" data-original-width="868" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYeQ4te2vBMU8C1HGSvmLPl5M06mFd0B-WNVjdXeOuOGZwWec2MgTXh06Q9SJ2AYSbyzIn34m27ni-sBg4BUF1CDqBmFd0-Og-JiyERMg0p8vy5dYPj2FhFcdRnk-a8eTbRrol0qx-rsQ/w640-h384/Wireshark4.gif" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Wireshark packets looked like this:</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj07agclPsvkZMLdMC49xDy4IUAa_VcQtDWeHNRFhI-897O1qwYVASlrYtDgmXB7owWRlPdtGDedvKBg8O3Km-TWCUel5A6ydX67bWc_K68cZmOS7kpQjQDVk5e4m4xT2P1n5hZfgNBZuM/s561/Packet.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="239" data-original-width="561" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj07agclPsvkZMLdMC49xDy4IUAa_VcQtDWeHNRFhI-897O1qwYVASlrYtDgmXB7owWRlPdtGDedvKBg8O3Km-TWCUel5A6ydX67bWc_K68cZmOS7kpQjQDVk5e4m4xT2P1n5hZfgNBZuM/w640-h272/Packet.jpg" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In other words this was a packet:</p></div><div><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">`U0(ñòßGAäwÆMP'Û10d
2021-06-26T23:24:45,10.79
2021-06-26T23:24:53,97.83
2021-06-26T23:25:01,86.53
2021-06-26T23:25:09,3.83
2021-06-26T23:25:17,39.38
2021-06-26T23:25:25,37.94
2021-06-26T23:25:33,31.59
2021-06-26T23:25:41,12.55
2021-06-26T23:25:49,74.67
2021-06-26T23:25:57,95.25</code></pre></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Some random meta-data at top, but it ends with a newline. Great.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Incidentally, that's actually the result of an app I built to simulate our actual data provider for the purposes of this blog post. It's called <a href="https://github.com/lprichar/DisklessAsyncStreams" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">DisklessAsynchronousStreams</a> (maybe don't try to say that 10 times fast). It's open source if you feel like exploring the code of this post in more detail.</p><h2 style="text-align: left;">Asynchronous Consumption</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><i>p.s. That's a fantastic subheading, and will absolutely be the next big diet fad, just wait and see.</i></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Getting back to the point, I soon learned the important magic for asynchronously pulling data without writing to disk is the setting the <a href="https://blog.infernored.com/p/f5b69611-164b-4ef9-9c40-221a8991cce5/HttpCompletionOption.ResponseHeadersRead" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">HttpCompletionOption.ResponseHeadersRead</code></a> flag when calling <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">GetAsync()</code> or <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">SendAsync()</code> on the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">HttpClient</code>. That tells the compiler to block only until the headers are received, then continue execution. Then calls to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">ReadLineAsync()</code> may proceed while data is still downloading. More specifically:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> response <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> httpClient<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>
uri<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> HttpCompletionOption<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ResponseHeadersRead<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
response<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EnsureSuccessStatusCode</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> stream <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> response<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Content<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ReadAsStreamAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> streamReader <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">StreamReader</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>stream<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> Encoding<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>UTF8<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">while</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">!</span>streamReader<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>EndOfStream<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> line <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> streamReader<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ReadLineAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> trade <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetTradeFromLine</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>rowNum<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> line<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">yield</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> trade<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The above code works, but only because of C# 8. Prior to C# 8 the return type would need to be <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">async Task<IEnumerable<Trade>></code> . Seems reasonable. Except, the compiler then gives you:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T></code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The easy solution with C# 8 and IAsyncEnumerable though is to return IAsyncEnumerable that can then subsequently be consumed with async foreach.</p><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private async IAsyncEnumerable<Trade> StreamReadLines()
{
...
}</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">p.s. if you're shaky on how yield works check out <a href="http://www.leerichardson.com/2008/03/how-systemlinqwhere-really-works.html" style="border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">How System.Linq.Where() Really Works</a></p><h2 style="text-align: left;">Asynchronous Limitations</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Here's an interesting error, guess what it means:</p><blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgb(62, 176, 239); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px 1.5em; quotes: none; vertical-align: baseline;"><div style="text-align: left;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Type</em>: System.IO.IOException</div><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><div style="text-align: left;"><em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Message</em><span style="color: #313b3f;">: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.</span></div></em><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><div style="text-align: left;"><em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Inner exception</em><span style="color: #313b3f;">:</span></div></em><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><div style="text-align: left;"><em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> Type</em><span style="color: #313b3f;">: </span>System.Net.Sockets.SocketError</div></em><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><div style="text-align: left;"><em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> SocketErrorCode</em><span style="color: #313b3f;">: ConnectionReset</span></div></em><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><div style="text-align: left;"><em style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> Message: </em><span style="color: #313b3f;">An existing connection was forcibly closed by the remote host.</span></div></em><span><div style="text-align: left;"> StackTrace:</div></span><span><div style="text-align: left;"> ...</div></span><span><div style="text-align: left;"> at System.IO.StreamReader.d__67.MoveNext()</div></span><span><div style="text-align: left;"> System.IO.StreamReader.d__59.MoveNext</div></span></blockquote><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you said the remote host closed the connection on us, congratulations you can read, but sadly that is not at all what happened. The actual problem is the consumer exceeded a buffer (it happens to the best of us) and then .NET lied to us and that made us sad.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The problem occurs when the consumer is too slow in reading the data from the producer. Basically if data is coming in faster than we're processing it then someone needs to hold that data in a certain sized slot of memory, and eventually data will exceed the size of the slot.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp4fkMpP1hzl_TMAkpvhyphenhyphenZ1wMS0HVtR3bKm_cjIahlStj_RNmtuevlA_kAtU2C0NfmtxSeSviKBUFwK6Atz-ig-UXYVIaOAawM86hi853rEvbCdlX0iEa9vfNEB8yr_P4VOJlOkhYni8o/s1673/IOException.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="509" data-original-width="1673" height="194" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp4fkMpP1hzl_TMAkpvhyphenhyphenZ1wMS0HVtR3bKm_cjIahlStj_RNmtuevlA_kAtU2C0NfmtxSeSviKBUFwK6Atz-ig-UXYVIaOAawM86hi853rEvbCdlX0iEa9vfNEB8yr_P4VOJlOkhYni8o/w640-h194/IOException.jpg" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Interestingly you can make it happen faster by setting a smaller value of <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">MaxResponseContentBufferSize</code> on <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">HttpClient</code>. Unfortunately you cannot set <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">MaxResponseContentBufferSize</code> beyond it's default size of 2 Gigs. Therefore make sure you don't do anything slow inside your main message processing loop.</p><h2 style="text-align: left;">One More Gotcha</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Don't expect consumers to successfully stream read data asynchronously with Fiddler open. Fiddler is awesome for watching regular HTTP traffic, but it batches entire requests up before forwarding them, and next thing you know you've wasted 30 minutes trying to figure out why you can't reproduce your production environment on a duplicate project while writing up a blog post. Heed my warning: don't be that person.</p><h2 style="text-align: left;">Conclusion</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Great, so I stopped saving data to disk but increased my download size substantially. Was it worth it? Fortunately I was very happy to discover a 50% reduction in batch processing time. Also it consumed less memory and CPU and electricity and cooling costs, and then the planet sent me a personal thank you note that I've got up on my fridge. Your results may vary. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Speaking of: this code is harder to maintain, so use it sparingly. But diskless asynchronous streams is a great technique to know about if you find the right problem. With any luck you too will start a new diet fad or be personally appreciated by a celestial body.</p></div></div>
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com2Herndon, VA 20170, USA38.9808589 -77.384119710.670625063821156 -112.5403697 67.291092736178854 -42.2278697tag:blogger.com,1999:blog-6393051114813114443.post-69109821144602395672021-03-22T22:55:00.003-05:002021-04-08T14:32:15.747-05:002 Ways to Log the Current User in ASP.Net Core<p><span style="background-color: white; color: #738a94; font-family: Georgia, serif; font-size: 23px;">How to automatically add current user info to logs in ASP.Net Core. First shown in ASP.Net Boilerplate with log4net. Next shown in ABP Framework with the Microsoft Logging Framework and Serilog.</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ5e_wXlhp2sjEpJizQED7PfRccg3mjM5daSEmiwn-2ut3yiuz_A_7LF4iqg1cLmpZ8Wuo-TkLjJ6NgbcA_De1Fl13AOVR1H4mDQjM0aJqu1g_NPlDNrhFhDOD2aDU70k6Fd_AvIDHso0/s1275/LoggingCurrentUser2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="699" data-original-width="1275" height="350" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ5e_wXlhp2sjEpJizQED7PfRccg3mjM5daSEmiwn-2ut3yiuz_A_7LF4iqg1cLmpZ8Wuo-TkLjJ6NgbcA_De1Fl13AOVR1H4mDQjM0aJqu1g_NPlDNrhFhDOD2aDU70k6Fd_AvIDHso0/w640-h350/LoggingCurrentUser2.png" width="640" /></a></div><br /><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you've ever had to debug a problem with a production system you know that good logs are absolutely essential. However, knowing what information might be useful, and how much is too much is almost an artform.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I had the opportunity to develop that artform recently when I published an ASP.Net Boilerplate based system into production. Overall the deployment went well, but I realized that I'd failed to include the currently logged in user or tenant in logs. That made debugging issues harder.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Therefore, this is the story of how to how to add information about the currently logged in user, potentially including the tenant in a multi-tenant solution, in ASP.Net Core. First I'll show it in ASP.Net Boilerplate with log4net. Next I'll show how with ABP Framework and the Microsoft Logging Framework via Serilog. Hopefully, you can find something here to adapt for your tech stack, and help you develop your inner log artistry.</p><h2 style="text-align: left;">ASP.Net Boilerplate + log4net</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">For log4net, the first trick is adding custom fields. That happens in the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">log4net.config</code> configuration file. It turns out to be somewhat unintuitive via log4net's <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">property{name}</code> syntax:</p><pre class="language-xml" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-xml" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>appender</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">name</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>RollingFileAppender<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>log4net.Appender.RollingFileAppender<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
...
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>layout</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>log4net.Layout.PatternLayout<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>conversionPattern</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">value</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>%-5level %date [%-5.5property{userid}] [%-5.5property{tenantid}] [%-5.5thread] %-40.40logger - %message%newline<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>layout</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>appender</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I surrounded the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">userid</code> and <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">tenantid</code> fields with brackets and used the fixed-width <a href="http://logging.apache.org/log4net/release/sdk/html/T_log4net_Layout_PatternLayout.htm" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">pattern layout</a> <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">-5.5</code> to pad integer values less than 5 characters to 5 characters.</p></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">To populate those fields in log4net you need set the property on a <a href="http://logging.apache.org/log4net/release/manual/contexts.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">context</a>, which makes it available for all logs. There are four contexts to choose from, but the one that makes the most sense here is the logical thread context, since that is the level at which requests are processed and it can persist across await points even if a different thread is used to resume the request. The code then looks like <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">LogicalThreadContext.Properties["userid"] = ??</code>. But where to set it.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The most appropriate place is in a middleware component during the request pipeline, right after authentication so that the current user is available. In other words:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Configure</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IApplicationBuilder</span> app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ILoggerFactory</span> loggerFactory<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseAuthentication</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseSessionLogging</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">UseSessionLogging</code> is an extension method that looks like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SessionLoggingMiddlewareUtil</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseSessionLogging</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IApplicationBuilder</span> app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token generic-method" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SessionLoggingMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I chose <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/extensibility?view=aspnetcore-5.0" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Factory-based middleware</a> activation in ASP.NET Core so that I could get dependency injection in order to get access to to an <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">IAbpSession</code>, upon which I could get the current user and tenant. So the last piece of the puzzle is then:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SessionLoggingMiddleware</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> ITransientDependency
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">readonly</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IAbpSession</span> _session<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SessionLoggingMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IAbpSession</span> session<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
_session <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> session<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Task</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">InvokeAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HttpContext</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">RequestDelegate</span> next<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
LogicalThreadContext<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Properties<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"userid"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> _session<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>UserId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
LogicalThreadContext<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Properties<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"tenantid"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> _session<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>TenantId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">next</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The full code is available in <a href="https://github.com/lprichar/LeesStore/pull/30/files" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">LeesStore PR #30</a>. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Note that using other appenders like an <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">ApplicationInsightsAppender</code> are similar with some minor variation. </p><pre class="language-xml" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-xml" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>appender</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">name</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>AiAppender<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Microsoft.ApplicationInsights.Log4NetAppender.ApplicationInsightsAppender, Microsoft.ApplicationInsights.Log4NetAppender<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>threshold</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">value</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Info<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>layout</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>log4net.Layout.PatternLayout<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>conversionPattern</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">value</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>%-5level %property{userid} %property{tenantid} %message%newline<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>layout</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>appender</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">AdoNetAppender</code> is slightly trickier:</p><pre class="language-xml" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-xml" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>appender</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">name</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>AdoNetAppender<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>MicroKnights.Logging.AdoNetAppender, MicroKnights.Log4NetAdoNetAppender<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
..
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>commandText</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">value</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>INSERT INTO LogEntries ([Date],[Level],[Logger],[Message],[Exception],[UserId],[TenantId]) VALUES (@log_date, @log_level, @logger, @message, @exception, @userid, @tenantid)<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
...
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>parameter</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>parameterName</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">value</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>@userid<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>dbType</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">value</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Int32<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>layout</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>log4net.Layout.RawPropertyLayout<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>key</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">value</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>auserid<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>layout</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>parameter</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>appender</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span></code></pre><h2 style="text-align: left;">ABP Framework + Serilog</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I love log4net. I've been using it forever. But serilog is more modern and feels more elegant. Using it's equivalent of custom fields for a "console appender" is as simple as placing them in curley brackets in an output template set up in Program.cs:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">Log<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Logger <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LoggerConfiguration</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Enrich<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FromLogContext</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>WriteTo<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Async</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>c <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> c<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">File</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Logs/logs.txt"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> outputTemplate<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span>
<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"{Level:u4} [{UserId}] [{TenantId}] [{Timestamp:HH:mm:ss}] {Message:lj}{NewLine}{Exception}"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>WriteTo<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Async</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>c <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> c<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Console</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateLogger</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Setting those custom fields is done with <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">LogContext.PushProperty()</code>. Where to place that code is a bit trickier. I'm still a fan of a custom middleware component, but plugging in a middleware component in ABP Framework doesn't happen in Startup.cs. That's because ABP Framework decentralizes that logic, allowing each dependent Module the ability to register custom middleware.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">However, there's no need for a custom module. Just add the middleware component like before but in the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">OnApplicationInitialization()</code> method of the [MyProject]ApiHostModule.</p><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
...
app.UseAuthentication();
app.UseSessionLogging();
}</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Then the middleware component itself is extremely similar to the last one:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SessionLoggingMiddleware</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> ITransientDependency
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">readonly</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ICurrentUser</span> _currentUser<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">readonly</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ICurrentTenant</span> _currentTenant<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SessionLoggingMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ICurrentUser</span> currentUser<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ICurrentTenant</span> currentTenant<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
_currentUser <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> currentUser<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
_currentTenant <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> currentTenant<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Task</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">InvokeAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HttpContext</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">RequestDelegate</span> next<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>Serilog<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>LogContext<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">PushProperty</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"UserId"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> _currentUser<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Id<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>Serilog<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>LogContext<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">PushProperty</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"TenantId"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> _currentTenant<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Id<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">next</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And now the console logs contain the user and tenant.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYKbTb1LE_BNymxjToRSgVjtF8qP5TRUUcaOteOsbGeyGhqp2ar4SFbNphw4cvVMcWerhXd5M16rd1Cwu7tbafDMvt8X97QoQhbqsRjUlTgBYu39BulyMMqkjeDAUBPvy-pDXbuhkwg5A/s1216/logswithuser.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="643" data-original-width="1216" height="338" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYKbTb1LE_BNymxjToRSgVjtF8qP5TRUUcaOteOsbGeyGhqp2ar4SFbNphw4cvVMcWerhXd5M16rd1Cwu7tbafDMvt8X97QoQhbqsRjUlTgBYu39BulyMMqkjeDAUBPvy-pDXbuhkwg5A/w640-h338/logswithuser.png" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Or perhaps you're sending them to Application Insights. Or if you're logging them to the database you can expose them on an internal page:</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFAgeLO0ah1VSALM8WJw4Bp1IZgSLnSkt_yDfww99la5eKmC4dutJO_prfKGjFPCAXE0eoAoZCm15Xxatm8QQtSmBjBhxDDFpJSeYyxSvgasiTXOx2FdAi3iNSNc10FAE-f8PLNRfFQBI/s3217/uilogswithuser.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="839" data-original-width="3217" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFAgeLO0ah1VSALM8WJw4Bp1IZgSLnSkt_yDfww99la5eKmC4dutJO_prfKGjFPCAXE0eoAoZCm15Xxatm8QQtSmBjBhxDDFpJSeYyxSvgasiTXOx2FdAi3iNSNc10FAE-f8PLNRfFQBI/w640-h166/uilogswithuser.png" width="640" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The full changes are in <a href="https://github.com/lprichar/LeesStore/pull/31/files" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">LeesStore PR 31</a></p><h2 style="text-align: left;">Conclusion</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">This concludes two fairly different approaches to logging. Hopefully you can adapt something you learned here to avoid some production pain, or just to develope your artistic sensibilities.</p><div><br /></div>
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-28045925706295753192021-02-10T23:08:00.003-05:002021-02-15T11:51:15.785-05:00Cake Frosting: More Maintainable C# DevOps<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKZKXCOplmtzX7sUn-fZFCq9ZwCrB0ckj_p9msPDPonJtuADMU1HdSb53bxtsn8VBAdmj3MSvarhma86DVQrbDRfmZr3ihv-7jSWjTilkCh2HDP1d7k01HMT4nvjes5waQF3KYOteJxoE/s2048/CakeFrosting.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1587" data-original-width="2048" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKZKXCOplmtzX7sUn-fZFCq9ZwCrB0ckj_p9msPDPonJtuADMU1HdSb53bxtsn8VBAdmj3MSvarhma86DVQrbDRfmZr3ihv-7jSWjTilkCh2HDP1d7k01HMT4nvjes5waQF3KYOteJxoE/w640-h496/CakeFrosting.jpg" width="640" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">This week <a href="https://cakebuild.net/blog/2021/02/cake-v1.0.0-released" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Cake V1.0</a> was released and with it: an upgrade to Frosting, a more robust technique for writing DevOps in a language the whole team can understand. The timing is fantastic, because last week I just posted <a href="http://www.leerichardson.com/2021/02/he-one-thing-i-wish-id-known-before.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">The One Thing I Wish I'd Known Before Using Cake</a>, in which I warned of uncontrolled growth of the more traditional build.cake file. The solution I offered there still stands, however Cake Frosting offers an even better solution for modularity, encapsulation and maintainability. And the tooling is better too, if you're ready to accept some tradeoffs.</p><h1 style="text-align: left;">What Is Frosting?</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Cake Frosting is one of four Cake "Runners", which are ways of running Cake and gaining access to it's vast plugin ecosystem and it's "Dependency Management" pattern whereby you define tasks and their dependencies rather than running C# code linearly. The four options are:</p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">.NET Tool</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">.NET Framework</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">.NET Core, and</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Frosting</li></ul><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The first three runners require building in a DSL, a domain specific language, created by the Cake team to remove unnecessary C# chrome and make your C# DevOps code concise and pretty.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That last runner allows you to abandon the traditional Cake DSL and instead write DevOps inside a .NET Console App with the addition of a Cake context and some custom attributes. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Essentially, instead of writing a DSL like this:</p><pre class=" language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class=" language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">projDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Directory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"./src"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Task</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Build"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IsDependentOn</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Clean"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Does</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DotNetCoreBuild</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>projDir<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">With Frosting you write it like this:</p><pre class=" language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class=" language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// Cake DSL aliases like DotNetCoreBuild are extension methods off ICakeContext</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> Cake<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Common<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Tools<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>DotNetCore<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">TaskName</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Build"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IsDependentOn</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">typeof</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>CleanTask<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">sealed</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BuildTask</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AsyncFrostingTask</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>BuildContext<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">override</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Task</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">RunAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BuildContext</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> projDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Directory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"./src"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DotNetCoreBuild</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>projDir<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> Task<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FromResult</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Granted I threw in some unnecessary asynchronicity to show it's support, but that still looks far more verbose by comparison. That's the big downside.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">However, in exchange for that verbosity you get C# classes with all of the modularity, encapsulation, and maintainability that infers. Furthermore, it's strongly typed, so unlike with the DSL if you mistype a variable, method, or alias, the tooling reliably tells you before you compile, let alone before you run. And Intellisense works reliably. Even better, you get refactorings and static analysis and maybe <a href="http://www.leerichardson.com/2013/11/24-resharper-tips.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ReSharper</a> if you're into that kind of thing.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Lastly: check out line 5 where it's got <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">strongly typed</em> dependency management. So not only will the Cake runner ensure when you run BuildTask, that CleanTask and any of it's dependencies are run (and only run once), but it will give a compiler error if CleanTask is renamed.</p><h1 style="text-align: left;">Getting Started</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The Frosting <a href="https://cakebuild.net/docs/getting-started/setting-up-a-new-frosting-project" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">setup documentation</a> is fairly straight forward, but here's a quick recap:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Prerequisites:</p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">.Net Core 3.1.301 or newer</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Mac, Windows, or Linux</li></ul><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Install Cake.Frosting.Template, which is a .NET Tool template pack that allows you to quickly create new Frosting projects. This is global, you only need to do it once.</li></ol><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">dotnet new --install Cake.Frosting.Template</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">2. Go to an empty folder and create a project based on the Frosting template from above</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">dotnet new cakefrosting</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">3. Run it with either the PowerShell or Bash bootstrapper</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">.\build.ps1 --target=Default</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">./build.sh --target=Default</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That's it, Cake just executed a "Default" task, it's dependent "World" task and it's dependent "Hello" task.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixi8hm4plTyXT7TPljltrp7s8D1j39mHG6mL8_IYAaKGADr4K7G1R8_HcB34X4FWIkvKEt6995TOsNdiFSN7-UqVaAzDzGu4WRSGQ2xCPn3v69Oz66gAsOR4IUMwsDW_7uLW2oKSbakBE/s1591/RunFrosting.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1591" data-original-width="1027" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixi8hm4plTyXT7TPljltrp7s8D1j39mHG6mL8_IYAaKGADr4K7G1R8_HcB34X4FWIkvKEt6995TOsNdiFSN7-UqVaAzDzGu4WRSGQ2xCPn3v69Oz66gAsOR4IUMwsDW_7uLW2oKSbakBE/w413-h640/RunFrosting.png" width="413" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you investigate the generated files you'll see the two bootstrappers, and a /build folder with a .csproj and a Program.cs file. </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1v8pv5qIDuvbQCryZrTHCiCbW63fdIL2TLExGab9ZQAOr8dkV4AspwDxcxAqkUmFG0M4eXsCNkXVphYigBPFqFAh6RwznCEWQHOnbkPbChCL_PtwJBJ9EkMsV9kkj3N4zj7Q_Sel4Qbs/s537/FolderLayout.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="537" data-original-width="391" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1v8pv5qIDuvbQCryZrTHCiCbW63fdIL2TLExGab9ZQAOr8dkV4AspwDxcxAqkUmFG0M4eXsCNkXVphYigBPFqFAh6RwznCEWQHOnbkPbChCL_PtwJBJ9EkMsV9kkj3N4zj7Q_Sel4Qbs/w291-h400/FolderLayout.png" width="291" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The Program.cs is the equivalent of Cake's traditional build.cake file, except with extra code for setting up a BuildContext object.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTrnzfioT7eQepKs_YgO57nB4mfvjI0u1HvJUJtoY2c9-MU5vajontrYIbwfNzxC-dGCK8XGec_kD1YQ6GKD36IXH-flrHJ2GpDv9WbpvC1gN_68QmcjjqWR_fCc8bc3-dsqmcendPizo/s1245/ProgramCs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1245" data-original-width="1077" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTrnzfioT7eQepKs_YgO57nB4mfvjI0u1HvJUJtoY2c9-MU5vajontrYIbwfNzxC-dGCK8XGec_kD1YQ6GKD36IXH-flrHJ2GpDv9WbpvC1gN_68QmcjjqWR_fCc8bc3-dsqmcendPizo/w554-h640/ProgramCs.png" width="554" /></a></div><br /><h1 style="text-align: left;">Adjusting To Frosting</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you're coming from the Cake DSL world then you'll need to be prepared to make some adjustments in how you code.</p><h2 style="text-align: left;">Aliases</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">All aliases in the DSL world are actually extension methods off of the context object. Thus in Frosting you'll need to know the namespace and have access to a context object.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">For instance, if you're trying to access the CleanDirectories command like <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">CleanDirectories("./**/bin")</code> to remove everything in all bin directories recursively, then you'll instead need to:</p><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Import the Cake.Common.IO namespace, as found on the <a href="https://cakebuild.net/api/Cake.Common.IO/DirectoryAliases/C75671FE" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">documentation</a> page</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Invoke the command off of the ICakeContext object (e.g. <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">context.CleanDirectories("./**/bin");</code>)</li></ol><h2 style="text-align: left;">Directories / Files</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you're used to the convenience of Cake's ConvertableDirectories and ConvertableFiles where you can just concatenate Files and Directories together like:</p><pre class=" language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class=" language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> projectDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Directory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"./project/"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> subProjectDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> projectDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">+</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Directory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"subproject"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> subProjectCsProj <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> subProjectDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">+</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">File</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"subproj.csproj"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Then sadly you'll finding Frosting much more verbose. It requires saving those objects in the constructor of the Context object.</p><pre class=" language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class=" language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BuildContext</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FrostingContext</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ConvertableDirectoryPath</span> ProjDir <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ConvertableDirectoryPath</span> SubProjDir <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ConvertableFilePath</span> SubProjCsProj <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BuildContext</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ICakeContext</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">base</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
ProjDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Directory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"./project"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
SubProjDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> ProjDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">+</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Directory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"subproj"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
SubProjCsProj <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> SubProjDir <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">+</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">File</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"subproject.csproj"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The convenience may or may not be worth the inconvenience.</p><h2 style="text-align: left;">Plugins and Tools</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Fortunately some things are nearly as simple. With the DSL accessing plugins was a directive at the top of the file:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">#addin "nuget:?package=Cake.AzureCli&version=1.2.0"</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">(shh, that's my open source <a href="http://www.leerichardson.com/2020/02/strongly-typed-dependency-managed-azure.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">AzureCli</a> Cake plugin I'm quietly plugging)</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The Frosting alternative is to just reference the project via NuGet.</p><pre class=" language-xml" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class=" language-xml" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>Project</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Sdk</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Microsoft.NET.Sdk<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>PropertyGroup</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>OutputType</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>Exe<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>OutputType</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>TargetFramework</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>netcoreapp3.1<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>TargetFramework</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>RunWorkingDirectory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>$(MSBuildProjectDirectory)<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>RunWorkingDirectory</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>PropertyGroup</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>ItemGroup</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>PackageReference</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Include</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Cake.AzureCli<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Version</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>1.2.0<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>PackageReference</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Include</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Cake.Frosting<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Version</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>1.0.0<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>ItemGroup</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>Project</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And tools are only slightly more complicated, requiring a call to InstallTool in Main():</p><pre class=" language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class=" language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Program</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Main</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> args<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CakeHost</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token generic-method" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseContext</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BuildContext</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">InstallTool</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Uri</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"nuget:?package=ReportGenerator&version=4.8.1"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Run</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>args<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><h1 style="text-align: left;">Summary</h1><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I'm a big fan of Frosting, however the tradeoff should be clear by now. Code is more verbose and many conveniences like aliases and directories are less convenient. But the strongly typed, maintainable code you'll get back is probably worth it, especially on larger projects. And more importantly two years into your project you definitely won't accidentally end up with a 2000 line build.cake file. And that, my friends, is golden.</p><a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-32514890226184377922021-02-02T23:55:00.001-05:002021-02-03T00:03:52.620-05:00The One Thing I Wish I'd Known Before Using Cake<p>Set yourself up for success on your next DevOps project by avoiding this gnarly Cake mistake</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSy1QiodH5C-rS0yaqFpTJj_3S_QgBmJ-yNL3W4Tgy-EtLnp1wuXS5OkcOvrlhCkUoLNgM4H3_F9LIXCigIGgdikFXjpdQ542FdslHcfLte81oTavSjZRVoKwYP6k-xMySJ-XKQCFDDo/s2048/Title.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1108" data-original-width="2048" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSy1QiodH5C-rS0yaqFpTJj_3S_QgBmJ-yNL3W4Tgy-EtLnp1wuXS5OkcOvrlhCkUoLNgM4H3_F9LIXCigIGgdikFXjpdQ542FdslHcfLte81oTavSjZRVoKwYP6k-xMySJ-XKQCFDDo/w640-h346/Title.jpg" width="640" /></a></div><br /> <span style="background-color: white; color: #313b3f; font-family: Georgia, serif; font-size: 20px;">Let's cut to the chase: A little known Werner Heisenberg axiom discovered during his 1927 quantum physics research states:</span><p></p><blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgb(62, 176, 239); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px 1.5em; quotes: none; vertical-align: baseline;">An equal number of calories spent on Ben and Jerry's Americone Dream Ice Cream is unequivocally more satisfying than those spent on any slice of cake, ever.</blockquote><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Wow! If only I'd known earlier. That guy was frickin brilliant!</p><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4IuGlZQdogsnHA_4FlLgQE9LdKGSByZ8aI0rBj-kgjE7B6GeAbC9P-YkzN46187AbDFZ1sGYlePpXl7PoyDyW1UP0dSQvzTX0PvqDsEuJs8toAvYhZiE8CsFiDQLDvlf01Bp6Jeqy-ug/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="479" data-original-width="374" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4IuGlZQdogsnHA_4FlLgQE9LdKGSByZ8aI0rBj-kgjE7B6GeAbC9P-YkzN46187AbDFZ1sGYlePpXl7PoyDyW1UP0dSQvzTX0PvqDsEuJs8toAvYhZiE8CsFiDQLDvlf01Bp6Jeqy-ug/w499-h640/image.png" width="499" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">While that anecdote is 100% true, this post is less about the cake certainty principal, as no one calls it, and more about the dependency management tool Cake, as in C# Make. I've blogged about it <a href="http://www.leerichardson.com/2018/05/intro-to-cake-cross-platform-build.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">many</a>, <a href="http://www.leerichardson.com/2018/05/continuous-integration-logic-4-hidden.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">many</a>, times. It's the C# equivalent to Grunt, Gulp, Maven, Rake, PSake, and replaces that nasty pile of PowerShell / bash scripts you keep in abject shame hidden away inside a folder /BoringImagesNothingToSeeHere.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now any kind of software that tracks tasks and their dependencies rather than mindlessly running procedural code is typically offered by a tool that rhymes with make and is wonderful (yea you heard me right "psake", Japanese rice wine need not apply). Dependency management tools decrease complexity and organize DevOps spaghetti. But Cake has an unfortunate problem that's only apparent after several years of it building it up.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Are you ready for this? Sure?</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyTFBkRrdpdEd7I84xLE8ULkWJ_0AwjK7DpBSYSjfxvcZU9cmeOy_FW2uZeJSNStOVGLEyNhOwtzbyQeGdrmO-SiIc59iNJwOB8FEVzzaxktZMeVJxYqTL0druN8bo6IYDS2dOJRyldto/s2048/CakeFileSm.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1108" data-original-width="2048" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyTFBkRrdpdEd7I84xLE8ULkWJ_0AwjK7DpBSYSjfxvcZU9cmeOy_FW2uZeJSNStOVGLEyNhOwtzbyQeGdrmO-SiIc59iNJwOB8FEVzzaxktZMeVJxYqTL0druN8bo6IYDS2dOJRyldto/w640-h346/CakeFileSm.jpg" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Holy jebus, what is that?!</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That, my friends, is a single 2,000+ line build.cake file amassed after two years of active development split into 10 columns in VS code, zoomed out to max, as viewed on a 4K monitor.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">It's also what space aliens use to terrorize computer science abductees into catatonia. It's use is now expressly forbidden under the Geneva Convention. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Sadly, I am it's author. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Wait, don't judge. I mean, it's gotten better. I swear: it's now all puppies and kittens dancing in synchrony on rainbows. It's been nominated for a Nobel peace prize.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Happy ending, but you might not be so lucky. If you are considering adopting Cake, and you absolutely should, here's the one bit of advise I wish I'd known:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><span style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: 700; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Don't use a build.cake file.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Whoa, heresy. Build.cake is the default file Cake uses when you initiate it with <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">build.sh</code> or <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">build.ps1</code>. It's the file generated when you run the command "Install to workspace" in VSCode (from the Cake plugin). Using anything else is inconvenient, poorly documented, and just weird. If you hid that idea in a box even Erwin Schrödinger would agree it was dead.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Yet if you follow the easy path and put all your tasks in there by default like I did, you will end up with the afore mentioned large file problem, which becomes a maintenance nightmare but furthermore lacks <a href="https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">encapsulation</a>, a core tenant of good design. In other words every task can access every other task, method or property even if it's completely unrelated. And if one task needs a plugin, all the tasks get that plugin.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Maybe there's a middle path. Let's explore our options.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The best tool available to solve Cake's weak sauce encapsulation story is the load directive:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">#load OtherFile.cake</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Once you start thinking about the large file and encapsulation problems and the only real tool you have to fix it, without giving up on build.cake you'll likely come up with this solution:</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL8Y01pzr4c7UcfmFR7Vx_9_Dht9TT5YCRZpqGfaDsgNHGbd7kH6gC2uDLZB_cWPqYuuJpN_O_ceKiitxHq8lA6hJ8-sa7l1zH9UQLNqYIDH88RiLYpsOZVLFisj5cSnquhWndxHrgueg/s1158/CakeSolution1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="962" data-original-width="1158" height="532" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL8Y01pzr4c7UcfmFR7Vx_9_Dht9TT5YCRZpqGfaDsgNHGbd7kH6gC2uDLZB_cWPqYuuJpN_O_ceKiitxHq8lA6hJ8-sa7l1zH9UQLNqYIDH88RiLYpsOZVLFisj5cSnquhWndxHrgueg/w640-h532/CakeSolution1.png" width="640" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Have one file per "public" Task, and make build.cake reference each of those. This was the intrim step I took to solve my large file problem. I thus had all the e.g. deployment tasks in one file and all the environment creation in another, and a nearly empty build.cake.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">This solution is good and relatively tidy, files sizes are smaller, but plugin usage is still not isolated. And it's still so tempting to slip something quick into build.cake if you (or the other dev's you're hoping to empower by writing DevOps <a href="https://youtu.be/WbaR2-v6JXQ" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">in a language the whole team can understand</a>) are in a hurry.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If I were starting Cake DevOps scripts on a new project I'd remove build.cake entirely:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqBv16OdDGjaqV9mYYQqlvUIPI3UuOQpoNoQH183zbDHgmNYpzGyC5UlyMz5tS8s9x_8ynLvYXbIaF0lfOUcsn0AdfZZFxXO-c98F6RBLX38jq5VnCyqxEbp2h4LbylIcjDVc8p5e2WCM/s1110/CakeSolution2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="590" data-original-width="1110" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqBv16OdDGjaqV9mYYQqlvUIPI3UuOQpoNoQH183zbDHgmNYpzGyC5UlyMz5tS8s9x_8ynLvYXbIaF0lfOUcsn0AdfZZFxXO-c98F6RBLX38jq5VnCyqxEbp2h4LbylIcjDVc8p5e2WCM/w640-h340/CakeSolution2.png" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Temptation removed. Plugin usage is isolated. And it's now clearer that any new "public" tasks like a new "Run UI Automation Tests" should be placed in a new dedicated file along with all dependencies. It's also easier to refactor as things grow more complicated:</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidthiyA98pVqZqR5mgp9YJqV-DZvvyqBiXr80LvREfroTt3VyJ_yC8dF78Aqz6T_c1XSFUl1Gcs3ABOdIkFE9CHej0xdnqN4U85_Llq8ZvtA7NeKXCXXrkZDdo-B_Kgmd9QWawgh0Afcg/s1423/CakeSolution3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1003" data-original-width="1423" height="452" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidthiyA98pVqZqR5mgp9YJqV-DZvvyqBiXr80LvREfroTt3VyJ_yC8dF78Aqz6T_c1XSFUl1Gcs3ABOdIkFE9CHej0xdnqN4U85_Llq8ZvtA7NeKXCXXrkZDdo-B_Kgmd9QWawgh0Afcg/w640-h452/CakeSolution3.png" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And before you accusing me of offering high level advice without any specifics, here's how to specify a custom cake file on a PC:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">.\build.ps1 -Script deploy.cake -target=deploy</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And here's how it looks on Linux/Mac:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">./build.sh --script 'deploy.cake' -target=deploy</code></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Subtle differences, case matters.</p><h1 style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;"><span style="color: #313b3f; font-family: Georgia, serif;"><span style="font-size: 20px;">Conclusion</span></span></h1><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><span style="color: #313b3f; font-family: Georgia, serif;"><span style="font-size: 20px;">Rocket Science? Not so much. Is this insight on the level of Heisenberg's Americone Dream Axium. Sadly, no. But perhaps avoiding the use of deploy.cake will prevent your imminent trial at The Hague. Just maybe.</span></span></p></div>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-6942277620274482052020-12-14T22:54:00.007-05:002020-12-15T10:18:29.652-05:00Add Superpowers to Your Next ASP.NET Project with the ABP Framework<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigMvEGYYZHALjTtLjztCQBDTL1mV8E8ESEAyot5ET6lzz23tGraTg0hEsHF0XGcgShchfLBc7EZWE7b_Z0yMycpReK0olrB8ZXhHaumLCxaJef0fw27E74MKwNzy1YHiR4ATzCPzYi13E/s2000/superman.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1333" data-original-width="2000" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigMvEGYYZHALjTtLjztCQBDTL1mV8E8ESEAyot5ET6lzz23tGraTg0hEsHF0XGcgShchfLBc7EZWE7b_Z0yMycpReK0olrB8ZXhHaumLCxaJef0fw27E74MKwNzy1YHiR4ATzCPzYi13E/w640-h426/superman.jpg" width="640" /></a></div><span style="background-color: white; color: #313b3f; font-family: Georgia, serif; font-size: 20px;"><p><span style="color: #313b3f; font-family: Georgia, serif;">Two years ago I</span><span style="color: #313b3f; font-family: Georgia, serif;"> </span><a href="http://www.leerichardson.com/2019/05/be-hero-on-day-1-with-aspnet-boilerplate.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">discovered</a><span style="color: #313b3f; font-family: Georgia, serif;"> </span><span style="color: #313b3f; font-family: Georgia, serif;">ASP.Net Boilerplate and on two subsequent projects realized enormous time savings and quality improvements thanks to it. The ABP Framework (aka </span><a href="https://abp.io/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ABP.IO</a><span style="color: #313b3f; font-family: Georgia, serif;">) </span><span style="color: #313b3f; font-family: Georgia, serif;">is the next version of ASP.Net Boilerplate, and it promises the same benefits, but on a cleaner, more modern stack.</span></p></span><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I've held off writing about the ABP Framework because when 1.0 was released, in 2019 with .NET Core 3, I felt it wasn't sufficiently mature to start a new project on ... yet. But with the launch of ABP Framework version 4.0 last week, which supports .NET Core 5, it's time to re-evaluate.</p><div><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; display: flex; flex-direction: column; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"><div class="twitter-tweet twitter-tweet-rendered" style="border: 0px; box-sizing: inherit; display: flex; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 10px 0px; max-width: 550px; padding: 0px; vertical-align: baseline; width: 550px;"><iframe allowfullscreen="true" allowtransparency="true" class="" data-tweet-id="1334770291948613634" frameborder="0" id="twitter-widget-0" scrolling="no" src="https://platform.twitter.com/embed/index.html?creatorScreenName=lprichar&dnt=false&embedId=twitter-widget-0&frame=false&hideCard=false&hideThread=false&id=1334770291948613634&lang=en&origin=https%3A%2F%2Fblog.infernored.com%2Fp%2F0d55263e-42bb-432b-aa0a-90bdb5c12fa4%2F&siteScreenName=infernoredtech&theme=light&widgetsVersion=ed20a2b%3A1601588405575&width=550px" style="border-style: initial; border-width: 0px; box-sizing: inherit; display: block; flex-grow: 1; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; height: 625px; line-height: inherit; margin: 0px auto !important; padding: 0px; position: static; vertical-align: middle; visibility: visible; width: 550px;" title="Twitter Tweet"></iframe></div></figure><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In this post I'll review what it is, and go over the benefits and features with an eye toward what's changed since ASP.Net Boilerplate.</p><h2 style="text-align: left;">What is the ABP Framework?</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In case you're new to it I describe both it and it's predecessor as follows:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">It is:</p><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">A one-time code generator for <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</em> ASP.Net Core projects, and</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">A framework,</li></ol><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">that provides an end-to-end working site on day 1, along with foundational features and best practices.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I like this definition because I think it's critical to understand both the code generation and framework aspects. Code generation grants the flexibility to easily customize the generated site to fit your needs. The framework allows the ABP.IO team to easily ship updates, enhancements and bug fixes through NuGet or NPM updates.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Previously, ASP.Net Boilerplate put the emphasis on the code-generator side. The ABP Framework instead weighs more toward the framework side, with the benefit that they can help keep your bits fresh.<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhphSEP9dxumxDY9ICstpUh4l9d0xiaEj-WrFJ_jDtyY7GXs_tahXacwtZCEQAeAw_22RUv33OgiLaXmIkAb7jfLO2Wf-vB5gyf4VWW-N_lPQJGaII4t_ZGK7Ts7VuZwUbOdN4B1iK2A-Y/s680/freshbits.jpg" style="background-color: transparent; margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="438" data-original-width="680" height="412" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhphSEP9dxumxDY9ICstpUh4l9d0xiaEj-WrFJ_jDtyY7GXs_tahXacwtZCEQAeAw_22RUv33OgiLaXmIkAb7jfLO2Wf-vB5gyf4VWW-N_lPQJGaII4t_ZGK7Ts7VuZwUbOdN4B1iK2A-Y/w640-h412/freshbits.jpg" width="640" /></a></p></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">ABP.IO is composed of two elements:</p><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">The ABP Framework, the free and open source foundation</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">ABP Commercial, the optional add-on component that provides additional features and grants support and helps keeps Volosoft in business</li></ol><h2 style="text-align: left;">Benefits</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">ABP.IO provides the same benefits as ASP.Net Boilerplate: it gets you up to speed extremely fast with a well thought out domain driven architecture, a ton of pre-implemented best practices, a ton of foundational features, and excellent documentation. Basically it allows you to kick butt on day 1, and well into the future.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjivmxzPbyIbNYeDVmijYC7axPH66uxR2TT2agh_oGM8WAhlAjh94ljDSqrptFKai5Echc7v8EN7mtqfq2JE48rAlNINbz1VvPYYgyw70iF6NLTTQ-rFA-NwZiOsfzTprLvDH8bfVwYeYY/s522/kickbutt.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="478" data-original-width="522" height="586" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjivmxzPbyIbNYeDVmijYC7axPH66uxR2TT2agh_oGM8WAhlAjh94ljDSqrptFKai5Echc7v8EN7mtqfq2JE48rAlNINbz1VvPYYgyw70iF6NLTTQ-rFA-NwZiOsfzTprLvDH8bfVwYeYY/w640-h586/kickbutt.jpg" width="640" /></a></div><br /><div><h2 style="border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;">Front End Features</h2><p style="border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"></p><h3 style="text-align: left;">Front-End Choices</h3><br /><span style="color: #313b3f; font-family: Georgia, serif;"><span style="background-color: white; font-size: 20px;">With ABP.IO you can choose from among three front-ends. Sadly it loses the Vue and React options from ASP.Net Boilerplate, but it still has an MVC and Angular front end, and the best news is it giveth where it taketh away with: Blazor! I generated a quick Blazor app and gave it a quick once-over and so far it looks great, just like the Angular one (see also </span></span><a href="https://blog.infernored.com/p/0d55263e-42bb-432b-aa0a-90bdb5c12fa4/Blazor%20WebAssembly%20vs%20Angular:%20Client%20Side%20Clash" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-size: 20px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Blazor vs Angular</a><span style="color: #313b3f; font-family: Georgia, serif;"><span style="background-color: white; font-size: 20px;">).</span></span><p></p><h3 style="text-align: left;">Themes</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">One thing that's entirely new with the front-end is <a href="https://docs.abp.io/en/abp/latest/UI/AspNetCore/Theming" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">themes</a>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjtjwK8Y_Q0_WRZkUsxE9c2QDKr5kPoc5jRxh7Xw-OFVP0SJujtmlZL0z-_mJgWeVTiSmmql2BzkMAqVIIpMmjcl3NE_WSugWTkUAbNeAUOU9HTCI1ChlxnvyZBA74pfjQddbfKXdT9cI/s1000/themes.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="751" data-original-width="1000" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjtjwK8Y_Q0_WRZkUsxE9c2QDKr5kPoc5jRxh7Xw-OFVP0SJujtmlZL0z-_mJgWeVTiSmmql2BzkMAqVIIpMmjcl3NE_WSugWTkUAbNeAUOU9HTCI1ChlxnvyZBA74pfjQddbfKXdT9cI/w640-h480/themes.jpg" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Themes are nice if you're on ABP Commercial, because the "Lepton" themes are attractive and you have several to choose from. If you're on the free ABP Framework there's a base one for all front-ends or several community developed ones to choose from (currently only for MVC and Razor front-ends).</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you need to heavily customize the look and feel of your site you will likely find themes are more work than with ASP.Net Boilerplate, especially in Angular. But, themes do allow the framework to send down bug fixes and enhancements, so this is a trade off.</p><h3 style="text-align: left;">UI Helpers</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">UI helpers are a new super helpful front-end feature. They offer reusable components that are far less code duplication than the previous version.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTslm0UyVGTgck84iyp2qRgCFXo-yo-wkZ_N5UmldbFlcmiOUsEvhCDz-PiR75WMH3vA7maDv7yUgy_BN0kCiWNCa0sZyaZwPUnCLtdJhYZFhC02IRLz57t2lFYqIUIbmylFZmbdObBYs/s2577/tag-helpers.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1220" data-original-width="2577" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTslm0UyVGTgck84iyp2qRgCFXo-yo-wkZ_N5UmldbFlcmiOUsEvhCDz-PiR75WMH3vA7maDv7yUgy_BN0kCiWNCa0sZyaZwPUnCLtdJhYZFhC02IRLz57t2lFYqIUIbmylFZmbdObBYs/w640-h302/tag-helpers.jpg" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The table helpers in particular (for Angular) make building data tables with pagination, sorting, and filtering super easy.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0O6G1KKVwx0rAFlzhDEqF6Tv9o7GOONM9SHAXDkGnGNmAX6Oay0CrPsoR_xhToxrMheOGRlEdBu1Y83cZRntVCRQKhXSD3_cG607nyppZoMdZ7OZ_PPaKRMexjklf2veILRTWs-vDgkk/s2048/datatable.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1152" data-original-width="2048" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0O6G1KKVwx0rAFlzhDEqF6Tv9o7GOONM9SHAXDkGnGNmAX6Oay0CrPsoR_xhToxrMheOGRlEdBu1Y83cZRntVCRQKhXSD3_cG607nyppZoMdZ7OZ_PPaKRMexjklf2veILRTWs-vDgkk/w640-h360/datatable.jpg" width="640" /></a></div><br /><h3 style="text-align: left;">Auto-Generated Service Proxies</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Just like in ASP.Net Boilerplate ABP.IO gives you Swagger files out of the box with Swashbuckle. However, in the Angular world ABP.IO drops NSwag in favor of a custom Typescript proxy generation with it's own CLI. One benefit is many smaller files rather than one gigantic proxy file.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi76AWIgmarYb1gs7HNGvAT3IDmjSB3l9AIfr8-M3YahxeCLiX_O5WJZFcV6MHc-WBo_BDi2iR6-vLkCOE5-9EBxw0EczmPxpvTf5mrVwecAjtOwiB-p9IjCBkG-MsSI8L1pI8pUT4-kJA/s1394/proxygeneration.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1286" data-original-width="1394" height="590" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi76AWIgmarYb1gs7HNGvAT3IDmjSB3l9AIfr8-M3YahxeCLiX_O5WJZFcV6MHc-WBo_BDi2iR6-vLkCOE5-9EBxw0EczmPxpvTf5mrVwecAjtOwiB-p9IjCBkG-MsSI8L1pI8pUT4-kJA/w640-h590/proxygeneration.png" width="640" /></a></div><br /><div><h2 style="text-align: left;">Back-End Features</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you've ever started a new project you know there's a lot of things to set up, and a lot of ways to do it wrong. This is where ABP.IO shines. It takes care of everything, and correctly too.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-MSzyvfvKkinbxRWk8EJvrfz8msiWJKAQPTS4w3CzfjaRu3mQ0wFU05F0LT5Vtrl-YtHxQt7k8BWccEXJuaDW7UEQp_buV2K1os6K0PAIn_52COMECHxUzgMlWfJcN7M44UPzTRCC91Q/s2048/back-end-overview.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1326" data-original-width="2048" height="414" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-MSzyvfvKkinbxRWk8EJvrfz8msiWJKAQPTS4w3CzfjaRu3mQ0wFU05F0LT5Vtrl-YtHxQt7k8BWccEXJuaDW7UEQp_buV2K1os6K0PAIn_52COMECHxUzgMlWfJcN7M44UPzTRCC91Q/w640-h414/back-end-overview.jpg" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">There's simply too many back-end features to cover. But here's an attempted quick overview anyway:</p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/latest/Dependency-Injection" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Dependency Injection</a> - ABP.IO removed Castle Windsor, and replaced it with Microsoft's dependency injection extension library implemented via Autofac, huge win! 🎉</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/2.8/Logging" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Logging</a> - ABP sets up ASP.NET Core's logging system for you, and now it additionally logs all EF SQL queries for easier performance debugging 😎</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/latest/Localization" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Localization</a> - Awesome feature front-to-back, but now in json and with Microsoft.Extensions.Localization instead of xml</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/latest/Authorization" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Authorization</a> - Declarative based authorization with permissions has always been a super power of ASP.Net Boilerplate, and it's just as awesome in V2, but now it has better support for oAuth 2 and Identity Server</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/latest/Multi-Tenancy" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Multi Tenancy</a> - If you need this feature you need to use ABP.IO, it will save weeks of dev effort (see also <a href="http://www.leerichardson.com/2019/12/multi-tenancy-is-hard-aspnet.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Multi-Tenancy is Hard: ASP.Net Boilerplate Makes it Easy</a>).</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">DDD Based <a href="https://docs.abp.io/en/abp/latest/Application-Services" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">App Services</a> - The DDD approach helps organize project code and keep it maintainable while framework implemented CRUD base classes help you avoid a ton of boilerplate</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/latest/Repositories" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Repository Pattern</a> - Great for modularity and simplified unit testing</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/latest/Validation" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Validation</a> - Server-based validation is simple and DRY, just as awesome as it had been</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Auditing - I have always <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">loved</em> this feature. By simply implementing an interface (IFullAuditedAggregateRoot) you get modified date, modified by, created date, and created by: no extra coding</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Soft delete - Just implement an interface and delete operations fill in an IsDeleted column, and data retrievals ignore records where it's true. Fantastic.</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><a href="https://docs.abp.io/en/abp/latest/Exception-Handling" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Exception Management</a> - This is hard to do right, but ABP.IO kills it. Unexpected exceptions product detailed logs and a pleasant generic message to the end user.</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">And more - ABP.IO brings forward a ton of awesome features like <a href="https://docs.abp.io/en/abp/latest/SignalR-Integration" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">SignalR</a> setup, <a href="https://docs.abp.io/en/abp/latest/Background-Jobs" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">background jobs</a>, an <a href="unsafe:javascript:;" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">event bus</a>, and <a href="https://docs.abp.io/en/abp/latest/Module-Development-Basics" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">modules</a> adds a ton of new features like C# based <a href="https://docs.abp.io/en/abp/latest/Data-Seeding" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">data-seeding</a> and the <a href="https://docs.abp.io/en/abp/latest/Virtual-File-System" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Virtual File System</a></li></ul><h2 style="text-align: left;">Summary</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That's a quick overview of ABP.IO. Having dug into the details, I would choose it for my next project. I recommend it.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you're interested in a deep dive on the details including two technical demo's please check out my hour long <a href="https://www.youtube.com/leerichardson200" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Code Hour</a> episode on ABP.IO.</p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="394" src="https://www.youtube.com/embed/ea0Zx9DLcGA" width="700" youtube-src-id="ea0Zx9DLcGA"></iframe></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If, after watching that you don't choose ABP.IO for your next project, I'll be surprised. After all, why wouldn't you want to be a superhero on your next project?</p></div><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; display: flex; flex-direction: column; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"></figure>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com1tag:blogger.com,1999:blog-6393051114813114443.post-46979898370842314282020-10-21T00:16:00.001-05:002020-10-21T11:19:04.173-05:00Six Lessons Learned and a New Tool Published After Organizing My 1st Virtual CodeCamp<p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><span style="color: #738a94; font-size: 23px;">6 lessons learned while moving the NoVA Code Camp online, and announcing Sessionized, a new open source app for Code Camp organizers</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjyhiJWcRvp-JO5EYIaXPpUp4NIec5y0wqMYOg5cqrGOAq6pQwenCfftpJhE11M8iqRDWXvP4L-8ZFx7Afg0H1GXBVqk0KztDdvdN2oo2IWD5L11u2YslLlR6PmygZA60R0Nm1B4JfBVo/s2341/liveevents.jpg" style="font-family: "Times New Roman"; font-size: medium; margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1159" data-original-width="2341" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjyhiJWcRvp-JO5EYIaXPpUp4NIec5y0wqMYOg5cqrGOAq6pQwenCfftpJhE11M8iqRDWXvP4L-8ZFx7Afg0H1GXBVqk0KztDdvdN2oo2IWD5L11u2YslLlR6PmygZA60R0Nm1B4JfBVo/w640-h316/liveevents.jpg" width="640" /></a></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">2020 hasn't generally been an awesome experience, fortunately organizing NoVA CodeCamp in a post-COVID world was. I met wonderful people, gained an appreciation for all conference organizers, and felt like I helped the developer community grow. </p><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; display: flex; flex-direction: column; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"><div class="twitter-tweet twitter-tweet-rendered" style="border: 0px; box-sizing: inherit; display: flex; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 10px 0px; max-width: 550px; padding: 0px; vertical-align: baseline; width: 550px;"><iframe allowfullscreen="true" allowtransparency="true" class="" data-tweet-id="1304171520378507271" frameborder="0" id="twitter-widget-0" scrolling="no" src="https://platform.twitter.com/embed/index.html?creatorScreenName=lprichar&dnt=false&embedId=twitter-widget-0&frame=false&hideCard=false&hideThread=false&id=1304171520378507271&lang=en&origin=https%3A%2F%2Fblog.infernored.com%2Fp%2F56d44f3c-c7e2-4085-8f5b-819b6a7556ab%2F&siteScreenName=infernoredtech&theme=light&widgetsVersion=ed20a2b%3A1601588405575&width=550px" style="border-style: initial; border-width: 0px; box-sizing: inherit; display: block; flex-grow: 1; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; height: 223px; line-height: inherit; margin: 0px auto !important; padding: 0px; position: static; vertical-align: middle; visibility: visible; width: 550px;" title="Twitter Tweet"></iframe></div></figure><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In this post I'll share what I learned organizing an event for my first time ever, introduce an open source tool I just published for other organizers, and hopefully provide information to help decrease stress for others figuring out how to move forward in a post-COVID world.</p><h2 style="text-align: left;">1. Expect More Response in Call for Speakers</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">NoVA Code Camp has used <a href="https://sessionize.com/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Sessionize</a> for a long time. It's a great tool for capturing and evaluating presentations. It costs nothing for free conferences like ours, is great for communicating with speakers, and as I'll explain shortly: has an awesome API.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">During call for speakers we received 75 fantastic submissions from a variety of locations and time zones (not just Northern Virginia). 75 was about 50% more than usual thanks to being online. However, reading through 75 presentations turned out to be a lot of work and I wish I'd started earlier and known to put extra time into the schedule for evaluation.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Y8HIb_z2G-Dk9dYd7e0qN4ACxu3wfLSSpPp2Sj24-wGyHCssnkh2m6G3nAaM2QxYMtd2ZHAkkR1jKlg5PVTlrqOFIVhuiOXXSZBGm8G_8SiQWuFPRARBmkqfLRUv3MSqmBdaP577STw/s1646/CFS.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1084" data-original-width="1646" height="422" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4Y8HIb_z2G-Dk9dYd7e0qN4ACxu3wfLSSpPp2Sj24-wGyHCssnkh2m6G3nAaM2QxYMtd2ZHAkkR1jKlg5PVTlrqOFIVhuiOXXSZBGm8G_8SiQWuFPRARBmkqfLRUv3MSqmBdaP577STw/w640-h422/CFS.jpg" width="640" /></a></div><br /><h2 style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;">2. Plan Shorter Sessions</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Historically our sessions have been 75 minutes each, which equates to 5 sessions in a track. With 37 speakers we would have need over 7 tracks! We only had 4 volunteers, so that simply wasn't going to work.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">At the same time, I was interviewing several experienced online organizers to get tips and tricks (thank you <a href="https://twitter.com/alexslotte" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Alex Slotte</a>, <a href="https://twitter.com/crmdevjim" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Jim Novak</a>, and of course <a href="https://twitter.com/edsnider" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Ed Snider</a> the main organizer for NoVA Code Camp in years past). One individual suggested that online audiences had a shorter attention span and that sessions should be shorter.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Voila, with a little culling (not easy!), and a reduction to 60 minutes (<span style="background-color: transparent;">45 for presentations + 10 minutes for Q&A + 5 for a coffee break</span>) we made it all fit. I have no data to prove the shorter attention span theory, but the conference timing seemed to work out nicely.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN2M-dRQPq3rbLDqnOh8HZW7fsZSjLDXJnD_bIoZrgy6sv9n5Gt-_rQpNqlqe6d3lLZzcqiz9bJt3CCjTW3hxQW5DAStUt0D86ZR3tgMkWu9dv1rs80JJi8sAGyuIuEQo4-rsB-u9KF0Y/s1574/schedule.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1574" data-original-width="1370" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN2M-dRQPq3rbLDqnOh8HZW7fsZSjLDXJnD_bIoZrgy6sv9n5Gt-_rQpNqlqe6d3lLZzcqiz9bJt3CCjTW3hxQW5DAStUt0D86ZR3tgMkWu9dv1rs80JJi8sAGyuIuEQo4-rsB-u9KF0Y/w558-h640/schedule.jpg" width="558" /></a></div><br /><h2 style="text-align: left;">3. Create Speaker Cards</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Marketing an online event is substantially different from marketing an in-person one. Once call for speakers closed we did the normal things: e-mailing previous attendees, notifying leaders of nearby meetups, and creating a registration page on Eventbrite (which also has no cost for free conferences). That achieved a moderate response.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Then one of our speakers, <a href="https://twitter.com/GantLaborde" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Gant Laborde</a>, who speaks regularly, made the suggestion of "speaker cards" to help the speakers to promote the event like he'd seen at a react conference.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH7iFjGi-Sjcs9pSR3ghpMQumFwWVTS10M7JzcG34MMdrTJcbk77lUFKn7_vXRGReI1xVMzWWwsAnI-ylzEXBGsU0O4a3jjbQyQbta6HO7oS8FayzbcLwX7RIknDgbdoiW-QtA6NXATDM/s1200/GantReact.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="628" data-original-width="1200" height="334" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH7iFjGi-Sjcs9pSR3ghpMQumFwWVTS10M7JzcG34MMdrTJcbk77lUFKn7_vXRGReI1xVMzWWwsAnI-ylzEXBGsU0O4a3jjbQyQbta6HO7oS8FayzbcLwX7RIknDgbdoiW-QtA6NXATDM/w640-h334/GantReact.jpg" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Sounded great, but the thought of making 27 images in Paint.Net was cringy (as my daughter would say), and so (of course) I wrote an app instead. It pulled Sessionize data from their API, provided text for the 27 tweets with speaker twitter handles, and linked to a "speaker page". </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinXIvr4qep5yytUUXHBwv2v_ZWXHOBP6fNS6x1-meQ4CiMDBa0sIvfE3oeqY7w9csYOpBRmdZLU12Y13EwZ9do_r9WMDEhw6qeyw71JX-B7BzLT4aSMdnJ0nrDF5i5wHe4Y3hfSUfPQnM/s1774/tweetstosend.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="992" data-original-width="1774" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinXIvr4qep5yytUUXHBwv2v_ZWXHOBP6fNS6x1-meQ4CiMDBa0sIvfE3oeqY7w9csYOpBRmdZLU12Y13EwZ9do_r9WMDEhw6qeyw71JX-B7BzLT4aSMdnJ0nrDF5i5wHe4Y3hfSUfPQnM/w640-h358/tweetstosend.jpg" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The speaker page it linked to provided a picture, presentation description, speaker bio, and a link to our Eventbrite registration page. Then I just took screenshots of each speaker page, copied the tweets, and pasted them all into <a href="https://buffer.com/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Buffer</a> for posting slowly over many days.</p><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; display: flex; flex-direction: column; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"><div class="twitter-tweet twitter-tweet-rendered" style="border: 0px; box-sizing: inherit; display: flex; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 10px 0px; max-width: 550px; padding: 0px; vertical-align: baseline; width: 550px;"><iframe allowfullscreen="true" allowtransparency="true" class="" data-tweet-id="1309194144313749504" frameborder="0" id="twitter-widget-1" scrolling="no" src="https://platform.twitter.com/embed/index.html?creatorScreenName=lprichar&dnt=false&embedId=twitter-widget-1&frame=false&hideCard=false&hideThread=false&id=1309194144313749504&lang=en&origin=https%3A%2F%2Fblog.infernored.com%2Fp%2F56d44f3c-c7e2-4085-8f5b-819b6a7556ab%2F&siteScreenName=infernoredtech&theme=light&widgetsVersion=ed20a2b%3A1601588405575&width=550px" style="border-style: initial; border-width: 0px; box-sizing: inherit; display: block; flex-grow: 1; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; height: 483px; line-height: inherit; margin: 0px auto !important; padding: 0px; position: static; vertical-align: middle; visibility: visible; width: 550px;" title="Twitter Tweet"></iframe></div></figure></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">It worked beautifully. The speakers loved it, it helped them promote, and we ended up with nearly 200 registered attendees by the day of. Incidentally, that 200 translated to 70 at peak, which is a good showing historically:</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMCWwrzBSsHp8d4YTr8VAOjTlp4UA32VB5l3zpz12eHzKqm6A93rm8-C1l-uQm70N8ppChwEu9SfgJBbQk6kq_6hZxwEjWOvV1Nn2kXOJdY_aU35f39ON1XYy8HEp_h0bx_gqcildpsSw/s382/attendees.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="341" data-original-width="382" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMCWwrzBSsHp8d4YTr8VAOjTlp4UA32VB5l3zpz12eHzKqm6A93rm8-C1l-uQm70N8ppChwEu9SfgJBbQk6kq_6hZxwEjWOvV1Nn2kXOJdY_aU35f39ON1XYy8HEp_h0bx_gqcildpsSw/s320/attendees.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><h2 style="text-align: left;">4. Allow Audience Interaction</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Audience interaction is a critical element of a Code Camp, and conferences generally. But how to reproduce that in-person feel while preventing unsavory individuals from doing inappropriate things?</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">We chose Discord to solve that problem. It allowed attendees to interact with each other and the speakers and the organizers. And it has automated tools for spotting inappropriate content. We additionally posted a code of conduct and had one of our organizers (Stan Reiser) who was an expert with Discord set up permissions and train everyone on how to mute and boot.</p></div><h2 style="text-align: left;">5. Perform 1-1 AV Checks For Everyone</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Personalized one-on-one AV checks for each speaker probably saved the conference.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">We'd settled on Microsoft Teams for the main event after much research and deliberation because it was inexpensive and their "Live Events" feature looked awesome for attendees.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Live Events allowed attendees to easily join without authenticating, provided Tivo-like features of pause and rewind, was mobile friendly, recorded presentations for later viewing or posting to YouTube (see also our new <a href="https://www.youtube.com/channel/UCMWwbVUXNQSt9CjFu2iAtOA/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">NoVA Code Camp YouTube Channel</a>), and provided a moderated Q&A. </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjyhiJWcRvp-JO5EYIaXPpUp4NIec5y0wqMYOg5cqrGOAq6pQwenCfftpJhE11M8iqRDWXvP4L-8ZFx7Afg0H1GXBVqk0KztDdvdN2oo2IWD5L11u2YslLlR6PmygZA60R0Nm1B4JfBVo/s2341/liveevents.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1159" data-original-width="2341" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjyhiJWcRvp-JO5EYIaXPpUp4NIec5y0wqMYOg5cqrGOAq6pQwenCfftpJhE11M8iqRDWXvP4L-8ZFx7Afg0H1GXBVqk0KztDdvdN2oo2IWD5L11u2YslLlR6PmygZA60R0Nm1B4JfBVo/w640-h316/liveevents.jpg" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Sounded great, but not everyone loved Teams. While the experience was excellent for attendees, getting speakers logged in as guests accounts in our single-user Office 365 account was finnicky. The good news for subsequent organizers: we talked with a Microsoft employee who said these were known issues and will be resolved in the next update.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Regardless, the number one piece of advice I can offer other organizers: leave a couple weeks in the schedule to do AV checks for every single speaker. 27 AV checks would be too much for any one person to do while staying employed. Fortunately, we assigned one moderator as MC for each channel so no one person had to do more than 7 AV checks.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In the check we ensured everyone could get in (the hard part), their audio sounded crisp and clean, the moderator pronounced their name correctly, they understood the 10 second delay, and understood how to work the moderated Q&A.</p></div><h2 style="text-align: left;">6. Sell Your Speakers During the Event (Announcing, Sessionized!)</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Everything seemed to be in order for the big day, but one last concern: Having attendees navigate through 27 presentations to pick which ones to attend could be intimidating. And how to keep people engaged after a talk ended?</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The default grid that Sessionize provides (pictured earlier in green) was ok, but it isn't especially pretty or usable. It also doesn't provide links to "watch now". It wasn't going to cut it for an online conference.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Fortunately implementing per-track and per-time slot views with links to speaker details pages with the app I'd already started only took a couple more evenings:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQehmD0lOAemA4bXgogt77S0-CS9S6ruX4RZsqmVnj20uydEYayWiLNbakq4W_xenFMq8yiUvPphwPeovtsEKLzDipDROy3UtVt0gSCxyHMvfd1yVcds7JjdzvopudddxT_RZfdeQB5Es/s2048/upnext.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1453" data-original-width="2048" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQehmD0lOAemA4bXgogt77S0-CS9S6ruX4RZsqmVnj20uydEYayWiLNbakq4W_xenFMq8yiUvPphwPeovtsEKLzDipDROy3UtVt0gSCxyHMvfd1yVcds7JjdzvopudddxT_RZfdeQB5Es/w640-h454/upnext.jpg" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjflnWYV_HYjvqja9R_OK-cdYCswBJbPO_DBrngUgwqyycN2fI87mqaQ-pMIPJ-N_rpkSulQWox8FT3HU4pMOTPcnAbpbdgfN98VkKzzKG67h7pxqkuwK-PjT1W1Ke9a-_Cjhf56HC_bRs/s1880/webtrack.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1731" data-original-width="1880" height="590" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjflnWYV_HYjvqja9R_OK-cdYCswBJbPO_DBrngUgwqyycN2fI87mqaQ-pMIPJ-N_rpkSulQWox8FT3HU4pMOTPcnAbpbdgfN98VkKzzKG67h7pxqkuwK-PjT1W1Ke9a-_Cjhf56HC_bRs/w640-h590/webtrack.jpg" width="640" /></a></div><br /><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Oh, and the moderators also asked for slides to show when out to lunch or if there were technical difficulties.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaJ9Q3eyBs0WG9jcHUSYLNnvixyX0MaxtYqsnfWkAGCNSJKyr1ogvv1KMBwsLiXNH2de2_7ZU1yHsZEiWz7-EtXqtRuOpqAjGXuE6tyICXq_zD697L21M0DKF9BXSAwPZ_AjxZXT07voM/s1922/technical-difficulties.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="862" data-original-width="1922" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaJ9Q3eyBs0WG9jcHUSYLNnvixyX0MaxtYqsnfWkAGCNSJKyr1ogvv1KMBwsLiXNH2de2_7ZU1yHsZEiWz7-EtXqtRuOpqAjGXuE6tyICXq_zD697L21M0DKF9BXSAwPZ_AjxZXT07voM/w640-h288/technical-difficulties.jpg" width="640" /></a></div><br /><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">But fortunately we never had to show that last screen. The CodeCamp went off without a hitch. Thanks to a great team (<a href="https://twitter.com/scottlock" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Scott Lock</a>, <a href="https://twitter.com/chixcancode" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">LaBrina Loving</a>, and Stan Reiser) and a lot of hard work up-front, all of the speakers got in, none of the Internet's unsavory characters did, and a good time was had by all😁.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And since it wasn't much extra effort to genericise and open source the tool, why not? Thus I just published <a href="https://github.com/lprichar/sessionized" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">sessionized</a>. I hope it helps another CodeCamp organizer somewhere. You can view NoVA Code Camp's implementation <a href="https://novacodecamp.org/app/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">here</a>.</p></div><h2 style="text-align: left;">Summary</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">2020 has brought many changes, most of them not so great. However, for Code Camp I think our changes were mostly positive. Of course I missed the in-person interaction (and the cronuts), but moving online brought us our first international speaker (thank you <a href="https://twitter.com/emanuil_tolev" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Emanuil</a>), the coffee was better (no offense Stan), we had a long time volunteer turned first time speaker (Go <a href="https://twitter.com/vijayamalla" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Vijay</a>!), a new volunteer (yayy <a href="https://twitter.com/chixcancode" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">LaBrina</a>!), and many excellent first-time and returning speakers to NoVA Code Camp (thank you all!).</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Overall we had an excellent Saturday of fun, learning, and networking all while staying safe. There was much rejoicing. And if you're an organizer I hope this post will help you find your way to much rejoicing at your next event.</p></div><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; display: flex; flex-direction: column; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"></figure>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-62491057003372938172020-08-18T21:21:00.005-05:002020-08-25T11:48:35.437-05:00Deploying ASP.Net Boilerplate Apps for Devs in a Hurry<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyS1lQphm83MOplq3Tcs1p28StdTxNKZKEdNBU0b3TVikzYaCfCR7QeCObVwlUx1hH0cJbOELDXM6oJTahvAnjPdaH4E128lecrRk9QbjZPFt9nN8T-FJ3Vy2rStxMxy373FWRuFFszAY/s2048/spacex-PIOgkhaF3WA-unsplash.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1365" data-original-width="2048" height="427" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyS1lQphm83MOplq3Tcs1p28StdTxNKZKEdNBU0b3TVikzYaCfCR7QeCObVwlUx1hH0cJbOELDXM6oJTahvAnjPdaH4E128lecrRk9QbjZPFt9nN8T-FJ3Vy2rStxMxy373FWRuFFszAY/w640-h427/spacex-PIOgkhaF3WA-unsplash.jpg" title="Photo by SpaceX on Unsplash" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><span face="" style="color: #313b3f;"><span>I've deployed two apps based on <a href="http://www.leerichardson.com/2019/05/be-hero-on-day-1-with-aspnet-boilerplate.html">ASP.Net Boilerplate</a> (Angular + ASP.Net Core) through to production. The second used Azure Kubernetes Services. It's slick, sophisticated, self-healing, extremely scalable, uses infrastructure as code with a multi-stage Azure DevOps build pipeline, and it's micro-services are independently deploy-able.</span></span></p><p style="background-color: white; border: 0px; box-sizing: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><span face="" style="color: #313b3f;">That second site is awesome. It's also complicated, took a lot of effort to build, and will take a lot of effort to maintain. This is not its story.</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOAGuDlJPaoczg8-xZ3vdBeJZQfS8LwfCTaETkDcBhxRMxYYeiSiMoAtD_rb0CRDg8zNHxLgupjQbsBrzbFkTi8yMOzSpTc7PaeAqL35jUBSGp-kAadU23nJoIQGSnT_oaoI-cIOLAyt4/s524/DevOpsAwesome.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="499" data-original-width="524" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOAGuDlJPaoczg8-xZ3vdBeJZQfS8LwfCTaETkDcBhxRMxYYeiSiMoAtD_rb0CRDg8zNHxLgupjQbsBrzbFkTi8yMOzSpTc7PaeAqL35jUBSGp-kAadU23nJoIQGSnT_oaoI-cIOLAyt4/s0/DevOpsAwesome.jpg" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">This is the story of my first site, where I threw the SPA (Single Page Application) into ASP.Net Core's wwwroot directory, and slung it up to Azure App Services as a single site, and called it a day. Kind of mostly.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Anyway, it didn't need micro-services, massive scalability, self-healing, and all that mumbo jumbo. It just needed to be simple, quick to build, and easy to maintain.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If deploying a SPA in an ASP.Net Core site is in your future, you're in a hurry, and quick and easy sounds good: this article is for you. I'll go over it in five steps:</p><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Create Database</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Deploy Database</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Create App Service</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Compile and Deploy Host</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Compile and Deploy Angular</li></ol><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you're already familiar with deploying Azure Resources via the Azure CLI skip to step 5. If you'd like to watch this as a video check out E31 of <a href="https://www.youtube.com/leerichardson200">Code Hour</a>.</p><iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="360" src="https://www.youtube.com/embed/_IupZolRAwY" width="640"></iframe><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Otherwise, here's the how to create and deploy starting from zero, optimizing for simplicity:</p><h2 style="text-align: left;">1. Create Database</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Obviously we need a database. Using the Azure Portal is wonderful, but let's say we want repeatability. Perhaps for other environments (e.g. test/prod), or for subsequent projects. So let's use a script.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">But how to avoid the problem of running it twice and creating duplicate resources? Parameters, right? And <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">if</code> statements to ensure the resource doesn't already exist.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">But what if we want to make a resource change, e.g. to the database SKU, and deploy it through to multiple environments? This is sounding complicated, and it's what products like <a href="https://www.terraform.io/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Terraform</a> are made for. With Terraform we can describe the desired state using configuration as code and the tool looks at actual state and makes it happen, like magic.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRflFCRhgJuMidiuPWydhuBCOmgqhBRwaJOLHYTV1YI9f0eSI5P1A3jAF_Ld7jgYoMBhFDeiiQqW76zpGHTmNz_qcMfctcojugbGLYOc638NXBpspeIsj2eYlMcA2KNxHc8DlkebnmqAI/s350/magicmeme.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="196" data-original-width="350" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRflFCRhgJuMidiuPWydhuBCOmgqhBRwaJOLHYTV1YI9f0eSI5P1A3jAF_Ld7jgYoMBhFDeiiQqW76zpGHTmNz_qcMfctcojugbGLYOc638NXBpspeIsj2eYlMcA2KNxHc8DlkebnmqAI/s0/magicmeme.gif" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Terraform sounds awesome (it is), but let's avoid 3rd party dependencies and not worry about idempotence at all for now. I'm also sorely tempted to use <a href="http://www.leerichardson.com/2018/05/intro-to-cake-cross-platform-build.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Cake </a>and the world famous (not really) <a href="http://www.leerichardson.com/2020/02/strongly-typed-dependency-managed-azure.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Cake.Azure</a> CLI Plugin, but we're in a hurry, let's avoid all nonessential 3rd party dependencies 😢.</p><pre class="language-powershell" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-powershell" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># todo: Use Terraform</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># todo: Convert this all to Cake for dependency management</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStoreQuickDeploy"</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$location</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"eastus"</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># login to Azure interactively, fyi this won't work in scripts</span>
az login
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># create a resource group to hold everything</span>
az <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">group</span> create <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>l <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$location</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># create a sql server</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlUsername</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"[username]"</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlPassword</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"[password]"</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlName</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"leesstorequickdeploy"</span>
az sql server create <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlName</span> `
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>u <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlUsername</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>p <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlPassword</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>l <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$location</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># create a sql database</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlDbName</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStoreQuickDeploy"</span>
az sql db create <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>s <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlDbName</span> `
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>compute<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>model <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Serverless"</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>e <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"GeneralPurpose"</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>f <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Gen5"</span> `
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> -</span>c 1 <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>max<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>size <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"1GB"</span></code></pre><h2 style="text-align: left;"><br /></h2><h2 style="text-align: left;">2. Deploy Database</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Obviously we need to get the database tables created and insert some data. That's exactly what the Entity Framework Migrations are for. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">It'd be tempting to update appsetting.json with the connection string info from step 1 and run <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">dotnet ef database update</code> or <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">Update-Database</code> just like we did locally. However, that approach won't support the multi-tenancy multi-database scenarios granted by ASP.Net Boilerplate (see also <a href="http://www.leerichardson.com/2019/12/multi-tenancy-is-hard-aspnet.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Multi-Tenancy is Hard: ASP.Net Boilerplate Makes it Easy</a>). Furthermore, if we ever do a multi-stage Azure DevOps pipeline, we'd want to publish a single asset that we could download and run in each stage for each environment.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Fortunately, this is exactly why ASP.Net Boilerplate provides the "Migrator" command line application. We just need to compile and run it.</p><pre class="language-powershell" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-powershell" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># note: convert connection string to a parameter, or at the very least</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># don't check it in to source control (the way I did ;) )</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$connectionString</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Server=leesstorequickdeploy.database.windows.net;Initial Catalog=LeesStoreQuickDeploy;UID=lee;Password=[pwd];"</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># clean</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Remove-Item</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\dist\Migrator\*.*"</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># publish migrator (single file so we can publish it as an asset)</span>
dotnet publish <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>c Release <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>o <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\dist\Migrator"</span> `
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>r <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"win-x64"</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/</span>p:PublishSingleFile=true `
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>\aspnet<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>core\src\LeesStore<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Migrator
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Copy-Item</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\aspnet-core\src\LeesStore.Migrator\log4net.config"</span> `
<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> ".\dist\Migrator"</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># run migrator with customized connection string</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Push-Location</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Set-Location</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\dist\Migrator"</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$env</span>:ConnectionStrings__Default = <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$connectionString</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>\LeesStore<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Migrator<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>exe <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>q
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Pop-Location</span></code></pre><h2 style="text-align: left;"><br /></h2><h2 style="text-align: left;">3. Create App Service</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">✔ Databases & Migrations<br style="box-sizing: inherit;" />❔ Webs of Azure</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">There are many options to deploy a website, even narrowing the universe to Azure. They all have pro's and con's. Virtual Machines (IaaS) are expensive and require maintenance. Kubernetes is complicated. Azure's Web App for Containers Instances is pretty awesome, and ASP.Net Boilerplate is already containerized. But then we'd need to maintain the container image and it adds complexity. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">App Services are simple and fast, and good enough for most scenarios:</p><pre class="language-powershell" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-powershell" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$appServicePlan</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStoreServicePlan"</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$webAppName</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"leesstore2"</span>
az appservice plan create <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$appServicePlan</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>sku Free <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>l <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$location</span>
az webapp create <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$webAppName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>p <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$appServicePlan</span></code></pre><h2 style="text-align: left;"><br /></h2><h2 style="text-align: left;">4. Compile and Deploy Host</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">A website without code is like a taco without fillings: an abomination.</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKQVogvN81clnhSgjhzpJWtuyHhjvdWmGbRhOF3AxdilZOBEDeEjBN5li0CDyWP17-EVTR_kTDcAlIT3U4pUFKqICwX2XoPNhVDiGZ7cCx6iLGmwYTl0PcoQrm8WSMh7UWpFlt_5d07Qw/s500/sendcodes.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKQVogvN81clnhSgjhzpJWtuyHhjvdWmGbRhOF3AxdilZOBEDeEjBN5li0CDyWP17-EVTR_kTDcAlIT3U4pUFKqICwX2XoPNhVDiGZ7cCx6iLGmwYTl0PcoQrm8WSMh7UWpFlt_5d07Qw/s0/sendcodes.jpg" /></a></div><div><br /></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">To fix it first we have to set the connection string. The rest should be relatively easy, just <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">dotnet publish</code>, compress the results, and upload them with an az command:</p><pre class="language-powershell" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-powershell" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># set connection string</span>
az webapp config appsettings <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$webappname</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>settings ConnectionStrings__Default=<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$connectionString</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># compile</span>
dotnet publish <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>c Release <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>o <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\dist\Host"</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>\aspnet<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>core\src\LeesStore<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Web<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Host
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># zip</span>
Compress<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>Archive <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>PassThru <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>Path <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\dist\Host\*"</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>DestinationPath <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\dist\Host.zip"</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># upload</span>
az webapp deployment source config<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>zip <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$webappname</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>src <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\dist\Host.zip"</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Maybe not so easy. If we run that script the chances are good we'll get some error about an IP restriction:</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEw_FHCN0J7LW8ky4wwNZ5hEByYYA1h9l_ptIte4d9OEWo5YP3UE-mOwyJfi5-Mh3j_7a7dASfRtqFC5tniahLS2w0zvC5wrPyfuyhD2bQT89WzmsTCcubzkJXf3hIQq7uScXx1OvhUOs/s1381/AnErrorOccurred.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="810" data-original-width="1381" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEw_FHCN0J7LW8ky4wwNZ5hEByYYA1h9l_ptIte4d9OEWo5YP3UE-mOwyJfi5-Mh3j_7a7dASfRtqFC5tniahLS2w0zvC5wrPyfuyhD2bQT89WzmsTCcubzkJXf3hIQq7uScXx1OvhUOs/s640/AnErrorOccurred.png" width="640" /></a></div><div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">SqlException: Cannot open server requested by login. Client with IP Address is now allowed to access the server. To enable access use the Windows Azure Management Portal or run sp_set_firewall_rule on the master database to create a firewall rule for this IP address or address range.</figcaption></figure><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Either add the IP to the SQL Firewall, or allow all Azure resources to access it like:</p><pre class="language-powershell" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-powershell" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># add firewall rule for access from Azure services</span>
az sql server firewall<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>rule create <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>s <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$sqlName</span> `
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> -</span>n Azure <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">start</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>ip<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>address 0<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>0<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>0<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>0 <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">end</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>ip<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>address 0<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>0<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>0<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>0</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Problem solved. Of course, behind every good error there's always another error:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQlu5-WA-eQhvjeF9ye0z6ZosQaodaWsafPfK2cayRsXgpZsyx81hwwM7Vru-b-I525TzBnCocZ6jrRF9zHMt53U1YIBoj4gfJmc-KsOIPzwTHh0ZnqMkzBMAb5Q93wOLDSOMJxGmhU_o/s662/MixedContent.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="661" data-original-width="662" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQlu5-WA-eQhvjeF9ye0z6ZosQaodaWsafPfK2cayRsXgpZsyx81hwwM7Vru-b-I525TzBnCocZ6jrRF9zHMt53U1YIBoj4gfJmc-KsOIPzwTHh0ZnqMkzBMAb5Q93wOLDSOMJxGmhU_o/s640/MixedContent.jpg" width="640" /></a></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">Failed to fetch swagger.json. Possible mixed-content issue? The page was loaded over https:// but a http:// URL was specified. Check that you are not attempting to load mixed content.</figcaption></figure><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">This sneaky problem is most likely that ASP.Net Boilerplate depends on knowing the host URL, the Angular URL, and any other possible URL's for CORS. Because we're going to publish Angular at the same URL we can set all three to the same URL, and per the error above they're currently set to http://localhost:[someport]. At some point we might add a custom URL and custom SSL cert, but for now we can just override them with the azurewebsites.net setting:</p><pre class="language-powershell" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-powershell" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># set url's</span>
<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$url</span> = <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"https://leesstore2.azurewebsites.net/"</span>
az webapp config appsettings <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>n <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$webappname</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>g <span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$resourceGroupName</span> `
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>settings `
App__ServerRootAddress=<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$url</span> `
App__ClientRootAddress=<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$url</span> `
App__CorsOrigins=<span class="token variable" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">$url</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And with any luck Swagger! 😁</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN5TFQQA_vRhJXiml-6RZqURygocw5i33f0e3BaHqW2fqpiGOQclyMX-UKQtO_9k1biEwRn1PGnR_KowyIcNXgMCLS-C0zhsuXXo9ZE4ceoUDi5Z_0QltNA0yysQSxdahegNXbTTdzODw/s778/swagger.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="778" data-original-width="662" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN5TFQQA_vRhJXiml-6RZqURygocw5i33f0e3BaHqW2fqpiGOQclyMX-UKQtO_9k1biEwRn1PGnR_KowyIcNXgMCLS-C0zhsuXXo9ZE4ceoUDi5Z_0QltNA0yysQSxdahegNXbTTdzODw/s640/swagger.jpg" /></a></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">Swagger UI</figcaption></figure><h2 style="text-align: left;">5. Compile and Deploy Angular</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That's great. But however much devs might like that UI, users won't exactly be blown away. We need the Angular site.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Step one is to compile the SPA. With Angular that's as easy as <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">ng build --prod</code>. Throwing on an <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">--aot</code>, however, will catch more compiler errors, that's good. Then let's send the resulting site to a temporary location and move it to the Hosts's /wwwroot folder.</p><pre class="language-powershell" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-powershell" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"># Compiler angular</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Push-Location</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Set-Location</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">".\angular"</span>
ng build <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>prod <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>aot <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">--</span>output<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>path <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"../dist/ng"</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Pop-Location</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Move-Item</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"dist/ng"</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"aspnet-core/src/LeesStore.Web.Host/wwwroot"</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If we run the Host site now, it'll continue to throw up the Swagger site. That's because the call to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">app.UseStaticFiles()</code> in <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">Startup.cs</code> excludes default files, like Angular's oh so important <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">index.html</code>.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">We could either add <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">app.UseDefaultFiles(new DefaultFilesOptions());</code> or replace the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">app.UseStaticFiles()</code> call with <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">app.UseFileServer()</code> and now if we run it locally (remembering to update the App section of appsetting.json) then Angular works at our Host port of 21021!</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPbT7i2K5of92j147foBJQtKzlQJCd5Qelx20c7o2ln9g_wXes6uLga3V-Fxjvp5z9U8tpdSOxbEOikYbwooQhP6wskRUxubVQAViX9ypX7RUnJOwMUX0EGv5CIatRmgRR9sVs9beuZL0/s775/Login21021.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="698" data-original-width="775" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPbT7i2K5of92j147foBJQtKzlQJCd5Qelx20c7o2ln9g_wXes6uLga3V-Fxjvp5z9U8tpdSOxbEOikYbwooQhP6wskRUxubVQAViX9ypX7RUnJOwMUX0EGv5CIatRmgRR9sVs9beuZL0/s640/Login21021.jpg" width="640" /></a></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">LeesStore Login Page</figcaption></figure><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Not bad, but there's still two problems.</p><h3 style="text-align: left;">Problem 1 - appconfig.json</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If we rerun the deploy script now things fail on the server:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxbRJGtsx7zLHJMbts1_j7lzw7OPiyCqWJMnOP6g-6Ogo5o2lL-cevbLqeXHLgIVA5dgdSoxaH0Cu8LS9YyzjMyfSIbEMy_zImeTqq1Q8qMQDbZJQJHoegGsmdk1FleN2g6e7yl1fqY0g/s1298/appconfig-json.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="789" data-original-width="1298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxbRJGtsx7zLHJMbts1_j7lzw7OPiyCqWJMnOP6g-6Ogo5o2lL-cevbLqeXHLgIVA5dgdSoxaH0Cu8LS9YyzjMyfSIbEMy_zImeTqq1Q8qMQDbZJQJHoegGsmdk1FleN2g6e7yl1fqY0g/s640/appconfig-json.jpg" width="640" /></a></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">GetAll net::ERR_CONNECTION_REFUSED</figcaption></figure><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">See the issue? The immediate error and the underlying problem are both in the screenshot.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The immediate error (in the Console) is that the site made a request to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">http://localhost:21021/.../GetAll</code>. The underlying problem (in the Network tab's Response window) is that when it made a call to appconfig.production.json, both the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">remoteServiceBaseUrl</code> and the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">appBaseUrl</code> were wrong. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">We could fix those problems in a variety of ways, but I especially like adding ASP.Net Core middleware to catch that request and dynamically generate the values based on what's in the appconfig.json (or in environment variables). Check this out:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Startup</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Configure</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseCors</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>_defaultCorsPolicyName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseDynamicAppConfig</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>_appConfiguration<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">//app.UseSpa();</span>
app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseFileServer</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Ha, a setup, didn't see that coming did you? We just used an undefined UseDynamicAppConfig() extension method in Startup.cs/Configure(). Again, this time for real:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DynamicAppConfigMiddlewareBuilder</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IApplicationBuilder</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseDynamicAppConfig</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IApplicationBuilder</span> builder<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IConfigurationRoot</span> appConfiguration<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> serverRootAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> appConfiguration<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"App:ServerRootAddress"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> clientRootAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> appConfiguration<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"App:ClientRootAddress"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> builder<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token generic-method" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DynamicAppConfigMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>serverRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> clientRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DynamicAppConfigMiddleware</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">readonly</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">RequestDelegate</span> _next<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">readonly</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> _serverRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">readonly</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> _clientRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DynamicAppConfigMiddleware</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">RequestDelegate</span> next<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> serverRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> clientRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
_next <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> next<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
_serverRootAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> serverRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
_clientRootAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> clientRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Task</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Invoke</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HttpContext</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">const</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> appConfigPath <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"/assets/appconfig.production.json"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> isRequestingAppConfig <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> appConfigPath<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Equals</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Request<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Path<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Value<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> StringComparison<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>CurrentCultureIgnoreCase<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>isRequestingAppConfig<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> response <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GenerateResponse</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Response<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">WriteAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>response<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">else</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _next<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Invoke</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GenerateResponse</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> cleanServerRootAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> _serverRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">TrimEnd</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'/'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> cleanClientRootAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> _clientRootAddress<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">TrimEnd</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'/'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> $<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">@"{{
""remoteServiceBaseUrl"": ""{cleanServerRootAddress}"",
""appBaseUrl"": ""{cleanClientRootAddress}""
}}"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That looks complicated, but it just intercepts any requests to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">/assets/appconfig.production.json</code> and writes out a string json in <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">GenerateResponse()</code> that includes values from the appConfiguration.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I love the idea of dynamically generating that config file rather than duplicating values, it feels very clean. And it even works!</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Rerun the deploy script, and holy cow!</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3FDUzgW8SJEJDFg4Jv61jM8AdmsbzVLIBoqWCLzi5IieDYwsUOAvTrpUr6z1j-UBGZ5vCQ5PEE1zAJ8NRmvo272JfjWhG_rZStTo_CphZJtY97iJbanuFnCQy1kmlEbcfAnX1hLqCwnU/s1298/abpworking.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="745" data-original-width="1298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3FDUzgW8SJEJDFg4Jv61jM8AdmsbzVLIBoqWCLzi5IieDYwsUOAvTrpUr6z1j-UBGZ5vCQ5PEE1zAJ8NRmvo272JfjWhG_rZStTo_CphZJtY97iJbanuFnCQy1kmlEbcfAnX1hLqCwnU/s640/abpworking.jpg" width="640" /></a></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">Home page for uncustomized ASP.Net Boilerplate Site</figcaption></figure><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">We can log in and access the database!</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And you know that's exciting because I just ended three paragraphs with exclamation points! (four? ugh, stupid off by one errors)</p><h4 style="text-align: left;">Problem 2: Angular Server-Side Routing</h4><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">But behind any apparent success there is at least ... one minor problem. In this case if we refresh the page on any URL other than the root we get a 404. This is a server-side routing problem. We need any requests to /app/[anything] to get rerouted to /index.html. Fortunately that's easy to fix with a little more middleware magic. Check out the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">app.UseSpa();</code> call on line 11 of Startup.cs above. If we uncomment that and add the following middleware:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SpaMiddlewareBuilder</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">static</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseSpa</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IApplicationBuilder</span> app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Use</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> next<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">next</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Response<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>StatusCode <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">==</span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">404</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">&&</span>
context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Request<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Path<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">StartsWithSegments</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"/app"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">&&</span>
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">!</span>Path<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HasExtension</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Request<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Path<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Value<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
context<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Request<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Path <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"/index.html"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">next</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now we can refresh on any page in Angular and it all just works.</p><h2 style="text-align: left;">🎉 Done!</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">We're done!! This warrants even more exclamation points!!!</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">SPA's add deployment complexity, but that deployment was pretty quick and easy. If you're interested in the source code check out <a href="https://github.com/lprichar/LeesStore/pull/22" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Pull Request 22</a> on <a href="https://github.com/lprichar/LeesStore" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">LeesStore</a> on GitHub. Now we just need to rewrite it all in Cake, use Terraform, and automate those scripts to run on the server. Tomorrow perhaps.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Was this interesting? I'd be happy to dig into more complex ABP deployment scenarios, just let me know in the comments or on <a href="https://twitter.com/lprichar" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">twitter</a>.</p></div><a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com2tag:blogger.com,1999:blog-6393051114813114443.post-76305758573281570212020-07-23T07:11:00.004-05:002020-08-09T22:03:16.620-05:00Blazor WebAssembly vs Angular: Client Side Clash<div a="" and="" angular="" answer="" application="" based="" blazor.="" blazor="" built="" co-op="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[],"markups":[["a",["href","http://typershark.io"]]],"sections":[[1,"p",[[0,[],0,"Think quick: you" daughter="" encourage="" for="" game="" help="" i="" learn="" like="" mature="" more="" multi-player="" my="" new="" or="" out="" p="" page="" primary="" project="" question="" re="" s="" set="" shiny="" should="" simple="" simultaneously="" single="" something="" spa="" starting="" technology="" that="" the="" to="" typershark.io="" typing="" use:="" web="" webassembly="" when="" which="" why="" you=""><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjux8uoyjekpiRLY95iHKrbTR04yX0AB4k5fVgyReaNqvHQtDeGdEL5XmgOYywoiUgM7gKreJckHgfeAPRBI8aS-3_khOgTT0NlfCOM0Tiq2OjHBh7WdVhpuu4bykz2cSdlwJ_ScSk_IeI/s2048/uriel-soberanes-L1bAGEWYCtk-unsplash.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1365" data-original-width="2048" height="416" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjux8uoyjekpiRLY95iHKrbTR04yX0AB4k5fVgyReaNqvHQtDeGdEL5XmgOYywoiUgM7gKreJckHgfeAPRBI8aS-3_khOgTT0NlfCOM0Tiq2OjHBh7WdVhpuu4bykz2cSdlwJ_ScSk_IeI/w625-h416/uriel-soberanes-L1bAGEWYCtk-unsplash.jpg" width="625" /></a></div><p><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Think quick: you're starting a new project, which single page application (SPA) technology should you use: That shiny Blazor WebAssembly you've heard so much about or something more mature like Angular, and why?</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That's the primary question I set out to answer when I built <a href="http://typershark.io/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">typershark.io</a>, a simple web based single or multi-player co-op game that I built to help encourage typing for my daughter and simultaneously to learn Blazor.</p><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPYN0OH1h7vgyXm-5ORi15XpSyBeW-norR1B1CzA0Dk2FfpwcMJzhzHn19ya_jPf3-MWUfesCQiNzlyTuRW4Fhe5Y1JnEBGO8zIO9zGCejq0FXl1perEJ_p7zYNxltxr8h9ih7Ypbodzk/s640/TyperShark.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="360" data-original-width="640" height="351" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPYN0OH1h7vgyXm-5ORi15XpSyBeW-norR1B1CzA0Dk2FfpwcMJzhzHn19ya_jPf3-MWUfesCQiNzlyTuRW4Fhe5Y1JnEBGO8zIO9zGCejq0FXl1perEJ_p7zYNxltxr8h9ih7Ypbodzk/w625-h351/TyperShark.gif" width="625" /></a></div><div .="" add-player.component.scss="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[["code",{"code":"<EditForm Model=\"TempPlayer\" OnValidSubmit=\"SetName\">\n <DataAnnotationsValidator />\n <ValidationSummary />\n ....\n <InputText type=\"text\" @bind-Value=\"TempPlayer.Name\" />\n ...\n</EditForm>\n\ncode {\n [Parameter]\n public EventCallback OnSetName { get; set; }\n\n [Parameter]\n public string InitialName { get; set; }\n\n \n\n private async Task SetName()\n {\n await OnSetName.InvokeAsync(TempPlayer.Name);\n }\n}","language":"csharp"}],["code",{"code":"<PlayerNameComponent InitialName=\"@MyInitialName\" OnSetName=\"@OnSetName\" />\n\n@code\n{\n private string PlayerName\n\n public void OnSetName(string playerName) \n {\n // do something\n }\n}","language":"csharp"}],["code",{"code":"@Component({\n template: `\n <form type=\"submit\" (ngSubmit)=\"addPlayer()\">\n <input type=\"text\" name=\"PlayerName\" [(ngModel)]=\"playerName\">\n <button type=\"submit\">Save Player</button>\n </form>\n `,\n styleUrls: [" defaultplayername:="" eventemitter="" input="" n="" output="" playername:="" public="" string=""><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I'm certainly no Blazor expert at this point, but I've sunk about 40+ hours into building the game, and after working professionally in Angular 2+ apps for the last two years I feel comfortable comparing the technologies and sharing my feelings. Also, as a consultant I've worked on 38 unique projects in the last two decades, and am no stranger to the considerations one faces when starting new projects, or the regrets one feels after making poor architectural decisions.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I'll compare them across ten categories where I feel their differences are interesting and might affect a project's technology choice:</p><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">View Typing</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Component Level CSS</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Validation</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Tooling</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Maturity</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Language</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Debugging</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Testability</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Interop</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Code Sharing</li></ol><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">First I'll give a quick overview of the Blazor WebAssembly technology, in case you've missed it. I'll assume you have a minimal grasp of Angular.</p><h2 style="text-align: left;">Blazor WebAssembly, What Is It?</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><a href="http://blog.stevensanderson.com/2017/11/05/blazor-on-mono/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Announced</a> in 2017, officially <a href="https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-now-available/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">released</a> just a couple months ago on May 19, 2020, Blazor WebAssembly is a technology that allows developers to write client-side code in C# and Razor (a pleasant hybrid of HTML and C#) and have it compile down to WebAssembly. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">WebAssembly is exciting because it's faster, more compact, and has more functionality than JavaScript. If it sounds like I'm blowing smoke read this excellent <a href="https://www.infoq.com/articles/webassembly-blazor/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Blazor article</a> by Jeremy Likness, here's an excerpt:</p><blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-bottom-width: 0px; border-image: initial; border-left: 3px solid rgb(62, 176, 239); border-right-color: initial; border-right-style: initial; border-right-width: 0px; border-top-color: initial; border-top-style: initial; border-top-width: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px 1.5em; quotes: none; vertical-align: baseline;">As a byte code format, there is no need to parse script and pre-compile for optimization. The code can be directly translated to native instructions. Startup times to load and begin execution of the code are orders of magnitude faster compared to asm.js</blockquote><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">On top of WebAssembly, Blazor adds data binding, components, JavaScript Interop, dependency injection, and the ability to run any .Net Standard code you can pull from NuGet – all natively in the browser. If that sounds exiting, it is. But is it ready for prod?</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Incidentally, check out episode 30 of Code Hour if you'd like to learn more about the features of Blazor WebAssembly.</p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="315" src="https://www.youtube.com/embed/6D6So52cNw4" width="560" youtube-src-id="6D6So52cNw4"></iframe></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><h2 style="text-align: left;">Server-Side or Client Side?</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In this article I will not explore the more mature server-side execution model of Blazor. In that mode Blazor does not compile C# to WebAssembly, instead it runs C# on the server-side and communicates HTML via SignalR, similar to AJAX UpdatePanels in WebForms (remember those?). Server-side Blazor <a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/supported-platforms?view=aspnetcore-3.1" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">supports</a> older browsers (IE 11+), but it has no offline support, and the server needs to maintain state for every single client, which limits scalability.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Incidentally, I wrote the 1st version of typershark.io in server-side Blazor and converted it. While server-side and WebAssembly Razors look nearly identical, the architectures are fundamentally very different, and thus the conversion was not straightforward. If you're starting a new project choose your execution model up front, don't plan on switching.</p><h2 style="text-align: left;">Components</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Before I can get to the categories I'll introduce a little code to ground the conversation. This code will take the form of a component. Components, in both Angular and Blazor, accomplish <a href="https://en.wikipedia.org/wiki/Information_hiding" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">information hiding</a> which increases maintainability.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Here's the Blazor code for a GetPlayerName component that can accept a default player name (perhaps pulled from local storage), prompt the user for the name, and upon submission will return the name the player provided:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EditForm</span> Model<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"TempPlayer"</span> OnValidSubmit<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"SetName"</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>DataAnnotationsValidator <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>ValidationSummary <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">InputText</span> type<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"text"</span> @bind<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span>Value<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"TempPlayer.Name"</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/</span>EditForm<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
code <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Parameter</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EventCallback</span> OnSetName <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Parameter</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> InitialName <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Task</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SetName</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> OnSetName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">InvokeAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>TempPlayer<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Name<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That can then be used from a parent component like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">PlayerNameComponent</span> InitialName<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"@MyInitialName"</span> OnSetName<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"@OnSetName"</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
@code
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">private</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">PlayerName</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">OnSetName</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> playerName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// do something</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><h2 style="text-align: left;">1. View Typing: Blazor++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Check out the EditForm element on line 1 of the PlayerNameComponent, with its Model attribute. That's a Blazor provided component that translates to a Form in HTML, but with the benefit of strongly typed errors in the view if there are type mismatches. That makes refactoring safer and easier, and it provides great IntelliSense. It's really nice! </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">By comparison an Angular PlayerName component feels very similar:</p><pre class="language-typescript" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-typescript" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">@<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Component</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
template<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token template-string" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">`
<form type="submit" (ngSubmit)="addPlayer()">
<input type="text" name="PlayerName" [(ngModel)]="playerName">
<button type="submit">Save Player</button>
</form>
`</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
styleUrls<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'./add-player.component.scss'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> playerName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token builtin" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
@<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Input</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> defaultPlayerName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token builtin" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
@<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Output</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> onAddPlayer<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> EventEmitter<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token builtin" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EventEmitter</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token builtin" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">addPlayer</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>onAddPlayer<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">emit</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>playerName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ngOnInit</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>playerName <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>defaultPlayerName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And here's how to use the component in angular:</p><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">@Component({
template: `
<app-add-player defaultPlayerName="Sally" (onAddPlayer)="myOnAddPlayer($event)"></app-add-player>
Your name is {{ playerName }}
`,
})
export class HomeComponent extends AppComponentBase {
public playerName = "initial value";
public myOnAddPlayer(playerName: string) {
this.playerName = playerName;
}
}</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The template code looks pleasant (it is, I actually really like Angular views and data binding syntax), but before runtime there's very little syntax validation, and certainly no type checking. And IntelliSense is poor, even if the view is in a separate .html file (I combined views and components for all code samples here for readability).</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">You can catch some issues with an <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">ng build --prod --aot</code> at the Angular CLI (even more in Angular 9 with <a href="https://auth0.com/blog/angular-9s-best-hidden-feature-strict-template-checking/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">strict template checking</a>), but full compilations can take minutes to run on larger applications, it's not a regular part of development, and it still misses the type checking. That makes refactorings more dangerous, and IntelliSense virtually useless. Blazor definitely wins this category.</p><h2 style="text-align: left;">2. Component Level CSS: Angular++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Where Blazor really falls over is hidden away on line 8 in the Angular AddPlayerComponent code sample above: <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">styleUrls: ['./add-player.component.scss'],</code>. Angular's ability to bundle <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">component-level</em> CSS, LESS, or SCSS styling is essential in a SPA app of any size. I simply could not return to a framework without it at this point. Fortunately, it may be on the horizon: check out this Blazor issue on <a href="https://github.com/dotnet/aspnetcore/issues/10170" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">CSS isolation</a>. Once that's solved Blazor will have removed a huge negative for me.</p><h2 style="text-align: left;">3. Validation: Angular++</h2><div><br /></div><string><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8My252vbk09iRXu2lo78IYslPs3g-JhXfMfzd5UzYJMIfK7xITQW8aZufXlZ0VOkFrlOAFUwgrVqMhY0rzdoOMoVSTt3tlSe5V-f-Z6wwV8L67fV3OnzbhQGsikEn6XZTH3ki-mDKiQI/s1771/BlazorValidation.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="865" data-original-width="1771" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8My252vbk09iRXu2lo78IYslPs3g-JhXfMfzd5UzYJMIfK7xITQW8aZufXlZ0VOkFrlOAFUwgrVqMhY0rzdoOMoVSTt3tlSe5V-f-Z6wwV8L67fV3OnzbhQGsikEn6XZTH3ki-mDKiQI/w625-h305/BlazorValidation.jpg" width="625" /></a></div><div><br /></div><div addplayercomponent="" and="" angular="" annotations.="" as="" blazor.="" c="" data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[],"markups":[],"sections":[[1,"p",[[0,[],0,"Take another look at Blazor" data="" dataannotationsvalidator="" doesn="" extremely="" feel="" from="" how="" i="" in="" is="" it="" just="" left="" love="" of="" perspective="" picks="" robust="" s="" show="" simple="" t="" that.="" the="" to="" unfortunately="" up="" uses="" validation.="" validation="" validationsummary=""><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Take another look at Blazor's AddPlayerComponent from the perspective of validation. I left in the DataAnnotationsValidator and ValidationSummary to show how extremely simple validation is in Blazor. It just picks up and uses C# data annotations. I love that. Unfortunately it just doesn't feel as robust as Angular validation.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Angular can track dirty state, or invalid state on a per field basis and roll it up to the form or even sub-form levels (imagine you have a form with multiple sections). The amount of flexibility offered in the reactive forms model (as opposed to the template driven forms approach I showed above) provides a huge advantage and I couldn't find anything comparable in Blazor (although as with everything Blazor I'm new at this, please write in the comments if I missed something). So validation is a win for Angular, but in its simplicity, Blazor's got game.</p><h2 style="text-align: left;">4. Tooling: Angular++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">You were expecting me to give Blazor the win because of strong typing and IntelliSense in forms? Not so fast. There are about three other failings that overshadow that win.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">First, Adding a new component, directive, or pipe in Angular is easy with the Angular CLI. Simply <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">ng generate component MyNewComponent</code> and you have a component class, view template, CSS/LESS/SCSS file and a test file, and Angular registers it for you. Blazor, on the other hand, gives you none of that. If you want separate view and component files you have to know to add a "code-behind" of the correct name and make it partial. Boo.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Next, while IntelliSense worked great inside of forms, I found it frequently failed to find built-in components like the aforementioned ValidationSummary, which I had to know about and copy-paste in. Also, frequently view errors failed to show up as compiler errors but only showed up in DevTools at runtime, or sometimes in some hidden generated file for the view that would randomly show up in the IDE. Boo.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Finally, Angular's live-reload makes its dev innerloop faster. The closest I could come with Blazor was hitting Control F5 (Run Without Debugging), and then I could make changes to .razor or .css files (just not code) and refresh, and I'd see non-C# changes quickly.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Overall tooling was a big win for Angular, but stay tuned, I bet Blazor will come out strong in the next version.</p><h2 style="text-align: left;">5. Maturity: Angular++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Maturity of a platform is important because running into edge cases or exploring a new scenario that lacks an answer on StackOverflow can add big delays to your project. I only ran into a few such issues building TyperShark, and was actually impressed with the content already out there. Blazor clearly has a passionate fan base. Nonetheless, Angular wins this category. If you're building a production app and have a tight deadline stick with the mature platform.</p><h2 style="text-align: left;">6. Language: Razor++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">⚠<em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> Controversial opinion alert</em></p><div><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><br /></em></div><p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://imgs.xkcd.com/comics/bad_opinions_2x.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="497" src="https://imgs.xkcd.com/comics/bad_opinions_2x.png" /></a></div><p></p><div data-mobiledoc="{"version":"0.3.2","atoms":[],"cards":[],"markups":[["a",["href","https://xkcd.com/2051/"]]],"sections":[[1,"p",[[0,[0],1,"https://xkcd.com/2051/"]]]]}"><p style="text-align: center;"><a href="https://xkcd.com/2051/">https://xkcd.com/2051/</a></p></div><p></p><div class="separator" style="clear: both;"><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">According to StackOverflow's 2019 developer survey C# is the 10th <a href="https://insights.stackoverflow.com/survey/2019#most-loved-dreaded-and-wanted" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">most loved</a> language while TypeScript is 3rd. There's a simple explanation for this. Those developers are all stupid, and I'll grant this category to Razor without further debate.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Ok, I lied, one more word on this. Retrieving data from the back-end in Angular typically involves RxJS subscriptions. I find RxJS to be overkill and obtuse in 99% of scenarios. Consider this RxJS code:</p><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this.userService
.findAll()
.finally(() => {
finishedCallback();
})
.subscribe(
(users: UserDtoPagedResultDto) => {
this.users = users.items;
this.showPaging(users);
},
err => console.log('HTTP Error', err),
);</code><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">vs the alternative in Razor:</p><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">try {
var users = await _userService.FindAll()
_users = users.Items;
ShowPaging(users);
} catch (Exception ex) {
Logger.LogInformation("HTTP Error", err);
} finally {
FinishedCallback?.Invoke();
}</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If the first code snippet doesn't raise your blood pressure and the second one lower it, you may need to see a doctor.</p><h2 style="text-align: left;">7. Debugging: Angular++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">For now Blazor WebAssembly <a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/debug?view=aspnetcore-3.1" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">can't</a> break on unhandled exceptions or hit breakpoints during app startup. This was a big frustration of mine. It meant that for most errors I had to copy stack traces out of Chrome Dev Tools and paste them into Resharper's Browse Stack Trace tool (best hidden feature ever). I know this will be fixed soon, but it is very frustrating now. The good news is, once this is fixed I suspect I'll prefer the Visual Studio debugging experience.</p><h2 style="text-align: left;">8. Testability: Tie</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Blazor is extremely testable. Everything Blazor provides is an interface for mockability, and dependency injection is a first class citizen. They clearly borrowed extensively from Angular's strengths. If Microsoft's historical lack of respect for testability has scared you off before: reconsider, it's no longer an issue.</p><h2 style="text-align: left;">9. Interop: Angular++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Obviously JavaScript Interop, the most common scenario, isn't an issue in Angular, so Angular wins. That said, calling into .Net Code from JavaScript (e.g. TyperShark's onkeypress event handler) or calling into JavaScript from .Net with <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">IJSRuntime</code> is extremely easy. Furthermore, integrating with packages pulled down from npm <a href="https://medium.com/swlh/using-npm-packages-with-blazor-2b0310279320" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">is doable</a>, although you might be doing it wrong if you need to.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Conversely, interop goes both ways. If you have a NuGet library that doesn't exist in JavaScript that you need client-side, then Angular falls flat and Blazor triumphs! That scenario seems far less likely given the massive JavaScript ecosystem, so I'll have to give the win to Angular.</p><h2 style="text-align: left;">10. Code Sharing: Blazor++</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">I saved the best for last. typershark.io can run in single player mode or multi-player mode. It has a core engine that produces sharks, tracks active sharks, figures out when sharks have timed out, and tracks which users (assuming multi-player mode) have typed which elements of the sharks. It sends notifications out like: SharkAdded, GameOver, or GameChanged. It's not super complicated, but it's not super simple. What's beautiful about it: I was able to get it to run client-side for offline support in single player mode or entirely server-side with SignalR callback events when run in multi-player mode. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Let me repeat that: the exact same C# code could run either in the browser <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">or </em>in the server <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">based on a runtime condition</em>.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">This feature could be <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">enormous, </em>depending on what you're building, and the fact that I never once needed to think about where my code was running was amazing. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Granted, you could probably get the same thing with node.js and Angular, but if you're using an ASP.Net Core stack and you also love C#, then this can be an absolutely awesome feature.</p><h2 style="text-align: left;">Conclusion</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If the game sounds fun check it out at <a href="http://www.typershark.io/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">typershark.io</a> (keep your expectations low). If the code sounds interesting check it out on <a href="https://github.com/lprichar/typershark" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">github</a> (I accept pull requests). If you're interested in more details about how I built it keep an eye on <a href="https://www.leerichardson.com/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">my blog</a> and/or subscribe to <a href="https://www.youtube.com/leerichardson200" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Code Hour</a>.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">More importantly, should you start your next project with Blazor WebAssembly? It depends. If you have a tight deadline, need a lot of JavaScript interop, or need maturity and stability, then go Angular, Vue or React. However, if you need to share C# code client-side and server-side, have a NuGet package that you want to interop with, or like me just really love C#, then pick Blazor. Either way Blazor is bright and shiny and fun to work with today, and it has an even shinier future ahead. I'll be keeping a sharp on it, if you've read this far you definitely should too.</p></div><p></p><div class="separator" style="clear: both; text-align: center;"></div></div></string></div></div>
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com4tag:blogger.com,1999:blog-6393051114813114443.post-45617636737828562732020-07-15T07:24:00.004-05:002020-07-15T07:29:58.499-05:00800+ Subscribers: A Tale of Inspiration (via Hanselminutes) and Pivot (Eric Ries)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimNSMP-3ja5jeVZth0gYQKTGOaYxdjGhgN9SgoRhVLQUTMMl4kawIF7jM8-UBLwPk2Oo4LHxfUCu4lMxFFCkUm6X80ltkNojep0cKfX8VyDsfOroA9hktSC4QwddPO8KmIQ0kEknvApgE/s1600/greg-rakozy-oMpAz-DN-9I-unsplash.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimNSMP-3ja5jeVZth0gYQKTGOaYxdjGhgN9SgoRhVLQUTMMl4kawIF7jM8-UBLwPk2Oo4LHxfUCu4lMxFFCkUm6X80ltkNojep0cKfX8VyDsfOroA9hktSC4QwddPO8KmIQ0kEknvApgE/s640/greg-rakozy-oMpAz-DN-9I-unsplash.jpg" width="640" /></a></div>
<br />
<br />
Three years ago last month Scott Hanselman recorded an episode of Hanselminutes he's undoubtedly already forgotten. I haven't.<br />
<a href="https://www.blogger.com/blogger.g?blogID=6393051114813114443" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><br />
I wasn't looking for inspiration the day I stumbled on that episode, but 29 of my own episodes, 47,000 views, and 5,000 watch hours of <a href="https://youtube.com/leerichardson200">Code Hour</a> later, my YouTube channel is a testament to Scott Hanselman's ability to inspire others.<br />
<br />
His interview with Daniel Shiffman in <a href="https://www.hanselminutes.com/584/get-on-the-coding-train-with-processing-and-daniel-shiffman">episode 584</a> made sharing knowledge in video form seem approachable, exciting, and rewarding. I'd been blogging for over a decade as a way to learn development topics more deeply, and give back to the community. Doing it visually seemed like a more efficient means to accomplish those goals.<br />
<br />
<h2>
Code Hour was born. It sucked.</h2>
I started "Code Hour" with the idea I'd live code Xamarin development for an hour weekly on Twitch and YouTube streaming, no post editing, just like Daniel Shiffman, and see what stuck.<br />
<br />
Nothing stuck. It was, I can now admit, pretty terrible.<br />
<br />
Don't believe me. Here's proof:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEKwoqud59wwK0LSXnyHKOZJQp8uQBF92edBebYD1bgt15v4IYt4B5HHCmGqEn39D0FXyLQNKcq2ajsy5oD8RTGJQfKCny96H5wFI7ET-VDqXv5k-_2AhOXoxBNWkYu6a4mGHWWpPRkQQ/s1600/Stats.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="315" data-original-width="1600" height="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEKwoqud59wwK0LSXnyHKOZJQp8uQBF92edBebYD1bgt15v4IYt4B5HHCmGqEn39D0FXyLQNKcq2ajsy5oD8RTGJQfKCny96H5wFI7ET-VDqXv5k-_2AhOXoxBNWkYu6a4mGHWWpPRkQQ/s640/Stats.jpg" width="640" /></a></div>
<br />
<br />
Viewership: near zero, for a year and a half despite weekly episodes. I learned a ton, but I certainly wasn't giving back to the community.<br />
<br />
Giving up would have been reasonable, probably prudent. But I'm a fan of patience and persistence, and if you've read <a href="http://www.leerichardson.com/2017/07/your-code-sucks-get-over-it.html">Your Code Sucks, Get Over It</a>, you'll know I believe in the power of separating ego from work product, and objectively looking for areas of improvement. I requested feedback from a co-worker (thank you Josh Blanchard) and learned in short: too much noise, not enough signal.<br />
<div>
<div>
<br /></div>
<div>
According to Eric Ries in the Lean Startup (do read it if you haven't) a pivot "is a structured course correction designed to test a new fundamental hypothesis about the product, strategy, and engine of growth". I had my new hypothesis: bad signal to noise ratio. I pivoted.<br />
<br />
<h2>
What Even Is Code Hour?</h2>
</div>
<div>
If you asked me today what it is I'd say ... well, this 1 minute promo about covers it:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/yqi7Dki2IqY/0.jpg" frameborder="0" height="360" src="https://www.youtube.com/embed/yqi7Dki2IqY?feature=player_embedded" width="640"></iframe></div>
<div>
<br /></div>
<div>
Basically I took my coworkers feedback to heart: episodes are now heavily post-edited live coding that "maximizes signal and minimizes noise".</div>
<div>
<br /></div>
<div>
In short: <i>an hour of live coding in about 30 minutes.</i></div>
<div>
<br /></div>
<div>
The format is now a high level overview on development, typically .Net related topics, with post edited diagrams and visuals, then a dive into the implementation details. It pulls the best elements of live coding like: </div><div><br /></div>
<div>
<ul>
<li>Real world tricks and tips</li>
<li>Common pitfalls based on experience</li>
<li>The joy that only comes from solving hard, unexpected problems</li>
</ul>
</div>
<div><br /></div><div>
Except without all the boring elements of live coding like compiling and excessive typing.<br />
<br />
I've also moved away from Xamarin and toward ASP.Net Core and <a href="https://aspnetboilerplate.com/">ASP.Net Boilerplate</a> in particular, for which there seems to be a voracious appetite (big thanks to all the retweets and shares from the <a href="http://abp.io/">ABP.IO</a> team and fans). In fact my most popular episode is:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/xmHTYF5RvMs/0.jpg" frameborder="0" height="360" src="https://www.youtube.com/embed/xmHTYF5RvMs?feature=player_embedded" width="640"></iframe></div>
<br /></div>
</div>
<div>
(I'll be releasing an updated version for ABP.IO shortly)</div>
<div>
<br />
One downside: before the pivot I could knock out an episode in 60 minutes. Now each episode is 8-16 hours per 30 minute show (thus > monthly rather than weekly episodes). It's time well spent.<br />
<br /></div><div>The pivot didn't yield immediate results, but I'm happy to say that as of this week I hit a goal I'd never have imagined two years ago: 800 subscribers.</div><div>
<br />
<blockquote class="twitter-tweet">
<div dir="ltr" lang="en">
Just hit 800 YouTube subscribers! Doubling every 4 months, this is more infectious than ... yea something. Anyway, thank you! Got a fun Blazor WebAssembly episode coming up shortly, join if you haven't: <a href="https://t.co/70AlikCMyv">https://t.co/70AlikCMyv</a> <a href="https://t.co/5BNxbdHciM">https://t.co/5BNxbdHciM</a></div>
— Lee (P )?Richardson 🚨 (@lprichar) <a href="https://twitter.com/lprichar/status/1283036848546295817?ref_src=twsrc%5Etfw">July 14, 2020</a></blockquote>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script><br />
<div>Ultimately sharing knowledge in video form has turned out to be approachable, exciting, and rewarding just like Daniel Shiffman and Scott Hanselman promised. It just required some patience, persistence, and finding the right audience. I've certainly learned a ton and had fun.<br /></div><div><br /></div></div>
<h2>
What's the Point?</h2>
<div>
I guess what I'm saying is: <a href="https://www.youtube.com/leerichardson200">subscribe</a> if you haven't. There's an upcoming episode on Blazor Web Assembly you'll love. But more importantly thank you to everyone that's provided inspiration: Scott Hanselman, Daniel Shiffman, Eric Reis, Josh Blanchard, the folks at ABP.IO, and to everyone who's shared, liked, commented and subscribed. You all rock! Thank you!<br />
<br />
But more importantly if you have an idea: be prepared to find inspiration in unexpected places, don't give up if your first version sucks, and be prepared to dispassionately analyze and improve. The world needs your idea. Now go do it!</div>
Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-41878793910472726362020-06-23T06:47:00.005-05:002020-06-24T09:27:25.293-05:00Secure External APIs with API Keys - and Keep the Villains at Bay<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_DWq06bum1w_I_OHRGO6je_2M0xnaR75aUxflNVoSjj1Keit4zlKsGGOhiets3n1tokuEc6mKvEcysDVzu-rYdE41FrrLJoSvdoY5qYKv7jbPaF1zfFdiEjQt9QJ7TZ7bEAvxwSOFANQ/s5472/ali-kokab-Yv2HzOr8jAA-unsplash.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3648" data-original-width="5472" height="416" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_DWq06bum1w_I_OHRGO6je_2M0xnaR75aUxflNVoSjj1Keit4zlKsGGOhiets3n1tokuEc6mKvEcysDVzu-rYdE41FrrLJoSvdoY5qYKv7jbPaF1zfFdiEjQt9QJ7TZ7bEAvxwSOFANQ/w625-h416/ali-kokab-Yv2HzOr8jAA-unsplash.jpg" width="625" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Suppose you've written a web app and exposed an external REST API based on Swagger and Swashbuckle in an ASP.Net Core site. Perhaps you blindly followed some rando's recent <a href="http://www.leerichardson.com/2020/05/mastering-external-web-apis-in-aspnet.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">blog post</a> about it, published it to production, and your customers are super happy except: Horrors, you've just realized you forgot to secure it and now it's open to all the villains of the Internet! Worse, your customers don't want to use their existing credentials, they want something called API Keys. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Good news: you've just stumbled on said <a href="https://twitter.com/lprichar" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">rando</a>'s follow-up blog post about how to secure those external web API's, and even better it's got diagrams, detailed videos, and a whole working <a href="https://github.com/lprichar/LeesStore/pull/16" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Pull Request</a> in a sample GitHub repo. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">One caveat: this post is fairly specific to the security model in the <a href="http://www.leerichardson.com/2019/05/be-hero-on-day-1-with-aspnet-boilerplate.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ASP.Net Boilerplate</a> framework, but even if you're not using that framework, this technique should be generally applicable.</p><div class="separator" style="clear: both;"><h2 id="what-are-api-keys" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.8em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">What Are API Keys?</h2><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The idea of API Keys is fairly standard with systems that offer an external API. They offer customers a way to connect to an API with credentials that are separate from their own. More importantly API Keys offer limited access, a critical element of a good security model. API Keys can't, for instance, log in to the site and create new API Keys, or manage users. They can only perform the limited actions that the external Web API grants. If the credentials become compromised, users can reject or delete them without affecting their own credentials.</p></div><div><img border="0" data-original-height="517" data-original-width="828" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkCcsfm2PdmKBaUORnqvska6kvIIOy05LLOEtbDzr-9nwEmhCVQzqUWDkt40n5QJlxI4Q6Tn8SjgpWvpOh7HT86Dvqc0m_vq3jwUx68PYAqzOUB2xauJool9zAtR8aHXQ5jxzZcn30saw/w640-h400/SecuringApisArchitecture-1.png" width="640" /></div><div><br /></div><div><h2 id="data-structure" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Data Structure</h2></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The first step in implementing API Keys is to design the data structure and build out the CRUD for the UI. Well, the CRD, anyway, updating API Keys doesn't make much sense.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Conveniently enough ASP.Net Boilerplate already provides a Users entity that ostensibly offers a superset of everything required. ASP.Net Boilerplate Users can have multiple Roles and each of those Roles can have multiple Permissions. </p><div><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjthyphenhyphenfddJAgo7cmFnOdvreW3iWkvJ3ukGLolafjymtAmTrzShvD4Nj8Vsg2yuJ61dSjMAZuN3f3dncTZcIAVASb5ZVr8SWjyzCerEg5T0F3bSY0L6vZOVSTeJz4pt36qyTMSwtqP3IJzOo/s727/UsersPermissionsCrowsFeet.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="74" data-original-width="727" height="64" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjthyphenhyphenfddJAgo7cmFnOdvreW3iWkvJ3ukGLolafjymtAmTrzShvD4Nj8Vsg2yuJ61dSjMAZuN3f3dncTZcIAVASb5ZVr8SWjyzCerEg5T0F3bSY0L6vZOVSTeJz4pt36qyTMSwtqP3IJzOo/w625-h64/UsersPermissionsCrowsFeet.png" width="625" /></a></div> </span></div><div><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;"><br /></span></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Developers can then restrict access to methods and classes via the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">AbpAuthorize("SomePermission")</code> attribute, which takes a Permission as a parameter. When an end user makes a request to an endpoint ABP determines the user from a bearer token in the request header, figures out their roles, and figures out which permissions belong to those roles. If one of those permissions matches the requirement in the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">AbpAuthorize()</code> attribute, the call is allowed through.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">API Keys should be similar. As far as fields they'll have an "API Key" instead of "Username", and a "Secret" instead of a "Password". Unlike users they'll likely only need one permission for decorating the external API instead of many. Thus, they'll have just a single Role to help link the single permission to the API Keys.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Therefore, implementing this should be as simple as having ApiKey inherit from User and pretend that Username is ApiKey and Password is Secret.</p><div><br /></div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrErVkqQ5Ry5VxVYSUNVfP5O4YAp3BayXc0rVL4WqGnkwP_9bYGriPg4nnykTa7CxRQaGnJXS2A1cnpmTOaIv-PVKCl43BaWeBy47nSx45p8_Htp6Sk-TFJ_bbjWPwa3zRtd4cqLFzjK4/" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="326" data-original-width="425" height="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrErVkqQ5Ry5VxVYSUNVfP5O4YAp3BayXc0rVL4WqGnkwP_9bYGriPg4nnykTa7CxRQaGnJXS2A1cnpmTOaIv-PVKCl43BaWeBy47nSx45p8_Htp6Sk-TFJ_bbjWPwa3zRtd4cqLFzjK4/w410-h314/ApiKeyInheritance.png" width="410" /></a></div></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;"><h2 id="crudy-keys" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Crudy Keys</h2><div><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;">Last month this rando also published an</span><span style="color: #313b3f; font-family: georgia, serif; font-size: 20px;"> </span><a href="http://www.leerichardson.com/2020/05/abp-crud-cheat-sheet-how-to-add-entity.html" style="border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-size: 20px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ABP CRUD Cheat Sheet</a><span style="color: #313b3f; font-family: georgia, serif; font-size: 20px;"> </span><span style="background-color: white; font-family: georgia, serif; font-size: 20px;"><font color="#313b3f">to help build out CRUD for new entities in ASP.Net Boilerplate apps. Following that guide for creating API Keys would be a great place to start. I'll include the original step and any customizations below. Also, if you want to follow along visually this dude also posted a video of the process including explaining topics like Table-Per-Hierarchy inheritance and published it as an episode to something called </font><a href="https://youtube.com/leerichardson200"><font color="#000000">Code Hour</font></a><font color="#313b3f"> (to which you should totally </font><font color="#000000">subscribe</font><font color="#313b3f">):</font></span></div><div><span style="background-color: white; font-family: georgia, serif; font-size: 20px;"><font color="#313b3f"><br /></font></span></div><div style="text-align: center;"><font color="#313b3f" face=""><span style="background-color: white; font-size: 20px;"><iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/8t0fhqrJT5o" width="560"></iframe></span></font></div><div><br /></div><h3 id="a1-add-entity" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A1. Add Entity</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The ApiKey contains zero additional columns:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKey</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">User</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><h3 id="a2-add-to-db-context" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A2. Add to DB Context</h3><h3 id="a3-add-migration" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A3. Add Migration</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The addition of inheritance to the User entity means Entity Framework will add a discriminator column because Entity Framework Core prefers the <a href="https://docs.microsoft.com/en-us/ef/core/modeling/inheritance" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Table per Hierarchy</a> inheritance strategy. It will take care of setting that discriminator column for all future data, but it won't for older data. To address that add either a second migration or add this to the first migration:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;">migrationBuilder<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Sql</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"UPDATE AbpUsers SET Discriminator = 'User'"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></code></pre><h3 id="a4-update-database" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A4. Update Database</h3><h3 id="a5-add-dto" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A5. Add DTO</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The only field we want to expose when viewing API Keys is the key (username). We want a custom mapping from Username to ApiKey when AutoMapper converts it. Therefore we want a DTO like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKeyDto</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EntityDto</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">long</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Required</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">StringLength</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>AbpUserBase<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>MaxUserNameLength<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> ApiKey <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And a mapping profile like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKeyDtoProfile</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Profile</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKeyDtoProfile</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token generic-method" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateMap</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKey</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKeyDto</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ForMember</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>i <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> i<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ApiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> opt <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> opt<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">MapFrom</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>i <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> i<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>UserName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><h3 id="a6-register-a-permission" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A6. Register a Permission</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">context.CreatePermission(PermissionNames.Pages_ApiKeys, L("ApiKeys"), multiTenancySides: MultiTenancySides.Host);</code></p><h3 id="a7-appservice" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A7. AppService</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The AppService has three things of note. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">First, the Create DTO is different from the View DTO, because users send in a Secret but never get one back. We can solve that by making a CreateApiKeyDto that inherits from the view DTO and customizes the final generic parameter</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AutoMapFrom</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">typeof</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>ApiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateApiKeyDto</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKeyDto</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Required</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">StringLength</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>AbpUserBase<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>MaxPlainPasswordLength<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> Secret <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AbpAuthorize</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>PermissionNames<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Pages_ApiKeys<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKeysAppService</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AsyncCrudAppService</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>ApiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> ApiKeyDto<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">long</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> PagedAndSortedResultRequestDto<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> CreateApiKeyDto<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Second, we need a custom method to retrieve unique API Keys and Secrets. A quick naive version would look like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateApiKeyDto</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">MakeApiKey</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateApiKeyDto</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
ApiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> User<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateRandomPassword</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
Secret <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> User<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateRandomPassword</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Finally, when we create ApiKeys we need to put in some fake value in the various required user fields, but most importantly we need to hash the secret with an <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">IPasswordHasher<User></code>.</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">override</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> Task<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>ApiKeyDto<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateApiKeyDto</span> input<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> fakeUniqueEmail <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> input<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ApiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">+</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"@noreply.com"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> apiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKey</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
UserName <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> input<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ApiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
EmailAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> fakeUniqueEmail<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
Name <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"API Key"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
Surname <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"API Key"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
IsEmailConfirmed <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
NormalizedEmailAddress <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> fakeUniqueEmail
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Password <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> _passwordHasher<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HashPassword</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> input<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Secret<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _userManager<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> apiRole <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _roleService<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EnsureApiRole</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _userManager<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SetRolesAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> apiRole<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Name <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> CurrentUnitOfWork<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SaveChangesAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ApiKeyDto</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
Id <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Id<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
ApiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>UserName
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That call to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">_roleService.EnsureApiRole()</code> basically just creates a Role and a Permission that we can decorate our external API calls with.</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// <summary></span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// ApiKeys should have the API permission. Users/ApiKeys must get permissions by association with a Role.</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// This code finds and returns a role called API or if it doesn't exist it creates and returns a role</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// called API that has the API permission. This code is called when an API Role is created. Thus, the API</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// role is created the 1st time a user creates an API Key for a tenant.</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// </summary></span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> Task<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>Role<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EnsureApiRole</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> apiRole <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _roleRepository<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetAll</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FirstOrDefaultAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>i <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> i<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Name <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">==</span> RoleNames<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Api<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiRole <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">!=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> apiRole<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> permissions <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> _permissionManager<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetAllPermissions</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Where</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>i <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> i<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Name <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">==</span> PermissionNames<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Api<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
apiRole <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Role</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
TenantId <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> CurrentUnitOfWork<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetTenantId</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
Name <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> RoleNames<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Api<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
DisplayName <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"API"</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _roleManager<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiRole<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _roleManager<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SetGrantedPermissionsAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiRole<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> permissions<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> apiRole<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><h3 id="a8-run-app-see-swagger-update-rejoice" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A8. Run App, See Swagger Update, Rejoice</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Great, the API is finished:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUHRfpr24NAUcyVgHYXIG1appEo3DJmujW32rhvqsCKlIOKzKraLqBx5LyPD1lS_dt16DxwCziZF49qSbblBc_OjpT4FBWnEMdvtqiHx8KxPDLJZ6KpBf6LxNsKcF91UH7uTE0jU8Id6c/s1743/ApiKeysSwagger.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1743" data-original-width="1398" height="781" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUHRfpr24NAUcyVgHYXIG1appEo3DJmujW32rhvqsCKlIOKzKraLqBx5LyPD1lS_dt16DxwCziZF49qSbblBc_OjpT4FBWnEMdvtqiHx8KxPDLJZ6KpBf6LxNsKcF91UH7uTE0jU8Id6c/w626-h781/ApiKeysSwagger.jpg" width="626" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><div><h3 id="b1-update-nswag" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B1. Update nSwag</h3><h3 id="b2-register-service-proxy" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B2. Register Service Proxy</h3><h3 id="b3-update-left-hand-nav" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B3. Update Left-Hand Nav</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">B4. Duplicate Tenant Folder and Find/Replace "Tenant" with "[Entity]" and "tenant" with "[entity]"</p><h3 id="b5-update-routeb6-register-new-components-in-app-module-ts" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B5. Update Route</h3><h3 id="b5-update-routeb6-register-new-components-in-app-module-ts" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B6. Register New Components in app.module.ts</h3><h3 id="b5-update-routeb6-register-new-components-in-app-module-ts" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;"><span style="font-size: 2.5rem;">B7. Fix Fields, Customize ... Rejoice?</span></h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">With the back-end work finished, the front-end is fairly straightforward. Just delete the edit dialog and in the create dialog to set the DTO on init and pick up the random passwords:</p><pre class="language-typescript" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-typescript" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ngOnInit</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>apiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateApiKeyDto</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>apiKeyServiceProxy
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">generateApiKey</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">first</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">subscribe</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">this</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>apiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And add a "Copy To Clipboard" button:</p><pre class="language-html" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-html" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>mat-form-field</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>col-sm-12<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>input</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">matInput</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>text<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">name</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Key<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[(ngModel)]</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>apiKey.apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">required</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">placeholder</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Key<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">readonly</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">#keyInput</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>button</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">mat-icon-button</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">matSuffix</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">type</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>button<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(click)</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>copyInputToClipboard(keyInput)<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>mat-icon</span> <span class="token attr-name" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">matTooltip</span><span class="token attr-value" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span>Copy to clipboard<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>content_copy<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>mat-icon</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>button</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
<span class="token tag" style="border: 0px; box-sizing: inherit; color: #e2777a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token tag" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"></</span>mat-form-field</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span>
</code></pre><pre class="language-typescript" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-typescript" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">copyInputToClipboard</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>inputElement<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> HTMLInputElement<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
inputElement<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">select</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
document<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">execCommand</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'copy'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
inputElement<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">setSelectionRange</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">0</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">0</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And now users can add API Keys:</p></div><div><br /></div></div><div class="separator" style="clear: both; text-align: center;"><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDsgshfVUHHgwz23Zws-jNueUvhP8hG1JwOL3Ws8uDstG6HCem1X7ZD-2KWBmejtaH6OCSwLnLj4Q4G0vaYUkaLlNBrGqrOukEX5fKto0DnnVRVt8jpwilkgfAKGB0_dFDS5EFjaCemd8/" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1372" data-original-width="2341" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDsgshfVUHHgwz23Zws-jNueUvhP8hG1JwOL3Ws8uDstG6HCem1X7ZD-2KWBmejtaH6OCSwLnLj4Q4G0vaYUkaLlNBrGqrOukEX5fKto0DnnVRVt8jpwilkgfAKGB0_dFDS5EFjaCemd8/w640-h376/AddApiKeyUi.jpg" width="640" /></a></div></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">But API users still aren't authenticating with those API Keys.</p><h2 id="clienttokenauthcontroller" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.8em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">ClientTokenAuthController</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The existing SPA site authenticates a username, password and tenant by calling into the TokenAuthController class. If the credentials check out that class returns an access token that the client appends to subsequent requests.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiju_0l0LDk-MIwQX8fVc85R4CvpQ0aHOZQb1qd9DPQsLxEr48nMUl1qVON4Y70e9QCzvvBcVBpKy8te_iwr0V6je5On_a1sOL_Jf0VwwnqHN0_Wx2Vu_RRDW_I-z-8t7yQNLwCjtFL_gg/s1126/ApiKeysSequenceDiagram.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1126" height="593" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiju_0l0LDk-MIwQX8fVc85R4CvpQ0aHOZQb1qd9DPQsLxEr48nMUl1qVON4Y70e9QCzvvBcVBpKy8te_iwr0V6je5On_a1sOL_Jf0VwwnqHN0_Wx2Vu_RRDW_I-z-8t7yQNLwCjtFL_gg/w625-h593/ApiKeysSequenceDiagram.png" width="625" /></a></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The Web API should do the same thing. Mostly just copy and paste the existing TokenAuthController class into a ClientTokenAuthController and put it in the external API folder (\Client\V1 from my previous blog post). The main customization is that the ClientTokenAuthController should take an ApiKey and Secret, and it should <em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">not</em> take a tenant (if <a href="http://www.leerichardson.com/2019/12/multi-tenancy-is-hard-aspnet.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">multi-tenancy</a> is enabled) because the ApiKey is unique across tenants.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The full code for the ClientTokenAuthController is in <a href="https://github.com/lprichar/LeesStore/pull/16/commits/3ebfde7c00b93d2d34069059562b746ed7cad0c9" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">this commit</a>, but the relevant part looks like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// <summary></span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// Authenticates an API Key and Secret. If successful AuthenticateResultModel will contain a token that</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// should be passed to subsequent methods in the header as a Bearer Auth token.</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// </summary></span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// <param name="model">Contains the API Key and Secret</param></span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/// <returns>The authentication results</returns></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HttpPost</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"api/client/v1/tokenauth"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> Name <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">nameof</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>Authenticate<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProducesResponseType</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">typeof</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>AuthenticateResultModel<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">200</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DontWrapResult</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>WrapOnError <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">false</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> WrapOnSuccess <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">false</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> LogError <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> Task<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>IActionResult<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Authenticate</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FromBody</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ClientAuthenticateModel</span> model<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/*
* This 1st Authenticate() looks only in ApiKeys, which are assumed to be unique across Tenants (unlike Users),
* thus we can pull back a TenantId on success and set the session to use it
*/</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> apiKeyAuthenticationResult <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> _apiKeyAuthenticationService<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Authenticate</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>model<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ApiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> model<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Secret<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">!</span>apiKeyAuthenticationResult<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Success<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// this 401 is much cleaner than what the regular TokenAuthController returns. It does a HttpFriendlyException which results in 500 :|</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UnauthorizedObjectResult</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>_session<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Use</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>apiKeyAuthenticationResult<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>TenantId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">/*
* This 2nd Authenticate is almost entirely guaranteed to succeed except for a few edge cases like if the
* tenant is inactive. However, it's necessary in order to get a loginResult and create an access token.
*/</span>
AbpLoginResult<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>Tenant<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> User<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> loginResult <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetLoginResultAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>
model<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ApiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
model<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Secret<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetTenancyNameOrNull</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">OkObjectResult</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateAccessToken</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>loginResult<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And after placing that class in the Client.V1 namespace, the SwaggerFileMapperConvention (from <a href="http://www.leerichardson.com/2020/05/mastering-external-web-apis-in-aspnet.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Mastering External API's</a>) will expose it in Swagger</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcxQq8-UKGkXCh7WkVBNxpCPWdAgXuOmbgRdTZTm3OUFgR48D3xw0poEUaTnXokAAv0Eh7G3OnkpCguiUjF9r2NqK7My96AsOCHvzSOYUG-nsw4__sk94UqGPp6lCU023Y1TNHIFVyxU8/s1902/TokenAuthSwaggerUi.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1902" data-original-width="1725" height="625" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcxQq8-UKGkXCh7WkVBNxpCPWdAgXuOmbgRdTZTm3OUFgR48D3xw0poEUaTnXokAAv0Eh7G3OnkpCguiUjF9r2NqK7My96AsOCHvzSOYUG-nsw4__sk94UqGPp6lCU023Y1TNHIFVyxU8/w568-h625/TokenAuthSwaggerUi.jpg" width="568" /></a></div><div><br /></div><div><h2 id="authenticating-the-external-api" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Authenticating The External API</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Finally, the last step is to lock down the existing method and ensure (ala TDD) that client's can't get in. If you're a visual learner this section along with details about password hashing and AutoMapper details is covered in Code Hour Episode 29:</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: center; vertical-align: baseline;"><iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/F6s8j4jSGcs" width="560"></iframe></p><div class="separator" style="clear: both; text-align: center;"><br /></div><div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">With that shameful self-promotion out of the way, next register an API Permission. Unlike the earlier permission this one is for accessing API endpoints, not managing API Keys:</p></div><div><br /></div><div><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">context.CreatePermission(PermissionNames.Api, L("Api"), multiTenancySides: MultiTenancySides.Tenant);</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now restrict the external API's controller with that permission:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AbpAuthorize</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>PermissionNames<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Api<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductController</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LeesStoreControllerBase</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now if when clients hit the /api/client/v1/product endpoint, they get an HTTP 401. Excellent!</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">To authenticate with an API Key and Password call into ClientTokenAuthController with an API Key and Secret and save the token onto the ClientApiController:</p></div><div><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> authenticateModel <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ClientAuthenticateModel</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
ApiKey <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> apiKey<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
Secret <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> secret
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> authenticateResultModel <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> clientApiProxy<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AuthenticateAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>authenticateModel<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
clientApiProxy<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>AccessToken <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> authenticateResultModel<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>AccessToken<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> product <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> clientApiProxy<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetProductAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>productId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">What's that? You're following along and it didn't compile?! No AccessToken property on ClientApiProxy?! Oh, that's easy! Just use the fact that the NSwag generated proxy is partial and has a PrepareRequest partial method:</p></div><div><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">partial</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ClientApiProxy</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> AccessToken <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">get</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">set</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">partial</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">PrepareRequest</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">System<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Net<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Http<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>HttpClient</span> client<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">System<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Net<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Http<span class="token punctuation" style="border: 0px; box-sizing: inherit; color: #cccccc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>HttpRequestMessage</span> request<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">string</span> url<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>AccessToken <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">!=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
request<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Headers<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Authorization <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AuthenticationHeaderValue</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Bearer"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> AccessToken<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Huzzah! Now check out that happy 200:</p></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7NnQa459FiWF1UQnhxeTfwRUZKtiPW1Ntloc_xLFtK0j-YlADZPvInSPZgTgro8BGFXwkkeKVodzc-YqrQsCSPugYT4PE_f2ApqO7j4aH54rSGQe9ghfP5uVxmfLlggG8qhEd6hXCJjg/s717/AuthenticationSuccess.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="343" data-original-width="717" height="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7NnQa459FiWF1UQnhxeTfwRUZKtiPW1Ntloc_xLFtK0j-YlADZPvInSPZgTgro8BGFXwkkeKVodzc-YqrQsCSPugYT4PE_f2ApqO7j4aH54rSGQe9ghfP5uVxmfLlggG8qhEd6hXCJjg/w625-h299/AuthenticationSuccess.jpg" width="625" /></a></div><div><br /></div><div><h2 id="-we-did-it-" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">🎉 We Did It!!</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you made it to the end of this post I am deeply impressed. I hope it was useful. The code is at the <a href="https://github.com/lprichar/LeesStore/pull/16/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Api Keys Pull Request</a> in my <a href="https://github.com/lprichar/LeesStore" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ASP.Net Demo Site</a>. If you found this helpful or have a better approach please let me know <a href="https://twitter.com/lprichar" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">@twitter</a> or in the comments. Happy coding!</p></div><figure class="kg-card kg-embed-card kg-card-hascaption" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; display: flex; flex-direction: column; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"><div class="fluid-width-video-container" style="border: 0px; box-sizing: inherit; flex-grow: 1; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; width: 700px;"></div></figure></div>
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-83117555356519698002020-05-28T12:00:00.008-05:002020-05-30T18:04:54.880-05:00Mastering External Web API's in ASP.Net Core and ABP with Swagger, ApiExplorer, and NSwag<a class="gie-single" href="http://www.gettyimages.com/detail/157580156" id="t8LkbLQhTlxZhKbxlov_GA" style="border: none; color: #a7a7a7; display: inline-block; font-weight: normal; text-decoration: none;" target="_blank">Embed from Getty Images</a><script>window.gie=window.gie||function(c){(gie.q=gie.q||[]).push(c)};gie(function(){gie.widgets.load({id:'t8LkbLQhTlxZhKbxlov_GA',sig:'psVwgevfZBam9P5eW3bVNhSyS6eikcTaQ5EbMN-XsNo=',w:'640px',h:'426px',items:'157580156',caption: true ,tld:'com',is360: false })});</script><script async="" charset="utf-8" src="//embed-cdn.gettyimages.com/widgets.js"></script><div><br /></div><br /><div class="separator" style="clear: both; text-align: left;"><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;"><font color="#313b3f">Recently a customer asked me to build out a small end user facing web API in addition to the existing one used by my SPA (Angular) app. A few weeks later someone asked me how to do this on my YouTube </font><a href="https://youtube.com/leerichardson200"><font color="#000000">channel</font></a><font color="#313b3f">.</font></span></div><div class="separator" style="clear: both; text-align: left;"><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><blockquote style="background-color: white; border-bottom: 0px; border-image: initial; border-left: 3px solid rgb(62, 176, 239); border-right: 0px; border-top: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px 1.5em; quotes: none; text-align: start; vertical-align: baseline;"><div style="text-align: left;">Excellent video!!! I have the same project and I am trying to add a second webapi to be used in a couple of pages, but I don't know where to start. Any example? Thanks</div><div style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: left; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;"><a href="https://www.youtube.com/watch?v=xmHTYF5RvMs&lc=UgzwN3P6Pk7c3o2R97N4AaABAg" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;"></a><a href="https://www.youtube.com/watch?v=xmHTYF5RvMs&lc=UgzwN3P6Pk7c3o2R97N4AaABAg" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Alejandro Souza</a></div></blockquote><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;"><font color="#313b3f">This seemed like a great opportunity to blog about my experience and share the knowledge of my approach and solution with a wider audience. </font><span style="background-color: transparent; color: #313b3f; text-align: center;">I also recorded this as an episode of </span><a href="https://www.youtube.com/leerichardson200" style="background-color: transparent; text-align: center;"><font color="#000000">Code Hour</font></a><span style="background-color: transparent; color: #313b3f; text-align: center;"> if you're more of a visual learner.</span></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;"></p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="360" src="https://www.youtube.com/embed/AmmW2MNTR-Y" width="640" youtube-src-id="AmmW2MNTR-Y"></iframe></div><span style="background-color: transparent; text-align: center;"><br /></span><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;">My current application is built on <a href="https://aspnetboilerplate.com/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ASP.Net Boilerplate</a> with the Angular template. While that isn't strictly important to this story, what is, is that it's an ASP.Net Core app with where <a href="https://github.com/domaindrivendev/Swashbuckle" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Swashbuckle</a> (a tool to "Generate beautiful API documentation") generates a Swagger document.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;">I initially considered adding an additional micro service to the Kubernetes cluster that my site is deployed in. The problem was that the new API was small, and the amount of work involved in setting up security, DI, logging, app settings, configuration, docker, and Kubernetes port routing seemed excessive.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: left; vertical-align: baseline;">I wanted a lighter weight alternative that extended my existing security model and kept my existing configuration. Something like this:</p><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVz8HIyWamvR5essffaRD3gaUhZKVKmQ3xSoUEJ55IITNnuJyiAPSyI5xDP6nfAerbgRttw_Lj6JO0347GSWr0gU0k83EQd9r9XmxFwn7db3_ZidNyrtXZCOqaQP-Q26ku8H3GcfXtxTA/" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="505" data-original-width="752" height="430" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVz8HIyWamvR5essffaRD3gaUhZKVKmQ3xSoUEJ55IITNnuJyiAPSyI5xDP6nfAerbgRttw_Lj6JO0347GSWr0gU0k83EQd9r9XmxFwn7db3_ZidNyrtXZCOqaQP-Q26ku8H3GcfXtxTA/w640-h430/MoreApisArchitecture.png" width="640" /></a></div><div style="text-align: left;"><h2 id="more-cowbell-swagger" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">More <s style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 32px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Cowbell</s> Swagger</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Adding a second swagger file to my existing web app was <a href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore#generate-multiple-swagger-documents" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">relatively easy</a>. Controlling what was in it, less so.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">To add that second swagger file I just had to call .SwaggerDoc a second time in services.AddSwaggerGen in Startup.cs</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2">services<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AddSwaggerGen</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>options <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token comment" style="border: 0px; box-sizing: inherit; color: #999999; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">// add two swagger files, one for the web app and one for clients</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SwaggerDoc</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"v1"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">OpenApiInfo</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
Title <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStore API"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
Version <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"v1"</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SwaggerDoc</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"client-v1"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">OpenApiInfo</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
Title <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStore Client API"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
Version <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"client-v1"</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Technically this is saying that I have two versions of the same API, rather than two separate API's, but the effect is the same. The 1st swagger file is exposed at http://localhost/swagger/v1/swagger.json, and the second one is exposed at http://localhost/swagger/client-v1/swagger.json.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That's a start. If you love the Swagger UI that Swashbuckle provides as much as I do, you'll agree it's worth trying to add both swagger files to it. That turned out to be easy with a second call to .SwaggerEndpoint in the UseSwaggerUI call in Startup.cs:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2">app<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">UseSwaggerUI</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>options <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> baseUrl <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> _appConfiguration<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"App:ServerRootAddress"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EnsureEndsWith</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'/'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SwaggerEndpoint</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>
$<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"{baseUrl}swagger/v1/swagger.json"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStore API V1"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SwaggerEndpoint</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>
$<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"{baseUrl}swagger/client-v1/swagger.json"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStore Client API V1"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></font>
</code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now I could choose between the two swagger files in the "Select a definition" dropdown in the top right:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqv-03Yv6Gjfs2oFWEWoPSqAmVb1A4c4M39cqJHrlTlPbCkKU8j6Yh8JMup1Y-51V1okDeXbjlcAaxlMZV0ucMjDzMfYq2_9jde9-K_eUwVWtWSmEn4dv9yD1t7xHHfvWsdrbQipKOqHE/" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="761" data-original-width="594" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqv-03Yv6Gjfs2oFWEWoPSqAmVb1A4c4M39cqJHrlTlPbCkKU8j6Yh8JMup1Y-51V1okDeXbjlcAaxlMZV0ucMjDzMfYq2_9jde9-K_eUwVWtWSmEn4dv9yD1t7xHHfvWsdrbQipKOqHE/w500-h640/SwaggerUI.png" width="500" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That's pretty nice, right?</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Except: both pages look identical. That's because all methods are currently included in both definitions.</p><h2 id="exploring-the-apiexplorer" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.8em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Exploring the ApiExplorer</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">To solve that, I needed to dig a little into how Swashbuckle works. It turns out that internally it uses <a href="https://andrewlock.net/introduction-to-the-apiexplorer-in-asp-net-core/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ApiExplorer</a>, an API metadata layer that ships with ASP.Net Core. And in particular, it uses the ApiDescription.GroupName property to determine which methods to put in which files. If the property is null or it's equal to the document name (e.g. "client-v1"), then Swashbuckle includes it. And, it's null by default, which is why both Swagger files are identical.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">There are two ways to set GroupName. I could have set it by setting the <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.apiexplorersettingsattribute?view=aspnetcore-3.1" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ApiExplorerSettings</a> attribute on every single method of my controllers, but that would have been tedious and hard to maintain. Instead, I chose the magical route.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; text-align: center; vertical-align: baseline;"><iframe allowfullscreen="" class="giphy-embed" frameborder="0" height="440" src="https://giphy.com/embed/12NUbkX6p4xOO4" width="480"></iframe></p><p><a href="https://giphy.com/gifs/shia-labeouf-12NUbkX6p4xOO4">via GIPHY</a></p><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That involves registering an action convention and assigning actions to documents based on namespaces, like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">SwaggerFileMapperConvention</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">IControllerModelConvention</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">void</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Apply</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ControllerModel</span> controller<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> controllerNamespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> controller<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">?</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ControllerType<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">?</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Namespace<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">if</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>controllerNamespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">==</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> namespaceElements <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> controllerNamespace<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Split</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'.'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> nextToLastNamespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> namespaceElements<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ElementAtOrDefault</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>namespaceElements<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Length <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">-</span> <span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">2</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">?</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ToLowerInvariant</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> isInClientNamespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> nextToLastNamespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">==</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"client"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
controller<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>ApiExplorer<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>GroupName <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> isInClientNamespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">?</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"client-v1"</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"v1"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"></p><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; border: 0px; box-sizing: inherit; display: flex; flex-direction: column; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"><div class="fluid-width-video-container" style="border: 0px; box-sizing: inherit; flex-grow: 1; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; width: 700px;"></div></figure><p></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you run that you'll see that everything is still duplicated. That's because of this sneaky line in Startup.cs</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2">services<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AddSwaggerGen</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>options <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
options<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DocInclusionPredicate</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>docName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> description<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></font></code></pre><p style="-webkit-text-stroke-width: 0px; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-style: normal; font-variant-caps: normal; font-variant-east-asian: inherit; font-variant-ligatures: normal; font-variant-numeric: inherit; font-weight: 400; letter-spacing: normal; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; orphans: 2; padding: 0px; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; widows: 2; word-spacing: 0px;"></p><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: center; border: 0px; box-sizing: inherit; display: flex; flex-direction: column; font-family: georgia, serif; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline; width: 700px;"><div class="fluid-width-video-container" style="border: 0px; box-sizing: inherit; flex-grow: 1; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; width: 700px;"></div></figure><p></p><p style="-webkit-text-stroke-width: 0px; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-style: normal; font-variant-caps: normal; font-variant-east-asian: inherit; font-variant-ligatures: normal; font-variant-numeric: inherit; font-weight: 400; letter-spacing: normal; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; orphans: 2; padding: 0px; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; widows: 2; word-spacing: 0px;">The DocInclusionPredicate wins when there's a conflict. If we take that out then, well, Radiohead says it best:</p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="360" src="https://www.youtube.com/embed/onRk0sjSgFU" width="640" youtube-src-id="onRk0sjSgFU"></iframe></div><h2 id="consuming-the-swagger" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Consuming the Swagger</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In case you've somehow missed it, I'm a <a href="http://www.leerichardson.com/2018/05/continuous-integration-logic-4-hidden.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">big fan of Cake</a>. It's a dependency management tool (like Make, Rake, Maven, Grunt, or Gulp) that allows writing scripts in C#. It contains a plugin for NSwag, which is one of several tools for auto-generating proxies from swagger files. I thus generated a proxy like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token preprocessor property" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">#addin nuget:?package=Cake.CodeGen.NSwag&version=1.2.0&loaddependencies=true</span>
…
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Task</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"CreateProxy"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Description</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Uses nswag to re-generate a c# proxy to the client api."</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Does</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> filePath <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DownloadFile</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"http://localhost:21021/swagger/client-v1/swagger.json"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Information</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"client swagger file downloaded to: "</span> <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">+</span> filePath<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> proxyClass <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"ClientApiProxy"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> proxyNamespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"LeesStore.Cmd.ClientProxy"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> destinationFile <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">File</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"./aspnet-core/src/LeesStore.Cmd/ClientProxy/ClientApiProxy.cs"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> settings <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CSharpClientGeneratorSettings</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
ClassName <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> proxyClass<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
CSharpGeneratorSettings <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
Namespace <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> proxyNamespace
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
NSwag<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">FromJsonSpecification</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>filePath<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GenerateCSharpClient</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>destinationFile<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> settings<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Ran it with <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">build.ps1 -target CreateProxy</code> or <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">build.sh -target CreateProxy</code> on Mac/linux, and out popped a strongly typed ClientApiProxy class that I could consume in a console like this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">using</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> httpClient <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HttpClient</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> clientApiProxy <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">new</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ClientApiProxy</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"http://localhost:21021/"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> httpClient<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">var</span> product <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">await</span> clientApiProxy<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductAsync</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>productId<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
Console<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">WriteLine</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>$<span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Your product is: '{product.Name}'"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span></font></code></pre><h2 id="-not-so-fast" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">🎉? ... Not So Fast</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Happy ending, everyone wins right? Not quite. If you're running in ASP.Net Boilerplate that always returns <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">Your product is ""</code>. Why? The quiet failure was tricky to track down. Watching site traffic in Fiddler I saw this:</p><pre class="language-javascript" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-javascript" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"result"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"name"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"The Product"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"quantity"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">0</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"id"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">2</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"targetUrl"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"success"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token boolean" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"error"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"unAuthorizedRequest"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token boolean" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">false</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"__abp"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token boolean" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That seems reasonable at first glance. However, that won't deserialize into a ProductDto because the ProductDto in the JSON is inside a "result" object. The wrapping feature is how (among other things) ABP returns UserFriendlyException messages to the user in nice modal dialogs.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnmywuhtHdiuKXLwCqat1FbCAic1vbStqhHbgUedAPC6tDicRMBIn7jhyphenhyphen0EP9vi0ED9kbaSQCB9VmKOImCrpo616_h7XYul-8PjOgCSm2q2KB8ZA4FFJNKtssFeHoruYlwgfnaT2fK9HQ/" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="632" data-original-width="1239" height="326" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnmywuhtHdiuKXLwCqat1FbCAic1vbStqhHbgUedAPC6tDicRMBIn7jhyphenhyphen0EP9vi0ED9kbaSQCB9VmKOImCrpo616_h7XYul-8PjOgCSm2q2KB8ZA4FFJNKtssFeHoruYlwgfnaT2fK9HQ/w640-h326/AnErrorOccurred.jpg" width="640" /></a></div><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The above screenshot came from JSON like this:</p><pre class="language-javascript" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-javascript" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"result"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"targetUrl"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"success"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token boolean" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">false</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"error"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"code"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">0</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"message"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"Dude, an exception just occurred, maybe you should check on that"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"details"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"validationErrors"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"unAuthorizedRequest"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token boolean" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">false</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"__abp"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token boolean" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The solution turned out to be pretty easy. Putting a DontWrapResult attribute onto the controller:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">DontWrapResult</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>WrapOnError <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">false</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> WrapOnSuccess <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">false</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> LogError <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">true</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductController</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LeesStoreControllerBase</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Resulted in nice clean JSON</p><pre class="language-javascript" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-javascript" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"name"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"The Product"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"quantity"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">0</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"id"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="token number" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">2</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And the console app writing <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">Your product is "The Product"</code>.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Fantastic.</p><h2 id="final-tips-and-tricks" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.8em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Final Tips and Tricks</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">One last thing. That method name "ProductAsync" seems a bit unfortunate. Where did it even come from?</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Turns out when I wrote this:</p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">HttpGet</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">"api/client/v1/product/{id}"</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">async</span> Task<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>ProductDto<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">GetProduct</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span> id<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span></font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The ApiExplorer only exposed the endpoint, not the method name. Thus Swashbuckle didn't include an operationId in the Swagger file and NSwag was forced to use elements in the endpoint to come up with a name. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The fix is to specify the name so Swashbuckle can generate an operationId. That's easy with the Name property in the HttpGet or HttpPost attribute. And thanks to nameof in C# 6 we can keep it strongly typed.</p><pre style="background: rgb(14, 15, 17); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #e5eff5; font-family: monospace, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.5em; margin-bottom: 3em; margin-top: 1.5em; max-width: 100%; min-width: 100%; overflow-x: auto; padding: 20px; vertical-align: baseline;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><font size="2">[HttpGet("api/client/v1/product/{id}", Name = nameof(GetProduct))]
public async Task<ProductDto> GetProduct(int id)</font></code></pre><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And that generates the <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">await clientApiProxy.GetProductAsync(productId);</code> I would expect.</p><h2 id="conclusion" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.8em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Conclusion</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">This post is the story of how to generate an unauthenticated client. Check back soon for a follow-up on how to generate API Keys to perform authentication and authorization on an external Web API.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In the meantime all the code is runnable in the <a href="https://github.com/lprichar/LeesStore/tree/multiple-apis" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">multiple-api's</a> branch or perusable in the <a href="https://github.com/lprichar/LeesStore/pull/15" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Multiple API's</a> Pull Request of the <a href="https://github.com/lprichar/LeesStore" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">LeesStore</a> demo site. I hope this is helpful. If so let me know on twitter <a href="https://twitter.com/lprichar" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">@lprichar</a> or in the comments.</p></div></div>
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-970607568355640572020-05-20T14:11:00.006-05:002020-05-26T11:43:22.538-05:00ABP CRUD Cheat Sheet: The Distilled, Essential Steps to Add an Entity in ASP.Net Boilerplate with Angular<p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"></p><figure class="kg-card kg-embed-card" style="-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: vertical; -webkit-text-stroke-width: 0px; align-items: center; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; display: flex; flex-direction: column; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-style: normal; font-variant-caps: normal; font-variant-east-asian: inherit; font-variant-ligatures: normal; font-variant-numeric: inherit; font-weight: 400; letter-spacing: normal; line-height: inherit; margin: 0.8em 0px 2.3em; orphans: 2; padding: 0px; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; widows: 2; width: 700px; word-spacing: 0px;"><div class="fluid-width-video-container" style="border: 0px; box-sizing: inherit; flex-grow: 1; font-family: inherit; font-size: 20px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; width: 700px;"></div></figure><p></p><div class="separator" style="clear: both; text-align: left;"><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;">While the process of making Create, Read, Update, and Delete (CRUD) pages in ASP.Net Boilerplate is</span><span style="color: #313b3f; font-family: georgia, serif; font-size: 20px;"> </span><a href="https://aspnetboilerplate.com/Pages/Documents/Articles/Introduction-With-AspNet-Core-And-Entity-Framework-Core-Part-1/index.html#ArticleMore" style="border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-size: 20px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">well documented</a><span style="color: #313b3f; font-family: georgia, serif; font-size: 20px;"> </span><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;">on their website, and while I did a detailed walk through in my video</span><span style="color: #313b3f; font-family: georgia, serif; font-size: 20px;"> </span><a href="https://youtu.be/xmHTYF5RvMs" style="border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-size: 20px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">E19: Be a Hero on Day 1 with ASP.Net Boilerplate</a><span style="color: #313b3f; font-family: georgia, serif; font-size: 20px;"> </span><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;">(particularly the demo starting at</span><span style="color: #313b3f; font-family: georgia, serif; font-size: 20px;"> </span><a href="https://youtu.be/xmHTYF5RvMs?t=2459" style="border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-size: 20px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">40:59</a><span style="background-color: white; color: #313b3f; font-family: georgia, serif; font-size: 20px;">), I feel the community could use a high level, quick, reference guide for starting the CRUD process from scratch with a new entity: an ABP CRUD Cheat Sheet.</span></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/xmHTYF5RvMs" width="320" youtube-src-id="xmHTYF5RvMs"></iframe></div><p style="-webkit-text-stroke-width: 0px; background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-style: normal; font-variant-caps: normal; font-variant-east-asian: inherit; font-variant-ligatures: normal; font-variant-numeric: inherit; font-weight: 400; letter-spacing: normal; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; orphans: 2; padding: 0px; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; widows: 2; word-spacing: 0px;"><br /></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Here are 15 steps broken down by server-side and client-side. They may seem complicated compared to adding an entity to a SharePoint or Power Apps app, but remember the end product is infinitely customizable, and when something goes wrong you can almost always code your way out of it.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">To use this reference I imagine you'd want to skim over it like a checklist each time you add a new entity to ensure you didn't forget anything. That's what I plan to do, anyway. I expect it will save me time and effort and reduce the unnecessary rework that comes with missing a step. Hopefully it will for you too.</p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Quick note: For readability when you see "Product" substitute your entity name. When you see "Category" substitute a foreign table. When you see "LeesStore", substitute your project name. These were the entities I used in the video, and on my <a href="https://github.com/lprichar/LeesStore" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">ABP Demo Site</a>, and I feel they read better than [EntitySingular] or [EntityPlural].</p><h2 id="a-server-side" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.8em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A. Server-Side</h2><h3 id="a1-add-entity" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.7em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A1. Add Entity</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LeesStore.Core/Products/Product.cs</em></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">public class Product : Entity<int> { ...}</code></p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">: IFullAudited</code> if you want a history of who created, deleted, and last edited and when</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">: ISoftDelete</code> if you're not doing auditing and want soft-deletes</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">: ICreationAudited</code> or <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">: IModificationAudited </code>if you're not doing full audit and want just last modified or creation info</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">: IMustHaveTenant</code> if you're doing multi-tenancy</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">[ForeignKey(nameof(Category))]public int CategoryId { get; set; }</code> in addition to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">public Category Category { get; set; }</code> if you want the ID of a foreign key</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">[Required]</code> to strings and foreign entities as needed</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">[MaxLength(255)]</code> to strings as needed</li></ul><h3 id="a2-add-to-dbcontext" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A2. Add to DbContext</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LeesStoreDbContext.cs</em></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">public DbSet<Product> Products { get; set; }</code></p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Migrations will show up empty if you forget to do this</li></ul><h3 id="a3-add-migration" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A3. Add Migration</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">Add-Migration "Add-Products"</code></p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Run from Package Manager Console window. Don't forget to set the Default project to [MyProject].EntityFrameworkCore or else you'll get:<br style="box-sizing: inherit;" /><br style="box-sizing: inherit;" />"No DbContext was found in assembly 'LeesStore.Web.Host'. Ensure that you're using the correct assembly and that the type is neither abstract nor generic."</li></ul><div><font color="#313b3f" face="georgia, serif"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1UF1s3yvHiWMevtye4GIpPcGinN5KiZKEKOSWa-8B6cZfEalKa5fktv7WQ45YB-wAk1-jRXaT3JlPT_Q9gbrswkmoXJp1zFLHpN4sW2X1-9kZCIx6kaX0SeKcdybuu3SHZkWgR88sOYY/" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="114" data-original-width="757" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1UF1s3yvHiWMevtye4GIpPcGinN5KiZKEKOSWa-8B6cZfEalKa5fktv7WQ45YB-wAk1-jRXaT3JlPT_Q9gbrswkmoXJp1zFLHpN4sW2X1-9kZCIx6kaX0SeKcdybuu3SHZkWgR88sOYY/w640-h96/PackageManagerConsole.jpg" width="640" /></a></div></font></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">Set Default Project in Package Manager Console</figcaption></figure><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Alternately: <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">dotnet ef migrations add Add-Products</code> from the LeesStore.EntityFrameworkCore directory</li></ul><h3 id="a4-update-database" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A4. Update Database</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Either:</p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">Update-Database</code> in Package Manager Console with Default project set per above; OR</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">dotnet ef database update</code> from the command line; OR</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Run the Migrator project, which is required if you are using one of the multi-database multi-tenant solutions (see <a href="http://www.leerichardson.com/2019/12/multi-tenancy-is-hard-aspnet.html" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Multi-Tenancy is Hard: ASP.Net Boilerplate Makes it Easy</a>) </li></ul><h3 id="a5-add-a-dto" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A5. Add a DTO</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LeesStore.Application/Products/Dto/ProductDto.cs</em></p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AutoMapFrom</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">typeof</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><font size="2">Product</font><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AutoMapTo</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">typeof</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><font size="2">Product</font><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductDto</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">EntityDto</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> … <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Copy over only fields that need to be updated to prevent <a href="https://andrewlock.net/preventing-mass-assignment-or-over-posting-in-asp-net-core/" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">overposting attacks</a></li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">AutoMapFrom and AutoMap to if it's a simple mapping. For more complex mappings instead add an auto-mapper profile:</li></ul><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductProfile</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Profile</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductProfile</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token generic-method" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateMap</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Product</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductDto</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span></span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ForMember</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>x <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> x<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><font size="2">LastModifiedByUsername</font><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> opt <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> opt<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">MapFrom</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>i <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> i<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>CreatorUser<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>UserName<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">[MaxLength(255)]</code>, <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">[Required]</code> , and other data annotations for server-side validation</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">: IValidatableObject</code> for custom validation</li></ul><h3 id="a6-register-a-permission" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A6. Register a Permission</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LeesStoreAuthorizationProvider.cs</em></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">context.CreatePermission(PermissionNames.Pages_Products, L("Products"), multiTenancySides: MultiTenancySides.Host);</code></p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">multiTenancySides is optional but you should treat it as required because the default value is both Host AND Tenant, which is probably wrong.</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Add your entity to LeesStore.xml or else localization will look bad in the UI</li></ul><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;"><text name="Projects" value="Projects" /></code></p><h3 id="a7-add-an-appservice" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A7. Add an AppService</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">LeesStore.Application/Products/ProductsAppService.cs</em></p><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AbpAuthorize</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>PermissionNames<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>Pages_Products<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">public</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">class</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ProductsAppService</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">AsyncCrudAppService</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><
</span> Product<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> ProductDto<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">int</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> PagedAndSortedResultRequestDto<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span> ProductDto
<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"> ></span></font></code></pre><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Either <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">[AbpAuthorize(SomePermission)]</code> or <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">[AbpAuthorize]</code> else it won't require authorization (it will be open to the Internet)</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">The final generic property should be a CreateEntityDto if creating has different bits</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Override <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">CreateFilteredQuery</code> if you need to .Include foreign entities e.g.</li></ul><pre class="language-csharp" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-size: 1.4rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-csharp" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">protected</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">override</span> IQueryable<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><</span>Product<span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> <span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateFilteredQuery</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="token class-name" style="border: 0px; box-sizing: inherit; color: #f8c555; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">PagedAndSortedResultRequestDto</span> input<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
<span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">return</span> <span class="token keyword" style="border: 0px; box-sizing: inherit; color: #cc99cd; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">base</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">CreateFilteredQuery</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>input<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="token function" style="border: 0px; box-sizing: inherit; color: #f08d49; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Include</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">(</span>i <span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="token operator" style="border: 0px; box-sizing: inherit; color: #67cdcc; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">></span> i<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">.</span>CreatorUser<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">;</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></font></code></pre><h3 id="a8-run-app-see-swagger-update-rejoice" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">A8. Run App, See Swagger Update, Rejoice</h3><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Ctrl+F5 (run without debugging starts your app fast)</li></ul><div><font color="#313b3f" face="georgia, serif"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj15V_7ssAkVTC2_ubB6h45VoSFowHsYrc24U0zIdOVRF38as7BCvpYLwWgwcQk2uZ-tHZ1ZhXkFuJZ7DeU4jHB5YtwEwgADKXwS6WMh3KrFXk5zEqCUSzF_MDvM156KaxjKkYvhyphenhyphenvVgR4/" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="937" data-original-width="1469" height="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj15V_7ssAkVTC2_ubB6h45VoSFowHsYrc24U0zIdOVRF38as7BCvpYLwWgwcQk2uZ-tHZ1ZhXkFuJZ7DeU4jHB5YtwEwgADKXwS6WMh3KrFXk5zEqCUSzF_MDvM156KaxjKkYvhyphenhyphenvVgR4/w640-h408/swagger.jpg" width="640" /></a></div></font></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">Swagger UI</figcaption></figure><h2 id="client-side" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Client-Side</h2><h3 id="b1-update-nswag" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.7em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B1. Update nSwag</h3><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">PC: \angular\nswag\refresh.bat</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Mac: <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">npx nswag run /runtime:NetCore31</code></li></ul><h3 id="b2-register-service-proxy" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B2. Register Service Proxy</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">src/shared/service-proxies/service-proxy.module.ts</em></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">ApiServiceProxies.ProductsServiceProxy,</code></p><h3 id="b3-update-left-hand-nav" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B3. Update Left-Hand Nav</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">src\app\layout\sidebar-nav.component.ts</em></p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">new MenuItem(this.l('Products'), 'Pages.Products', 'local_grocery_store', '/app/products’),</code></p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Replace <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">local_grocery_store</code> with an icon from <a href="https://material.io/resources/icons/?style=baseline" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">Material Icons</a></li></ul><h3 id="b4-duplicate-tenant-folder-and-find-replace-tenant-with-entity-and-tenant-with-entity-" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B4. Duplicate Tenant Folder and Find/Replace "Tenant" with "[Entity]" and "tenant" with "[entity]"</h3><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Within every file name; and</li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Inside of each file including .ts files and .html files</li></ul><h3 id="b5-update-route" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B5. Update Route</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">src\app\app-routing.module.ts</em></p><pre class="language-javascript" style="background: rgb(45, 45, 45); border-radius: 5px; border: 1px solid rgb(0, 0, 0); box-sizing: inherit; color: #cccccc; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-size: 1.4rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; hyphens: none; line-height: 1.5; margin-bottom: 0.5em; margin-top: 0.5em; max-width: 100%; min-width: 100%; overflow-wrap: normal; overflow: auto; padding: 1em; tab-size: 4; vertical-align: baseline; word-break: normal;"><code class="language-javascript" style="background: transparent; border-radius: 3px; border: 0px; box-sizing: inherit; font-family: consolas, monaco, "andale mono", "ubuntu mono", monospace; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; hyphens: none; line-height: inherit; margin: 0px; overflow-wrap: normal; padding: 0px; tab-size: 4; vertical-align: baseline; word-break: normal; word-spacing: normal;"><font size="2"><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span>
path<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'products'</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
component<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> ProductsComponent<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
data<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">{</span> permission<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token string" style="border: 0px; box-sizing: inherit; color: #7ec699; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">'Pages.Products'</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span>
canActivate<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">:</span> <span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">[</span>AppRouteGuard<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">]</span>
<span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="token punctuation" style="border: 0px; box-sizing: inherit; font-family: inherit; font-size: 14px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">,</span></font></code></pre><h3 id="b6-register-new-components-in-app-module-ts" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B6. Register new components in app.module.ts</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><em style="border: 0px; box-sizing: inherit; color: #090a0b; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">src\app\app.module.ts</em></p><ul style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Add all three components to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">declarations:</code></li><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Add both modal dialogs to <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline;">entryComponents:</code></li></ul><h3 id="b7-fix-fields-tidy-up-ui-rejoice" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 2.5rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3em; margin: 0.5em 0px 0.2em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">B7. Fix Fields, Tidy Up UI, Rejoice</h3><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Fix columns in the table of the main component and columns in the create and edit components. Fix linting errors, and anything that doesn't run. </p><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Relax. Smile. You did it. Well done! 😁</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHkGYKTldnK4gylbp9HJRvyMfpgYDglHeooq5eG_T9w-3RGMZA0yv9Q_PzXGWBt75xE7lrP5kZNlSQAGQlsz_qNXN8vAHKXadZEzHeI2ZHfLfmMN_Q3nf0L3N4KYcWbX37ZPbioUg-clA/" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1175" data-original-width="2087" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHkGYKTldnK4gylbp9HJRvyMfpgYDglHeooq5eG_T9w-3RGMZA0yv9Q_PzXGWBt75xE7lrP5kZNlSQAGQlsz_qNXN8vAHKXadZEzHeI2ZHfLfmMN_Q3nf0L3N4KYcWbX37ZPbioUg-clA/w640-h360/finalui.jpg" width="640" /></a></div><figure class="kg-card kg-image-card kg-card-hascaption" style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0.8em 0px 2.3em; padding: 0px; vertical-align: baseline;"><figcaption style="border: 0px; box-sizing: inherit; color: #5d7179; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 15px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.5em; margin: 1em 0px 0px; padding: 0px; text-align: center; vertical-align: baseline;">Completed UI for a new product</figcaption></figure><h2 id="conclusion" style="background-color: white; border: 0px; box-sizing: inherit; color: #090a0b; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 3.2rem; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.25em; margin: 0.5em 0px 0.4em; min-width: 100%; padding: 0px; text-rendering: optimizelegibility; vertical-align: baseline;">Conclusion</h2><p style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">If you found this useful please tweet at <a href="https://twitter.com/lprichar" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">@lprichar</a>, or add a comment and let me know. If you found a bug, please add a comment. If you'd rather see this as a github page, please tell me, I'm game. Otherwise: I hope this helps, and happy coding!</p>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-87143876341413932912020-02-24T21:39:00.000-05:002020-03-02T15:52:14.752-05:00Strongly Typed, Dependency Managed Azure in C#: Introducing Cake.AzureCLI<i>The story, nay legend, of providing strongly typed, cross platform, dependency managed access to all 2,935 Azure CLI commands in C#.</i><br />
<i><br />
</i> <br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhoU3NTaVKarO7BY6VV0iLajikSW6ofMz8RIO-Waw1GWnPT6yoIvpF8spgJxv45Oo2xAgNtkOOEvrZEo74DKe_ZSTgDNNDpcedA9dldAXJoKLU7ZBXYrlBjKX8UCqnfmZRCaDyD6b1mes/s1600/CakeAzureCliIntellisense.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="961" height="279" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhoU3NTaVKarO7BY6VV0iLajikSW6ofMz8RIO-Waw1GWnPT6yoIvpF8spgJxv45Oo2xAgNtkOOEvrZEo74DKe_ZSTgDNNDpcedA9dldAXJoKLU7ZBXYrlBjKX8UCqnfmZRCaDyD6b1mes/s640/CakeAzureCliIntellisense.gif" width="640" /></a></div><br />
You can now have strongly typed, cross platform, dependency managed access to all 2,935 Azure CLI commands in C#, with full intellisense including examples. That's because I just published a Cake plugin for AzureCLI called <a href="https://github.com/lprichar/Cake.AzureCli">Cake.AzureCli</a>.<br />
<br />
<br />
This blog post is a little about what it is and how to use it, but it's more about how I built it. That's because I had a blast solving this problem and my solution might even entertain you: parsing thousands of help files through the CLI, storing results in 16 meg intermediate JSON files, and code generating 276K lines of code with T4 templates.<br />
<div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsDcGNfjB7ESr3xBydHbm1nyPP7rN7V6_cbtfA-Fr3-VS7Lq2PVtE10rsHCg1CuxWPB1K0HNnmspcoSneuayhDOkuc3MLwE3WVNNMuO_VW9bcs7gFyn_JhhdELjjXenyd8jFyiYZJPTHE/s1600/YouDidWhatNow.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="800" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsDcGNfjB7ESr3xBydHbm1nyPP7rN7V6_cbtfA-Fr3-VS7Lq2PVtE10rsHCg1CuxWPB1K0HNnmspcoSneuayhDOkuc3MLwE3WVNNMuO_VW9bcs7gFyn_JhhdELjjXenyd8jFyiYZJPTHE/s640/YouDidWhatNow.jpg" width="640" /></a></div><div><br />
</div>In the process I apparently also broke Cake's static site generator.</div><div><br />
<blockquote class="twitter-tweet"><div dir="ltr" lang="en">We also have an issue adding the addin to the <a href="https://t.co/CiFD8bupHK">https://t.co/CiFD8bupHK</a> site, since the static site generator used to create the site runs into an out of memory exception. We have planned to migrate to <a href="https://twitter.com/statiqdev?ref_src=twsrc%5Etfw">@statiqdev</a> once available which should help in such scenarios.</div>— Pascal Berger (@hereispascal) <a href="https://twitter.com/hereispascal/status/1229521053174681600?ref_src=twsrc%5Etfw">February 17, 2020</a></blockquote><script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script><br />
Oops.<br />
<br />
But first, I suppose the most relevant information is the what and the how.<br />
<br />
<div style="border: 0px; box-sizing: inherit; font-stretch: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><h2>Have & Eat Your Cake.AzureCLI</h2><br />
This plugin runs in Cake. If you aren't familiar with cake, please check out Code Hour Episode 16, <a href="https://youtu.be/WbaR2-v6JXQ">Intro to Cake</a>, where I go over what it is and why you should care. </div></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/WbaR2-v6JXQ/0.jpg" frameborder="0" height="365" src="https://www.youtube.com/embed/WbaR2-v6JXQ?feature=player_embedded" width="650"></iframe></div><br />
<br />
If you don't have a spare hour right now: it's a dependency management system (like make, ant, maven, or rake) except in C#. It also has a huge plugin ecosystem, one that's now "slightly" larger with access to all of Azure CLI.<br />
<br />
Right, you didn't watch the video, and you're still skeptical, right? You're wondering what was wrong with the official <a href="https://www.nuget.org/profiles/azure-sdk">azure-sdk</a> nuget plugins. The answer is: they aren't Cake enabled and so they don't support dependency management. If that statement isn't meaningful to you, please, watch just the "Scripts" section of my talk starting at <a href="https://youtu.be/WbaR2-v6JXQ?t=548">9:08</a>. <br />
<br />
Now that you're 100% convinced let's dig in. Using Cake.AzureCLI is as simple as adding a preprocessor directive to pull it from NuGet:<br />
<div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: blue;">#addin "nuget:?package=Cake.AzureCli&version=1.2.0"</span></div></div>And then accessing commands like Az().. So a simple program to log in and list all your resource groups might look like this:<br />
<div><br />
</div><div><div style="line-height: 19px;"><div><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">var</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> target = Argument(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"target"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">, </span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"Default"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">); </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">var</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> username = Argument<</span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">string</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">>(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"username"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">, </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">null</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">); </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">var</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> password = Argument<</span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">string</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">>(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"password"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">, </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">null</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">); Task(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"Login"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">) .Does(() => { </span></span><span style="background-color: white; color: green; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">// 'az login' is accessed via Az().Login() </span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> Az().Login(</span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">new</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">AzLoginSettings</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> { Username = username, </span></span><span style="background-color: white; color: green; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">// all commands can be customized if necessary with a ProcessArgumentBuilder </span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> Arguments = </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">new</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">ProcessArgumentBuilder</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">() </span></span><span style="background-color: white; color: green; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">// anything appended with .AppendSecret() will be rendered as [REDACTED] </span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> </span></span><span style="background-color: white; color: green; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">// if cake is run with `-verbosity=diagnostic` </span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> .Append(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"--password"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">).AppendSecret(password) }); }); Task(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"ListResourceGroups"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">) .IsDependentOn(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"Login"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">) </span></span><span style="background-color: white; color: green; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">// yayy dependency management! </span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> .Does(() => { </span></span><span style="background-color: white; color: green; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">// listing names of all resource groups </span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> Information(</span></span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">"Resource Groups:"</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">); </span></span><span style="background-color: white; color: green; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">// all results are strongly typed as dynamic if results are json </span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">dynamic</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> allResourceGroups = Az().Group.List(</span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">new</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">AzGroupListSettings</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;">()); </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">foreach</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> (</span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">var</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> resourceGroup </span></span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">in</span><span style="font-family: "consolas" , "courier new" , monospace;"><span style="background-color: white; font-size: 14px; white-space: pre;"> allResourceGroups) { Information(resourceGroup.name); } }); RunTarget(target); </span></span></div><div>And that should hopefully provide enough background to go create sql instances, scale up or down kubernetes clusters, and provision VM's with dependency management, from the comfort of a language you know and love. <br />
<span style="background-color: transparent; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> </span></div><h2>The Making Of</h2></div></div><br />
<blockquote class="tr_bq">"But Lee, I'm dying to know, how did you build this work of art?"</blockquote>Oh, I'm so very glad you asked. Writing something this large by hand was obviously not going to work. Plus it needs to be easy to update when Azure team releases new versions. Code generation it was. And I always wanted to learn T4 templates.<br />
<br />
I first came up with a data structure, always a solid place to start. I wanted something that would support Azure CLI, but that could also be used to generically represent any CLI tool, because ideally this solution could work for other CLI programs as well. I came up with this:<br />
<div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-lL00U8Ti1I2LevxM23zsxyXt_0ATt0HLG6AV4Qnu6URvEMrEbHjT6uhldxHv2mfaQQo5EsUexihqRptvIVkKAMJohtr8khyphenhyphen2jgSZoYQQLJm_j3sZm0HSaA_qRI2ebtZ_WTRVFaYK1VE/s1600/DependenciesGraph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="577" data-original-width="699" height="528" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-lL00U8Ti1I2LevxM23zsxyXt_0ATt0HLG6AV4Qnu6URvEMrEbHjT6uhldxHv2mfaQQo5EsUexihqRptvIVkKAMJohtr8khyphenhyphen2jgSZoYQQLJm_j3sZm0HSaA_qRI2ebtZ_WTRVFaYK1VE/s640/DependenciesGraph.png" width="640" /></a></div><div><br />
</div><br />
A Program contains a single root Group (az). Groups can contain other Groups recursively (e.g. az contains az aks which contains az aks nodepool). Groups can contain Commands (e.g. az aks contains az aks create). And for documentation Commands can have Examples and Arguments.<br />
<br />
It's basically a tree, with Commands as leafs, and so will work nicely in json. But how to populate it?<br />
<br />
<div><h2>Fill er up</h2></div><div><blockquote class="tr_bq">"Well, that's not how I would have done it"</blockquote><br />
said a skeptical co-worker when I told him I was executing thousands of az [thing] --help commands and parsing the results. See, AzureCLI was written in Python and is open source, so theoretically I could have downloaded their source and generated what I needed from there in Python.<br />
<br />
But I really wanted a more generic approach that I or someone else could apply to any CLI program. So I parsed each "xyz --help" into an intermediary object: a Page. That's basically just a collection of headers, name-value pairs, and paragraphs. Then I converted pages to groups or commands and recursed to produce a 350,385 line, 15 megabyte behemoth.</div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_PRbGi8SNOXrT-_DC13vrjRQlh46hjRR_dGuhtsnBmKN2gHNgt-Os6YuG_gobUdXpNqcPmHffE5jgSX39fIJIK1rSUAIc785srA6GMbMcM6mzkPREc_l3EhlXxKYfMQt-FVGjrDSNydM/s1600/ThisWillEndWell.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="465" data-original-width="620" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_PRbGi8SNOXrT-_DC13vrjRQlh46hjRR_dGuhtsnBmKN2gHNgt-Os6YuG_gobUdXpNqcPmHffE5jgSX39fIJIK1rSUAIc785srA6GMbMcM6mzkPREc_l3EhlXxKYfMQt-FVGjrDSNydM/s640/ThisWillEndWell.jpg" width="640" /></a></div><div><br />
</div><br />
Incidentally a fun side-effect of this approach is you can see all the changes across Azure CLI version changes e.g. <a href="https://github.com/lprichar/Cake.AzureCli/commit/4ff8cbb55c77589901ce88aeadfc26f82952a26f#diff-17de3e6393bfe4d796d6385126a26948">this commit</a> shows changes from 2.0.77 to 2.1.0 (although GitHub doesn't like showing diffs across 16 Meg files in the browser for some reason, can't imagine why).<br />
<br />
<div><h2>T4 Templates</h2><br />
I'd never used T4 templates. Turns out they're super awesome. Well, super powerful, and pretty awesome anyway. They are a little annoying when every time you hit save or tab off a .tt file it takes 13 seconds to generate your 178 thousand lines of code -- even on an 8 core i9 with 64 gigs of ram and an SSD. Oh, and then at that scale Visual Studio seems to crash periodically, although I'm sure Resharper doesn't help.<br />
<br />
But whatever, they work. And this part is cool: If you set hostspecific=true, then you can access this.Host to get the current directory, read a json file, then deserializing it to model objects that live in a .Core project that you can reference inside of the tt file yet not reference inside of your main project (Cake.AzureCli). If you're interested check out <a href="https://github.com/lprichar/Cake.AzureCli/blob/master/src/Cake.AzureCli/Az.tt">Az.tt</a>.<br />
<br />
What to generate was interesting too. The easy part is exposing a method to cake. You just write an extension method like this:</div><div><br />
</div><div><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">class</span> AzAliases { [<span style="color: blue;">CakeMethodAlias</span>] <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">AzCliGroup</span> Az(<span style="color: blue;">this</span> <span style="color: blue;">ICakeContext</span> context) { <span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: blue;">AzCliGroup</span>(context); } } </div></div></div>And Cake is good to go. But what about generating 2,935 extension methods? Turns out, not such a great idea. The intellisense engine in Visual Studio code is powered by <a href="http://www.omnisharp.net/">OmniSharp</a>. As awesome as OmniSharp is, it just isn't quite powerful enough to generate intellisense quickly or accurately with that architecture. However, if you group commands into "namespaces" like Az().Aks.Create() instead of AzAksCreate(), then you get nice intellisense at every level:<br />
<div><br />
<div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf-NO7UVhFrCQHV-9c5EtTzZdD8yZkSar0sZsrzDtbPiW0sqLEmlLhzzXmpGuY_qs9n6cE4tAF7rdb2gZaEIdbFqSf4Tnf7ZTASGnnBTf_YVu1D6VgsOAsLmmpVubOOV-wULvvpFyPL7E/s1600/CakeAzureCliIntellisense.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="961" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf-NO7UVhFrCQHV-9c5EtTzZdD8yZkSar0sZsrzDtbPiW0sqLEmlLhzzXmpGuY_qs9n6cE4tAF7rdb2gZaEIdbFqSf4Tnf7ZTASGnnBTf_YVu1D6VgsOAsLmmpVubOOV-wULvvpFyPL7E/s640/CakeAzureCliIntellisense.gif" width="640" /></a></div><div><br />
</div><br />
<h2>Conclusion</h2><br />
While this project may not solve world hunger just yet, I do hope it'll make someone's life a little easier. More importantly, I hope this technique will entertain or better yet inspire someone (you) to create something cool. If it does, please let me know about it in the comments or on <a href="https://twitter.com/lprichar">twitter</a>.</div><br />
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com2tag:blogger.com,1999:blog-6393051114813114443.post-16660391233763066442020-01-22T22:25:00.001-05:002020-01-29T16:14:13.892-05:00Conquer ASP.Net Boilerplate Query Performance in LINQPad, (Announcing LINQPad.ABP)<div 101="" a="" abp="" abstraction="" abstractions="" access="" an="" and="" annotation="" app="" application.="" application="" approach.="" apps="" architecture="" are="" article="" as="" asp.net="" automated="" based="" be="" because="" between="" blockquote="" boilerplate="" business="" call="" called="" can="" centric="" changes="" chosen="" code="" compatible="" connection="" context="" convenient="" create="" data-mobiledoc="{"version":"0.3.1","atoms":[],"cards":[["image",{"src":"https://blog.infernored.com/content/images/2019/12/repository-pattern.png","caption":"The \"No Repository\" architecture shows direct access to database context from a controller. The \"With Repository\" architecture shows an abstraction layer between the controller and the database context and shows how unit tests can use a custom persistence layer to facilitate testing"}],["code",{"code":"#if DEBUG\n private string _connectionString; \n\n /// <summary>\n /// For LINQPad\n /// </summary>\n public MyAppDbContext(string connectionString) : base(new DbContextOptions<MyAppDbContext>())\n {\n _connectionString = connectionString;\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n if (_connectionString == null)\n {\n base.OnConfiguring(optionsBuilder); // Normal operation\n return;\n }\n\n // We have a connection string\n var dbContextOptionsBuilder = new DbContextOptionsBuilder();\n optionsBuilder.UseSqlServer(_connectionString);\n base.OnConfiguring(dbContextOptionsBuilder);\n }\n#endif","language":"C#"}],["image",{"src":"https://blog.infernored.com/content/images/2019/12/AddConnection.png"}],["code",{"code":"var thing = this.Things.Where(t => t.Id == 1);\nthing.Dump();","language":"C#"}],["image",{"src":"https://blog.infernored.com/content/images/2019/12/LINQPadQuery-1.PNG"}],["code",{"code":"[DependsOn(typeof(MyProjEntityFrameworkModule))]\npublic class LinqPadModule : LinqPadModuleBase {\n\tpublic LinqPadModule(MyProjEntityFrameworkModule abpProjectNameEntityFrameworkModule)\n\t{\n\t\tabpProjectNameEntityFrameworkModule.SkipDbSeed = true;\n\t}\n\t\n\tpublic override void InitializeServices(ServiceCollection services) {\n\t\tIdentityRegistrar.Register(services);\n\t}\n}\n\nasync Task Main()\n{\n\tvar abpCtx = Util.Cache(LinqPadAbp.InitModule<LinqPadModule>, \"LinqPadAbp\");\n\n\tusing (var uowManager = abpCtx.StartUow(this, tenantId: 5, userId: 8))\n\t{\n\t\tvar fundService = abpCtx.IocManager.Resolve<IFundService>();\n\t\tvar entity = await thingService.GetEntityByIdAsync(1045);\n\t\tentity.Dump();\n\t}\n}","language":"C#"}]],"markups":[["a",["href","https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application"]],["code"],["a",["href","https://www.nuget.org/packages/LINQPad.ABP/1.0.0"]],["a",["href","https://github.com/lprichar/LINQPad.ABP"]]],"sections":[[1,"p",[[0,[],0,"When performance problems rear their gnarly head and there name is EntityFramework, there is but one blade you must wield: LINQPad. However, if you" data="" database="" datacontext="" dependency="" describe="" described="" development="" diagnose="" diagram="" difference="" dire.="" directly="" docs="" document="" enable="" enabling="" even="" executed.="" facilitate="" for="" framework="" from="" gives="" h1="" handling="" have="" help="" how="" however="" i="" idea="" if="" implementing="" in="" injection="" insulate="" int="" intended="" into="" irepository="" is="" it="" just="" layer="" less="" linqpad.="" linqpad.abp="" linqpad="" ll="" logic="" management.="" microsoft="" more="" mvc="" nice="" no="" nuget="" of="" often="" or="" out="" p="" packge="" pattern:="" pattern="" patterns="" performance="" populate="" post="" present="" problem="" problems:="" problems="" queries="" released="" repository="" rewrite="" run="" s="" see="" show="" simplifying="" situation="" solve="" sql="" store="" super="" tdd="" test-driven="" testing="" than="" that="" the="" these="" thing="" this="" to="" transactions="" translated="" turns="" two="" understand="" understood="" unit="" use="" used="" uses="" using="" ve="" ways="" when="" which="" with="" without="" wonderful="" work="" would="" your=""><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Ever made it to production only to realize your code fails miserably at scale? When performance problems rear their gnarly head and there name is EntityFramework, there is but one blade to slice that gordeon knot: LINQPad. </div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">However, if you're using the ASP.Net Boilerplate (ABP) framework, the situation is a tad more dire. That's because ABP uses a repository pattern, which, it turns out, is less than compatible with LINQPad's DataContext centric approach.</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">In this post I'll describe two ways to use LINQPad with ABP apps to solve performance problems:</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">1. Rewrite repository pattern based queries to run in LINQPad with a data context. This works well for small problems.</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">2. Enable LINQPad to call directly into your code, support authentication, multi-tenancy, and the unit of work and repository patterns with the help of a NuGet packge I just released called LINQPad.ABP. This helps immensely for more complex performance problems.</div><h2>Repository Pattern 101</h2><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br />
The Repository and Unit of Work patterns used in ASP.Net Boilerplate apps are a wonderful abstraction for simplifying unit testing, enabling annotation based transactions, and handling database connection management. As described in this article from the Microsoft MVC <a href="https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">docs</a>:</div><blockquote style="background-color: white; border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: rgb(62, 176, 239); border-left-style: solid; border-right-color: initial; border-right-style: initial; border-top-color: initial; border-top-style: initial; border-width: 0px 0px 0px 3px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px 0px 1.5em; min-width: 100%; padding: 0px 1.5em; quotes: none; vertical-align: baseline;">The repository and unit of work patterns are intended to create an abstraction layer between the data access layer and the business logic layer of an application. Implementing these patterns can help insulate your application from changes in the data store and can facilitate automated unit testing or test-driven development (TDD)</blockquote><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That document gives a nice diagram to show the difference between an architecture with and without a repository pattern:</div><div><br />
</div><img src="https://blog.infernored.com/content/images/2019/12/repository-pattern.png" /><br />
<span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"><br />
However, these abstractions present a problem for LINQPad. When using LINQPad to diagnose performance problems it would often be super convenient to call directly into your app's code to see the queries translated into SQL and executed. However, even if LINQPad understood dependency injection, it would have no idea how to populate a</span><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"> </span><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; color: #313b3f; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">IRepository<thing int=""><span style="font-size: 0.8em;"><thing int=""></thing></span></thing></code><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;">, what to do with a </span><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; color: #313b3f; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">[UnitOfWork(TransactionScopeOption.RequiresNew)]</code><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"> </span><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;">attribute, or what value to return for</span><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"> </span><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; color: #313b3f; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">IAbpSession.UserId</code><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"> </span><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;">or</span><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"> </span><code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; color: #313b3f; font-family: monospace, monospace; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">IAbpSession.TenantId</code><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;">. Fortunately, I just released a <a href="https://www.nuget.org/packages/LINQPad.ABP/">NuGet Package</a> to make that easy. </span><br />
<div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">But first, the simplest way to solve the problem for single queries is just to rewrite the query without a repository pattern and paste it into LINQPad.</div><h2>Undoing Repository Pattern</h2><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"><br />
This is where this blog post gets into the weeds. If you'd rather watch me perform the following steps please check out my latest episode of Code Hour:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/Lft0AbW49MU/0.jpg" frameborder="0" height="315" src="https://www.youtube.com/embed/Lft0AbW49MU?feature=player_embedded" width="560"></iframe></div><br />
<br />
<div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Otherwise, here it is in written form:</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Step one is to enable ABP'S data context to support a constructor that takes a connection string. If you add the following code to your DataContext:</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: grey; font-family: "consolas"; font-size: 9.5pt;">#if</span><span style="font-family: "consolas"; font-size: 9.5pt;"> DEBUG<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">private</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">string</span><span style="font-family: "consolas"; font-size: 9.5pt;"> _connectionString;<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: grey; font-family: "consolas"; font-size: 9.5pt;">///</span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: grey; font-family: "consolas"; font-size: 9.5pt;"></span><br />
<summary></summary><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: grey; font-family: "consolas"; font-size: 9.5pt;">///</span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;"> For LINQPad</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: grey; font-family: "consolas"; font-size: 9.5pt;">///</span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: grey; font-family: "consolas"; font-size: 9.5pt;"></span></div></div><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span><br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">public</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #2b91af; font-family: "consolas"; font-size: 9.5pt;">MyProjDbContext</span><span style="font-family: "consolas"; font-size: 9.5pt;">(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">string</span><span style="font-family: "consolas"; font-size: 9.5pt;"> connectionString)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> : </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">base</span><span style="font-family: "consolas"; font-size: 9.5pt;">(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">new</span><span style="font-family: "consolas"; font-size: 9.5pt;"> DbContextOptions())<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> _connectionString = connectionString;<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">protected</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">override</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">void</span><span style="font-family: "consolas"; font-size: 9.5pt;"> OnConfiguring(DbContextOptionsBuilder optionsBuilder)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">if</span><span style="font-family: "consolas"; font-size: 9.5pt;"> (_connectionString == </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">null</span><span style="font-family: "consolas"; font-size: 9.5pt;">)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">base</span><span style="font-family: "consolas"; font-size: 9.5pt;">.OnConfiguring(optionsBuilder); </span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// Normal operation</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">return</span><span style="font-family: "consolas"; font-size: 9.5pt;">;<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// We have a connection string</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">var</span><span style="font-family: "consolas"; font-size: 9.5pt;"> dbContextOptionsBuilder = </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">new</span><span style="font-family: "consolas"; font-size: 9.5pt;"> DbContextOptionsBuilder();<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> optionsBuilder.UseSqlServer(_connectionString);<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">base</span><span style="font-family: "consolas"; font-size: 9.5pt;">.OnConfiguring(dbContextOptionsBuilder);<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: grey; font-family: "consolas"; font-size: 9.5pt;">#endif</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal"><br />
</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"></div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Then in LINQPad you can</div><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Add a connection</li>
<li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">"Use a typed data context from your own assembly"</li>
<li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Select a Path to Custom Assembly like "MyProjSolution\server\src\MyProj.Web.Host\bin\Debug\netcoreapp2.1\MyProj.EntityFrameworkCore.dll"</li>
<li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Enter a Full Type Name of Typed DbContext like "MyProj.EntityFrameworkCore.MyAppDbContext"</li>
<li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">LINQPad should instantiate your DbContext via a constructor that accepts a string, then provide your connection string</li>
</ol><img src="https://blog.infernored.com/content/images/2019/12/AddConnection.png" /><br />
<br />
<div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Now, when you start a new query you can write:</div><div><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">var</span><span style="font-family: "consolas"; font-size: 9.5pt;"> thing = </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">this</span><span style="font-family: "consolas"; font-size: 9.5pt;">.Things.Where(t => t.Id == 1);<br />
<span style="font-size: 9.5pt;">thing.Dump();</span></span></div><br />
<div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">And if you run it you'll see the resulting SQL statement.</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Not bad. If you paste in any real code you'll need to add using statements and replace <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">_thingRepository.GetAll()</code> with <code style="background: rgb(229, 239, 245); border-radius: 3px; border: 0px; box-sizing: inherit; font-family: monospace, monospace; font-size: 0.8em; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 1em; margin: 0px; padding: 0px 5px 2px; vertical-align: baseline; word-break: break-all;">this.Things</code> and you'll be translating LINQ to SQL in no time.</div><img height="399" src="https://blog.infernored.com/content/images/2019/12/LINQPadQuery-1.PNG" width="640" /><br />
<br />
<div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Pretty cool. It certainly works for simple queries.</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">However, in my experience performance problems rarely crop up in the easy parts of the system. Performance problems always seem to happen in places where multiple classes interact because there was simply too much logic for the author to have stuffed it all into one class and have been able to sleep at night.</div><h2>Enter: LINQPad.ABP</h2><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;"><br />
To enable LINQPad to call directly into ABP code you'll need to set up dependency injection, define a module that's starts up your core module, specify a current user and tenant to impersonate, and somehow override the default unit of work to use LINQPad's context rather than ABP's. That's a lot of work.</div><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">Fortunately, I just published <a href="https://github.com/lprichar/LINQPad.ABP" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">LINQPad.ABP</a>, an Open Source <a href="https://www.nuget.org/packages/LINQPad.ABP/1.0.0" style="background-color: transparent; border: 0px; box-shadow: rgb(21, 23, 26) 0px -1px 0px inset; box-sizing: inherit; color: #15171a; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration-line: none; transition: all 0.2s ease-in-out 0s; vertical-align: baseline; word-break: break-word;">NuGet Package</a> that does all this for you. To enable it:</div><ol style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; list-style-image: initial; list-style-position: initial; margin: 0px 0px 1.5em; max-width: 100%; min-width: 100%; padding: 0px 1.5em 0px 1.3em; vertical-align: baseline;"><li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0px 0px 0.5em; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">In LINQPad add a reference to "LINQPad.ABP"</li>
<li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Add a custom Module that's dependent on your project's specific EF Module</li>
<li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Create and Cache a LINQPad ABP Context</li>
<li style="border: 0px; box-sizing: inherit; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.6em; margin: 0.5em 0px; padding: 0px 0px 0px 0.3em; vertical-align: baseline; word-break: break-word;">Start a UnitOfWork and specify the user and tenant you want to impersonate</li>
</ol><div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">The code will look like this:</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// you may need to depend on additional modules here eg MyProjApplicationModule</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;">[DependsOn(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">typeof</span><span style="font-family: "consolas"; font-size: 9.5pt;">(MyProjEntityFrameworkModule))]<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// this is a lightweight custom module just for LINQPad</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">public</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">class</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #2b91af; font-family: "consolas"; font-size: 9.5pt;">LinqPadModule</span><span style="font-family: "consolas"; font-size: 9.5pt;"> : LinqPadModuleBase<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">public</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #2b91af; font-family: "consolas"; font-size: 9.5pt;">LinqPadModule</span><span style="font-family: "consolas"; font-size: 9.5pt;">(MyProjEntityFrameworkModule abpProjectNameEntityFrameworkModule)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// tell your project's EF module to refrain from seeding the DB</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> abpProjectNameEntityFrameworkModule.SkipDbSeed = </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">true</span><span style="font-family: "consolas"; font-size: 9.5pt;">;<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">public</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">override</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">void</span><span style="font-family: "consolas"; font-size: 9.5pt;"> InitializeServices(ServiceCollection services)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// add any custom dependency injection registrations here</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> IdentityRegistrar.Register(services);<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;">}<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">async</span><span style="font-family: "consolas"; font-size: 9.5pt;"> Task Main()<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// LINQPad.ABP caches (expensive) module creation in LINQPad's cache</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">var</span><span style="font-family: "consolas"; font-size: 9.5pt;"> abpCtx = Util.Cache(LinqPadAbp.InitModule<linqpadmodule>(), </linqpadmodule></span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"LinqPadAbp"</span><span style="font-family: "consolas"; font-size: 9.5pt;">);<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// specify the tenant or user you want to impersonate here</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">using</span><span style="font-family: "consolas"; font-size: 9.5pt;"> (</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">var</span><span style="font-family: "consolas"; font-size: 9.5pt;"> uowManager = abpCtx.StartUow(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">this</span><span style="font-family: "consolas"; font-size: 9.5pt;">, tenantId: 5, userId: 8))<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: green; font-family: "consolas"; font-size: 9.5pt;">// retrieve what you need with IocManager in LINQPad.ABP's context</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">var</span><span style="font-family: "consolas"; font-size: 9.5pt;"> thingService = abpCtx.IocManager.Resolve<ifundservice>();<o:p></o:p></ifundservice></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">var</span><span style="font-family: "consolas"; font-size: 9.5pt;"> entity = </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">await</span><span style="font-family: "consolas"; font-size: 9.5pt;"> thingService.GetEntityByIdAsync(1045);<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> entity.Dump();<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div><span style="font-family: "consolas"; font-size: 9.5pt;">}</span><br />
<br />
<div style="background-color: white; border: 0px; box-sizing: inherit; color: #313b3f; font-family: Georgia, serif; font-size: 20px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; min-width: 100%; padding: 0px; vertical-align: baseline;">That may look like a lot of code, but truest me, it's way simpler than it would otherwise be. And now you can call into your code and watch every single query and how it gets translated to SQL. </div><h2>Summary</h2><span style="background-color: white; color: #313b3f; font-family: "georgia" , serif; font-size: 20px;"><br />
I hope this helps you track down a hard bug faster. If maybe then please <a href="https://www.youtube.com/leerichardson200">subscribe</a>, like, comment, and/or let me know on <a href="https://twitter.com/lprichar">twitter</a>.</span><br />
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-57753373224981875632019-12-10T23:49:00.000-05:002019-12-10T23:59:28.448-05:00Multi-Tenancy is Hard: ASP.Net Boilerplate Makes it EasyIf you're liable to start a new web project that even might need multi-tenancy, you should probably use ASP.Net Boilerplate (ABP). As I've blogged about previously, <a href="http://www.leerichardson.com/2019/05/be-hero-on-day-1-with-aspnet-boilerplate.html">ABP will save weeks</a> of dev time on new websites, even without multi-tenancy. However, as soon as you bring on a second customer, I'd estimate you'll eliminate over a month of development time (extrapolating from my 2 ABP project data points, solid math).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://images.unsplash.com/photo-1529700215145-58542a1f36b6?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2000&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="534" data-original-width="800" height="426" src="https://images.unsplash.com/photo-1529700215145-58542a1f36b6?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2000&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ" width="640" /></a></div>
<br />
But what even is multi-tenancy? What are typical solutions? And how does ABP save so much dev time? Fortunately, I just released a new episode of Code Hour to answer these questions:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/7690sLYO6UY/0.jpg" frameborder="0" height="315" src="https://www.youtube.com/embed/7690sLYO6UY?feature=player_embedded" width="560"></iframe></div>
<br />
<br />
If you don't have 35 minutes to invest right now (less at chipmunk speed, even less if you stop after ~6 minutes when I switch to live coding) then let me tl;dr (tl;dw? 😜):<br />
<br />
<i>Multi tenancy is a software architecture in which a single application is shared between multiple customers. Each customer only sees their own data and is completely unaware that there are other customers.</i><br />
<br />
There are several ways to approach the problem, as described in ABP's <a href="https://aspnetboilerplate.com/Pages/Documents/Multi-Tenancy">Multi-Tenancy Documentation</a>.<br />
<br />
<h4>
1. Multiple Deployment - Multiple Database</h4>
<br />
This is the less work up-front approach. There's no need for a framework, you just deploy your app multiple times, once per tenant. This offers the best performance (because tenants can be scaled independently) and best data isolation (e.g. database backups will never contain other customers data).<br />
<br />
In exchange it requires the highest maintenance cost and most challenging deployments. The maintenance challenge is you'll need to pay for an app and database for each customer, and if you're passing those costs on, it could be detrimental to smaller customers. The deployment risk is you'll have to be extremely structured in deployments of app and database script to all environments and carefully consolidate error logs. <br />
<br />
But there are three other common solutions, and in these scenarios ABP brings huge benefits to the table:<br />
<br />
<h4>
2. Single Deployment - Single Database</h4>
<br />
This is my favorite approach because it's simplest and least expensive to maintain. In this solution each database table contains a foreign key to a tenants table. All database queries must filter to retrieve items for the current user's tenant and insert records with the current users tenant. When doing it by hand it would be a pain to apply these filters to every single query. Enter ABP.<br />
<br />
By inheriting from the <span style="font-family: "courier new" , "courier" , monospace;">IMustHaveTenant</span> interface, ABP give all entities a foreign key to a Tenants table. Then, silently in the background, ABP figures out the tenant of the currently logged in user and for all queries only returns the records from that tenant. If a user creates an entity with <span style="font-family: "courier new" , "courier" , monospace;">IMustHaveTenant</span>, then ABP additionally automatically sets the correct foreign key. No code is required and all database queries pick up this filter (just like the soft delete I described in <a href="https://www.youtube.com/watch?v=xmHTYF5RvMs">Be a Hero On Day 1</a>).<br />
<br />
The downside to this approach is that one tenant with a lot of data could affect the performance of other tenants, and some users might worry about security since all data lives in the same database. So there's another approach ABP provides:<br />
<br />
<h4>
3. Single Deployment - Multiple Database</h4>
<div>
<br /></div>
When a user from the host (host = a singleton tenant that can create other tenants) creates a tenant, they can specify a connection string specific to that tenant. ABP even offers a cool solution to data migrations that I explain in the video (at <a href="https://www.youtube.com/watch?v=7690sLYO6UY&feature=youtu.be&t=775">~12:55</a>). But the end result is much better data isolation, great performance, but still a potentially high price tag since you could be paying for one database per customer.<br />
<br />
<br />
<h4>
4. Single Deployment - Hybrid Databases</h4>
<br />
ABP offers the best of the last two solutions by allowing some tenants to live in shared database instances and others to live in their own databases. This offers data isolation and performance to tenants that need it (or will pay for it), and value for tenants that don't (or won't). <br />
<br />
What's awesome about ABP is that it works identically from a code perspective for all of the above multi-tenancy approaches. The only difference is whether a tenant's connection string property is provided or not. The filtering, permissions, and migrations are otherwise all identical.<br />
<br />
<h4>
Summary</h4>
<br />
If you've interested in more details (such as how to disable tenant filtering) please check out the video (and like and subscribe and all that). Also, hit me up <a href="https://twitter.com/lprichar">on twitter</a> or in the comments if you have any questions, comments, or threats.Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-7082055316219925182019-09-12T08:16:00.001-05:002019-09-12T10:20:06.362-05:00Stored Procedures in ASP.Net BoilerplateUsing stored procedures in <a href="http://www.leerichardson.com/2019/05/be-hero-on-day-1-with-aspnet-boilerplate.html">ASP.Net Boilerplate</a> is a little trickier than you might imagine. There's the problem of getting them into the database with EF Code-First migrations. Then there's the issue of how to call them through the repository pattern while keeping things unit testable.<br />
<br />
And did you know there are three different way to call stored procedures? Which you use depends on on whether they return an existing entity, return nothing, or return something else entirely. That last option is the trickiest.<br />
<br />
Fortunately I just released Episode 23 of Code Hour, that lays it all out:<br />
<br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/fboRUsd00N8" width="560"></iframe><br />
<br />
All the code is available in this tidy little <a href="https://github.com/lprichar/LeesStore/pull/2">sproc pull request</a>.<br />
<br />
See also: the official ASP.Net boilerplate documentation on <a href="https://aspnetboilerplate.com/Pages/Documents/Articles/Using-Stored-Procedures,-User-Defined-Functions-and-Views/index.html">stored procedures</a>.Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-70712825761083617992019-08-26T08:16:00.003-05:002019-09-07T08:00:38.836-05:003 Ways To Refactor EF Linq Queries w/o Killing PerfExtracting a method from an Entity Framework LINQ query can quietly kill performance. Here are three easy solutions including: Expressions, Extension Methods, and LinqKit.<br />
<br />
<a class="gie-single" href="http://www.gettyimages.com/detail/621640760" id="53nfjfTdRvJcdrXzFpAZ9g" style="border: none; color: #a7a7a7; display: inline-block; font-weight: normal; text-decoration: none;" target="_blank">Embed from Getty Images</a><script>window.gie=window.gie||function(c){(gie.q=gie.q||[]).push(c)};gie(function(){gie.widgets.load({id:'53nfjfTdRvJcdrXzFpAZ9g',sig:'R-qKVZTVs4dKJI40T3anST94REl5xyEe5oemcNZ-AQQ=',w:'509px',h:'339px',items:'621640760',caption: true ,tld:'com',is360: false })});</script><script async="" charset="utf-8" src="//embed-cdn.gettyimages.com/widgets.js"></script><br />
<br />
<b>Enumeration<Problem><problem><problem></problem></problem></b><br />
<br />
Last week I was shocked to discover that refactoring Entity Framework LINQ queries for readability or reusability by extracting a method can quietly swap a query out of SQL and into in-memory processing and kill performance.<br />
<br />
Here's a simplified version of my problem.<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">private</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">async</span><span style="font-family: "consolas"; font-size: 10pt;"> Task<List<User>><list sers=""> GetUsersMatching(IMainFilterDto filter, </list></span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">string</span><span style="font-family: "consolas"; font-size: 10pt;"> prefix)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">var</span><span style="font-family: "consolas"; font-size: 10pt;"> usersQuery = </span><span style="font-family: "consolas"; font-size: 10pt;">Users.Where(u =></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> (filter.StartDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime > filter.StartDate) &&<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> (filter.EndDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime <= filter.EndDate) &&<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> u.Name.StartsWith(prefix));<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> <span style="color: blue;">return</span></span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10pt;">await</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="font-family: "consolas"; font-size: 10pt;">usersQuery.ToListAsync();</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">}</span></div><span style="font-family: "consolas"; font-size: 10pt; line-height: 107%;"><br />
</span> <span style="font-family: "consolas"; font-size: 10pt; line-height: 107%;"><br />
</span> I had a site-wide filtering object supplied by the front-end, but then I needed to do something else specific to the task at hand like the .StartsWith().<br />
<br />
Then elsewhere I needed something very similar:<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">private</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">async</span><span style="font-family: "consolas"; font-size: 10pt;"> <list bpusers=""><list ser="">Task<List<User>> GetUsersWithoutRoles(IMainFilterDto filter)<o:p></o:p></list></list></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">var</span><span style="font-family: "consolas"; font-size: 10pt;"> usersQuery = Users.Include(i => i.Roles).Where(u =><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> (filter.StartDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime > filter.StartDate) &&<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> (filter.EndDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime <= filter.EndDate) &&<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> !u.Roles.Any()<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> );<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">return</span><span style="font-family: "consolas"; font-size: 10pt;"> usersQuery.ToList();<o:p></o:p></span></div><span style="font-family: "consolas"; font-size: 10pt; line-height: 107%;">}</span><br />
<br />
Uch. The common code between the two isn't DRY and feels awful. If I ever needed to change it, perhaps by replacing > with >= I'd have to track down all the places with that code. I was tempted to extract it like this:<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">private</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">bool</span><span style="font-family: "consolas"; font-size: 10pt;"> ApplyMainFilter(IMainFilterDto filter, User u)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">return</span><span style="font-family: "consolas"; font-size: 10pt;"> (filter.StartDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime > filter.StartDate) &&<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> (filter.EndDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime <= filter.EndDate);<o:p></o:p></span></div><span style="font-family: "consolas"; font-size: 10pt; line-height: 107%;">}</span><br />
<br />
And use it like this:<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"><span style="color: blue; font-family: "consolas"; font-size: 10pt;">private</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10pt;">async</span><span style="font-family: "consolas"; font-size: 10pt;"> <list ser=""><list bpusers="">Task<List<User>> GetUsersWithoutRoles(IMainFilterDto filter)<o:p></o:p></list></list></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;"> var</span><span style="font-family: "consolas"; font-size: 10pt;"> usersQuery = Users.Where(u =><o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="font-family: "consolas"; font-size: 13.3333px;">ApplyMainFilter</span><span style="font-family: "consolas"; font-size: 10pt;">(filter, u) &&<br />
<span style="font-size: 10pt;"> u.Name.StartsWith(prefix));</span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div>That certainly reads better. And when I tested it, it returns the exact same results. Sadly, when I ran it through LINQPad the original query (where filter has a non-null start date but null end date) turns from this:<br />
<br />
<span style="color: blue; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">SELECT [stuff]<br />
FROM</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[Users]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: blue; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">AS</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[u]<br />
</span><span style="color: blue; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">WHERE </span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">(</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[u]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">.</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[CreationTime]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">></span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">@__filter_StartDate_0</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">) </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">AND</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> ((</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[u]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">.</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[Name]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">LIKE</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">+</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> N</span><span style="color: #dc1414; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">'%'</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">AND</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> (</span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">LEFT</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">(</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[u]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">.</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">[Name]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">, </span><span style="color: magenta; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">LEN</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">(</span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">)) </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">=</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">)) </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">OR</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> (</span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">=</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> N</span><span style="color: #dc1414; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;">''</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">))</span><br />
<br />
into:<br />
<br />
<span style="color: blue; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 14.2667px;">SELECT [stuff]<br />
FROM</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 14.2667px;"> </span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 14.2667px;">[Users]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 14.2667px;"> </span><span style="color: blue; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 14.2667px;">AS</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 14.2667px;"> </span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 14.2667px;">[u]</span><span style="color: blue; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">WHERE </span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">(</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">[u]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">.</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">[Name]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">LIKE</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">+</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> N</span><span style="color: #dc1414; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">'%'</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">AND</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> (</span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">LEFT</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">(</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">[u]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">.</span><span style="color: #a31515; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">[Name]</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">, </span><span style="color: magenta; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">LEN</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">(</span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">)) </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">=</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">)) </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">OR</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> (</span><span style="color: #2b91af; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">@__prefix_1</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> </span><span style="color: grey; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">=</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;"> N</span><span style="color: #dc1414; font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">''</span><span style="font-family: "verdana" , sans-serif; font-size: 10pt; line-height: 107%;">)</span><br />
<div class="MsoNormal"><span style="color: blue; font-family: "verdana" , sans-serif; font-size: 10.0pt; line-height: 107%;"><o:p></o:p></span></div><br />
It dropped out all the code in ApplyMainFilter()! That may not look terrible in this simple example, but imagine more complex scenarios. It could result in <i>a lot </i>more records returning from the database. It could create a network bottleneck or put excess strain on the middleware.<br />
<br />
Worst of all it could prevent the database from doing what it does best: use indexes to optimize query execution. This could mean bypassing existing indexes, preventing query optimization with future indexes, or reducing the effectiveness of performance recommendations in e.g. the Azure SQL database by hiding the problem from the database entirely.<br />
<br />
Incidentally, if you'd prefer to see a video of the problem and solutions, check out Episode 22 of <a href="http://youtube.com/leerichardson200">Code Hour</a>:<br />
<br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/hYry3i5Nvzw" width="560"></iframe><br />
<br />
<b>return solution[0]</b><br />
<br />
The solution turned out to be fairly easy once I identified the problem. Understanding how Entity Framework works internally helped. It's all about <a href="http://www.leerichardson.com/2008/03/expression-trees-why-linq-to-sql-is.html">expression trees</a>, which I've written about before (ok, I wrote that 11 years ago, but the fundamentals it describes are still solid).<br />
<br />
Anticipating all the possible ways someone might pass arbitrary C# language into a where clause and turning it all into SQL is a hard problem. I needed to give Entity Framework a hand. One way to do that is to return a fully parseable expression tree like Expression<func bool=""><Func<User, bool></func>> rather than just a bool or a Func<User, bool>. It looked like this:<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">private</span><span style="font-family: "consolas"; font-size: 10pt;"> Expression<Func<User, <func func="" nbsp="" ser="" span=""><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">bool</span><span style="font-family: "consolas"; font-size: 10pt;">>> GetMainFilterQuery(IMainFilterDto filter)<o:p></o:p></span></func></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">return</span><span style="font-family: "consolas"; font-size: 10pt;"> u => (filter.StartDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime > filter.StartDate) &&<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> (filter.EndDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime <= filter.EndDate);<o:p></o:p></span></div><br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">}<o:p></o:p></span></div><br />
Executed like this:<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">private</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">async</span><span style="font-family: "consolas"; font-size: 10pt;"> <list ser=""><list ser="">Task<List<User>> GetUsersMatching(IMainFilterDto filter, </list></list></span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">string</span><span style="font-family: "consolas"; font-size: 10pt;"> prefix)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">var</span><span style="font-family: "consolas"; font-size: 10pt;"> usersQuery = Users<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> .Where(GetMainFilterQuery(filter))<o:p></o:p></span></div><br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> .Where(u => u.Name.StartsWith(prefix));<o:p></o:p></span></div><br />
Isn't that an aesthetically pleasing solution? It's reusable, reads well, and converts to SQL.<br />
<br />
<b>But Wait, There's More</b><br />
<br />
But, if you're up for reading further I thought I'd present one more more interesting option. If you're into flow style API's then an extension method approach may be perfect:<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">public</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">static</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">class</span><span style="font-family: "consolas"; font-size: 10pt;"> QueryUtils<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">public</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">static</span><span style="font-family: "consolas"; font-size: 10pt;"> IQueryable<user> AppendMainFilterQuery(</user></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;"> this</span><span style="font-family: "consolas"; font-size: 10pt;"> IQueryable<user> existingQuery, IMainFilterDto filter)<o:p></o:p></user></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> {<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">return</span><span style="font-family: "consolas"; font-size: 10pt;"> existingQuery.Where(u => (</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> filter.StartDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || </span><span style="font-family: "consolas"; font-size: 10pt;">u.CreationTime > filter.StartDate) &&</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> (filter.EndDate == </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">null</span><span style="font-family: "consolas"; font-size: 10pt;"> || u.CreationTime <= filter.EndDate));<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> }<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">}<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">Which is a little harder to read, but allows this:</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">private</span><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">async</span><span style="font-family: "consolas"; font-size: 10pt;"> <list ser=""><list ser="">Task<List<User>> GetUsersMatching(IMainFilterDto filter, </list></list></span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">string</span><span style="font-family: "consolas"; font-size: 10pt;"> prefix)<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;">{<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 10.0pt;">var</span><span style="font-family: "consolas"; font-size: 10pt;"> usersQuery = Users</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> .Where(u => u.Name.StartsWith(prefix))<o:p></o:p></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas"; font-size: 10pt;"> .AppendMainFilterQuery(filter);</span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div>That reads nicely, is reusable, and like the 1st solution keeps the SQL exactly how it was initially.<br />
<br />
<b>OR LinqKit?</b><br />
<b><br />
</b> I ran all this by <a href="https://twitter.com/hernandezrobert">a smart co-worker</a> who recommended I check out <a href="https://github.com/scottksmith95/LINQKit">LinqKit</a> in case I ever needed to do anything more complicated. Among other things LinqKit allows you to build up expressions across multiple methods. For instance if I needed an OR clause instead of an AND clause it might look like this:<br />
<br />
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="color: blue; font-family: "consolas";">private</span><span style="font-family: "consolas";"> ExpressionStarter<User> GetMainFilterPredicate(IMainFilterDto filter)<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas";"><span style="font-size: x-small;">{<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="font-family: "consolas";"> </span><span style="color: blue; font-family: "consolas";">var</span><span style="font-family: "consolas";"> predicate = PredicateBuilder.New<User>().Start(u => <o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="font-family: "consolas";"> (filter.StartDate == </span><span style="color: blue; font-family: "consolas";">null</span><span style="font-family: "consolas";"> || u.CreationTime > filter.StartDate) &&<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="font-family: "consolas";"> (filter.EndDate == </span><span style="color: blue; font-family: "consolas";">null</span><span style="font-family: "consolas";"> || u.CreationTime <= filter.EndDate));<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="font-family: "consolas";"> </span><span style="color: blue; font-family: "consolas";">return</span><span style="font-family: "consolas";"> predicate;<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas";"><span style="font-size: x-small;">}<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="color: blue; font-family: "consolas";">private</span><span style="font-family: "consolas";"> <list ser=""><span style="font-size: 13.3333px;">Task<List<User>></span> GetUsersMatching(IMainFilterDto filter, </list></span><span style="color: blue; font-family: "consolas";">string</span><span style="font-family: "consolas";"> prefix)<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas";"><span style="font-size: x-small;">{<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="font-family: "consolas";"> </span><span style="color: blue; font-family: "consolas";">var</span><span style="font-family: "consolas";"> predicate = GetMainFilterPredicate(filter);<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas";"><span style="font-size: x-small;"> predicate = predicate.Or(u => u.Name.StartsWith(prefix));<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-size: x-small;"><span style="font-family: "consolas";"> </span><span style="color: blue; font-family: "consolas";">return</span><span style="font-family: "consolas";"> Users.Where(predicate).ToListAsync();<o:p></o:p></span></span></div><div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "consolas";"><span style="font-size: x-small;">}</span></span></div><br />
Pretty nifty.<br />
<br />
<b>Summary</b><br />
<br />
I like the 1st approach if I don't need anything more complex, but regardless, identifying how not to refactor LINQ queries is the important part. If you have any other creative solutions please share in the comments or hit me up on <a href="https://twitter.com/lprichar">twitter</a>.<br />
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com0tag:blogger.com,1999:blog-6393051114813114443.post-1388450860819146232019-07-25T13:57:00.002-05:002019-07-29T17:09:36.661-05:00Fighting File Downloads and Dinosaurs with NSwag (via ASP.Net Boilerplate)Technically it was the dinosaurs, approximately 240 million years ago, that first solved downloading files from web servers. So doing it with a modern tech stack with an auto-generated client-side proxy should be easy, right?<br />
<br />
<a class="gie-single" href="http://www.gettyimages.com/detail/71849656" id="26rjEYI4RqxfLHL8CnsueQ" style="border: none; color: #a7a7a7; display: inline-block; font-weight: normal; text-decoration: none;" target="_blank">Embed from Getty Images</a><script>window.gie=window.gie||function(c){(gie.q=gie.q||[]).push(c)};gie(function(){gie.widgets.load({id:'26rjEYI4RqxfLHL8CnsueQ',sig:'VKObqxqCJ7s-1JkZ3HKwP8GRth1HLQ0qx8HCiWcBcHE=',w:'530px',h:'323px',items:'71849656',caption: true ,tld:'com',is360: false })});</script><script async="" charset="utf-8" src="//embed-cdn.gettyimages.com/widgets.js"></script><br />
<br />
Sadly, I've lived with this embarrassing hack to a rudimentary problem for months because a confluence of technologies that make my life easy for common actions make it hard for infrequent ones. And sometimes, when life is hard, you give up and write something godawful to teach life a lesson. Make it take the <a href="https://knowyourmeme.com/memes/cave-johnson-combustible-lemons">lemons</a> back.<br />
<br />
This week, I won round 2 by solving the problem correctly. Pure joy, I'm tellin' ya. I just had to share.<br />
<br />
Fellow humanoids: prepare to rejoice.<br />
<br />
<h3>
The Problem</h3>
<br />
My tech stack looks like this:<br />
<br />
<ul>
<li>ASP.Net Core - for back end</li>
<li>Angular 7 - for front end (it requires a custom CORS policy, more on that later)</li>
<li>Swashbuckle - exposes a dynamically generated swagger json file </li>
<li><a href="https://github.com/RicoSuter/NSwag">NSwag</a> - consumes the swagger file and generates a client proxy</li>
</ul>
<br />
<div>
It happens to look like that because I use this excellent framework called <a href="https://aspnetboilerplate.com/">ASAP.Net Boilerplate</a> (also check out this amazing <a href="https://www.youtube.com/watch?v=xmHTYF5RvMs&t=8s">ASP.Net Boilerplate Overview</a>, then subscribe, the guy who produced it must be a genius). But whatever, you should totally use that stack anyway because those four technologies were preordained by the gods as a path to eternal bliss. That's a fact, the Buddha said it, go look it up.</div>
<br />
<div>
Also, the API client proxy that NSwag generates is <a href="https://www.urbandictionary.com/define.php?term=Totes">totes</a> amazing -- saves a huge amount of time and energy. Unless, it turns out, you're trying to download a dynamically generated Excel file in TypeScript on button click and trigger a download.</div>
<div>
<br /></div>
<h3>
A Naive Solution</h3>
<div>
<br /></div>
<div>
After a brief web search one couldn't be blamed for <a href="https://www.urbandictionary.com/define.php?term=Nuggeting">nuggetting</a> (a real word, apparently, but not what you think) EPPlus and writing an ASP.Net controller like this:</div>
<div>
<br /></div>
<div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">[Route(</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"api/[controller]"</span><span style="font-family: "consolas"; font-size: 9.5pt;">)]<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">public</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">class</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #2b91af; font-family: "consolas"; font-size: 9.5pt;">ProductFilesController</span><span style="font-family: "consolas"; font-size: 9.5pt;"> : AbpController<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">{<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> [HttpPost]<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> [Route(</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"{filename}.xlsx"</span><span style="font-family: "consolas"; font-size: 9.5pt;">)]<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">public</span><span style="font-family: "consolas"; font-size: 9.5pt;"> ActionResult Download(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">string</span><span style="font-family: "consolas"; font-size: 9.5pt;"> fileName)<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">var</span><span style="font-family: "consolas"; font-size: 9.5pt;"> fileMemoryStream = GenerateReportAndWriteToMemoryStream();<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">return</span><span style="font-family: "consolas"; font-size: 9.5pt;"> File(fileMemoryStream,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> fileName + </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">".xlsx"</span><span style="font-family: "consolas"; font-size: 9.5pt;">);<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">private</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">byte</span><span style="font-family: "consolas"; font-size: 9.5pt;">[] GenerateReportAndWriteToMemoryStream()<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">using</span><span style="font-family: "consolas"; font-size: 9.5pt;"> (ExcelPackage package = </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">new</span><span style="font-family: "consolas"; font-size: 9.5pt;"> ExcelPackage())<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"Data"</span><span style="font-family: "consolas"; font-size: 9.5pt;">);<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> worksheet.Cells[1, 1].Value = </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"Hello World"</span><span style="font-family: "consolas"; font-size: 9.5pt;">;<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">return</span><span style="font-family: "consolas"; font-size: 9.5pt;"> package.GetAsByteArray();<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
</div>
<div class="MsoNormal">
I took the approach above and naively expected Swashbuckle to generate a reasonable swagger.json file. It generated this:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"/api/ProductFiles/{filename}.xlsx"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"post"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"tags"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"ProductFiles"</span><span style="font-family: "consolas"; font-size: 9.5pt;">],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"operationId"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"ApiProductFilesByFilename}.xlsxPost"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"consumes"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"produces"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"parameters"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [{<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"name"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"fileName"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"in"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"path"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"required"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">true</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"type"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"string"</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"responses"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"200"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"description"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"Success"</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: "consolas"; font-size: 9.5pt; line-height: 107%;">},</span><o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
See the problem? You're clearly smarter than me. I ran NSwag and it generated this:</div>
</div>
<div>
<br /></div>
<div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">export</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">class</span><span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #2b91af; font-family: "consolas"; font-size: 9.5pt;">ApiServiceProxy</span><span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> productFiles(fileName: </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">string</span><span style="font-family: "consolas"; font-size: 9.5pt;">): Observable<</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">void</span><span style="font-family: "consolas"; font-size: 9.5pt;">> {<o:p></o:p></span></div>
</div>
<div>
<br /></div>
<div>
Oh no. No, Observable of void, is not going to work. It needs to return something, anything. Clearly I needed to be more explicit about the return type in the controller:</div>
<div>
<br /></div>
<div>
<div class="MsoNormal">
<span style="color: blue; font-family: "consolas"; font-size: 9.5pt; line-height: 107%;">public</span><span style="font-family: "consolas"; font-size: 9.5pt; line-height: 107%;"> ActionResult<FileContentResult> Download(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt; line-height: 107%;">string</span><span style="font-family: "consolas"; font-size: 9.5pt; line-height: 107%;"> fileName) { ... }</span><o:p></o:p></div>
</div>
<div>
<br /></div>
<div>
And Swagger?</div>
<div>
<br /></div>
<div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"/api/ProductFiles/{filename}.xlsx"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"post"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"tags"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"ProductFiles"</span><span style="font-family: "consolas"; font-size: 9.5pt;">],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"operationId"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"ApiProductFilesByFilename}.xlsxPost"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"consumes"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"produces"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"text/plain"</span><span style="font-family: "consolas"; font-size: 9.5pt;">, </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"application/json"</span><span style="font-family: "consolas"; font-size: 9.5pt;">, </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"text/json"</span><span style="font-family: "consolas"; font-size: 9.5pt;">],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> ...</span></div>
</div>
<div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"200"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"description"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"Success"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"schema"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"$ref"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"#/definitions/FileContentResult"</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
</div>
<div>
<br /></div>
<div>
Perfect! Swagger says a FileContentResult is the result and NSwag generates the exact code I was hoping for. Everything looks peachy ... until you run it and the server says:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">System.ArgumentException: Invalid type parameter 'Microsoft.AspNetCore.Mvc.FileContentResult' specified for 'ActionResult<t>'.</t></span></div>
<div>
<br /></div>
</div>
<div>
Gah! And what about specifying <span style="font-family: "consolas"; font-size: 12.6667px;">FileContentResult </span>as the return type? Fail. It's back to void.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTc8cQkO8LQ9Ll83vNzcnSnBPjJpT4bCdVNCzDL_uwKiB0MqJm8y4SIB94XSYY4keF75jE0Xwh_jz6JugNBhJecjn4ZFa_lvRpEIGX7oePqlcuq44beCiq1Z4mlKlHpL8Gaux7HtyjJ-M/s1600/IGiveUp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="500" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTc8cQkO8LQ9Ll83vNzcnSnBPjJpT4bCdVNCzDL_uwKiB0MqJm8y4SIB94XSYY4keF75jE0Xwh_jz6JugNBhJecjn4ZFa_lvRpEIGX7oePqlcuq44beCiq1Z4mlKlHpL8Gaux7HtyjJ-M/s320/IGiveUp.jpg" width="320" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
<a href="https://www.urbandictionary.com/define.php?term=O%20Hai">Ohai</a> ProducesResponseType attribute.</div>
<div>
<br /></div>
<div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">[HttpPost]<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">[Route(</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"{filename}.xlsx"</span><span style="font-family: "consolas"; font-size: 9.5pt;">)]<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">[ProducesResponseType(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">typeof</span><span style="font-family: "consolas"; font-size: 9.5pt;">(FileContentResult), (</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">int</span><span style="font-family: "consolas"; font-size: 9.5pt;">)HttpStatusCode.OK)]<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
</div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">public</span><span style="font-family: "consolas"; font-size: 9.5pt;"> ActionResult Download(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">string</span><span style="font-family: "consolas"; font-size: 9.5pt;"> fileName)<o:p></o:p></span></div>
</div>
<div>
<br /></div>
<div>
Swagger, do you like me now? Yes. NSwag? Yes! Serverside runtime you love me right? Yup. Finally NSwag you'll give me back that sweet FileContentResult if I'm friendly and sweet?</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">ERROR SyntaxError: Unexpected token P in JSON at position 0</span></div>
<div>
<br /></div>
<div>
inside the blobToText() function?!</div>
<div>
<br /></div>
<div>
NOOOOOOOOOOOOOOOOOO</div>
<div>
😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡</div>
<div>
OOOOOOOOOOOOOOOOOO!</div>
<div>
<br /></div>
<h3>
I Give Up</h3>
<div>
<br /></div>
<div>
It was a disaster. blobToText()? Grr. At some point while fighting it I was even getting these red herring CORS errors that I can't reproduce now that I spent hours fighting. All I know is if you see CORS errors don't bother with [EnableCors], just read the logs closely it's probably something else.</div>
<div>
<br /></div>
<div>
That was about six months ago. It's taken me that long to calm down. To everyone I've interacted with since, I do apologize for the perpetual yelling.</div>
<div>
<br /></div>
<div>
At the time I solved it by adding a hidden form tag, an ngNoForm, a target="_blank", and a bunch of hidden inputs. I don't know how I slept at night.</div>
<div>
<br /></div>
<div>
But I was actually pretty close and with persistence found the path to enlightenment.</div>
<div>
<br /></div>
<h3>
Less Complaining, More Solution</h3>
<div>
<br /></div>
<div>
Ok, ok, I've dragged this on long enough. On a good <a href="https://www.urbandictionary.com/define.php?term=Googlefoo">googlefu</a> day I stumbled on <a href="https://stackoverflow.com/a/53722309/40783">the solution</a> of telling Swashbuckle to map all instances of FileContentResult with "file" in startup.cs:</div>
<div>
<br /></div>
<div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">services.AddSwaggerGen(options =><o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;">{<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> options.MapType<filecontentresult>(() => </filecontentresult></span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">new</span><span style="font-family: "consolas"; font-size: 9.5pt;"> Schema<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> Type = </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"file"</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> });<o:p></o:p></span></div>
</div>
<div>
<br /></div>
<div>
That generates this swagger file:</div>
<div>
<br /></div>
<div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"/api/ProductFiles/{filename}.xlsx"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"post"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"tags"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"ProductFiles"</span><span style="font-family: "consolas"; font-size: 9.5pt;">],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"operationId"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"ApiProductFilesByFilename}.xlsxPost"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"consumes"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"produces"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [</span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"text/plain"</span><span style="font-family: "consolas"; font-size: 9.5pt;">, </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"application/json"</span><span style="font-family: "consolas"; font-size: 9.5pt;">, </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"text/json"</span><span style="font-family: "consolas"; font-size: 9.5pt;">],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"parameters"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: [{<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"name"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"fileName"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"in"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"path"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"required"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt;">true</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"type"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"string"</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }],<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"responses"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"200"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"description"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"Success"</span><span style="font-family: "consolas"; font-size: 9.5pt;">,<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"schema"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: {<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"type"</span><span style="font-family: "consolas"; font-size: 9.5pt;">: </span><span style="color: #a31515; font-family: "consolas"; font-size: 9.5pt;">"file"</span><span style="font-family: "consolas"; font-size: 9.5pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: .0001pt; margin-bottom: 0in; mso-layout-grid-align: none; text-autospace: none;">
<span style="font-family: "consolas"; font-size: 9.5pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: "consolas"; font-size: 9.5pt; line-height: 107%;">}</span><o:p></o:p></div>
</div>
<div>
<br /></div>
<div>
Type: file, yes of course. Solved problems are always so simple. Which NSwag turns into this function:<br />
<span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> productFiles</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">(</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">fileName</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">: </span><span style="background-color: white; color: #267f99; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">string</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">): </span><span style="background-color: white; color: #267f99; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">Observable</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"><</span><span style="background-color: white; color: #267f99; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">FileResponse</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">> {</span></div>
<div>
</div>
<div>
<br />
Which allows me to write this fancy little <a href="https://www.urbandictionary.com/define.php?term=thang">thang</a>:</div>
<div>
<span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> public</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> </span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">download</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">() {
</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> </span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">const</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> </span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">fileName</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> = </span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">moment</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">().</span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">format</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">(</span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">'YYYY-MM-DD'</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">);
</span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> this</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">.</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">apiServiceProxy</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">.</span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">productFiles</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">(</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">fileName</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">)
.</span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">subscribe</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">(</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">fileResponse</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> </span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">=></span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> {
</span><span style="background-color: white; color: blue; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> const</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> </span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">a</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> = </span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">document</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">.</span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">createElement</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">(</span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">'a'</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">);
</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> a</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">.</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">href</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> = </span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">URL</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">.</span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">createObjectURL</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">(</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">fileResponse.data</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">);
</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> a</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">.</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">download</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> = </span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">fileName</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> + </span><span style="background-color: white; color: #a31515; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">'.xlsx'</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">;
</span><span style="background-color: white; color: #001080; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;"> a</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">.</span><span style="background-color: white; color: #795e26; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">click</span><span style="background-color: white; font-family: "consolas" , "courier new" , monospace; font-size: 14px; white-space: pre;">();
});
}
</span></div>
<div>
So pretty, right?! And it even works!! </div>
<div>
<br /></div>
<div>
What's even awesomer is if you add additional parameters like </div>
<div>
<br /></div>
<div>
<div class="MsoNormal">
<span style="color: blue; font-family: "consolas"; font-size: 9.5pt; line-height: 107%;">public</span><span style="font-family: "consolas"; font-size: 9.5pt; line-height: 107%;"> ActionResult Download(</span><span style="color: blue; font-family: "consolas"; font-size: 9.5pt; line-height: 107%;">string</span><span style="font-family: "consolas"; font-size: 9.5pt; line-height: 107%;"> fileName, [FromBody]ProductFileParamsDto paramsDto)</span><o:p></o:p></div>
</div>
<div>
<br /></div>
<div>
Then NSwag generates a ProductFileParamsDto and makes it a parameter.</div>
<div>
<br /></div>
<div>
Fantabulous. All <a href="https://github.com/lprichar/LeesStore/pull/1/files">the code</a> is available in a nice tidy pull request for perusal.</div>
<div>
<br /></div>
<h3>
Conclusion</h3>
<div>
<br /></div>
<div>
I really think this issue is why the dinosaurs left. But now hopefully, with some luck, you won't share their fate.</div>
<a href="http://www.codeproject.com/" rel="tag" style="display: none;">CodeProject</a>Lee Richardsonhttp://www.blogger.com/profile/01314803491511307042noreply@blogger.com1