<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sanjeevi Subramani</title>
    <description>The latest articles on DEV Community by Sanjeevi Subramani (@ssanjeevi).</description>
    <link>https://dev.to/ssanjeevi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F446057%2Fc844a4f2-0ea1-4934-ae52-512ba9a00636.jpeg</url>
      <title>DEV Community: Sanjeevi Subramani</title>
      <link>https://dev.to/ssanjeevi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ssanjeevi"/>
    <language>en</language>
    <item>
      <title>Low Level Design GitHub Materials</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Fri, 17 Jun 2022 09:53:47 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/low-level-design-github-materials-5cle</link>
      <guid>https://dev.to/ssanjeevi/low-level-design-github-materials-5cle</guid>
      <description>&lt;h1&gt;
  
  
  𝟏) 𝐓𝐇𝐄 𝐋𝐋𝐃
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Low level Design / Machine Coding Question Collections
&lt;/h1&gt;




&lt;h3&gt;
  
  
  What is Machine Coding Round ?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Machine Coding Round has become very popular interview round in most Product and startup companies like Flipkart, Cleartrip, navi and Udaan,the way the round is structured is the candidate will be provided with a Problem statement and the minimum set of features which needs to implemented within the 90 min window period, we as a candidate need to identity the data models, the service interfaces which will be consumed by the clients and other set of functions and classes, we should be able to present the same to the panel with are design choices / design patterns being made / used and the complete working code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is the purpose behind this LLD repo ?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;During my recent Preparation, found out that there was no single resources where we get a collections of all the questions and the corresponding Answers, so currently updating the repo with all the materials I found out from the web and the Questions which has been asked during my interview. feel free to contribute any questions you have got during your recent interview.There other useful YT channel and Git repo which are attached in the resources section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is target Audience, do all companies ask ?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are currently targeting/looking out for any SDE - I,II opportunities. It totally depends on the company you interviewing with, you can check with the HR if they evaluate via machine coding round, but certain companies do ask a object oriented design round where they focus only on one particular feature and DB design as well, so its good get practiced with few problems beforehand.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Below are the list of LLD problem which are asked during my machine coding rounds from tech companies and the resources I collected.
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Note : page is under construction, you can click on the individual packages to view all the questions and solutions.
&lt;/h5&gt;




&lt;p&gt;| Low Level Design Question   &lt;/p&gt;

&lt;p&gt;| Question Link to PDF / Drive   &lt;/p&gt;

&lt;p&gt;| Company Asked  &lt;/p&gt;

&lt;p&gt;| Credits to author   &lt;/p&gt;

&lt;p&gt;|&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/Cricket%20Match%20Dashboard"&gt;Cricket Match Dashboard&lt;/a&gt; | &lt;a href="https://leetcode.com/discuss/interview-question/990227/udaan-assignment-cricket-match-dashboard"&gt;Leetcode&lt;/a&gt; | Udaan Assignment | |&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/Event_calendar_flipkart"&gt;Event Calendar&lt;/a&gt; | &lt;a href="https://github.com/kumaransg/LLD/blob/main/Event_calendar_flipkart/Event%20Calendar.pdf"&gt;PDF link&lt;/a&gt; | Flipkart LLD Question | |&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/FoodKart"&gt;FoodKart or food ordering System&lt;/a&gt; | &lt;a href="https://docs.google.com/document/d/1Bmkz9omByHqVvwU45cvkBRSwJAPKw9yaDsRlEnCg_lg/edit#"&gt;Doc link&lt;/a&gt; | Flipkart LLD Question | |&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/StockExchange"&gt;Stock Exchange&lt;/a&gt; | &lt;a href="https://github.com/kumaransg/LLD/tree/main/StockExchange"&gt;Problem Link&lt;/a&gt; | Navi LLD Question | |&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/PropertyHunt"&gt;PropertyHunt or property Listing site&lt;/a&gt; | &lt;a href="https://github.com/kumaransg/LLD/tree/main/PropertyHunt/Question%20Image"&gt;Question image&lt;/a&gt; | ClearTrip LLD Question | |&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/ledger_company_navi"&gt;ledger company&lt;/a&gt; | &lt;a href="https://www.geektrust.in/coding-problem/backend/ledger-co"&gt;Question Link&lt;/a&gt; | Navi LLD Question | &lt;a href="https://github.com/gauravmassand/ledger-company"&gt;Github code&lt;/a&gt; |&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/leetcode-lld-flipkart-coding-blox"&gt;Leetcode Like platform LLD&lt;/a&gt; | &lt;a href="https://github.com/kumaransg/LLD/blob/main/leetcode-lld-flipkart-coding-blox/SDE2-%20MC%20Question.pdf"&gt;PDF link&lt;/a&gt; | Flipkart LLD Question | &lt;a href="https://github.com/hocyadav/leetcode-lld-flipkart-coding-blox"&gt;Github code&lt;/a&gt; |&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently asked Problems
&lt;/h2&gt;

&lt;p&gt;| Low Level Design Question | Question Link to PDF / Drive | Company Asked | Credits to author |&lt;br&gt;
| &lt;a href="https://github.com/kumaransg/LLD/tree/main/Ride%20Sharing%20"&gt;Ride Sharing like App&lt;/a&gt; | &lt;a href="https://github.com/kumaransg/LLD/tree/main/Ride%20Sharing%20/RideShare_MachineCoding_Sample"&gt;Problem Link&lt;/a&gt; | Frequently asked in all companies |&lt;/p&gt;


&lt;h3&gt;
  
  
  Contribute
&lt;/h3&gt;



&lt;p&gt;Contributions welcome!&lt;/p&gt;

&lt;p&gt;If you found this resource helpful, give it a 🌟 otherwise contribute to it and give it a .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kumaransg/LLD"&gt;https://github.com/kumaransg/LLD&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  𝟐) 𝐋𝐎𝐖-𝐋𝐄𝐕𝐄𝐋 𝐃𝐄𝐒𝐈𝐆𝐍 𝐏𝐑𝐈𝐌𝐄𝐑
&lt;/h1&gt;
&lt;h1&gt;
  
  
  low-level-design-primer
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Learn low level design of system at scale. prepare for the low level design (LLD) / Machine Coding round interviews.&lt;/p&gt;
&lt;h2&gt;
  
  
  Learn to design low level system
&lt;/h2&gt;

&lt;p&gt;Learning low level design of scalable systems will help you become better engineer.&lt;/p&gt;

&lt;p&gt;This repo is an organized collection of resources to help you learn low level design of systesm's.&lt;/p&gt;
&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Low level Design &lt;a href="https://github.com/prasadgujar/low-level-design-primer/blob/master/questions.md"&gt;Questions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Low level Design &lt;a href="https://github.com/prasadgujar/low-level-design-primer/blob/master/solutions.md"&gt;Solutions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Low Level Design &lt;a href="https://github.com/prasadgujar/low-level-design-primer/blob/master/resources.md"&gt;Resources&lt;/a&gt; #TODO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new questions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improve new questions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add new solutions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix errors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improve sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new sections&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Under development
&lt;/h2&gt;

&lt;p&gt;Interested in adding a section or helping complete one in-progress? &lt;a href="https://github.com/prasadgujar/low-level-design-primer/edit/master/README.md"&gt;Contribute&lt;/a&gt;!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to guide and study material along with various resources.&lt;/li&gt;
&lt;li&gt;add more questions and improve exisiting questions.&lt;/li&gt;
&lt;li&gt;add solutions for the problems along with their detailed explaination (maybe video)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Credits and sources are provided throughout this repo.&lt;/p&gt;

&lt;p&gt;Special thanks to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/donnemartin/"&gt;Donne Martin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/donnemartin/system-design-primer"&gt;System Design Primer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.careercup.com/"&gt;Cracking the Coding Interview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com/"&gt;Leetcode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/"&gt;GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gopalbala"&gt;G Balasubramanian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/anomaly2104"&gt;Udit Agarwal&lt;/a&gt; 
## Contact Info
Feel free to contact me to discuss any issues, questions, or comments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My contact info can be found on my &lt;a href="https://github.com/prasadgujar"&gt;Github Page&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TODO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/prasadgujar/low-level-design-primer"&gt;https://github.com/prasadgujar/low-level-design-primer&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  𝟑)𝐀𝐰𝐞𝐬𝐨𝐦𝐞 𝐒𝐨𝐟𝐭𝐰𝐚𝐫𝐞 𝐄𝐧𝐠𝐢𝐧𝐞𝐞𝐫𝐢𝐧𝐠 𝐈𝐧𝐭𝐞𝐫𝐯𝐢𝐞𝐰
&lt;/h1&gt;
&lt;h1&gt;
  
  
  Awesome Software Engineering Interview
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;This repository aims at providing collated content at a single place to prepare for Software Engineering interviews.&lt;/p&gt;
&lt;h2&gt;
  
  
  Content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/imkgarg/Software-Engineering-Interview-Primer/blob/master/Coding.md"&gt;Coding/DS, Algo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imkgarg/Awesome-Software-Engineering-Interview/blob/master/CodingCompanyTopQuestions.md"&gt;Top DSA interview questions - Companywise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imkgarg/Software-Engineering-Interview-Primer/blob/master/LowLevelDesign.md"&gt;Object Oriented Design/Low Level Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imkgarg/Software-Engineering-Interview-Primer/blob/master/SystemDesign.md"&gt;System Design/High Level Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imkgarg/Awesome-Software-Engineering-Interview/blob/master/CSFundamentals.md"&gt;CS Fundamentals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imkgarg/Awesome-Software-Engineering-Interview/blob/master/Behavioral.md"&gt;Behavioral&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Under development
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Low level design questions - Company Wise&lt;/li&gt;
&lt;li&gt;Top interview questions - Company Wise&lt;/li&gt;
&lt;li&gt;How to ace Behavioural interview rounds&lt;/li&gt;
&lt;li&gt;Mock interview platforms&lt;/li&gt;
&lt;li&gt;Resume building&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;Feel free to submit pull requests to help with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add new questions/topics&lt;/li&gt;
&lt;li&gt;Improve new questions/topics&lt;/li&gt;
&lt;li&gt;Fix errors&lt;/li&gt;
&lt;li&gt;Improve sections&lt;/li&gt;
&lt;li&gt;Add new sections&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Contact info
&lt;/h2&gt;

&lt;p&gt;Feel free to contact me to discuss any issues, questions, or comments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/imkgarg"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/TechMaestroCommunity"&gt;Youtube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/karan-garg/"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I am providing code and resources in this repository to you under an open source license. Because this is my personal repository, the license you receive to my code and resources is from me and not my employer (Microsoft).&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Copyright 2017 Karan Garg

Creative Commons Attribution 4.0 International License (CC BY 4.0)

http://creativecommons.org/licenses/by/4.0/

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/imkgarg/Awesome-Software-Engineering-Interview"&gt;https://github.com/imkgarg/Awesome-Software-Engineering-Interview&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  𝟒)𝐂𝐚𝐜𝐡𝐞 𝐋𝐨𝐰 𝐋𝐞𝐯𝐞𝐥 𝐒𝐲𝐬𝐭𝐞𝐦 𝐃𝐞𝐬𝐢𝐠𝐧
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Cache - Low level system design &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_5z6MSDp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://travis-ci.org/anomaly2104/cache-low-level-system-design.svg%3Fbranch%3Dmaster" alt="Build status" width="90" height="20"&gt;
&lt;/h1&gt;

&lt;p&gt;Repository for low level system design of a cache&lt;/p&gt;

&lt;h2&gt;
  
  
  Video explanation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://youtu.be/B7iCXl_KSoM"&gt;https://youtu.be/B7iCXl_KSoM&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem statement
&lt;/h2&gt;

&lt;p&gt;&lt;a href="//problem-statement.md"&gt;Check here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/anomaly2104/cache-low-level-system-design"&gt;https://github.com/anomaly2104/cache-low-level-system-design&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  𝟓)𝐂𝐡𝐞𝐬𝐬 𝐋𝐨𝐰-𝐋𝐞𝐯𝐞𝐥 𝐒𝐲𝐬𝐭𝐞𝐦 𝐃𝐞𝐬𝐢𝐠𝐧
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Chess - Low level system design &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O8ckqoVa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://travis-ci.org/anomaly2104/chess-low-level-system-design.svg%3Fbranch%3Dmaster" alt="Build status" width="90" height="20"&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Video Explanation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://youtu.be/RVHNcng0oF0"&gt;https://youtu.be/RVHNcng0oF0&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statements
&lt;/h2&gt;

&lt;p&gt;&lt;a href="//problem-statement.md"&gt;Problem Statement&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further enhancements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Implement checkmate feature.&lt;/li&gt;
&lt;li&gt;Write more unit tests.&lt;/li&gt;
&lt;li&gt;Support special move of pawn where it can go diagonal when it kills.&lt;/li&gt;
&lt;li&gt;At many places, we are evaluating conditions like:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OR Operation&lt;/strong&gt; : We are allowed to do something if any condition out of given conditions fulfill. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;And Operation&lt;/strong&gt; : We are allowed to do something if all conditions fulfill.
Try to improve the design for this.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Add history of moves for each player.&lt;/li&gt;
&lt;li&gt;Add support for casteling move.&lt;/li&gt;
&lt;li&gt;Can we remove putting currentCell in Piece? How about introducing something like position?

&lt;ul&gt;
&lt;li&gt;A piece will have a position and you can always get the cell back from board using this position.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/anomaly2104/chess-low-level-system-design"&gt;https://github.com/anomaly2104/chess-low-level-system-design&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  𝟔)𝐓𝐡𝐞 𝐒𝐲𝐬𝐭𝐞𝐦 𝐃𝐞𝐬𝐢𝐠𝐧
&lt;/h1&gt;

&lt;h1&gt;
  
  
  System Design:
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is system?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A system is a loosely used term for an architecture or collection of software or technology that communicate with each other or interact with each other in order to serve a certain set of users with a certain set of requirements.&lt;/li&gt;
&lt;li&gt;A system can be defined and built keeping these three factors in mind:

&lt;ol&gt;
&lt;li&gt;The user of the systems &lt;/li&gt;
&lt;li&gt;The requirements of those users, and &lt;/li&gt;
&lt;li&gt;The components that are chosen in order to build that system to serve those users and their requirements.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is design?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Design is a process of understanding the user requirements and selecting the components, modules, and software technologies how they are going to be intertwined and communicating with each other to actually serve the need of the system.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Components of System Design:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Components are the basic building blocks of system components.&lt;/li&gt;
&lt;li&gt;It could be divided into two parts:

&lt;ol&gt;
&lt;li&gt;Logical entities:&lt;/li&gt;
&lt;li&gt;Data&lt;/li&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;Applications&lt;/li&gt;
&lt;li&gt;Cache&lt;/li&gt;
&lt;li&gt;Message Queues&lt;/li&gt;
&lt;li&gt;Infra&lt;/li&gt;
&lt;li&gt;Communication Protocol&lt;/li&gt;
&lt;li&gt;Requests (API, RPC, etc.)&lt;/li&gt;
&lt;li&gt;Tangible entities:&lt;/li&gt;
&lt;li&gt;Text, images, videos..&lt;/li&gt;
&lt;li&gt;MongoDB, MySQL, Cassandra..&lt;/li&gt;
&lt;li&gt;Java, Golang, Python, React..&lt;/li&gt;
&lt;li&gt;Redis, MemeCache..&lt;/li&gt;
&lt;li&gt;Kafka, RabbitMQ..&lt;/li&gt;
&lt;li&gt;AWS, GCP, Azure..&lt;/li&gt;
&lt;li&gt;APIs, RPCs, Messages..&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Client Server Architecture:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Client-server architecture is a computing model in which the server hosts, delivers and manages most ofthe resources and services to be consumed by the client. &lt;/li&gt;
&lt;li&gt;Client: a piece ofsoftware or application that takes the input and sends request to the servers.&lt;/li&gt;
&lt;li&gt;Server: a piece ofsoftware that receives and processes requestsfrom clients.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Load balancer: responsible for distributing incoming network traffic across a group of backend servers to optimize resource usage.
&lt;/h2&gt;

&lt;h4&gt;
  
  
  A typical topological data flow goes as follows:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Client requests data from server&lt;/li&gt;
&lt;li&gt;Load balancer routes the request to the appropriate server&lt;/li&gt;
&lt;li&gt;Server processes the request client&lt;/li&gt;
&lt;li&gt;Server queries appropriate database for some data&lt;/li&gt;
&lt;li&gt;Database returns the queried data back to the server&lt;/li&gt;
&lt;li&gt;The server processes the data and sends the data back to the client&lt;/li&gt;
&lt;li&gt;This process repeats

&lt;ul&gt;
&lt;li&gt;
#### Types of Architecture:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Thin client:

&lt;ul&gt;
&lt;li&gt;A thin client is designed to be especially small so that the bulk of the data processing occurs on the server.&lt;/li&gt;
&lt;li&gt;Example: Ecommerce, streaming applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Thick client:

&lt;ul&gt;
&lt;li&gt;A thick client (fat client) is one that will perform the bulk of the processing in client/server applications. With thick clients, there is no need for continuous server communications as it is mainly communicating archival storage information to the server. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  - Example: Gaming apps, video editing software.
&lt;/h2&gt;
&lt;h4&gt;
  
  
  Tier based architecture:
&lt;/h4&gt;
&lt;/li&gt;
&lt;li&gt;1-Tier:

&lt;ul&gt;
&lt;li&gt;It is the simplest one as it is equivalent to running the application on the personal computer. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2-Tier:

&lt;ul&gt;
&lt;li&gt;It is like Client-Server architecture, where communication takes place between client and server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;3-Tier:

&lt;ul&gt;
&lt;li&gt;The 3-tier architecture has three different layers.

&lt;ul&gt;
&lt;li&gt;Presentation layer&lt;/li&gt;
&lt;li&gt;Business Logic layer&lt;/li&gt;
&lt;li&gt;Database layer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;N-Tier: 

&lt;ul&gt;
&lt;li&gt;An N-Tier Application program is one that is distributed among three or more separate computers in a distributed network. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Proxies:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Proxy is an intermediary server between client and the internet. &lt;/li&gt;
&lt;li&gt;Proxy servers allow to hide, conceal and make your network id anonymous by hiding your IP address.&lt;/li&gt;
&lt;li&gt;Proxy servers offers the following basic functionalities:

&lt;ul&gt;
&lt;li&gt;Firewall and network data filtering.&lt;/li&gt;
&lt;li&gt;Network connection sharing&lt;/li&gt;
&lt;li&gt;Data caching&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h4&gt;
  
  
  Types of proxy:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Forward Proxy&lt;/li&gt;
&lt;li&gt;In this the client requests its internal network server to forward to the internet. &lt;/li&gt;
&lt;li&gt;Reverse Proxy &lt;/li&gt;
&lt;li&gt;In this the requests are forwarded to one or more proxy servers and the response from the proxy server is retrieved as if it came directly from the original server. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Data and Data Flow:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Different formats of data (representation):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In Business Layer:&lt;/li&gt;
&lt;li&gt;Texts, Videos, Images, etc. &lt;/li&gt;
&lt;li&gt;In Application Layer:&lt;/li&gt;
&lt;li&gt;JSON/XML&lt;/li&gt;
&lt;li&gt;In Data Stores:&lt;/li&gt;
&lt;li&gt;Databases, Tables, Indexes, Cache, Queues, etc.&lt;/li&gt;
&lt;li&gt;Network Layer:&lt;/li&gt;
&lt;li&gt;Packets.&lt;/li&gt;
&lt;li&gt;Hardware Layer:&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - 0s and 1s. 
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Data Generation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Users&lt;/li&gt;
&lt;li&gt;Internal Data (System populates on their own).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Insights 
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Data Flow Methods:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;APIs.&lt;/li&gt;
&lt;li&gt;Messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Events.
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Factors to be considered:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Type of data&lt;/li&gt;
&lt;li&gt;Volume&lt;/li&gt;
&lt;li&gt;Consumption/Retrieval&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Security 
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Types of System (Examples):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Authorization System&lt;/li&gt;
&lt;li&gt;Streaming System&lt;/li&gt;
&lt;li&gt;Transactional System&lt;/li&gt;
&lt;li&gt;Heavy Compute System &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Databases:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Types of databases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If we consider data as people, in terms of buildings, then the way those buildings house people can be said as databases.&lt;/li&gt;
&lt;li&gt;Some common types of databases are:

&lt;ul&gt;
&lt;li&gt;Relational&lt;/li&gt;
&lt;li&gt;Non-relational&lt;/li&gt;
&lt;li&gt;File type&lt;/li&gt;
&lt;li&gt;Network, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Anatomy of applications and services:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Applications or services performs certain tasks, and at different layers they have different responsibility.

&lt;ul&gt;
&lt;li&gt;Tech stack:&lt;/li&gt;
&lt;li&gt;All the codes in applications are written in some languages using some frameworks.&lt;/li&gt;
&lt;li&gt;Any application can be written solely with the use of language. But frameworks do most of the bootstrapping so we can use this feature to make an application on the top of the framework.&lt;/li&gt;
&lt;li&gt;Responsibilities:&lt;/li&gt;
&lt;li&gt;Client app:

&lt;ul&gt;
&lt;li&gt;Render UI.&lt;/li&gt;
&lt;li&gt;Handle interactions.&lt;/li&gt;
&lt;li&gt;Collect data.&lt;/li&gt;
&lt;li&gt;Communicate with backend (API) to fetch and store data.&lt;/li&gt;
&lt;li&gt;Render static data/informations.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Backend app:

&lt;ul&gt;
&lt;li&gt;Expose API endpoints.&lt;/li&gt;
&lt;li&gt;House business logics.&lt;/li&gt;
&lt;li&gt;Handle data modelling/transformation.&lt;/li&gt;
&lt;li&gt;Interact with data stores.&lt;/li&gt;
&lt;li&gt;Interact with other services.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Elements/factors of application development:

&lt;ul&gt;
&lt;li&gt;Feature requirements.&lt;/li&gt;
&lt;li&gt;Layer.&lt;/li&gt;
&lt;li&gt;Tech Stack.&lt;/li&gt;
&lt;li&gt;Code structure/design pattern.&lt;/li&gt;
&lt;li&gt;Data store interactions.&lt;/li&gt;
&lt;li&gt;Performance/cost.&lt;/li&gt;
&lt;li&gt;Deployment.&lt;/li&gt;
&lt;li&gt;Monitoring.&lt;/li&gt;
&lt;li&gt;Operational excellence/reliability.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Application Programming Interface (API):
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An API is a set of defined rules that explain how computers or applications communicate with one another. &lt;/li&gt;
&lt;li&gt;Advantages:

&lt;ul&gt;
&lt;li&gt;Communication.&lt;/li&gt;
&lt;li&gt;Abstraction.&lt;/li&gt;
&lt;li&gt;Platform agnostic.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples:

&lt;ul&gt;
&lt;li&gt;Private APIs: The hidden APIs. Not accessible to everyone.&lt;/li&gt;
&lt;li&gt;Public APIs: Available to public. (Ex: Google maps api)&lt;/li&gt;
&lt;li&gt;Web APIs: Superset of public and private APIs. &lt;/li&gt;
&lt;li&gt;SDK/Library APIs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Factors to consider:

&lt;ul&gt;
&lt;li&gt;API contracts &lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Data format&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Standards:

&lt;ul&gt;
&lt;li&gt;REST: &lt;/li&gt;
&lt;li&gt;Stands for REpresentational State Transfer.&lt;/li&gt;
&lt;li&gt;Guidelines:

&lt;ul&gt;
&lt;li&gt;Client Server.&lt;/li&gt;
&lt;li&gt;Cacheable.&lt;/li&gt;
&lt;li&gt;Layered.&lt;/li&gt;
&lt;li&gt;Stateless.&lt;/li&gt;
&lt;li&gt;Uniform Interface.&lt;/li&gt;
&lt;li&gt;Code on demand. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;RPC&lt;/li&gt;
&lt;li&gt;SOAP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Caching:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A hardware or software component which helps in serving the data which is either frequently requested or it is expensive to compute on, so cache stores the computed response and saves the cost of computing.&lt;/li&gt;
&lt;li&gt;Cache hit: If a response for a request is available in cache memory, it is called a cache hit.&lt;/li&gt;
&lt;li&gt;Cache miss: If a response for a request is not available in cache memory, it is called a cache miss.&lt;/li&gt;
&lt;li&gt;Invalidation and eviction:

&lt;ul&gt;
&lt;li&gt;Invalidation: &lt;/li&gt;
&lt;li&gt;The data that is kept in cache is not there for forever, it is volatile. &lt;/li&gt;
&lt;li&gt;The data is going to change at some point of time, hence we need to update the cache as well.&lt;/li&gt;
&lt;li&gt;The process of updating the data in cache by replacing the old value with new value is called data invalidation.&lt;/li&gt;
&lt;li&gt;Methods to invalidate:

&lt;ul&gt;
&lt;li&gt;Cache expiry (TTL: Time to live).&lt;/li&gt;
&lt;li&gt;Remove the cache. (When a new request come, cache miss will happen, and data will be fetched.) &lt;/li&gt;
&lt;li&gt;Update the cache.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Eviction:&lt;/li&gt;
&lt;li&gt;A cache eviction algorithm is a way of deciding which element to evict when the cache is full.&lt;/li&gt;
&lt;li&gt;Catch eviction methods:

&lt;ul&gt;
&lt;li&gt;FIFO.&lt;/li&gt;
&lt;li&gt;LRU.&lt;/li&gt;
&lt;li&gt;LFU.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache Patterns:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Where can be keep cache?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  MESSAGE QUEUE:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h2uViar2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/55986045/122849696-a2009880-d329-11eb-96a8-16a8d578aa20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h2uViar2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/55986045/122849696-a2009880-d329-11eb-96a8-16a8d578aa20.png" alt="image" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.datadriveninvestor.com/what-is-message-queue-b5468ff6db50"&gt;Message queue&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Performance Metrics (used to evaluate how good the system is performing):
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;
  
  
  Throughput
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Throughput is the number of actions executed or results produced in a certain amount of time.&lt;/li&gt;
&lt;li&gt;In system design, throughput comes into picutre when we need to understand how many API calls are being served in a particular amount of time.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Bandwidth
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Bandwidth is the maximum amount of data that can travel through a 'channel'.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Latency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Latency is the time required to perform some action or to produce some result.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Response Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Response time is the time between a client sending a request and receiving a response. It is the sum of round trip latency and service time. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  EXAMPLES (analogies):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Water Analogy:&lt;/li&gt;
&lt;li&gt;Latency is the amount of time it takes to travel through the tube.&lt;/li&gt;
&lt;li&gt;Bandwidth is how wide the tube is.&lt;/li&gt;
&lt;li&gt;The amount of water flow will be your throughput&lt;/li&gt;
&lt;li&gt;Vehicle Analogy:&lt;/li&gt;
&lt;li&gt;Vehicle travel time from source to destination is latency.&lt;/li&gt;
&lt;li&gt;Types of Roadways are bandwidth.&lt;/li&gt;
&lt;li&gt;Number of Vehicles traveling is throughput.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Performance metrics of different components:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;
  
  
  Applications:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;API Response Time&lt;/li&gt;
&lt;li&gt;Throughput of APIs&lt;/li&gt;
&lt;li&gt;Error occurences&lt;/li&gt;
&lt;li&gt;Bug/defect in the code&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Databases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time taken by various database queries&lt;/li&gt;
&lt;li&gt;Number of queries executed per unit time(or throughput)&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Caches:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Latency of writing to cache&lt;/li&gt;
&lt;li&gt;Number of cache eviction and invalidation&lt;/li&gt;
&lt;li&gt;Memory of cache instance&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Message Queues:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Rate of production and consumption&lt;/li&gt;
&lt;li&gt;Fraction of stale or unprocessed messages&lt;/li&gt;
&lt;li&gt;Number of consumers affects bandwidth and throughput&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Workers:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Time taken for job completion&lt;/li&gt;
&lt;li&gt;Resources used in processing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Server instances:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Memory/RAM&lt;/li&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Fault v/s Failure:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fault is the cause, failure is the effect. &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Scaling:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The ability to handle more request by buying more machines/bigger machines.&lt;/li&gt;
&lt;li&gt;Key features:

&lt;ul&gt;
&lt;li&gt;Able to handle the increased load.&lt;/li&gt;
&lt;li&gt;Not complex to implement and maintain.&lt;/li&gt;
&lt;li&gt;Performance shouldn' takr a hit or rather performance should increase.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h2&gt;
  
  
  Vertical Scaling:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When we increase the capacity of existing resource it is vertical scaling.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h2&gt;
  
  
  Horizontal Scaling:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When we increase the number of resources it is horizontal scaling.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h2&gt;
  
  
  Horizontal v/s Vertical Scaling:
&lt;/h2&gt;

&lt;p&gt;| Horizontal | Vertical | |------------|----------| |Need load balancers.|Load balancers not needed.| |Resilient.|Single point of failure.| |Slow remote procedure calls.|Fast inter process communication.| |Data inconsistency.|Data consistent.| |Scales well as uses increases.| Hardware limit.|&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Database Replication:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Replication: To have a copy.&lt;/li&gt;
&lt;li&gt;Having exact copy of data present in other databases in other machines.&lt;/li&gt;
&lt;li&gt;The database that has main source of writes/updates becomes the primary db. (Master)&lt;/li&gt;
&lt;li&gt;The database which has the copies from the primary db's is called the secondary database. (Slave)&lt;/li&gt;
&lt;li&gt;Why do we need replication?

&lt;ul&gt;
&lt;li&gt;Having replicas helps in tolerating faults.&lt;/li&gt;
&lt;li&gt;Having replicas helps in reducing latency.&lt;/li&gt;
&lt;li&gt;Replica databases can be used for read queries, whereas the primary one can be used for write queries. (Gain application performance)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Replication lag:

&lt;ul&gt;
&lt;li&gt;The time it takes for the value to be copied from the primary to secondary database.&lt;/li&gt;
&lt;li&gt;If replication lag is huge, then it becomes a problem.&lt;/li&gt;
&lt;li&gt;Replicas will give inconsistent data.&lt;/li&gt;
&lt;li&gt;To overcome this there are several consistenct models:

&lt;ul&gt;
&lt;li&gt;Synchronous replication:&lt;/li&gt;
&lt;li&gt;All replicas have to be updated before host is acknowledged. &lt;/li&gt;
&lt;li&gt;Advantages:

&lt;ul&gt;
&lt;li&gt;No lag.&lt;/li&gt;
&lt;li&gt;Data is always consistent.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Disadvantage:

&lt;ul&gt;
&lt;li&gt;Performance might take a hit, because every write will have to wait for all replicas to get updated as well as acknowledge. (High latency)&lt;/li&gt;
&lt;li&gt;If any replica goes down, and couldn't give any acknowledgement, write will fail.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Asynchronous replication: &lt;/li&gt;
&lt;li&gt;Host is acknowledged after primary database is updated. Replicas update asynchronously.&lt;/li&gt;
&lt;li&gt;Advantage:

&lt;ul&gt;
&lt;li&gt;Write opeartion becomes faster.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Disadvantage:

&lt;ul&gt;
&lt;li&gt;If any replica fails, system will be in a inconsistent state.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Semi-synchronous replication:&lt;/li&gt;
&lt;li&gt;Whenever a new write is issued, the primary database will update the value to all the replicas, and will wait for one of the replicas to acknowledge.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CAP (Consistency, Availability, and Partitioning)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;
  
  
  Consistency:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In a consistent system, once a client writes a value to any server and gets a response, it expects to get that value (or a fresher value) back from any server it reads from.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Availability:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In an available system, if the client sends a request to a server and the server has not crashed, then the server must eventually respond to the client. The server is not allowed to ignore the client's requests.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  Partitioning:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The system continues to function and upholds its consistency guarantees in spite of network partitions.&lt;/li&gt;
&lt;li&gt;If we can tolerate the partition, and even though if partition happens and system can still be available and consistent is called partition tolerance.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;h3&gt;
  
  
  CAP theorem (Brewer Theorem):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Any network shared system wants to have these three properties.&lt;/li&gt;
&lt;li&gt;In such a system, having all three properties is nearly impossible.&lt;/li&gt;
&lt;li&gt;We need to sacrifice one of them.&lt;/li&gt;
&lt;li&gt;Partition tolerance happens due to network failures, and we do not have complete control over network failures.&lt;/li&gt;
&lt;li&gt;Hence, partition tolerance becomes a mandatory property to support.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Database Sharding
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/sanyathisside/System-Design"&gt;https://github.com/sanyathisside/System-Design&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  𝟕)𝐒𝐚𝐦𝐩𝐥𝐞 𝐩𝐫𝐨𝐛𝐥𝐞𝐦𝐬 𝐟𝐨𝐫 𝐋𝐋𝐃
&lt;/h1&gt;

&lt;h4&gt;
  
  
  LLD implemented for following sample problems
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/imk13/low-level-design/blob/master/deck-of-cards"&gt;Deck of cards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imk13/low-level-design/blob/master/mychess.com"&gt;Mychess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imk13/low-level-design/blob/master/cab_booking_system"&gt;Cab booking system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imk13/low-level-design/blob/master/food-ordering-system"&gt;Food ordering system&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/imk13/low-level-design"&gt;https://github.com/imk13/low-level-design&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  𝟖) 𝐒𝐜𝐚𝐥𝐞𝐫 𝐀𝐜𝐚𝐝𝐞𝐦𝐲 𝐍𝐨𝐭𝐞𝐬 𝐟𝐨𝐫 𝐒𝐲𝐬𝐭𝐞𝐦 𝐃𝐞𝐬𝐢𝐠𝐧
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/naqushab/ScalerAcademy/tree/develop/Useful"&gt;https://github.com/naqushab/ScalerAcademy/tree/develop/Useful&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  𝟗) 𝐋𝐋𝐃 𝐑𝐞𝐬𝐨𝐮𝐫𝐜𝐞𝐬
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Low-level Design
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://workat.tech/machine-coding"&gt;work@tech Machine Coding section&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc"&gt;[Youtube] Christopher - Design patterns in OOPS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLAC2AM9O1C5KioUMeH9qIjbAV_RMmX8rd"&gt;[Youtube] The Code Mate - LLD Series&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLGLfVvz_LVvS5P7khyR4xDp7T9lCk9PgE"&gt;[Youtube] Derek Banas - OOPS Playlist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://refactoring.guru"&gt;RefactoringGuru Website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://designpatterns.devm.tech"&gt;Head first Design patterns - Book summary (Principles and patterns)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PL564gOx0bCLqTolRIHIsR2JPv11w8LESW"&gt;[Youtube] Udit Agarwal LLD playlist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLTgRMOcmRb3MVU6oeXRp0naSuk9kcnnfC"&gt;[Youtube] Design patterns and SOLID&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLx5t1p9LqYUe_3LrWrrJN5agu5Jcd-3bG"&gt;[Youtube] Google's Clean code talks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.educative.io/courses/grokking-the-object-oriented-design-interview"&gt;Educative's Grokking Object-oriented Design Interview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLA8lYuzFlBqAy6dkZHj5VxUAaqr4vwrka"&gt;[Youtube] Success in Tech&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLx2RZGha5vYlGw7PxsYlMrNC3-f2ihsBM"&gt;[Youtube] Low level System design&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PL12BCqE-Lp650Cg6FZW7SoZwN8Rw1WJI7"&gt;[Youtube] Low Level Design by Amazonian&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLBtMh4xfa9FGzQI8QpUgWI1J9wDdB6RFo"&gt;[Youtube] SDE Skills - Object oriented design&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://roadmap.sh/guides/design-patterns-for-humans"&gt;Design Patterns for Humans [PHP] [Github]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://java-design-patterns.com/"&gt;Design patterns implemented in Java [Github]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@nrkapri/how-to-approach-object-oriented-design-questions-step-by-step-67ed6a5a30e5"&gt;[Medium] How to approach Object Oriented Design Questions step by step&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rooftopslushie.com/request/How%20to%20approach%20OOD%20Questions%20for%20SDE-1-9654"&gt;[Rooftop Slushie] How to approach an LLD question for SDE1?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hashnode.com/series/object-oriented-design-ckh0jxdzs07qw20s16jmh8og7"&gt;[Hashnode] Blog series on Software Design - by Maxi Contieri&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hashnode.com/series/code-smells-ckh0jrbfm07pu20s1bc0yaae1"&gt;[Hashnode] Blog series on Code smells - by Maxi Contieri&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/braindevoiler/design-patterns"&gt;[Github] Design patterns - Code examples&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This repo is just a collection of Low-level Design resources available on the Internet and these resources are created by their respective owners.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.toLICENSE"&gt;MIT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/sbvkrishna/low-level-design"&gt;https://github.com/sbvkrishna/low-level-design&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Reference
&lt;/h1&gt;

&lt;p&gt;Contributed by&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/ansh-/"&gt;https://www.linkedin.com/in/ansh-/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Setup Azure Front door for ASP.NET MVC Webapp hosted in Azure App Service with Azure AD Authentication</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Thu, 16 Jun 2022 09:59:51 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/how-to-setup-azure-front-door-for-aspnet-mvc-webapp-hosted-in-azure-app-service-with-azure-ad-authentication-33jf</link>
      <guid>https://dev.to/ssanjeevi/how-to-setup-azure-front-door-for-aspnet-mvc-webapp-hosted-in-azure-app-service-with-azure-ad-authentication-33jf</guid>
      <description>&lt;h1&gt;
  
  
  Create Webapp - Azure App Service
&lt;/h1&gt;

&lt;p&gt;Create a webapp - azure app service to host the webapp we are creating.&lt;/p&gt;

&lt;h1&gt;
  
  
  Create Azure AD protected Webapp
&lt;/h1&gt;

&lt;p&gt;Create a dotnet core webapp with Azure AD authentication using Open ID connect.&lt;/p&gt;

&lt;p&gt;Follow this article to create a webapp with Azure AD:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-asp-webapp"&gt;https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-asp-webapp&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Create Azure Front Door
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oJQpowl4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364525515/FOniSusml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oJQpowl4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364525515/FOniSusml.png" alt="image.png" width="778" height="826"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Front Door endpoint
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GVVtCSmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364591964/SpKI0m5vq_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GVVtCSmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364591964/SpKI0m5vq_.png" alt="image.png" width="880" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Front door origin group
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WGT2aeUg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364603623/WqPeEFZiB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WGT2aeUg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364603623/WqPeEFZiB.png" alt="image.png" width="880" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Front door origin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zIzJuf_a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364608300/THHHaFUOR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zIzJuf_a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364608300/THHHaFUOR.png" alt="image.png" width="880" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Front door settings look like this after all above steps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--duKtObjx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365196283/T7foAoxN3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--duKtObjx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365196283/T7foAoxN3.png" alt="image.png" width="880" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--atvBzovd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365379553/edHFHHfKY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--atvBzovd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365379553/edHFHHfKY.png" alt="image.png" width="868" height="804"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qnZrL1Tj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365358814/tmdJUJwpt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qnZrL1Tj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365358814/tmdJUJwpt.png" alt="image.png" width="855" height="823"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this we have to update the host header to empty so that the&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RWLuWrBt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365480936/gl_JhTQLk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RWLuWrBt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655365480936/gl_JhTQLk.png" alt="image.png" width="865" height="834"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Update redirect Uri in Azure AD
&lt;/h1&gt;

&lt;p&gt;Update the redirect Uri in Azure AD with the Front door endpoint url&lt;/p&gt;

&lt;h1&gt;
  
  
  Update Webapp with the redirect Uri of Front door
&lt;/h1&gt;

&lt;p&gt;When the Web App sits behind Azure Front Door, we need to configure the redirect_uri in the /authorize request to be the Front Door's address.&lt;/p&gt;

&lt;p&gt;In the code below we override the "OnRedirectToIdentityProvider" event and inject the Front Door's address. When I was trying this out, I simply hardcoded the address but ideally, you'd extract it from the headers that Front Door injects into the request.&lt;/p&gt;

&lt;p&gt;This is the code I used when trying to authenticate my dotnet core Server App (.net 6) running on an Azure App Service, Protected by Azure AD, running behind Azure Front Door.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void ConfigureServices(IServiceCollection services)
{
    // ... existing code

    services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
                .EnableTokenAcquisitionToCallDownstreamApi(new[] { "User.Read" })
                .AddInMemoryTokenCaches();

    services.Configure&amp;lt;OpenIdConnectOptions&amp;gt;(OpenIdConnectDefaults.AuthenticationScheme, options =&amp;gt;
    {
        options.Events = new OpenIdConnectEvents
        {
            OnRedirectToIdentityProvider = (context) =&amp;gt;
            {   
                // Override the redirect_uri
                // Ideally extract this from config 
                // Or context.Request.Headers["X-Forwarded-Host"]
                // see: https://docs.microsoft.com/en-us/azure/frontdoor/front-door-http-headers-protocol#front-door-to-backend

                context.ProtocolMessage.RedirectUri 
                    = "https://YOUR-FRONT-DOOR-or-APP-GATEWAY/signin-oidc";
                return Task.FromResult(0);
            }
        };
    });

    services.Configure&amp;lt;ForwardedHeadersOptions&amp;gt;(options =&amp;gt;
    {
        options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                        ForwardedHeaders.XForwardedProto;
        options.KnownNetworks.Clear();
        options.KnownProxies.Clear();
    });

    // ... existing code
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... existing code

    // Don't forget to add this ...
    app.UseForwardedHeaders();

    // ... existing code
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the code works, the "redirect_uri" param should point to your Front Door/Gateway as shown here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KEo9f-BH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364777509/732_Bfilc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KEo9f-BH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1655364777509/732_Bfilc.png" alt="image.png" width="880" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reference
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/61733729/authentication-with-azure-ad-redirect-uri-is-incorrect-using-frontdoor"&gt;https://stackoverflow.com/questions/61733729/authentication-with-azure-ad-redirect-uri-is-incorrect-using-frontdoor&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Create Dotnet 6 API with Swagger UI</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Tue, 22 Mar 2022 11:28:35 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/create-dotnet-6-api-with-swagger-ui-22pe</link>
      <guid>https://dev.to/ssanjeevi/create-dotnet-6-api-with-swagger-ui-22pe</guid>
      <description>&lt;h1&gt;
  
  
  Tutorial: Create a minimal web API with ASP.NET Core
&lt;/h1&gt;

&lt;p&gt;Minimal APIs are architected to create HTTP APIs with minimal dependencies. They are ideal for microservices and apps that want to include only the minimum files, features, and dependencies in ASP.NET Core.&lt;/p&gt;

&lt;p&gt;This tutorial teaches the basics of building a minimal web API with ASP.NET Core. For a tutorial on creating a web API project based on &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-6.0"&gt;controllers&lt;/a&gt; that contains more features, see &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-6.0"&gt;Create a web API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This tutorial creates the following API:&lt;/p&gt;

&lt;p&gt;| API | Description | Request body | Response body |&lt;br&gt;
| &lt;code&gt;GET /&lt;/code&gt; | Browser test, "Hello World" | None | Hello World! |&lt;br&gt;
| &lt;code&gt;GET /todoitems&lt;/code&gt; | Get all to-do items | None | Array of to-do items |&lt;br&gt;
| &lt;code&gt;GET /todoitems/complete&lt;/code&gt; | Get completed to-do items | None | Array of to-do items |&lt;br&gt;
| &lt;code&gt;GET /todoitems/{id}&lt;/code&gt; | Get an item by ID | None | To-do item |&lt;br&gt;
| &lt;code&gt;POST /todoitems&lt;/code&gt; | Add a new item | To-do item | To-do item |&lt;br&gt;
| &lt;code&gt;PUT /todoitems/{id}&lt;/code&gt; | Update an existing item | To-do item | None |&lt;br&gt;
| &lt;code&gt;DELETE /todoitems/{id}&lt;/code&gt; | Delete an item | None | None |&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;
&lt;h1&gt;
  
  
  Visual Studio
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yksfmIeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947592051/8uBM2uyAm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yksfmIeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947592051/8uBM2uyAm.png" alt="image.png" width="880" height="514"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a Web API project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start Visual Studio 2022 and select &lt;strong&gt;Create a new project&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Create a new project&lt;/strong&gt; dialog:

&lt;ul&gt;
&lt;li&gt;Enter &lt;code&gt;API&lt;/code&gt; in the &lt;strong&gt;Search for templates&lt;/strong&gt; search box.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;ASP.NET Core Web API&lt;/strong&gt; template and select &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mztq-bJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947624328/IgNKDtIWV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mztq-bJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947624328/IgNKDtIWV.png" alt="image.png" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name the project &lt;em&gt;TodoApi&lt;/em&gt; and select &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Additional information&lt;/strong&gt; dialog:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1fO4DI97--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947691761/Ix0K0unBx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1fO4DI97--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947691761/Ix0K0unBx.png" alt="image.png" width="880" height="575"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Examine the code
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Program.cs&lt;/code&gt; file contains the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =&amp;gt;
{
    var forecast = Enumerable.Range(1, 5).Select(index =&amp;gt;
       new WeatherForecast
       (
           DateTime.Now.AddDays(index),
           Random.Shared.Next(-20, 55),
           summaries[Random.Shared.Next(summaries.Length)]
       ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF =&amp;gt; 32 + (int)(TemperatureC / 0.5556);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project template creates a &lt;code&gt;WeatherForecast&lt;/code&gt; API with support for &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-6.0"&gt;Swagger&lt;/a&gt;. Swagger is used to generate useful documentation and help pages for web APIs.&lt;/p&gt;

&lt;p&gt;The following highlighted code adds support for Swagger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the app
&lt;/h3&gt;

&lt;p&gt;Press Ctrl+F5 to run without the debugger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--khGj3n19--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947836290/RTy1By_LK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--khGj3n19--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647947836290/RTy1By_LK.png" alt="image.png" width="495" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Visual Studio launches the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-6.0"&gt;Kestrel web server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Swagger page &lt;code&gt;/swagger/index.html&lt;/code&gt; is displayed. Select &lt;strong&gt;&lt;code&gt;GET &amp;gt; Try it out&amp;gt; Execute&lt;/code&gt;&lt;/strong&gt;. The page displays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://curl.haxx.se/"&gt;Curl&lt;/a&gt; command to test the WeatherForecast API.&lt;/li&gt;
&lt;li&gt;The URL to test the WeatherForecast API.&lt;/li&gt;
&lt;li&gt;The response code, body, and headers.&lt;/li&gt;
&lt;li&gt;A drop down list box with media types and the example value and schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copy and paste the &lt;strong&gt;Request URL&lt;/strong&gt; in the browser: &lt;code&gt;https://localhost:&amp;lt;port&amp;gt;/WeatherForecast&lt;/code&gt;. JSON similar to the following is returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "date": "2021-10-19T14:12:50.3079024-10:00",
    "temperatureC": 13,
    "summary": "Bracing",
    "temperatureF": 55
  },
  {
    "date": "2021-10-20T14:12:50.3080559-10:00",
    "temperatureC": -8,
    "summary": "Bracing",
    "temperatureF": 18
  },
  {
    "date": "2021-10-21T14:12:50.3080601-10:00",
    "temperatureC": 12,
    "summary": "Hot",
    "temperatureF": 53
  },
  {
    "date": "2021-10-22T14:12:50.3080603-10:00",
    "temperatureC": 10,
    "summary": "Sweltering",
    "temperatureF": 49
  },
  {
    "date": "2021-10-23T14:12:50.3080604-10:00",
    "temperatureC": 36,
    "summary": "Warm",
    "temperatureF": 96
  }
]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update the generated code
&lt;/h2&gt;

&lt;p&gt;This tutorial focuses on creating a web API, so we'll delete the Swagger code and the &lt;code&gt;WeatherForecast&lt;/code&gt; code. Replace the contents of the &lt;code&gt;Program.cs&lt;/code&gt; file with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () =&amp;gt; "Hello World!");

app.Run();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following highlighted code creates a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.webapplicationbuilder"&gt;Web application builder&lt;/a&gt; and a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.webapplication"&gt;application&lt;/a&gt; with preconfigured defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () =&amp;gt; "Hello World!");

app.Run();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following code creates an HTTP GET endpoint &lt;code&gt;/&lt;/code&gt; which returns &lt;code&gt;Hello World!&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.MapGet("/", () =&amp;gt; "Hello World!");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;app.Run();&lt;/code&gt; runs the app.&lt;/p&gt;

&lt;p&gt;Remove the two &lt;code&gt;"launchUrl": "swagger",&lt;/code&gt; lines from the &lt;em&gt;Properties/launchSettings.json&lt;/em&gt; file. When the &lt;code&gt;launchUrl&lt;/code&gt; isn't specified, the web browser requests the &lt;code&gt;/&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;p&gt;Run the app. &lt;code&gt;Hello World!&lt;/code&gt; is displayed. The updated &lt;code&gt;Program.cs&lt;/code&gt; file contains a minimal but complete app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add NuGet packages
&lt;/h2&gt;

&lt;p&gt;NuGet packages must be added to support the database and diagnostics used in this tutorial.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From the &lt;strong&gt;Tools&lt;/strong&gt; menu, select &lt;strong&gt;NuGet Package Manager &amp;gt; Manage NuGet Packages for Solution&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;Browse&lt;/strong&gt; tab, and verify that &lt;strong&gt;Include prerelease&lt;/strong&gt; is checked.&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Microsoft.EntityFrameworkCore.InMemory&lt;/strong&gt; in the search box, and then select &lt;code&gt;Microsoft.EntityFrameworkCore.InMemory&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;Project&lt;/strong&gt; checkbox in the right pane and then select &lt;strong&gt;Install&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Follow the preceding instructions to add the &lt;code&gt;Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore&lt;/code&gt; package.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Add the API code
&lt;/h2&gt;

&lt;p&gt;Replace the contents of the &lt;code&gt;Program.cs&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext&amp;lt;TodoDb&amp;gt;(opt =&amp;gt; opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();

app.MapGet("/", () =&amp;gt; "Hello World!");

app.MapGet("/todoitems", async (TodoDb db) =&amp;gt;
    await db.Todos.ToListAsync());

app.MapGet("/todoitems/complete", async (TodoDb db) =&amp;gt;
    await db.Todos.Where(t =&amp;gt; t.IsComplete).ToListAsync());

app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =&amp;gt;
    await db.Todos.FindAsync(id)
        is Todo todo
            ? Results.Ok(todo)
            : Results.NotFound());

app.MapPost("/todoitems", async (Todo todo, TodoDb db) =&amp;gt;
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
});

app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =&amp;gt;
{
    var todo = await db.Todos.FindAsync(id);

    if (todo is null) return Results.NotFound();

    todo.Name = inputTodo.Name;
    todo.IsComplete = inputTodo.IsComplete;

    await db.SaveChangesAsync();

    return Results.NoContent();
});

app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =&amp;gt;
{
    if (await db.Todos.FindAsync(id) is Todo todo)
    {
        db.Todos.Remove(todo);
        await db.SaveChangesAsync();
        return Results.Ok(todo);
    }

    return Results.NotFound();
});

app.Run();

class Todo
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
}

class TodoDb : DbContext
{
    public TodoDb(DbContextOptions&amp;lt;TodoDb&amp;gt; options)
        : base(options) { }

    public DbSet&amp;lt;Todo&amp;gt; Todos =&amp;gt; Set&amp;lt;Todo&amp;gt;();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The model and database context classes
&lt;/h2&gt;

&lt;p&gt;The sample app contains the following model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Todo
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;em&gt;model&lt;/em&gt; is a class that represents data that the app manages. The model for this app is the &lt;code&gt;Todo&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;The sample app also contains the following database context class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TodoDb : DbContext
{
    public TodoDb(DbContextOptions&amp;lt;TodoDb&amp;gt; options)
        : base(options) { }

    public DbSet&amp;lt;Todo&amp;gt; Todos =&amp;gt; Set&amp;lt;Todo&amp;gt;();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;database context&lt;/em&gt; is the main class that coordinates &lt;a href="https://docs.microsoft.com/en-us/ef/core/"&gt;Entity Framework&lt;/a&gt; functionality for a data model. This class is created by deriving from the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext"&gt;DB context&lt;/a&gt; class.&lt;/p&gt;

&lt;p&gt;The following highlighted code adds the database context to the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-6.0"&gt;dependency injection (DI)&lt;/a&gt; container and enables displaying database-related exceptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext&amp;lt;TodoDb&amp;gt;(opt =&amp;gt; opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DI container provides access to the database context and other services.&lt;/p&gt;

&lt;p&gt;The following code creates an HTTP POST endpoint &lt;code&gt;/todoitems&lt;/code&gt; to add data to the in-memory database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.MapPost("/todoitems", async (Todo todo, TodoDb db) =&amp;gt;
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Postman to test the app
&lt;/h2&gt;

&lt;p&gt;This tutorial uses Postman to test the API.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;a href="https://www.getpostman.com/downloads/"&gt;Postman&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Start the web app.&lt;/li&gt;
&lt;li&gt;Start Postman.&lt;/li&gt;
&lt;li&gt;Disable &lt;strong&gt;SSL certificate verification&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;From &lt;strong&gt;File&lt;/strong&gt; &amp;gt; &lt;strong&gt;Settings&lt;/strong&gt; ( &lt;strong&gt;General&lt;/strong&gt; tab), disable &lt;strong&gt;SSL certificate verification&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;[!WARNING] Re-enable SSL certificate verification after testing the controller.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Test posting data
&lt;/h3&gt;

&lt;p&gt;The following instructions post data to the app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new request.&lt;/li&gt;
&lt;li&gt;Set the HTTP method to &lt;code&gt;POST&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the URI to &lt;code&gt;https://localhost:&amp;lt;port&amp;gt;/todoitems&lt;/code&gt;. For example: &lt;code&gt;https://localhost:5001/todoitems&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;Body&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;raw&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set the type to &lt;strong&gt;JSON&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the request body enter JSON for a to-do item:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Send&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3I9iEedY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647948193135/c80ldSRmW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3I9iEedY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1647948193135/c80ldSRmW.png" alt="image.png" width="880" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Examine the GET endpoints
&lt;/h2&gt;

&lt;p&gt;The sample app implements several GET endpoints using calls to &lt;code&gt;MapGet&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;| API | Description | Request body | Response body |&lt;br&gt;
| &lt;code&gt;GET /&lt;/code&gt; | Browser test, "Hello World" | None | &lt;code&gt;Hello World!&lt;/code&gt; |&lt;br&gt;
| &lt;code&gt;GET /todoitems&lt;/code&gt; | Get all to-do items | None | Array of to-do items |&lt;br&gt;
| &lt;code&gt;GET /todoitems/{id}&lt;/code&gt; | Get an item by ID | None | To-do item |&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.MapGet("/", () =&amp;gt; "Hello World!");

app.MapGet("/todoitems", async (TodoDb db) =&amp;gt;
    await db.Todos.ToListAsync());

app.MapGet("/todoitems/complete", async (TodoDb db) =&amp;gt;
    await db.Todos.Where(t =&amp;gt; t.IsComplete).ToListAsync());

app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =&amp;gt;
    await db.Todos.FindAsync(id)
        is Todo todo
            ? Results.Ok(todo)
            : Results.NotFound());

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Test the GET endpoints
&lt;/h2&gt;

&lt;p&gt;Test the app by calling the two endpoints from a browser or Postman. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET https://localhost:5001/todoitems&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET https://localhost:5001/todoitems/1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The call to &lt;code&gt;GET /todoitems&lt;/code&gt; produces a response similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test the GET endpoints with Postman
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new request.&lt;/li&gt;
&lt;li&gt;Set the HTTP method to &lt;strong&gt;GET&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set the request URI to &lt;code&gt;https://localhost:&amp;lt;port&amp;gt;/todoitems&lt;/code&gt;. For example, &lt;code&gt;https://localhost:5001/todoitems&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Send&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This app uses an in-memory database. If the app is restarted, the GET request doesn't return any data. If no data is returned, first &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0&amp;amp;tabs=visual-studio#post"&gt;POST&lt;/a&gt; data to the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Return values
&lt;/h2&gt;

&lt;p&gt;ASP.NET Core automatically serializes the object to &lt;a href="https://www.json.org"&gt;JSON&lt;/a&gt; and writes the JSON into the body of the response message. The response code for this return type is &lt;a href="https://developer.mozilla.org/docs/Web/HTTP/Status/200"&gt;200 OK&lt;/a&gt;, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.&lt;/p&gt;

&lt;p&gt;The return types can represent a wide range of HTTP status codes. For example, &lt;code&gt;GET /todoitems/{id}&lt;/code&gt; can return two different status values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If no item matches the requested ID, the method returns a &lt;a href="https://developer.mozilla.org/docs/Web/HTTP/Status/404"&gt;404 status&lt;/a&gt; &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.notfound"&gt;Not found&lt;/a&gt; error code.&lt;/li&gt;
&lt;li&gt;Otherwise, the method returns 200 with a JSON response body. Returning &lt;code&gt;item&lt;/code&gt; results in an HTTP 200 response.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Examine the PUT endpoint
&lt;/h2&gt;

&lt;p&gt;The sample app implements a single PUT endpoint using &lt;code&gt;MapPut&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =&amp;gt;
{
    var todo = await db.Todos.FindAsync(id);

    if (todo is null) return Results.NotFound();

    todo.Name = inputTodo.Name;
    todo.IsComplete = inputTodo.IsComplete;

    await db.SaveChangesAsync();

    return Results.NoContent();
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method is similar to the &lt;code&gt;MapPost&lt;/code&gt; method, except it uses HTTP PUT. A successful response returns &lt;a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html"&gt;204 (No Content)&lt;/a&gt;. According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.httppatchattribute"&gt;HTTP PATCH&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test the PUT endpoint
&lt;/h3&gt;

&lt;p&gt;This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call.&lt;/p&gt;

&lt;p&gt;Update the to-do item that has Id = 1 and set its name to &lt;code&gt;"feed fish"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Id": 1,
  "name": "feed fish",
  "isComplete": false
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Examine the DELETE endpoint
&lt;/h2&gt;

&lt;p&gt;The sample app implements a single DELETE endpoint using &lt;code&gt;MapDelete&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =&amp;gt;
{
    if (await db.Todos.FindAsync(id) is Todo todo)
    {
        db.Todos.Remove(todo);
        await db.SaveChangesAsync();
        return Results.Ok(todo);
    }

    return Results.NotFound();
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use Postman to delete a to-do item:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the method to &lt;code&gt;DELETE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the URI of the object to delete (for example &lt;code&gt;https://localhost:5001/todoitems/1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Send&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prevent over-posting
&lt;/h2&gt;

&lt;p&gt;Currently the sample app exposes the entire &lt;code&gt;Todo&lt;/code&gt; object. Production apps typically limit the data that's input and returned using a subset of the model. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. &lt;strong&gt;DTO&lt;/strong&gt; is used in this article.&lt;/p&gt;

&lt;p&gt;A DTO may be used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevent over-posting.&lt;/li&gt;
&lt;li&gt;Hide properties that clients are not supposed to view.&lt;/li&gt;
&lt;li&gt;Omit some properties in order to reduce payload size.&lt;/li&gt;
&lt;li&gt;Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To demonstrate the DTO approach, update the &lt;code&gt;Todo&lt;/code&gt; class to include a secret field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Todo
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
    public string? Secret { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The secret field needs to be hidden from this app, but an administrative app could choose to expose it.&lt;/p&gt;

&lt;p&gt;Verify you can post and get the secret field.&lt;/p&gt;

&lt;p&gt;Create a DTO model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class TodoItemDTO
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }

    public TodoItemDTO() { }
    public TodoItemDTO(Todo todoItem) =&amp;gt;
    (Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the code to use &lt;code&gt;TodoItemDTO&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDbContext&amp;lt;TodoDb&amp;gt;(opt =&amp;gt; opt.UseInMemoryDatabase("TodoList"));
var app = builder.Build();

app.MapGet("/todoitems", async (TodoDb db) =&amp;gt;
    await db.Todos.Select(x =&amp;gt; new TodoItemDTO(x)).ToListAsync());

app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =&amp;gt;
    await db.Todos.FindAsync(id)
        is Todo todo
            ? Results.Ok(new TodoItemDTO(todo))
            : Results.NotFound());

app.MapPost("/todoitems", async (TodoItemDTO todoItemDTO, TodoDb db) =&amp;gt;
{
    var todoItem = new Todo
    {
        IsComplete = todoItemDTO.IsComplete,
        Name = todoItemDTO.Name
    };

    db.Todos.Add(todoItem);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todoItem.Id}", new TodoItemDTO(todoItem));
});

app.MapPut("/todoitems/{id}", async (int id, TodoItemDTO todoItemDTO, TodoDb db) =&amp;gt;
{
    var todo = await db.Todos.FindAsync(id);

    if (todo is null) return Results.NotFound();

    todo.Name = todoItemDTO.Name;
    todo.IsComplete = todoItemDTO.IsComplete;

    await db.SaveChangesAsync();

    return Results.NoContent();
});

app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =&amp;gt;
{
    if (await db.Todos.FindAsync(id) is Todo todo)
    {
        db.Todos.Remove(todo);
        await db.SaveChangesAsync();
        return Results.Ok(new TodoItemDTO(todo));
    }

    return Results.NotFound();
});

app.Run();

public class Todo
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
    public string? Secret { get; set; }
}

public class TodoItemDTO
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }

    public TodoItemDTO() { }
    public TodoItemDTO(Todo todoItem) =&amp;gt;
    (Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}

class TodoDb : DbContext
{
    public TodoDb(DbContextOptions&amp;lt;TodoDb&amp;gt; options)
        : base(options) { }

    public DbSet&amp;lt;Todo&amp;gt; Todos =&amp;gt; Set&amp;lt;Todo&amp;gt;();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify you can't post or get the secret field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use JsonOptions
&lt;/h2&gt;

&lt;p&gt;The following code uses &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.json.jsonoptions"&gt;Json Options&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.Http.Json;

var builder = WebApplication.CreateBuilder(args);

// Configure JSON options
builder.Services.Configure&amp;lt;JsonOptions&amp;gt;(options =&amp;gt;
{
    options.SerializerOptions.IncludeFields = true;
});

var app = builder.Build();

app.MapGet("/", () =&amp;gt; new Todo { Name = "Walk dog", IsComplete = false });

app.Run();

class Todo
{
    // These are public fields instead of properties.
    public string? Name;
    public bool IsComplete;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following code uses &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions"&gt;Json Serializer Options&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);

app.MapGet("/", () =&amp;gt; Results.Json(new Todo {
                      Name = "Walk dog", IsComplete = false }, options));

app.Run();

class Todo
{
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The preceding code uses &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-configure-options#web-defaults-for-jsonserializeroptions"&gt;web defaults&lt;/a&gt;, which converts property names to camel case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test minimal API
&lt;/h2&gt;

&lt;p&gt;For an example of testing a minimal API app, see &lt;a href="https://github.com/davidfowl/CommunityStandUpMinimalAPI/blob/main/TodoApi.Tests/TodoTests.cs"&gt;this GitHub sample&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0&amp;amp;tabs=visual-studio"&gt;https://docs.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0&amp;amp;tabs=visual-studio&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Configurable Retry logic for SQL server connection in Dotnet C#</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Thu, 24 Feb 2022 14:23:39 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/configurable-retry-logic-for-sql-server-connection-in-dotnet-c-2c64</link>
      <guid>https://dev.to/ssanjeevi/configurable-retry-logic-for-sql-server-connection-in-dotnet-c-2c64</guid>
      <description>&lt;p&gt;The implementation in this sample is as simple as possible to demonstrate step-by-step customization. It doesn't include advanced practices like thread safety, async, and concurrency. For a deep-dive into a real implementation, you can study the pre-defined retry logic in the Microsoft.Data.SqlClient GitHub repository.&lt;/p&gt;

&lt;p&gt;Define custom configurable retry logic classes:&lt;/p&gt;

&lt;p&gt;Enumerator: Define a fixed sequence of time intervals and extend the acceptable range of times from two minutes to four minutes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CustomEnumerator : SqlRetryIntervalBaseEnumerator
{
    // Set the maximum acceptable time to 4 minutes
    private readonly TimeSpan _maxValue = TimeSpan.FromMinutes(4);

    public CustomEnumerator(TimeSpan timeInterval, TimeSpan maxTime, TimeSpan minTime)
        : base(timeInterval, maxTime, minTime) {}

    // Return fixed time on each request
    protected override TimeSpan GetNextInterval()
    {
        return GapTimeInterval;
    }

    // Override the validate method with the new time range validation
    protected override void Validate(TimeSpan timeInterval, TimeSpan maxTimeInterval, TimeSpan minTimeInterval)
    {
        if (minTimeInterval &amp;lt; TimeSpan.Zero || minTimeInterval &amp;gt; _maxValue)
        {
            throw new ArgumentOutOfRangeException(nameof(minTimeInterval));
        }

        if (maxTimeInterval &amp;lt; TimeSpan.Zero || maxTimeInterval &amp;gt; _maxValue)
        {
            throw new ArgumentOutOfRangeException(nameof(maxTimeInterval));
        }

        if (timeInterval &amp;lt; TimeSpan.Zero || timeInterval &amp;gt; _maxValue)
        {
            throw new ArgumentOutOfRangeException(nameof(timeInterval));
        }

        if (maxTimeInterval &amp;lt; minTimeInterval)
        {
            throw new ArgumentOutOfRangeException(nameof(minTimeInterval));
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retry logic: Implement retry logic on any command that isn't part of an active transaction. Lower the number of retries from 60 to 20.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CustomRetryLogic : SqlRetryLogicBase
{
    // Maximum number of attempts
    private const int maxAttempts = 20;

    public CustomRetryLogic(int numberOfTries,
                             SqlRetryIntervalBaseEnumerator enumerator,
                             Predicate&amp;lt;Exception&amp;gt; transientPredicate)
    {
        if (!(numberOfTries &amp;gt; 0 &amp;amp;&amp;amp; numberOfTries &amp;lt;= maxAttempts))
        {
            // 'numberOfTries' should be between 1 and 20.
            throw new ArgumentOutOfRangeException(nameof(numberOfTries));
        }

        // Assign parameters to the relevant properties
        NumberOfTries = numberOfTries;
        RetryIntervalEnumerator = enumerator;
        TransientPredicate = transientPredicate;
        Current = 0;
    }

    // Prepare this object for the next round
    public override void Reset()
    {
        Current = 0;
        RetryIntervalEnumerator.Reset();
    }

    public override bool TryNextInterval(out TimeSpan intervalTime)
    {
        intervalTime = TimeSpan.Zero;
        // First try has occurred before starting the retry process. 
        // Check if retry is still allowed
        bool result = Current &amp;lt; NumberOfTries - 1;

        if (result)
        {
            // Increase the number of attempts
            Current++;
            // It's okay if the RetryIntervalEnumerator gets to the last value before we've reached our maximum number of attempts.
            // MoveNext() will simply leave the enumerator on the final interval value and we will repeat that for the final attempts.
            RetryIntervalEnumerator.MoveNext();
            // Receive the current time from enumerator
            intervalTime = RetryIntervalEnumerator.Current;
        }
        return result;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Provider: Implements a retry provider that retries on synchronous operations without a Retrying event. Adds TimeoutException to the existing SqlException transient exception error numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CustomProvider : SqlRetryLogicBaseProvider
{
    // Preserve the given retryLogic on creation
    public CustomProvider(SqlRetryLogicBase retryLogic)
    {
        RetryLogic = retryLogic;
    }

    public override TResult Execute&amp;lt;TResult&amp;gt;(object sender, Func&amp;lt;TResult&amp;gt; function)
    {
        // Create a list to save transient exceptions to report later if necessary
        IList&amp;lt;Exception&amp;gt; exceptions = new List&amp;lt;Exception&amp;gt;();
        // Prepare it before reusing
        RetryLogic.Reset();
        // Create an infinite loop to attempt the defined maximum number of tries
        do
        {
            try
            {
                // Try to invoke the function
                return function.Invoke();
            }
            // Catch any type of exception for further investigation
            catch (Exception e)
            {
                // Ask the RetryLogic object if this exception is a transient error
                if (RetryLogic.TransientPredicate(e))
                {
                    // Add the exception to the list of exceptions we've retried on
                    exceptions.Add(e);
                    // Ask the RetryLogic for the next delay time before the next attempt to run the function
                    if (RetryLogic.TryNextInterval(out TimeSpan gapTime))
                    {
                        Console.WriteLine($"Wait for {gapTime} before next try");
                        // Wait before next attempt
                        Thread.Sleep(gapTime);
                    }
                    else
                    {
                        // Number of attempts has exceeded the maximum number of tries
                        throw new AggregateException("The number of retries has exceeded the maximum number of attempts.", exceptions);
                    }
                }
                else
                {
                    // If the exception wasn't a transient failure throw the original exception
                    throw;
                }
            }
        } while (true);
    }

    public override Task&amp;lt;TResult&amp;gt; ExecuteAsync&amp;lt;TResult&amp;gt;(object sender, Func&amp;lt;Task&amp;lt;TResult&amp;gt;&amp;gt; function, CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public override Task ExecuteAsync(object sender, Func&amp;lt;Task&amp;gt; function, CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a retry provider instance consisting of the defined custom types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static SqlRetryLogicBaseProvider CreateCustomProvider(SqlRetryLogicOption options)
{
    // 1. create an enumerator instance
    CustomEnumerator customEnumerator = new CustomEnumerator(options.DeltaTime, options.MaxTimeInterval, options.MinTimeInterval);
    // 2. Use the enumerator object to create a new RetryLogic instance
    CustomRetryLogic customRetryLogic = new CustomRetryLogic(5, customEnumerator, (e) =&amp;gt; TransientErrorsCondition(e, options.TransientErrors));
    // 3. Create a provider using the RetryLogic object
    CustomProvider customProvider = new CustomProvider(customRetryLogic);
    return customProvider;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following function will evaluate an exception by using the given list of retryable exceptions and the special TimeoutException exception to determine if it's retryable:'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Return true if the exception is a transient fault.
private static bool TransientErrorsCondition(Exception e, IEnumerable&amp;lt;int&amp;gt; retriableConditions)
{
    bool result = false;

    // Assess only SqlExceptions
    if (retriableConditions != null &amp;amp;&amp;amp; e is SqlException ex)
    {
        foreach (SqlError item in ex.Errors)
        {
            // Check each error number to see if it is a retriable error number
            if (retriableConditions.Contains(item.Number))
            {
                result = true;
                break;
            }
        }
    }
    // Other types of exceptions can also be assessed
    else if (e is TimeoutException)
    {
        result = true;
    }
    return result;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the customized retry logic:&lt;/p&gt;

&lt;p&gt;Define the retry logic parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Define the retry logic parameters
var options = new SqlRetryLogicOption()
{
    // Tries 5 times before throwing an exception
    NumberOfTries = 5,
    // Preferred gap time to delay before retry
    DeltaTime = TimeSpan.FromSeconds(1),
    // Maximum gap time for each delay time before retry
    MaxTimeInterval = TimeSpan.FromSeconds(20),
    // SqlException retriable error numbers
    TransientErrors = new int[] { 4060, 1024, 1025}
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the customized retry logic:&lt;/p&gt;

&lt;p&gt;Define the retry logic parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Define the retry logic parameters
var options = new SqlRetryLogicOption()
{
    // Tries 5 times before throwing an exception
    NumberOfTries = 5,
    // Preferred gap time to delay before retry
    DeltaTime = TimeSpan.FromSeconds(1),
    // Maximum gap time for each delay time before retry
    MaxTimeInterval = TimeSpan.FromSeconds(20),
    // SqlException retriable error numbers
    TransientErrors = new int[] { 4060, 1024, 1025}
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a custom retry provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Create a custom retry logic provider
SqlRetryLogicBaseProvider provider = CustomRetry.CreateCustomProvider(options);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign the retry provider to the SqlConnection.RetryLogicProvider or SqlCommand.RetryLogicProvider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Assumes that connection is a valid SqlConnection object 
// Set the retry logic provider on the connection instance
connection.RetryLogicProvider = provider;
// Establishing the connection will trigger retry if one of the given transient failure occurs.
connection.Open();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to enable the configurable retry logic switch before using it. For more information, &lt;a href="https://docs.microsoft.com/en-us/sql/connect/ado-net/appcontext-switches?view=sql-server-ver15#enable-configurable-retry-logic"&gt;see Enable configurable retry logic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reference :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/sql/connect/ado-net/configurable-retry-logic-core-apis-sqlclient?view=sql-server-ver15"&gt;https://docs.microsoft.com/en-us/sql/connect/ado-net/configurable-retry-logic-core-apis-sqlclient?view=sql-server-ver15&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Managed Identity in Dotnet Core API deployed in Azure App Service to Azure SQL Server</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Thu, 10 Feb 2022 11:52:06 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/managed-identity-in-dotnet-core-api-deployed-in-azure-app-service-to-azure-sql-server-3a3n</link>
      <guid>https://dev.to/ssanjeevi/managed-identity-in-dotnet-core-api-deployed-in-azure-app-service-to-azure-sql-server-3a3n</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EWXgwaTa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1644492661354/ZEQfSFFvA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EWXgwaTa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1644492661354/ZEQfSFFvA.png" alt="image.png" width="448" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Grant database access to Azure AD user
&lt;/h2&gt;

&lt;p&gt;First, enable Azure Active Directory authentication to SQL Database by assigning an Azure AD user as the admin of the server. This user is different from the Microsoft account you used to sign up for your Azure subscription. It must be a user that you created, imported, synced, or invited into Azure AD. For more information on allowed Azure AD users, see Azure AD features and limitations in SQL Database.&lt;/p&gt;

&lt;p&gt;If your Azure AD tenant doesn't have a user yet, create one by following the steps at Add or delete users using Azure Active Directory.&lt;/p&gt;

&lt;p&gt;Find the object ID of the Azure AD user using the az ad user list and replace . The result is saved to a variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;azureaduser=$(az ad user list --filter "userPrincipalName eq '&amp;lt;user-principal-name&amp;gt;'" --query [].objectId --output tsv)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this Azure AD user as an Active Directory admin using az sql server ad-admin create command in the Cloud Shell. In the following command, replace with the server name (without the .database.windows.net suffix).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az sql server ad-admin create --resource-group myResourceGroup --server-name &amp;lt;server-name&amp;gt; --display-name ADMIN --object-id $azureaduser

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Set up your dev environment
&lt;/h2&gt;

&lt;p&gt;Visual Studio for Windows is integrated with Azure AD authentication. To enable development and debugging in Visual Studio, add your Azure AD user in Visual Studio by selecting File &amp;gt; Account Settings from the menu, and select Sign in or Add.&lt;/p&gt;

&lt;p&gt;To set the Azure AD user for Azure service authentication, select Tools &amp;gt; Options from the menu, then select Azure Service Authentication &amp;gt; Account Selection. Select the Azure AD user you added and select OK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Older way of using System.Data.SqlClient before new version of Microsoft.Data.SqlClient version came to picture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Azure.Core;
using Azure.Identity;
using Microsoft.Azure.Services.AppAuthentication;

namespace DummyApi
{
    public class AzureSqlAuthTokenService : IDBAuthTokenService
    { 
        // See https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/services-support-managed-identities#azure-sql
        private static readonly string[] _azureSqlScopes = new[]
        {
        "https://database.windows.net//.default"
        };

        private static readonly TokenCredential _credential = new ChainedTokenCredential(
            new ManagedIdentityCredential(),
            new EnvironmentCredential());

        public string GetToken()
        {
            AzureServiceTokenProvider provider = new AzureServiceTokenProvider(serviceProviderConnection);
            var token = provider.GetAccessTokenAsync("https://database.windows.net/").Result;
            return token;
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Above code "serviceProviderConnection" will have following value when debugging in local Visual Studio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RunAs=Developer; DeveloperTool=VisualStudio

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will be updated to following when deployed to App Service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RunAs=App

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refer full values in this link :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/overview/azure/service-to-service-authentication#connection-string-support"&gt;https://docs.microsoft.com/en-us/dotnet/api/overview/azure/service-to-service-authentication#connection-string-support&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to call the above code when connecting to SQLConnection - follow this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
                using (SqlConnection _connection = new SqlConnection())
                {
                    _connection.ConnectionString = sqlConnectionString;
                    _connection.AccessToken = authTokenService.GetToken();

                    _connection.Open();

                    // do some stuff with the sqlconnection to read or write record in SQL.

                    _connection.Close();

                    return true;
                }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Modify your project - new way of using Microsoft.Data.SqlClient
&lt;/h2&gt;

&lt;p&gt;In Visual Studio, open the Package Manager Console and add the NuGet package Microsoft.Data.SqlClient&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install-Package Microsoft.Data.SqlClient -Version 4.0.1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Token creation part is handled by this library by default.&lt;/p&gt;

&lt;p&gt;In the ASP.NET Core and SQL Database tutorial, the MyDbConnection connection string in appsettings.json isn't used at all yet. The local environment and the Azure environment both get connection strings from their respective environment variables in order to keep connection secrets out of the source file. But now with Active Directory authentication, there are no more secrets. In appsettings.json, replace the value of the MyDbConnection connection string with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Server=tcp:&amp;lt;server-name&amp;gt;.database.windows.net;Authentication=Active Directory Default; Database=&amp;lt;database-name&amp;gt;;"



                using (SqlConnection _connection = new SqlConnection(sqlConnectionString))
                {
                    _connection.Open();

                    // do some stuff with the sqlconnection to read or write record in SQL.

                    _connection.Close();

                    return true;
                }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Use managed identity connectivity
&lt;/h2&gt;

&lt;p&gt;Next, you configure your App Service app to connect to SQL Database with a system-assigned managed identity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable managed identity on app
&lt;/h3&gt;

&lt;p&gt;To enable a managed identity for your Azure app, use the az webapp identity assign command in the Cloud Shell. In the following command, replace .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az webapp identity assign --resource-group myResourceGroup --name &amp;lt;app-name&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an example of the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "additionalProperties": {},
  "principalId": "21dfa71c-9e6f-4d17-9e90-1d28801c9735",
  "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47",
  "type": "SystemAssigned"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Grant permissions to managed identity
&lt;/h3&gt;

&lt;p&gt;In the Cloud Shell, sign in to SQL Database by using the SQLCMD command. Replace with your server name, with the database name your app uses, and and with your Azure AD user's credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sqlcmd -S &amp;lt;server-name&amp;gt;.database.windows.net -d &amp;lt;db-name&amp;gt; -U &amp;lt;aad-user-name&amp;gt; -P "&amp;lt;aad-password&amp;gt;" -G -l 30

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the SQL prompt for the database you want, run the following commands to grant the permissions your app needs. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE USER [&amp;lt;identity-name&amp;gt;] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [&amp;lt;identity-name&amp;gt;];
ALTER ROLE db_datawriter ADD MEMBER [&amp;lt;identity-name&amp;gt;];
ALTER ROLE db_ddladmin ADD MEMBER [&amp;lt;identity-name&amp;gt;];
GO

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is the name of the managed identity in Azure AD. If the identity is system-assigned, the name is always the same as the name of your App Service app. For a deployment slot, the name of its system-assigned identity is /slots/. To grant permissions for an Azure AD group, use the group's display name instead (for example, myAzureSQLDBAccessGroup).&lt;/p&gt;

&lt;p&gt;Type EXIT to return to the Cloud Shell prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Publish your changes
&lt;/h2&gt;

&lt;p&gt;All that's left now is to publish your changes to Azure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ycH5aQRz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1644493190254/IlmPU8Hwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ycH5aQRz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1644493190254/IlmPU8Hwr.png" alt="image.png" width="620" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database?tabs=windowsclient%2Cefcore%2Cdotnet"&gt;https://docs.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database?tabs=windowsclient%2Cefcore%2Cdotnet&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Bot Framework chatbot in VNET using Directline Extension and App Service</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Sun, 23 Jan 2022 15:33:15 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/bot-framework-chatbot-in-vnet-using-directline-extension-and-app-service-1gjk</link>
      <guid>https://dev.to/ssanjeevi/bot-framework-chatbot-in-vnet-using-directline-extension-and-app-service-1gjk</guid>
      <description>&lt;h1&gt;
  
  
  Enable Direct Line App Service extension
&lt;/h1&gt;

&lt;p&gt;The complete code is available in this GitHub Repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/SSanjeevi/VirtualAssistantDirectlineExtn"&gt;https://github.com/SSanjeevi/VirtualAssistantDirectlineExtn&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Update bot code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In Visual Studio, open your bot project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow your app to use named pipes:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the Startup.cs file. In the Configure method, add a call to the UseNamedPipes method.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseDefaultFiles()
        .UseStaticFiles()
        .UseWebSockets()
         // Allow the bot to use named pipes.
        .UseNamedPipes(System.Environment.GetEnvironmentVariable("APPSETTING_WEBSITE_SITE_NAME") + ".directline");
        .UseRouting()
        .UseAuthorization()
        .UseEndpoints(endpoints =&amp;gt;
        {
            endpoints.MapControllers();
        });

    // app.UseHttpsRedirection();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Save the Startup.cs file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy your updated bot to Azure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enable bot Direct Line App Service extension
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the Azure portal, go to your Azure Bot resource.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From the left panel menu under Bot management select Channels to configure the Azure Bot Service channels your bot accepts messages from.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If it is not already enabled, select the Direct Line channel and follow instructions to enable the channel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Connect to channels table select the Edit link on the Direct Line row.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll down to the App Service extension Keys section.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the Show link to reveal one of the keys. Copy this value for use later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to the home page, select App Services at the top of the page. Alternatively, display the portal menu and then select the App Services menu item, in the left panel. Azure displays the App Services page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the search box enter your Azure Bot resource name. Your resource will be listed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notice that if you hover over the icon or the menu item, you get the list of the last resources you viewed. Chances are your Azure Bot resource will be listed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select your resource link.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Settings section, select the Configuration menu item.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the right panel, add the following settings:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Name - Value DirectLineExtensionKey - The value of the App Service extension key you copied earlier. DIRECTLINE_EXTENSION_VERSION - latest&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If your bot is hosted in a sovereign or otherwise restricted Azure cloud, where you don't access Azure via the public portal, you will also need to add the following setting:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Still within the Configuration section, select the General settings section and turn on Web sockets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select Save to save the settings. This restarts the Azure App Service.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Confirm the extension and the bot are configured
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In your browser, navigate to https://.azurewebsites.net/.bot. If everything is correct, the page will return this JSON content: {"v":"123","k":true,"ib":true,"ob":true,"initialized":true}. This is the information you obtain when everything works correctly, where&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;v displays the build version of the Direct Line App Service extension.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;k determines whether the extension can read an extension key from its configuration. initialized determines whether the extension can use the extension key to download the bot metadata from Azure Bot Service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ib determines whether the extension can establish an inbound connection with the bot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ob determines whether the extension can establish an outbound connection with the bot.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Use Web Chat with the Direct Line App Service extension
&lt;/h1&gt;

&lt;p&gt;Generally speaking, the approach is the same as before. With the exception that in version 4.9.1 or later of Web Chat there is built-in support for establishing a two-way WebSocket, which instead of connecting to &lt;a href="https://directline.botframework.com/"&gt;https://directline.botframework.com/&lt;/a&gt; connects directly to the Direct Line App Service extension hosted with your bot. The Direct Line URL for your bot will be https://.azurewebsites.net/.bot/, the Direct Line endpoint on your app service extension. If you configure your own domain name, or your bot is hosted in a sovereign Azure cloud, substitute in the appropriate URL and append the /.bot/ path to access the Direct Line App Service extension's REST APIs.&lt;/p&gt;

&lt;p&gt;Exchange the secret for a token by following the instructions in the Authentication article. Instead of obtaining a token at &lt;a href="https://directline.botframework.com/v3/directline/tokens/generate"&gt;https://directline.botframework.com/v3/directline/tokens/generate&lt;/a&gt;, you will generate the token directly from your Direct Line App Service extension at https://.azurewebsites.net/.bot/v3/directline/tokens/generate.&lt;/p&gt;

&lt;p&gt;For an example that shows how to fetch a token see Web Chat Samples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en-US"&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Web Chat&amp;lt;/title&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&amp;gt;
    &amp;lt;script
      crossorigin="anonymous"
      src="https://cdn.botframework.com/botframework-webchat/latest/webchat-minimal.js"
    &amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;style&amp;gt;
      html,
      body {
        background-color: #f7f7f7;
        height: 100%;
      }

      body {
        margin: 0;
      }

      #webchat {
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
        height: 100%;
        margin: auto;
        max-width: 480px;
        min-width: 360px;
      }
    &amp;lt;/style&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div id="webchat" role="main"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;script&amp;gt;
      (async function() {
        &amp;lt;!-- NOTE: It is highly recommended to replace the below fetch with a call to your own token service as described in step 2 above, and to avoid exposing your channel secret in client side code. --&amp;gt;
        const res = await fetch('https://&amp;lt;your_app_service&amp;gt;.azurewebsites.net/.bot/v3/directline/tokens/generate', { method: 'POST', headers:{'Authorization':'Bearer ' + '&amp;lt;Your Bot's Direct Line channel secret&amp;gt;'}});
        const { token } = await res.json();

        window.WebChat.renderWebChat(
          {
            directLine: await window.WebChat.createDirectLineAppServiceExtension({
              domain: 'https://&amp;lt;your_app_service&amp;gt;.azurewebsites.net/.bot/v3/directline',
              token
            })
          },
          document.getElementById('webchat')
        );

        document.querySelector('#webchat &amp;gt; *').focus();
      })().catch(err =&amp;gt; console.error(err));
    &amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the JavaScript bot implementation, make sure that WebSockets are enabled in the web.config file, as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;configuration&amp;gt;
    &amp;lt;system.webServer&amp;gt;
        &amp;lt;webSocket enabled="true"/&amp;gt;
        ...
    &amp;lt;/system.webServer&amp;gt;
&amp;lt;/configuration&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Troubleshooting
&lt;/h1&gt;

&lt;p&gt;In &lt;a href="https://github.com/SSanjeevi/VirtualAssistantDirectlineExtn"&gt;this GitHub Repo&lt;/a&gt; i have integrated the SeriLog so that any issue you face after implementing this you can see the logs in log stream in app service by following this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lkgforit.com/troubleshooting-by-writing-logs-at-the-application-start-for-net-core-app-using-serilog-14a1914701af"&gt;https://lkgforit.com/troubleshooting-by-writing-logs-at-the-application-start-for-net-core-app-using-serilog-14a1914701af&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Microsoft Loop New Product in Office 365 - Looks stunning</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Wed, 29 Dec 2021 09:19:28 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/microsoft-loop-new-product-in-office-365-looks-stunning-57ji</link>
      <guid>https://dev.to/ssanjeevi/microsoft-loop-new-product-in-office-365-looks-stunning-57ji</guid>
      <description>&lt;h1&gt;
  
  
  Introducing Microsoft Loop
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c5jaBMTp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769476587/03pGk83I7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c5jaBMTp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769476587/03pGk83I7.png" alt="image.png" width="880" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Think, plan, and create - together
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.microsoft.com/en-us/microsoft-loop?ms.url=microsoftcommicrosoft-loop"&gt;https://www.microsoft.com/en-us/microsoft-loop?ms.url=microsoftcommicrosoft-loop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Microsoft Loop is a new app that combines a powerful and flexible canvas with portable components that stay in sync and move freely across Microsoft 365 apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/BkhaV46HM2E"&gt;https://youtu.be/BkhaV46HM2E&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Work together, even when youre apart
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sD0IP5Wb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769282718/Ha7njUpfZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sD0IP5Wb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769282718/Ha7njUpfZ.png" alt="image.png" width="160" height="160"&gt;&lt;/a&gt;Cocreate, build on each others ideas, and add a little personality. Loop is an entirely new way to work togetherdesigned for the hybrid world.&lt;/p&gt;

&lt;h3&gt;
  
  
  See everything in one place
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---rp46Y6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769288806/WoHw8S5IL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---rp46Y6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769288806/WoHw8S5IL.png" alt="image.png" width="160" height="160"&gt;&lt;/a&gt;Organize what you need for your project, such as files, links, and data from other apps, in a single workspace. Work in chat, meetings, or documents using portable components that are always up to date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stay in sync and on track
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8yrrs_ha--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769296559/kPp-2u9PJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8yrrs_ha--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769296559/kPp-2u9PJ.png" alt="image.png" width="160" height="160"&gt;&lt;/a&gt;Jump in, catch up, and get going with Loop. Connect naturally with emojis and expressions. Easily collaborate and track progress with notifications, highlighted changes, status labels, and task lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Microsoft Loop meets you where you are
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hdCA0Swf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769785219/28Az0Ernr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hdCA0Swf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769785219/28Az0Ernr.png" alt="image.png" width="880" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NscZruiv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769802072/G-Z5J3m_J.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NscZruiv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640769802072/G-Z5J3m_J.png" alt="image.png" width="880" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Loop components
&lt;/h2&gt;

&lt;p&gt;Collaborate in the flow of work with Loop components. Work together on lists, tables, notes, or even a customer sales opportunity from Dynamics 365 on a Loop page or in a chat, email, meeting, or document. Loop components in Microsoft 365 apps are rolling out now.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Implementing Middleware in Bot Framework Composer</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Tue, 28 Dec 2021 12:33:57 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/implementing-middleware-in-bot-framework-composer-2ga3</link>
      <guid>https://dev.to/ssanjeevi/implementing-middleware-in-bot-framework-composer-2ga3</guid>
      <description>&lt;h1&gt;
  
  
  Implementing Middleware in Bot Framework Composer
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-middleware?view=azure-bot-service-4.0"&gt;https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-middleware?view=azure-bot-service-4.0&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling state in middleware
&lt;/h2&gt;

&lt;p&gt;A common method to save state is to call the save changes method at the end of the turn handler. Here is a diagram with a focus on the call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I4-W3QbN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640693479835/PGc1AN44k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I4-W3QbN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640693479835/PGc1AN44k.png" alt="image.png" width="880" height="749"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem with this approach is that any state updates made from some custom middleware that happens after the bot's turn handler has returned will not be saved to durable storage. The solution is to move the call to the save changes method to after the custom middleware has completed by adding an instance of the auto-save changes middleware to the beginning of the middleware stack, or at least before any of the middleware that might update state. The execution is shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TXV3zjs8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640693535161/qVovCVxIM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TXV3zjs8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1640693535161/qVovCVxIM.png" alt="image.png" width="880" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add the state management objects that will need updating to a bot state set object, and then use that when you create your auto-save changes middleware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Middleware for Composer Bot
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create a class file&lt;/li&gt;
&lt;li&gt;Inherit this interface - Microsoft.Bot.Builder.IMiddleware&lt;/li&gt;
&lt;li&gt;Implement OnTurnAsync Method like below code sample&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will have access to context, Activity and other stuffs you do in bot framework library implementations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To Access config values use this config_val.AppsettingKeyName&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To Access user Activity use context.Activity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To Access user message use context.Activity.Text&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To Access config values use this config_val.AppsettingKeyName if the appsettings json file contains the key name as 'AppsettingKeyName'&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    public class SampleMiddleware : Microsoft.Bot.Builder.IMiddleware
    {
        private readonly IConfiguration config_val;

        public SampleMiddleware (IConfiguration iconfig)
        {
            config_val = iconfig;
        }

        public virtual async Task OnTurnAsync(ITurnContext context, NextDelegate nextTurn, CancellationToken cancellationToken)
        {
            // Condition to filter based on message or event
            if (context.Activity.Type == "message")
            {
                    var userText = context.Activity.Text;
                    // Do some stuff here with Activity or user input text

                    // To Access config values use this 
                    config_val.AppsettingKeyName

                    // use below code if you want to run the default flow happens remove below code if / 
                    //you don't want to trigger bot action and end the turn.
                    await nextTurn(cancellationToken).ConfigureAwait(false);
            }
        }
   }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initiate the Middleware in Startup of Composer Bot
&lt;/h2&gt;

&lt;p&gt;Initialize the middleware in the startup.cs file inside the ConfigureServices method like below code snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson();
            services.AddBotRuntime(Configuration);

            //code to initialize middleware
            services.AddSingleton&amp;lt;IMiddleware, SampleMiddleware&amp;gt;();
        }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks Happy Coding :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Create custom actions in Bot Framework Composer</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Fri, 24 Dec 2021 08:15:35 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/create-custom-actions-in-bot-framework-composer-384h</link>
      <guid>https://dev.to/ssanjeevi/create-custom-actions-in-bot-framework-composer-384h</guid>
      <description>&lt;h1&gt;
  
  
  Create custom actions
&lt;/h1&gt;

&lt;p&gt;In Bot Framework Composer, actions are the main contents of a trigger. Composer provides different types of actions, such as Send a response, Ask a question, and Create a condition. Besides these built-in actions, additional actions can be added through packages or by creating components that includes custom actions.&lt;/p&gt;

&lt;p&gt;This article explains how to create a custom action that multiplies two inputs together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup the component project
&lt;/h2&gt;

&lt;p&gt;To create a custom action (or any component), first setup a new project, and add the necessary package dependencies for working with adaptive dialogs and the Bot Framework SDK.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Locate the .sln file for the bot, and open it in an editor (like Visual Studio or Visual Studio Code).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new project named MultiplyDialog to your solution. In Visual Studio right-click on the solution in the Solution Explorer and select Add &amp;gt; New Project. Use the Class Library project template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a reference to the Microsoft.Bot.Builder.Adaptive.Runtime package. Use the same version as the bot depends on.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;PackageReference Include="Microsoft.Bot.Builder.Dialogs.Adaptive.Runtime" Version="4.13.1" /&amp;gt;
Add a project reference from the bot project to the component project. Right-click on the &amp;lt;myBot&amp;gt; project and select Add &amp;gt; Project Reference. Choose the MultiplyDialog project and click OK.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the entire solution to restore all packages and validate the dependency tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the custom action
&lt;/h2&gt;

&lt;p&gt;Actions in Composer are special implementations of the Dialog base class. This allows each action in the trigger to be pushed onto the dialog stack, and executed in turn.&lt;/p&gt;

&lt;p&gt;In the new project, rename the Class1.cs file to MultiplyDialog.cs, and update it's contents to look like the below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using AdaptiveExpressions.Properties;
using Microsoft.Bot.Builder.Dialogs;
using Newtonsoft.Json;

public class MultiplyDialog : Dialog
{
    [JsonConstructor]
    public MultiplyDialog([CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
        : base()
    {
        // enable instances of this command as debug break point
        RegisterSourceLocation(sourceFilePath, sourceLineNumber);
    }

    [JsonProperty("$kind")]
    public const string Kind = "MultiplyDialog";

    [JsonProperty("arg1")]
    public NumberExpression Arg1 { get; set; }

    [JsonProperty("arg2")]
    public NumberExpression Arg2 { get; set; }

    [JsonProperty("resultProperty")]
    public StringExpression ResultProperty { get; set; }

    public override Task&amp;lt;DialogTurnResult&amp;gt; BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
    {
        var arg1 = Arg1.GetValue(dc.State);
        var arg2 = Arg2.GetValue(dc.State);

        var result = Convert.ToInt32(arg1) * Convert.ToInt32(arg2);
        if (this.ResultProperty != null)
        {
            dc.State.SetValue(this.ResultProperty.GetValue(dc.State), result);
        }

        return dc.EndDialogAsync(result: result, cancellationToken: cancellationToken);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the schema file
&lt;/h2&gt;

&lt;p&gt;The .schema file for the component is a partial schema that will be merged into the main .schema file for the bot. Although it is possible to edit the main sdk.schema file for the bot directly, doing so is not recommended. Merging partial schema files will isolate changes, allow for easier recovery from errors, and enable easier packaging of your component for reuse.&lt;/p&gt;

&lt;p&gt;Create a new file in the project named MultiplyDialog.schema and update the contents to the below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
    "$role": "implements(Microsoft.IDialog)",
    "title": "Multiply",
    "description": "This will return the result of arg1*arg2",
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "arg1": {
            "$ref": "schema:#/definitions/integerExpression",
            "title": "Arg1",
            "description": "Value from callers memory to use as arg 1"
        },
        "arg2": {
            "$ref": "schema:#/definitions/integerExpression",
            "title": "Arg2",
            "description": "Value from callers memory to use as arg 2"
        },
        "resultProperty": {
            "$ref": "schema:#/definitions/stringExpression",
            "title": "Result",
            "description": "Value from callers memory to store the result"
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the BotComponent class
&lt;/h2&gt;

&lt;p&gt;The adaptive runtime will dynamically discover and inject components at startup time.&lt;/p&gt;

&lt;p&gt;Create a new MultiplyDialogBotComponent.cs file in the project and update the contents to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs.Declarative;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

public class MultiplyDialogBotComponent : BotComponent
{
     public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
     {
         // Anything that could be done in Startup.ConfigureServices can be done here.
         // In this case, the MultiplyDialog needs to be added as a new DeclarativeType.
         services.AddSingleton&amp;lt;DeclarativeType&amp;gt;(sp =&amp;gt; new DeclarativeType&amp;lt;MultiplyDialog&amp;gt;(MultiplyDialog.Kind));
     }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the appsettings.json file of the bot project (located at \settings)to include the MultiplyDialogBotComponent in the runtimeSettings/components array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"runtimeSettings": {
   "components": [
      {
         "name": "MultiplyDialog"
      }
   ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the entire solution to validate everything was added correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Merge schema files
&lt;/h2&gt;

&lt;p&gt;The final step is to merge the partial schema file from the MultiplyDialog project into the main sdk.schema file for the bot. This makes the custom action available for use in Composer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Navigate to the schemas folder in the myBot project. This folder contains a PowerShell script and a bash script. Use an elevated PowerShell terminal to execute the PowerShell script. You will need to either copy/paste the contents of the script, or ensure your execution-policy allows for running unsigned scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To validate the script executed successfully, search for MultiplyDialog inside the MyBot\schemas\sdk.schema file and validate that the partial schema from the MultiplyDialog.schema file is included in sdk.schema.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test
&lt;/h2&gt;

&lt;p&gt;Open the bot project in Composer to test the added custom action. If the project is already loaded, return to Home in Composer, and reload the project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the bot in Composer. Select a trigger add the custom action to.&lt;/li&gt;
&lt;li&gt;Select + under the trigger node to see the actions menu. Then choose Custom Actions &amp;gt; Multiply.&lt;/li&gt;
&lt;li&gt;On the Properties panel on the right side, enter two numbers in the argument fields: Arg1 and Arg2. Enter "dialog.result" in the Result property field.&lt;/li&gt;
&lt;li&gt;Add a Send a response action. Enter "The result is: ${dialog.result}" in the Language Generation editor.&lt;/li&gt;
&lt;li&gt;Select Start Bot to test the bot in Web Chat. When triggered, the bot will respond with the test result entered in the previous step.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to pass Appsettings settings to Custom Action
&lt;/h2&gt;

&lt;p&gt;You can just use the settings scope memory. for example "settings.yourSettings". Please refer to the custom action sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StringExpression yourSettings = "settings.yoursettings"
var yourSettingsValue = yourSettings.GetValue(dc.State);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you sent an multi element json element as collection you can send while passing in parameter:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;json(settings.yourSettings)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Appsettings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  "yourSettings": {
    "value1": true
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In custom Action&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonProperty("appSettings")]
public ValueExpression AppSettings { get; set; }

dynamic appSettings = AppSettings.GetValue(dc.State);

var yourAppsettings = appSettings["yourSettings"]

var value1 = appSettings["yourSettings"]["value1"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Power BI Report on Bot Analytics for Chatbot in Bot Framework Composer</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Wed, 15 Dec 2021 10:34:55 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/power-bi-report-on-bot-analytics-for-chatbot-in-bot-framework-composer-1gc</link>
      <guid>https://dev.to/ssanjeevi/power-bi-report-on-bot-analytics-for-chatbot-in-bot-framework-composer-1gc</guid>
      <description>&lt;h1&gt;
  
  
  Tutorial: View analytics with Power BI
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Purpose
&lt;/h3&gt;

&lt;p&gt;The BOT framework Composer sample provides a Power BI template that can be used to understand how your bot is performing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GgG1_jW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639564238462/hIDiRfPUY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GgG1_jW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639564238462/hIDiRfPUY.png" alt="Overall usage" width="709" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Overall usage
&lt;/h4&gt;

&lt;p&gt;Personalize your experience for your brand and customers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sboPobwb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563482860/My-jJtDOD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sboPobwb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563482860/My-jJtDOD.png" alt="All dialogs overview" width="880" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  All dialogs overview
&lt;/h4&gt;

&lt;p&gt;All dialogs' popularity and status based off of SDK telemetry&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cFYSQOHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563487150/vXZq9lbAf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cFYSQOHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563487150/vXZq9lbAf.png" alt="Dialog overview" width="880" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Dialog overview
&lt;/h4&gt;

&lt;p&gt;Review a specific dialog's popularity and status&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---jiDJSFo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563491124/ND5NEhvBq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---jiDJSFo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563491124/ND5NEhvBq.png" alt="LUIS intents" width="880" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  LUIS intents
&lt;/h4&gt;

&lt;p&gt;A count of LUIS intents per day&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EFvZmk3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563495836/q90RHL706.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EFvZmk3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563495836/q90RHL706.png" alt="All conversation metrics" width="880" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  All conversation metrics
&lt;/h4&gt;

&lt;p&gt;Highlights the average number of conversations per unique user and the average duration by day&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FGPJBntx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563503764/r7xUY7NWf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FGPJBntx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563503764/r7xUY7NWf.png" alt="Conversations drill down" width="880" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Conversations drill down
&lt;/h4&gt;

&lt;p&gt;Per conversation, this highlights the dialogs triggered and common utterances&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WeJ0BWkd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563512529/OYb3aGabv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WeJ0BWkd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563512529/OYb3aGabv.png" alt="Transcript" width="880" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Transcript
&lt;/h4&gt;

&lt;p&gt;Review interactions, sessions, and the transcript between a bot and its users&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y4903pCa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563530955/-RlE66szF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y4903pCa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563530955/-RlE66szF.png" alt="Demographics" width="880" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Demographics
&lt;/h4&gt;

&lt;p&gt;See where users are connecting to your bot&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s3PalUui--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563534798/5bvkdAcYP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s3PalUui--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563534798/5bvkdAcYP.png" alt="Word cloud" width="880" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Word Cloud
&lt;/h4&gt;

&lt;p&gt;Commonly user queries&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VjGFH2Rx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563540099/JGXsEyIZJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VjGFH2Rx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563540099/JGXsEyIZJ.png" alt="Sentiment analysis" width="880" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Sentiment analysis
&lt;/h4&gt;

&lt;p&gt;Average user sentiment results provided by LUIS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ttKqzXds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563544702/DeR1ogn0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ttKqzXds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563544702/DeR1ogn0a.png" alt="QnA Maker insights" width="880" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  QnA Maker insights
&lt;/h4&gt;

&lt;p&gt;Insights on matched user queries with QnA Maker&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--18EdTeel--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563517912/nm5WqQB4o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--18EdTeel--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563517912/nm5WqQB4o.png" alt="User feedback" width="880" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  User feedback
&lt;/h4&gt;

&lt;p&gt;Insights on user submitted feedback&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://powerbi.microsoft.com/desktop/"&gt;Install Power BI Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/SSanjeevi/BotFramework-Composer/blob/main/reports/Power-BI-Report-Composer.pbit"&gt;Download the Bot Composer analytics Power BI template&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/composer/quickstart-create-bot?tabs=v2x"&gt;Create a Bot in Composer&lt;/a&gt; to deploy your Azure resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Time To Complete
&lt;/h3&gt;

&lt;p&gt;10 minutes&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario
&lt;/h3&gt;

&lt;p&gt;A Power BI dashboard showing Application Insights telemetry captured from a Bot Composer BOT.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tutorial: View analytics with Power BI
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Get your Application Insights Application ID
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Log in to the &lt;a href="https://portal.azure.com/"&gt;Azure Portal&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to the Application Insights resource created.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the sidebar, navigate to &lt;strong&gt;Configure &amp;gt; API Access&lt;/strong&gt; on the sidebar. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oD6DMzku--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563470212/_yXWutIYJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oD6DMzku--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563470212/_yXWutIYJ.png" alt="Screenshot highlighting the API Access tab in an Application Insights resource" width="367" height="388"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the Application ID for the next step. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SWshglUh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639564050921/qD-stuspf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SWshglUh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639564050921/qD-stuspf.png" alt="Screenshot highlighting the Application ID of an Application Insights resource" width="840" height="333"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Tutorial: View analytics with Power BI
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Open the Power BI template
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open the &lt;a href="https://github.com/SSanjeevi/BotFramework-Composer/blob/main/reports/Power-BI-Report-Composer.pbit"&gt;Bot Composer analytics template&lt;/a&gt; and paste your &lt;strong&gt;Application Insights Application ID&lt;/strong&gt;. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--evdHUXqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563553120/BkIJbJCcU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--evdHUXqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639563553120/BkIJbJCcU.png" alt="Screenshot of the load template view of a new Composer Bot analytics Power BI template" width="880" height="309"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After loading the tables with your populated data, you should now see insights from your Virtual Assistant.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Note: You may run into authentication issues when opening the template, particularly if you have opened the template previously using another Application ID. If so, perform the following steps to re-authenticate the template with your Application Insights service:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Template&lt;/li&gt;
&lt;li&gt;File &amp;gt; Options and Settings &amp;gt; Data Source Settings&lt;/li&gt;
&lt;li&gt;Click "Global permissions"&lt;/li&gt;
&lt;li&gt;Click on anything resembling "api.logalytics.io" and Clear Permissions &amp;gt; Clear Permissions &amp;gt; Delete&lt;/li&gt;
&lt;li&gt;Close and Re-open the Template&lt;/li&gt;
&lt;li&gt;Paste your Application Insights AppId&lt;/li&gt;
&lt;li&gt;Click Load&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Important&lt;/em&gt;: Select Organizational Account &amp;gt; Sign In &amp;gt; Connect&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Additional Telemetry
&lt;/h2&gt;

&lt;p&gt;By default, a Bot composer Bot based project collects personally identifiable information (e.g. Conversation drill-down and transcripts) which will lead to the respective sections in the PowerBI dashboard to function as expected. If you wish to not collect this information make the changes to &lt;code&gt;appsettings.json&lt;/code&gt; by following this article: &lt;a href="https://docs.microsoft.com/en-us/composer/how-to-capture-telemetry?tabs=v2x#configure-telemetry"&gt;https://docs.microsoft.com/en-us/composer/how-to-capture-telemetry?tabs=v2x#configure-telemetry&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Raised a PR to Bot Framework Composer: &lt;a href="https://github.com/microsoft/BotFramework-Composer/pull/8641"&gt;https://github.com/microsoft/BotFramework-Composer/pull/8641&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Enterprise Application Development with C# 9 and .NET 5: Enhance your C# and .NET skills by mastering the process of...</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Fri, 10 Dec 2021 14:23:23 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/enterprise-application-development-with-c-9-and-net-5-enhance-your-c-and-net-skills-by-mastering-the-process-of-db5</link>
      <guid>https://dev.to/ssanjeevi/enterprise-application-development-with-c-9-and-net-5-enhance-your-c-and-net-skills-by-mastering-the-process-of-db5</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KlKeGKZX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639138696684/UYgdpR8nr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KlKeGKZX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1639138696684/UYgdpR8nr.jpeg" alt="515F14H42uL._SX404_BO1,204,203,200_.jpg" width="406" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;Explore the advanced features of C# and .NET 5 to enhance your code and productivity Follow clear and easy instructions for building an end-to-end enterprise application Learn how to build scalable web applications and host them on the cloud&lt;/p&gt;

&lt;h2&gt;
  
  
  Book Description
&lt;/h2&gt;

&lt;p&gt;.NET Core is one of the most popular programming platforms in the world for an increasingly large community of developers thanks to its excellent cross-platform support. This book will show you how to confidently use the features of .NET 5 with C# 9 to build robust enterprise applications.&lt;/p&gt;

&lt;p&gt;Throughout the book, you'll work on creating an enterprise app and adding a key component to the app with each chapter, before nally getting it ready for testing and deployment. You'll learn concepts relating to advanced data structures, the Entity Framework Core, parallel programming, and dependency injection. As you progress, you'll cover various authentication and authorization schemes provided by .NET Core to make your apps and APIs secure. Next, you'll build web apps using ASP.NET Core 5 and deploy them on the cloud while working with various cloud components using Azure. The book then shows you how to use the latest Microsoft Visual Studio 2019 and C# 9 to simplify developer tasks, and also explores tips and tricks in Visual Studio 2019 to improve your productivity. Later, you'll discover various testing techniques such as unit testing and performance testing as well as dierent methods to deploy enterprise apps.&lt;/p&gt;

&lt;p&gt;By the end of this book, youll be able to create enterprise apps using the powerful features of .NET 5 and deploy them on the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you will learn
&lt;/h2&gt;

&lt;p&gt;Design enterprise apps by making the most of the latest features of .NET 5 Discover dierent layers of an app, such as the data layer, API layer, and web layer Explore end-to-end architecture, implement an enterprise web app using .NET and C# 9, and deploy the app on Azure Focus on the core concepts of web application development such as dependency injection, caching, logging, conguration, and authentication, and implement them in .NET 5 Integrate the new .NET 5 health and performance check APIs with your app Understand how .NET 5 works and contribute to the .NET 5 platform&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this book is for
&lt;/h2&gt;

&lt;p&gt;If you are a developer, architect, or senior programmer who wants to leverage the features of .NET 5 and the C# language, as well as grasp essential techniques to build your skills, then this C# .NET 5 book is for you. Beginner to intermediate-level knowledge of the .NET framework and C# programming is required to understand the concepts covered in this book more effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Designing and Architecting the Enterprise Application&lt;/li&gt;
&lt;li&gt;Introducing .NET 5 Core and Standard&lt;/li&gt;
&lt;li&gt;Introducing C# 9&lt;/li&gt;
&lt;li&gt;Threading and Asynchronous Operations&lt;/li&gt;
&lt;li&gt;Dependency Injection in .NET&lt;/li&gt;
&lt;li&gt;Configuration in .NET Core&lt;/li&gt;
&lt;li&gt;Logging in .NET 5&lt;/li&gt;
&lt;li&gt;Understanding Caching&lt;/li&gt;
&lt;li&gt;Working with Data in .NET 5&lt;/li&gt;
&lt;li&gt;Creating an ASP.NET Core 5 Web API&lt;/li&gt;
&lt;li&gt;Creating an ASP.NET Core 5 Web Application&lt;/li&gt;
&lt;li&gt;Understanding Authentication&lt;/li&gt;
&lt;li&gt;Understanding Authorization&lt;/li&gt;
&lt;li&gt;Health and Diagnostics&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Deploying the Application in Azure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Buy Here
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://packt.link/821x8"&gt;https://packt.link/821x8&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://packt.link/SUSXs"&gt;https://packt.link/SUSXs&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Authors
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Ravindra-Akella/e/B08T97LYCV/ref=dp_byline_cont_book_1"&gt;https://www.amazon.com/Ravindra-Akella/e/B08T97LYCV/ref=dp_byline_cont_book_1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Arun-Kumar-Tamirisa/e/B08X4ZWZLR/ref=dp_byline_cont_book_2"&gt;https://www.amazon.com/Arun-Kumar-Tamirisa/e/B08X4ZWZLR/ref=dp_byline_cont_book_2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Suneel-Kumar-Kunani/e/B08TCHBP9J/ref=dp_byline_cont_book_3"&gt;https://www.amazon.com/Suneel-Kumar-Kunani/e/B08TCHBP9J/ref=dp_byline_cont_book_3&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Generate Adaptive Card for Bot Framework UI using C#</title>
      <dc:creator>Sanjeevi Subramani</dc:creator>
      <pubDate>Sun, 05 Dec 2021 15:21:07 +0000</pubDate>
      <link>https://dev.to/ssanjeevi/generate-adaptive-card-for-bot-framework-ui-using-c-3nba</link>
      <guid>https://dev.to/ssanjeevi/generate-adaptive-card-for-bot-framework-ui-using-c-3nba</guid>
      <description>&lt;h1&gt;
  
  
  Getting Started
&lt;/h1&gt;

&lt;p&gt;An Adaptive Card is a JSON-serialized card object model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptive Card structure
&lt;/h2&gt;

&lt;p&gt;The basic structure of a card is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AdaptiveCard&lt;/code&gt; - The root object describes the AdaptiveCard itself, including its element makeup, its actions, how it should be spoken, and the schema version required to render it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;body&lt;/code&gt; - The body of the card is made up of building-blocks known as &lt;code&gt;elements&lt;/code&gt;. Elements can be composed in nearly infinite arrangements to create many types of cards. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;actions&lt;/code&gt; - Many cards have a set of actions a user may take on it. This property describes those actions which typically get rendered in an "action bar" at the bottom.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Card
&lt;/h3&gt;

&lt;p&gt;This sample card which includes a single line of text followed by an image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "type": "AdaptiveCard",
    "version": "1.0",
    "body": [
        {
            "type": "TextBlock",
            "text": "Here is a ninja cat"
        },
        {
            "type": "Image",
            "url": "http://adaptivecards.io/content/cats/1.png"
        }
    ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;Type&lt;/code&gt; property
&lt;/h2&gt;

&lt;p&gt;Every element has a &lt;code&gt;type&lt;/code&gt; property which identifies what kind of object it is. Looking at the above card, you can see we have two elements, a &lt;code&gt;TextBlock&lt;/code&gt; and an &lt;code&gt;Image&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All Adaptive Card elements &lt;strong&gt;stack vertically&lt;/strong&gt; and &lt;strong&gt;expand to the width of their parent&lt;/strong&gt; (think &lt;code&gt;display: block&lt;/code&gt; in HTML). However, you can use a &lt;code&gt;ColumnSet&lt;/code&gt; to create side-by-side columns of containers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptive Elements
&lt;/h2&gt;

&lt;p&gt;The most fundamental elements are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TextBlock&lt;/strong&gt; - adds a block of text with properties to control what the text looks like&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image&lt;/strong&gt; - adds an image with properties to control what the image looks like&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Container elements
&lt;/h2&gt;

&lt;p&gt;Cards can also have containers, which arrange a collection of child elements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Container&lt;/strong&gt; - Defines a a collection of elements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ColumnSet/Column&lt;/strong&gt; - Defines a collection of columns, each column is a container&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FactSet&lt;/strong&gt; - Container of Facts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ImageSet&lt;/strong&gt; - Container of Images so that UI can show appropriate photo gallery experience for a collection of images.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Input elements
&lt;/h2&gt;

&lt;p&gt;Input elements allow you to ask for native UI to build simple forms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input.Text&lt;/strong&gt; - get text content from the user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input.Date&lt;/strong&gt; - get a Date from the user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input.Time&lt;/strong&gt; - get a Time from the user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input.Number&lt;/strong&gt; - get a Number from the user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input.ChoiceSet&lt;/strong&gt; - Give the user a set of choices and have them pick&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input.Toggle&lt;/strong&gt; - Give the user a single choice between two items and have them pick&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Actions
&lt;/h2&gt;

&lt;p&gt;Actions add buttons to the card. These can perform a variety of actions, like opening a URL or submitting some data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Action.OpenUrl&lt;/strong&gt; - the button opens an external URL for viewing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action.ShowCard&lt;/strong&gt; - Requests a sub-card to be shown to the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action.Submit&lt;/strong&gt; - Ask for all of the input elements to be gathered up into an object which is then sent to you through some method defined by the host application.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example Action.Submit&lt;/strong&gt; : With Skype, an Action.Submit will send a Bot Framework bot activity back to the bot with the &lt;strong&gt;Value&lt;/strong&gt; property containing an object with all of the input data on it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For more details look at&lt;/p&gt;

&lt;p&gt;&lt;a href="https://adaptivecards.io"&gt;https://adaptivecards.io&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  In this Article
&lt;/h2&gt;

&lt;p&gt;When working Bot framework SDK to develop chatbot, we will use the Adaptive cards mostly so that we can achieve many card styles with forms and fields highly customizable - &lt;a href="https://adaptivecards.io/designer/"&gt;refer this site&lt;/a&gt; to understand more on this.&lt;/p&gt;

&lt;p&gt;When we use Adaptive card, we may want to dynamically generate the card with more customization of fields using C#, let's see a sample adaptive card generator code fully in C# in this article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Sample Adaptive Card in C Sharp
&lt;/h1&gt;

&lt;p&gt;We have &lt;a href="https://www.nuget.org/packages/AdaptiveCards"&gt;Adaptive card library in Nuget&lt;/a&gt; which we can use for this purpose.&lt;/p&gt;

&lt;p&gt;Let's see the code how it looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public static AdaptiveCard GenerateAdaptivePromptCard(List&amp;lt;Item&amp;gt; listOfOptions)
    {
        List&amp;lt;AdaptiveChoice&amp;gt; categoryChoices = new List&amp;lt;AdaptiveChoice&amp;gt;();
        foreach (var item in listOfOptions)
        {
            categoryChoices.Add(new AdaptiveChoice
            {
                Title = item.Label,
                Value = item.Value,
            });
        }

        var columns = new AdaptiveColumn
        {
            Separator = true,
        };
        columns.Items.Add(new AdaptiveTextBlock
        {
            Text = "text",
            Wrap = true,
            Weight = AdaptiveTextWeight.Bolder,
            Size = AdaptiveTextSize.Large,
        });
        columns.Items.Add(new AdaptiveTextBlock
        {
            Text = "reprompt message",
            Wrap = true,
            Weight = AdaptiveTextWeight.Lighter,
            Size = AdaptiveTextSize.Default,
        });

        columns.Items.Add(new AdaptiveTextBlock
        {
            Text = "text block message",
            Wrap = true,
        });
        columns.Items.Add(new AdaptiveChoiceSetInput
        {
            Id = "12432",
            Style = AdaptiveChoiceInputStyle.Compact,
            IsMultiSelect = false,
            Choices = categoryChoices,
            Value = categoryId,
        });
        columns.Items.Add(new AdaptiveTextInput
        {
            Id = "234324",
            Value = "test",
            IsRequired = true,
        });
        columns.Items.Add(new AdaptiveTextInput
        {
            Id = DescriptionLabel,
            Value = "value",
            IsMultiline = true,
            IsRequired = true,
            Height = AdaptiveHeight.Stretch,
        });

        var columnSet = new AdaptiveColumnSet();
        columnSet.Columns.Add(columns);

        var container = new AdaptiveContainer();
        container.Style = AdaptiveContainerStyle.Emphasis;
        container.Items.Add(columnSet);

        var mainCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
        mainCard.Body.Add(container);

        mainCard.Actions.Add(new AdaptiveSubmitAction
        {
            Title = "sample submit action",
        });

        return mainCard;
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here i have used the following classes and properties from the NuGet library to generate and customize them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AdaptiveChoice&lt;/li&gt;
&lt;li&gt;AdaptiveColumn&lt;/li&gt;
&lt;li&gt;AdaptiveTextBlock&lt;/li&gt;
&lt;li&gt;AdaptiveTextWeight&lt;/li&gt;
&lt;li&gt;AdaptiveTextSize&lt;/li&gt;
&lt;li&gt;AdaptiveChoiceInputStyle&lt;/li&gt;
&lt;li&gt;AdaptiveChoiceSetInput&lt;/li&gt;
&lt;li&gt;AdaptiveTextInput&lt;/li&gt;
&lt;li&gt;AdaptiveHeight&lt;/li&gt;
&lt;li&gt;AdaptiveColumnSet&lt;/li&gt;
&lt;li&gt;AdaptiveContainer&lt;/li&gt;
&lt;li&gt;AdaptiveContainerStyle&lt;/li&gt;
&lt;li&gt;AdaptiveSubmitAction&lt;/li&gt;
&lt;li&gt;AdaptiveSchemaVersion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like the above code we can customize the Adaptive Card in C#.&lt;/p&gt;

&lt;p&gt;Thanks.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
