<?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: Douglas Minnaar</title>
    <description>The latest articles on DEV Community by Douglas Minnaar (@drminnaar).</description>
    <link>https://dev.to/drminnaar</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%2F51969%2Fc263fde6-4909-48cf-8c9d-e13ee7263f60.png</url>
      <title>DEV Community: Douglas Minnaar</title>
      <link>https://dev.to/drminnaar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/drminnaar"/>
    <language>en</language>
    <item>
      <title>GraphQL For .NET</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Sun, 03 Jul 2022 00:41:00 +0000</pubDate>
      <link>https://dev.to/drminnaar/graphql-for-net-38lc</link>
      <guid>https://dev.to/drminnaar/graphql-for-net-38lc</guid>
      <description>&lt;p&gt;I have recently created &lt;a href="https://github.com/drminnaar/graphql-dotnet-series" rel="noopener noreferrer"&gt;a project on Github&lt;/a&gt; that demonstrates how to build a GraphQL API through the use of a number of examples. I created the project in order to help serve as a guide for .NET developers that are new to GraphQL and would like to learn how to get started. As a final step to this project, I also demonstrate how to create the required infrastructure in Microsoft Azure to host the GraphQL API.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;




&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project Overview&lt;/li&gt;
&lt;li&gt;Learn how to build a .NET 6 GraphQL API from scratch&lt;/li&gt;
&lt;li&gt;Learn how to define GraphQL queries, and mutations&lt;/li&gt;
&lt;li&gt;Learn how to provide validation and error handling&lt;/li&gt;
&lt;li&gt;Add EntityFramework support both in-memory and SQLite database&lt;/li&gt;
&lt;li&gt;Add support for query projection, filtering, sorting, and paging&lt;/li&gt;
&lt;li&gt;Provision Azure App Service using Azure CLI, Azure, Powershell, and Azure Bicep&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;




&lt;p&gt; &lt;/p&gt;

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

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This project explores how to build and deploy a &lt;em&gt;&lt;a href="https://graphql.org" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;&lt;/em&gt; API in a number of easy to follow examples.&lt;/li&gt;
&lt;li&gt;Each example introduces a new concept that is clear, small, and easy to understand&lt;/li&gt;
&lt;li&gt;All examples are built using &lt;em&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-6" rel="noopener noreferrer"&gt;.NET 6 (LTS)&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href="https://chillicream.com/docs/hotchocolate" rel="noopener noreferrer"&gt;ChilliCream Hot Chocolate (Open-Source GraphQL Server for Microsoft .NET platform)&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The GraphQL API is deployed to &lt;em&gt;Azure App Service&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The project demonstrates how to provision an &lt;em&gt;Azure App Service&lt;/em&gt; using &lt;em&gt;&lt;a href="https://docs.microsoft.com/en-us/cli/azure/" rel="noopener noreferrer"&gt;Azure CLI&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href="https://docs.microsoft.com/en-us/powershell/azure/?view=azps-8.0.0" rel="noopener noreferrer"&gt;Azure Powershell&lt;/a&gt;&lt;/em&gt;, and &lt;em&gt;&lt;a href="https://docs.microsoft.com/EN-US/azure/azure-resource-manager/bicep/" rel="noopener noreferrer"&gt;Azure Bicep&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;All examples are based on a fictitious company called &lt;em&gt;MyView&lt;/em&gt;, that provides a service to view games and game ratings. It also allows reviewers to post and delete game reviews. Therefore, in the examples that follow, I demonstrate how to build a GraphQL API that provides the following capabilities:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List games&lt;/li&gt;
&lt;li&gt;List games with associated reviews&lt;/li&gt;
&lt;li&gt;Find a game by id&lt;/li&gt;
&lt;li&gt;Post a game review&lt;/li&gt;
&lt;li&gt;Delete a game review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The details of the provided examples are as follows:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📘 &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-1" rel="noopener noreferrer"&gt;Example 1&lt;/a&gt;
 

&lt;ul&gt;
&lt;li&gt;Create empty API project&lt;/li&gt;
&lt;li&gt;Add GraphQL Server support through the use of the &lt;a href="https://chillicream.com/docs/hotchocolate" rel="noopener noreferrer"&gt;ChilliCream Hot Chocolate&lt;/a&gt; nuget package&lt;/li&gt;
&lt;li&gt;Create a games query&lt;/li&gt;
&lt;li&gt;Create a games mutation&lt;/li&gt;
&lt;li&gt;Add metadata to support schema documentation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📘 &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-2" rel="noopener noreferrer"&gt;Example 2&lt;/a&gt;
 

&lt;ul&gt;
&lt;li&gt;Add global error handling&lt;/li&gt;
&lt;li&gt;Add input validation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📘 &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-3" rel="noopener noreferrer"&gt;Example 3&lt;/a&gt;
 

&lt;ul&gt;
&lt;li&gt;Add EntityFramework support with an in-memory database&lt;/li&gt;
&lt;li&gt;Add support for query filtering, sorting, and paging&lt;/li&gt;
&lt;li&gt;Add projection support&lt;/li&gt;
&lt;li&gt;Add query type extensions to allow splitting queries into multiple classes&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📘 &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-4" rel="noopener noreferrer"&gt;Example 4&lt;/a&gt;
 

&lt;ul&gt;
&lt;li&gt;Change project to use SQlite instead of an in-memory database&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
Lastly, I provide the instructions on how to provision an Azure App Service and deploy the GraphQL API to it. The details are as follows:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provision Azure App Service using Azure CLI&lt;/li&gt;
&lt;li&gt;Provision Azure App Service using Azure Powershell&lt;/li&gt;
&lt;li&gt;Provision Azure App Service using Azure Bicep&lt;/li&gt;
&lt;li&gt;Deploy GraphQL API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;📘 &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/iac" rel="noopener noreferrer"&gt;Find all the infrastructure as code here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;



&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Required Setup and Tools
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;It is recommended that the following tools and frameworks are installed before trying to run the examples:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0" rel="noopener noreferrer"&gt;.NET 6 SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All code in this example is developed with C# 10 using the latest cross-platform .NET 6 framework.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0" rel="noopener noreferrer"&gt;.NET 6 SDK&lt;/a&gt; official website for details on how to download and setup for your development environment.&lt;br&gt;
   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find more information on &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; with &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.vscode-dotnet-pack" rel="noopener noreferrer"&gt;relevant C# and .NET extensions&lt;/a&gt;.&lt;br&gt;
   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/install" rel="noopener noreferrer"&gt;Bicep Installation and Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything you need to install and configure your windows, linux, and macos environment&lt;br&gt;
   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep" rel="noopener noreferrer"&gt;Official Bicep Visual Studio Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Provides Bicep language support&lt;br&gt;
   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stedolan.github.io/jq/" rel="noopener noreferrer"&gt;JQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;jq is a lightweight and flexible command-line JSON processor&lt;br&gt;
   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-node-azure-pack" rel="noopener noreferrer"&gt;Azure Tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A package of all the Visual Studio Code extensions that you will need to work with Azure&lt;br&gt;
   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.azurecli" rel="noopener noreferrer"&gt;Azure CLI Tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools for developing and running commands of the Azure CLI&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;



&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  Example 1
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-1" rel="noopener noreferrer"&gt;Example 1&lt;/a&gt; demonstrates how to get started in terms of creating and running a GraphQL Server.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📘 &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-1" rel="noopener noreferrer"&gt;The full example can be found on Github.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1 - Create project
&lt;/h3&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# create empty solution&lt;/span&gt;
dotnet new sln &lt;span class="nt"&gt;--name&lt;/span&gt; MyView

&lt;span class="c"&gt;# create basic webapi project using minimal api's&lt;/span&gt;
dotnet new webapi &lt;span class="nt"&gt;--no-https&lt;/span&gt; &lt;span class="nt"&gt;--no-openapi&lt;/span&gt; &lt;span class="nt"&gt;--framework&lt;/span&gt; net6.0 &lt;span class="nt"&gt;--use-minimal-apis&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; MyView.Api

&lt;span class="c"&gt;# add webapi project to solution&lt;/span&gt;
dotnet sln ./MyView.sln add ./MyView.Api

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Add GraphQL Capability to Web API
&lt;/h3&gt;

&lt;p&gt;In this section, we turn the web application into a GraphQL API by installing the &lt;a href="https://chillicream.com/docs/hotchocolate" rel="noopener noreferrer"&gt;Chillicream Hot Chocolate&lt;/a&gt; GraphQL nuget package called &lt;code&gt;HotChocolate.AspNetCore&lt;/code&gt;. This package contains the Hot Chocolate GraphQL query execution engine and query validation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# From the /MyView.Api project folder, type the following commands:&lt;/span&gt;

&lt;span class="c"&gt;# Add HotChocolate packages&lt;/span&gt;
dotnet add package HotChocolate.AspNetCore &lt;span class="nt"&gt;--version&lt;/span&gt; 12.11.1

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Add Types
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We are building a GraphQL API to allow querying and managing game reviews. Therefore, to get started we need to create a &lt;em&gt;Game&lt;/em&gt; and &lt;em&gt;GameReview&lt;/em&gt; type. A few things to note about the types we create:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I append the suffix "Dto" to indicate that the type is a &lt;a href="https://en.wikipedia.org/wiki/Data_transfer_object" rel="noopener noreferrer"&gt;Data Transfer Object&lt;/a&gt;. I use this to make it explicitly clear as to the intent of the type.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;GraphQLName&lt;/code&gt; attribute is used to rename the type for public consumption. The types will be exposed as &lt;code&gt;Game&lt;/code&gt; and &lt;code&gt;GameReview&lt;/code&gt; as opposed to &lt;code&gt;GameDto&lt;/code&gt; and &lt;code&gt;GameReviewDto&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;GraphQLDescription&lt;/code&gt; attribute is used to provide a description of the type that is used by the GraphQL server to provide more detailed schema information&lt;/li&gt;
&lt;li&gt;The types are defined as a &lt;em&gt;record&lt;/em&gt; type, but can be declared as classes. I have chosen to use the &lt;em&gt;record&lt;/em&gt; type as it allows me to define data contracts that are immutable and support value based equality comparison (should I require it).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Basic game information"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Game"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;GameDto&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;GameDto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Reviews&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A unique game identifier"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A brief description of game"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The name of the game"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The date that game was released"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;ReleasedOn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A list of game reviews"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ICollection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Reviews&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// GameReviewDto.cs&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Game review information"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GameReview"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;GameReviewDto&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Game identifier"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Reviewer identifier"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Game rating"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A brief description of game experience"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - Create First Query
&lt;/h3&gt;

&lt;p&gt;One or more queries must be defined in order to support querying data.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;For our first example we will create a query to support retrieving of &lt;em&gt;game related (games, reviews)&lt;/em&gt; data. A few things to note are as follows:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At this stage we do not not have a database configured and will instead use in-memory data to demonstrate fetching of data.&lt;/li&gt;
&lt;li&gt;I use the &lt;code&gt;GraphQLDescription&lt;/code&gt; attribute to provide GraphQL schema documentation &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// In this example, we use GameData (in-memory list) to provide sample dummy game related data&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Query games"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GamesQuery&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Get list of games"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetGames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GameData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Find game by id"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;GameDto&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;FindGameById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;GameData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 - Create First Mutation
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We will add 2 operations. One to create, and one to remove a game review. A few things to note are as follows:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At this stage we do not not have a database configured and will instead use in-memory data to demonstrate saving of data.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;GraphQLDescription&lt;/code&gt; attribute is used to provide GraphQL schema documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Manage games"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GamesMutation&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Submit a game review"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="nf"&gt;SubmitGameReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameData&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Game not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
         &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Remove a game review"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="nf"&gt;DeleteGameReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;reviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameData&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Game not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;reviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Game review not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 - Configure API with GraphQL services
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We need to configure the API to use the ChilliCream Hotchocolate GraphQL services and middleware.&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddGraphQLServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Adds a GraphQL server configuration to the DI&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddMutationType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GamesMutation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Add GraphQL root mutation type&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddQueryType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GamesQuery&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Add GraphQL root query type&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ModifyRequestOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// allow exceptions to be included in response when in development&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncludeExceptionDetails&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7 - Map GraphQL Endpoint
&lt;/h3&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGraphQL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Adds a GraphQL endpoint to the endpoint configurations&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 8 - Run GraphQL API
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Run the Web API project by typing the following command:&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# From the /MyView.Api project folder, type the following commands:

dotnet run

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr5tlsqsdzgjwg61j2zs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr5tlsqsdzgjwg61j2zs.png" alt="Screenshot" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Schema Information
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Selecting the &lt;em&gt;&lt;em&gt;Browse Schema&lt;/em&gt;&lt;/em&gt; options allows one to view the schema information for queries, mutations, and objects as can be seen by the following screen shots.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h5&gt;
  
  
  Objects Schema
&lt;/h5&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyr7s3ll6wlc0m7x03gw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyr7s3ll6wlc0m7x03gw4.png" alt="object-schema" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h5&gt;
  
  
  Queries Schema
&lt;/h5&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9n39essnzv70vfce9d4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9n39essnzv70vfce9d4.png" alt="query-schema" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h5&gt;
  
  
  Mutations Schema
&lt;/h5&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxxizn7t6qttojy9bn8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxxizn7t6qttojy9bn8r.png" alt="mutation-schema" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Write GraphQL Queries
&lt;/h3&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# List all games and associated reviews:&lt;/span&gt;

&lt;span class="s"&gt;query listGames {&lt;/span&gt;
  &lt;span class="s"&gt;games {&lt;/span&gt;
    &lt;span class="s"&gt;gameId&lt;/span&gt;
    &lt;span class="s"&gt;title&lt;/span&gt;
    &lt;span class="s"&gt;releasedOn&lt;/span&gt;
    &lt;span class="s"&gt;summary&lt;/span&gt;
    &lt;span class="s"&gt;reviews {&lt;/span&gt;
      &lt;span class="s"&gt;reviewerId&lt;/span&gt;
      &lt;span class="s"&gt;rating&lt;/span&gt;
      &lt;span class="s"&gt;summary&lt;/span&gt;
    &lt;span class="s"&gt;}&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Find a game (with reviews) by game id&lt;/span&gt;

&lt;span class="c1"&gt;# Add the following JSON snippet to the variables section:&lt;/span&gt;

&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gameId"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8f7e254f-a6ce-4f13-a44c-8f102a17f2f5"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Write query to find a game (with reviews)&lt;/span&gt;

&lt;span class="na"&gt;query findGameById ($gameId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UUID!) {&lt;/span&gt;
  &lt;span class="s"&gt;findGameById (gameId&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$gameId) {&lt;/span&gt;
    &lt;span class="s"&gt;gameId&lt;/span&gt;
    &lt;span class="s"&gt;title&lt;/span&gt;
    &lt;span class="s"&gt;reviews {&lt;/span&gt;
      &lt;span class="s"&gt;reviewerId&lt;/span&gt;
      &lt;span class="s"&gt;rating&lt;/span&gt;
      &lt;span class="s"&gt;summary&lt;/span&gt;
    &lt;span class="s"&gt;}&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffizuzfrdl32mxpdiwi6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffizuzfrdl32mxpdiwi6.png" alt="queries" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Write Mutations
&lt;/h3&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Submit a game review&lt;/span&gt;

&lt;span class="c1"&gt;# Define the following JSON in the 'Variables' section:&lt;/span&gt;

&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gameReview"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gameId"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8f7e254f-a6ce-4f13-a44c-8f102a17f2f5"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviewerId"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;025fefe4-e2de-4765-9af3-f5dcd6d47458"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rating"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;75&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enim&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;quidem&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;enim.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Eius&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;aut&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;velit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;voluptas."&lt;/span&gt;
  &lt;span class="pi"&gt;},&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Write a mutation to submit a game review&lt;/span&gt;

&lt;span class="na"&gt;mutation submitGameReview($gameReview&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GameReviewInput!) {&lt;/span&gt;
  &lt;span class="s"&gt;submitGameReview(gameReview&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$gameReview) {&lt;/span&gt;
    &lt;span class="s"&gt;gameId&lt;/span&gt;
    &lt;span class="s"&gt;reviewerId&lt;/span&gt;
    &lt;span class="s"&gt;rating&lt;/span&gt;
    &lt;span class="s"&gt;summary&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Write a mutation to DELETE a game review&lt;/span&gt;

&lt;span class="c1"&gt;# Define the following JSON in the 'variables' section:&lt;/span&gt;

&lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gameId"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8f7e254f-a6ce-4f13-a44c-8f102a17f2f5"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reviewerId"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;025fefe4-e2de-4765-9af3-f5dcd6d47458"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Write mutation to delete game review&lt;/span&gt;

&lt;span class="na"&gt;mutation deleteGameReview($gameId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UUID!, $reviewerId&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UUID!) {&lt;/span&gt;
  &lt;span class="s"&gt;deleteGameReview(gameId&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$gameId, reviewerId&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$reviewerId) {&lt;/span&gt;
    &lt;span class="s"&gt;gameId&lt;/span&gt;
    &lt;span class="s"&gt;reviewerId&lt;/span&gt;
    &lt;span class="s"&gt;rating&lt;/span&gt;
    &lt;span class="s"&gt;summary&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoa91owgd7yb9vvtcm3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoa91owgd7yb9vvtcm3e.png" alt="mutations" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;




&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Example 2
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-2" rel="noopener noreferrer"&gt;Example 2&lt;/a&gt; demonstrates the following concepts:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement input validations (like validating a review that is submitted)&lt;/li&gt;
&lt;li&gt;Implement global error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📘 &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-2" rel="noopener noreferrer"&gt;The full example can be found on Github.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Implement Input Validation
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Currently, we have no validation in place when submitting a &lt;code&gt;GameReview&lt;/code&gt;. In this section, we are going to provide input validation through the use of the [Fluent Validation] nuget package.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1 - Add Fluent Validation packages
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
dotnet add package FluentValidation.AspNetCore &lt;span class="nt"&gt;--version&lt;/span&gt; 11.1.1
dotnet add package FluentValidation.DependencyInjectionExtensions &lt;span class="nt"&gt;--version&lt;/span&gt; 11.1.0

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2 - Create Validator
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We need to define a class that will handle validation for the &lt;code&gt;GameReview&lt;/code&gt; type. To do this, we create a &lt;code&gt;GameReviewValidator&lt;/code&gt; as follows:&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GameReviewValidator&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbstractValidator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;GameReviewValidator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;RuleFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameId&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GameData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"A game having id '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' does not exist"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nf"&gt;RuleFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LessThanOrEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GreaterThanOrEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nf"&gt;RuleFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MinimumLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MaximumLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3 -  Use GameReviewValidator
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;GameReviewValidator&lt;/code&gt; is used in the &lt;code&gt;GamesMutation&lt;/code&gt; class to validate the &lt;code&gt;GameReviewDto&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We use constructor dependency injection to provide the &lt;code&gt;GameReviewValidator&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code &lt;code&gt;_validator.ValidateAndThrow(gameReview);&lt;/code&gt; will execute the validation rules defined for &lt;code&gt;GameReviewDto&lt;/code&gt; and throw a validation exception if there are any validation failures.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Manage games"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GamesMutation&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;AbstractValidator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_validator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;GamesMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractValidator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_validator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validator&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Submit a game review"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="nf"&gt;SubmitGameReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// use fluent validator&lt;/span&gt;
      &lt;span class="n"&gt;_validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ValidateAndThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4 - Add Validation Service
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// configure fluent validation for GameReviewDto&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTransient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AbstractValidator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;GameReviewValidator&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Global Error Handling
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We are throwing exceptions in a number of areas. Those exceptions will be allowed to bubble all the way to the client if allowed to. The following list highlights the areas where we are throwing exceptions along with the GraphQL response resultiing from the exception:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="nf"&gt;SubmitGameReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// use fluent validator&lt;/span&gt;
      &lt;span class="n"&gt;_validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ValidateAndThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unexpected Execution Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"locations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"line"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"column"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"submitGameReview"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Validation failed: &lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt; -- Rating: 'Rating' must be greater than or equal to '0'. Severity: Error&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt; -- Summary: 'Summary' must not be empty. Severity: Error&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt; -- Summary: The length of 'Summary' must be at least 20 characters. You entered 0 characters. Severity: Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"stackTrace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"   at FluentValidation.AbstractValidator`..."&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete Game
 
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="nf"&gt;DeleteGameReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;reviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameData&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;GameNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithGameId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unexpected Execution Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"locations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"line"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"column"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"deleteGameReview"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Exception of type 'MyView.Api.Games.GameNotFoundException' was thrown."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"stackTrace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"   at MyView.Api.Games.GamesMutation.DeleteGameReview ..."&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1 - Create Custom Error Filter
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We create a new class called &lt;code&gt;ServerErrorFilter&lt;/code&gt; that inherits from the &lt;code&gt;IErrorFilter&lt;/code&gt; interface as follows:&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServerErrorFilter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IErrorFilter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IWebHostEnvironment&lt;/span&gt; &lt;span class="n"&gt;_environment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ServerErrorFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IWebHostEnvironment&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="n"&gt;_environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="nf"&gt;OnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ErrorBuilder&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"An unexpected server fault occurred"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServerFault&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2 - Add ValidationException Handler
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServerErrorFilter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IErrorFilter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="nf"&gt;OnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ValidationException&lt;/span&gt; &lt;span class="n"&gt;validationException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validationException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"There is a validation error"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;errorBuilder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ErrorBuilder&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"There is a validation error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BadUserInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;validationFailure&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;validationException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;errorBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BadUserInput&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;validationFailure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PropertyName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToUpper&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;validationFailure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrorMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errorBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3 - Add GameNotFoundException Handler
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServerErrorFilter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IErrorFilter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="nf"&gt;OnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;GameNotFoundException&lt;/span&gt; &lt;span class="n"&gt;gameNotFoundException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameNotFoundException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Game not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ErrorBuilder&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"A game having id '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;gameNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; could not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceNotFound&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_GAME_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gameNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4 - Add GameReviewNotFoundException Handler
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServerErrorFilter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IErrorFilter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="nf"&gt;OnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IError&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;GameReviewNotFoundException&lt;/span&gt; &lt;span class="n"&gt;gameReviewNotFoundException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReviewNotFoundException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Game review not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ErrorBuilder&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"A game review having game id '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;gameReviewNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' and reviewer id '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;gameReviewNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' could not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceNotFound&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_GAME_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gameReviewNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ServerErrorCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceNotFound&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_REVIEWER_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gameReviewNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5 - Configure GraphQL Service to support Error Filter
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddGraphQLServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="c1"&gt;// Add global error handling&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddErrorFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ServerErrorFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ServerErrorFilter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ModifyRequestOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncludeExceptionDetails&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 6 - Test Error Handling
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"There is a validation error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"submitGameReview"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BAD_USER_INPUT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"BAD_USER_INPUT_RATING"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'Rating' must be greater than or equal to '0'."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"BAD_USER_INPUT_SUMMARY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The length of 'Summary' must be at least 20 characters. You entered 0 characters."&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A game having id '8f7e254f-a6ce-4f13-a44c-8f102a17f2f4 could not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"deleteGameReview"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RESOURCE_NOT_FOUND"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"RESOURCE_NOT_FOUND_GAME_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8f7e254f-a6ce-4f13-a44c-8f102a17f2f4"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A game review having game id '8f7e254f-a6ce-4f13-a44c-8f102a17f2f5' and reviewer id '8b019864-4af2-4606-88b5-13e5eb62ff4e' could not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"deleteGameReview"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RESOURCE_NOT_FOUND"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"RESOURCE_NOT_FOUND_GAME_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8f7e254f-a6ce-4f13-a44c-8f102a17f2f5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"RESOURCE_NOT_FOUND_REVIEWER_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8b019864-4af2-4606-88b5-13e5eb62ff4e"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;




&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Example 3
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;For &lt;em&gt;&lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-3" rel="noopener noreferrer"&gt;Example 3&lt;/a&gt;&lt;/em&gt;, we extend &lt;em&gt;&lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-2" rel="noopener noreferrer"&gt;Example 2&lt;/a&gt;&lt;/em&gt; to cover the following topics:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add EntityFramework support with in-memory database&lt;/li&gt;
&lt;li&gt;Add support for query projection, filtering, sorting, and paging&lt;/li&gt;
&lt;li&gt;Add query type extensions to allow splitting queries into multiple classes&lt;/li&gt;
&lt;li&gt;Add database seeding (seed with fake data)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Add EntityFramework Support
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add required nuget packages&lt;/li&gt;
&lt;li&gt;Create the following entities that will be used to help represent the data stored in our database

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Game&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GameReview&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Reviewer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Create a context that will serve as our Repository/UnitOfWork called &lt;code&gt;AppDbContext&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;Configure data services&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Add EntityFramework Packages
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# add required EntityFramework packages&lt;/span&gt;
dotnet add package Microsoft.EntityFrameworkCore.Design &lt;span class="nt"&gt;--version&lt;/span&gt; 6.0.6
dotnet add package Microsoft.EntityFrameworkCore.InMemory &lt;span class="nt"&gt;--version&lt;/span&gt; 6.0.6

&lt;span class="c"&gt;# add HotChocolate package providing EntityFramework support&lt;/span&gt;
dotnet add package HotChocolate.Data.EntityFramework &lt;span class="nt"&gt;--version&lt;/span&gt; 12.11.1

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Define Entities
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;ReleasedOn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ICollection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Reviews&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GameReview&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Reviewer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;ReviewedOn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reviewer&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Picture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ICollection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GameReviews&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Create AppDbContext
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppDbContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DbContext&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DbContextOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DbSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Games&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;!;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DbSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Reviews&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;!;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DbSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Reviewers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;!;&lt;/span&gt;

   &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ModelBuilder&lt;/span&gt; &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;reviewer&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Configure Data Services
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// configure in-memory database&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContextFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseInMemoryDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"myview"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableDetailedErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableSensitiveDataLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDbContextFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDbContext&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Update GamesQuery
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Get list of games"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetGames&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TagWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GamesQuery&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;::&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetGames&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OrderByDescending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleasedOn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;GameDto&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Reviews&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;
            &lt;span class="p"&gt;}),&lt;/span&gt;
            &lt;span class="n"&gt;ReleasedOn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleasedOn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;
         &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Find game by id"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameDto&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FindGameById&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TagWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GamesQuery&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;::&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FindGameById&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefaultAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;GameDto&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;Reviews&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;
         &lt;span class="p"&gt;}),&lt;/span&gt;
         &lt;span class="n"&gt;ReleasedOn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleasedOn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Update GamesMutation
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Submit a game review"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;SubmitGameReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;GameReviewDto&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// use fluent validator&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ValidateAndThrowAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefaultAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;GameNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithGameId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reviewer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviewers&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefaultAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviewer&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;ReviewerNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithReviewerId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefaultAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
            &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; 
            &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;GameReview&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ReviewedOn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;
         &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveChangesAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;


   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Remove a game review"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReviewDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;DeleteGameReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;reviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefaultAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;reviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;GameReviewNotFoundException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithGameReviewId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reviewerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;GameReviewDto&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;GameId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;Rating&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;Summary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gameReviewFromDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Add Query Projection, Paging, Filtering and Sorting Support
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;There are 2 steps required to enable projections, paging, filtering and sorting.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1 - Add Attributes To Queries
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Add the following attributes to the method performing queries. The ordering of the attributes is important and should be defined in the following order&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;UsePaging&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UseProjection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UseFiltering&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UseSorting&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Get list of games"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UsePaging&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UseProjection&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UseFiltering&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UseSorting&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetGames&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GraphQLDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Find game by id"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UseProjection&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameDto&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FindGameById&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;gameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2 - Configure GraphQL Service
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddGraphQLServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;   
   &lt;span class="c1"&gt;// The .AddTypeExtension allows having queries defined in multiple files&lt;/span&gt;
   &lt;span class="c1"&gt;// whilst still having a single root query&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddQueryType&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Add GraphQL root query type&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTypeExtension&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GamesQuery&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTypeExtension&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ReviewerQuery&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Add Projection, Filtering and Sorting support. The ordering matters.    &lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddProjections&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFiltering&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSorting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
   &lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Add Database Seeding
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Define Seeder class to generate fake data
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Seeder&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;SeedDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WebApplication&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;serviceScope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateAsyncScope&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceScope&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceProvider&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

         &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnsureCreatedAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviewers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AnyAsync&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reviewers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;
               &lt;span class="n"&gt;_reviewersText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;JsonSerializerOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;PropertyNameCaseInsensitive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})!;&lt;/span&gt;

            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reviewers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;

         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AnyAsync&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;
               &lt;span class="n"&gt;_gamesText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;JsonSerializerOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;PropertyNameCaseInsensitive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})!;&lt;/span&gt;

            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;

         &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveChangesAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_gamesText&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@"
      [
         .
         .
         .
      ]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_reviewersText&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@"
      [
         .
         .
         .
      ]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Configure when to Seed database
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Program.cs&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGraphQL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// seed database after all middleware is setup&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Seeder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SeedDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;




&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Example 4
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;For &lt;em&gt;&lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-4" rel="noopener noreferrer"&gt;Example 4&lt;/a&gt;&lt;/em&gt;, we extend &lt;em&gt;&lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/example-3" rel="noopener noreferrer"&gt;Example 3&lt;/a&gt;&lt;/em&gt; to use a SQLite database.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Configure SQLite
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Add Packages
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# add required EntityFramework packages&lt;/span&gt;
dotnet add package Microsoft.EntityFrameworkCore.Design &lt;span class="nt"&gt;--version&lt;/span&gt; 6.0.6
dotnet add package Microsoft.EntityFrameworkCore.SQLite &lt;span class="nt"&gt;--version&lt;/span&gt; 6.0.6

&lt;span class="c"&gt;# add HotChocolate package providing EntityFramework support&lt;/span&gt;
dotnet add package HotChocolate.Data.EntityFramework &lt;span class="nt"&gt;--version&lt;/span&gt; 12.11.1

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Configure AppDbContext
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Update the &lt;code&gt;OnModelCreating&lt;/code&gt; method to provide all the required entity-to-table mappings and relationships.&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppDbContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DbContext&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;

   &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ModelBuilder&lt;/span&gt; &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// configure Game&lt;/span&gt;
      &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// configure table&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

         &lt;span class="c1"&gt;// configure properties&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleasedOn&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"released_on"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

         &lt;span class="c1"&gt;// configure primary key&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pk_game_id"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="c1"&gt;// configure game relationship&lt;/span&gt;
         &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;WithOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;


      &lt;span class="c1"&gt;// configure Reviewer&lt;/span&gt;
      &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;reviewer&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// configure table&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

         &lt;span class="c1"&gt;// configure properties&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Picture&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"picture"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

         &lt;span class="c1"&gt;// configure primary key&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pk_reviewer_id"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="c1"&gt;// configure reviewer relationship&lt;/span&gt;
         &lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameReviews&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;WithOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;


      &lt;span class="c1"&gt;// configure GameReview&lt;/span&gt;
      &lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameReview&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;gameReview&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// configure table&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"game_review"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="c1"&gt;// configure properties&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"game_id"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reviewer_id"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rating&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewedOn&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reviewed_on"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsRequired&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Summary&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;HasDefaultValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="c1"&gt;// configure primary key&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pk_gamereview_gameidreviewerid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="c1"&gt;// configure game relationship&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviews&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasConstraintName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fk_gamereview_gameid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="n"&gt;gameReview&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasDatabaseName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ix_gamereview_gameid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="c1"&gt;// configure reviewer relationship&lt;/span&gt;
         &lt;span class="n"&gt;gameReview&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reviewer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GameReviews&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasConstraintName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fk_gamereview_reviewerid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

         &lt;span class="n"&gt;gameReview&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReviewerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasDatabaseName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ix_gamereview_reviewerid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OnModelCreating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Configure Data Services
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContextFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSqlite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data Source=myview.db"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableDetailedErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableSensitiveDataLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDbContextFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDbContext&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Create Database Migrations
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Before running the application, we need to create the database migrations in order to create/update the SQLite database. After the migrations and database update are complete, a SQLite database called &lt;code&gt;myview.db&lt;/code&gt; will be created in the root of the project folder.&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# navigate to API project folder&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ./MyView.Api

&lt;span class="c"&gt;# create the database migrations&lt;/span&gt;
dotnet ef migrations add &lt;span class="s2"&gt;"CreateInitialDatabaseSchema"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Create and Update SQLite Database
&lt;/h3&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# run the migrations to create database&lt;/span&gt;
dotnet ef database update

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;




&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy GraphQL API
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In this section, we will cover the following primary topics:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provision Azure App Service&lt;/li&gt;
&lt;li&gt;Deploy GraphQL API to Azure App Service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Provision Azure App Service
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We will be deploying the &lt;em&gt;&lt;em&gt;'MyView API'&lt;/em&gt;&lt;/em&gt; into [Azure App Service]. However, before we can deploy our API, we first need to provision our &lt;em&gt;Azure App Service&lt;/em&gt;. This section demonstrates how to provision an Azure App Service using 3 different techniques and are listed as follows:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure CLI&lt;/li&gt;
&lt;li&gt;Azure Powershell&lt;/li&gt;
&lt;li&gt;Azure Bicep&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Regardless of the chosen technique, there are 3 general steps that need to be completed in order to provision the &lt;em&gt;Azure App Service&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a resource group&lt;/li&gt;
&lt;li&gt;Create an App Service Plan&lt;/li&gt;
&lt;li&gt;Create an App Service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Once all the required resources are created, we will be ready to deploy the &lt;em&gt;&lt;em&gt;'MyView API'&lt;/em&gt;&lt;/em&gt; to &lt;em&gt;Azure&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Create Azure App Service Using Azure CLI
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;All the commands that are required to create the &lt;em&gt;Azure App Service&lt;/em&gt; using the &lt;em&gt;Azure CLI&lt;/em&gt; can be found in the &lt;code&gt;iac/azcli/deploy.azcli&lt;/code&gt; file that is part of the &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/iac" rel="noopener noreferrer"&gt;example github repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"australiaeast"&lt;/span&gt;

&lt;span class="c"&gt;# STEP 1 - create resource group&lt;/span&gt;
&lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-rg"&lt;/span&gt;
az group create &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt;

&lt;span class="c"&gt;# STEP 2 - create appservice plan&lt;/span&gt;
&lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-asp"&lt;/span&gt;
&lt;span class="nv"&gt;$appSku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"F1"&lt;/span&gt;
az appservice plan create &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--sku&lt;/span&gt; &lt;span class="nv"&gt;$appSku&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--is-linux&lt;/span&gt;

&lt;span class="c"&gt;# STEP 3 - create webapp&lt;/span&gt;
&lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-webapp-api"&lt;/span&gt;
&lt;span class="nv"&gt;$webapp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; az webapp create &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--plan&lt;/span&gt; &lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--runtime&lt;/span&gt; &lt;span class="s1"&gt;'"DOTNETCORE|6.0"'&lt;/span&gt;

&lt;span class="c"&gt;# STEP 4 - cleanup&lt;/span&gt;
az group delete &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Create Azure App Service Using Azure Powershell
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;All the commands that are required to create the &lt;em&gt;Azure App Service&lt;/em&gt; using the &lt;em&gt;Azure Powershell&lt;/em&gt; can be found in the &lt;code&gt;/azpwsh/deploy.azcli&lt;/code&gt; file that is part of the &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/iac" rel="noopener noreferrer"&gt;example github repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"australiaeast"&lt;/span&gt;

&lt;span class="c"&gt;# STEP 1 - create resource group&lt;/span&gt;
&lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-rg"&lt;/span&gt;
New-AzResourceGroup &lt;span class="nt"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="nt"&gt;-Location&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt;

&lt;span class="c"&gt;# STEP 2 - create appservice plan&lt;/span&gt;
&lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-asp"&lt;/span&gt;
&lt;span class="nv"&gt;$appSku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"F1"&lt;/span&gt;
New-AzAppServicePlan &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Location&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Tier&lt;/span&gt; &lt;span class="nv"&gt;$appSku&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Linux&lt;/span&gt;

&lt;span class="c"&gt;# STEP 3 - create webapp&lt;/span&gt;
&lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-webapp-api"&lt;/span&gt;
New-AzWebApp &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Location&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-AppServicePlan&lt;/span&gt; &lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt;

&lt;span class="c"&gt;# STEP 4 - configure webapp&lt;/span&gt;

&lt;span class="c"&gt;## At this point, the webapp is not using .NET v6 as is required.&lt;/span&gt;
&lt;span class="c"&gt;## This can be verified by the following commands&lt;/span&gt;
az webapp config show &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; netFrameworkVersion

Get-AzWebApp &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    | Select-Object &lt;span class="nt"&gt;-ExpandProperty&lt;/span&gt; SiteConfig &lt;span class="sb"&gt;`&lt;/span&gt;
    | Select-Object &lt;span class="nt"&gt;-Property&lt;/span&gt; NetFrameworkVersion

Get-AzWebApp &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    | ConvertTo-Json &lt;span class="sb"&gt;`&lt;/span&gt;
    | jq &lt;span class="s2"&gt;".SiteConfig.NetFrameworkVersion"&lt;/span&gt;

&lt;span class="c"&gt;## lets configure the webapp with the correct version of .NET&lt;/span&gt;
Set-AzWebApp &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-AppServicePlan&lt;/span&gt; &lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-NetFrameworkVersion&lt;/span&gt; &lt;span class="s1"&gt;'v6.0'&lt;/span&gt;

&lt;span class="nv"&gt;$apiVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2020-06-01"&lt;/span&gt;
&lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Get-AzResource &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceType&lt;/span&gt; Microsoft.Web/sites/config &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ResourceName&lt;/span&gt; &lt;span class="nv"&gt;$appName&lt;/span&gt;/web &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;-ApiVersion&lt;/span&gt; &lt;span class="nv"&gt;$apiVersion&lt;/span&gt;
&lt;span class="nv"&gt;$config&lt;/span&gt;.Properties.linuxFxVersion &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"DOTNETCORE|6.0"&lt;/span&gt;
&lt;span class="nv"&gt;$config&lt;/span&gt; | Set-AzResource &lt;span class="nt"&gt;-ApiVersion&lt;/span&gt; &lt;span class="nv"&gt;$apiVersion&lt;/span&gt; &lt;span class="nt"&gt;-Force&lt;/span&gt;

&lt;span class="c"&gt;# cleanup&lt;/span&gt;
Remove-AzResourceGroup &lt;span class="nt"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="nt"&gt;-Force&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Create Azure App Service Using Azure Bicep
&lt;/h4&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In this example, I demonstrate both a basic and more advanced option (uses modules) to deploy bicep templates.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h5&gt;
  
  
  Azure Bicep - Basic
&lt;/h5&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;All the commands and templates that are required to create the &lt;em&gt;Azure App Service&lt;/em&gt; using &lt;em&gt;Azure Bicep&lt;/em&gt; can be found in the &lt;code&gt;iac/bicep/basic&lt;/code&gt; folder that is part of the &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/iac" rel="noopener noreferrer"&gt;example github repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# file: iac/bicep/basic/deploy.azcli&lt;/span&gt;

&lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"australiaeast"&lt;/span&gt;

&lt;span class="c"&gt;# STEP 1 - create resource group&lt;/span&gt;
&lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-rg"&lt;/span&gt;
az group create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt;

&lt;span class="c"&gt;# STEP 2 - deploy template&lt;/span&gt;
&lt;span class="nv"&gt;$aspName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-asp"&lt;/span&gt;
&lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-webapp-api"&lt;/span&gt;
&lt;span class="nv"&gt;$deploymentName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-deployment"&lt;/span&gt;

az deployment group create &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$deploymentName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--template-file&lt;/span&gt; ./main.bicep &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--parameters&lt;/span&gt; &lt;span class="nv"&gt;appName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$appName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--parameters&lt;/span&gt; &lt;span class="nv"&gt;aspName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$aspName&lt;/span&gt;

&lt;span class="c"&gt;# cleanup&lt;/span&gt;
az group delete &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// file: iac/bicep/basic/main.bicep&lt;/span&gt;

&lt;span class="c1"&gt;// parameters&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The name of app service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The name of app service plan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;aspName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The location of all resources&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resourceGroup&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The Runtime stack of current web app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;linuxFxVersion&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOTNETCORE|6.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;skuName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// variables&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="nx"&gt;asp&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Microsoft.Web/serverfarms@2021-02-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;aspName&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="na"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;skuName&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nl"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Microsoft.Web/sites@2021-02-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;serverFarmId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="na"&gt;httpsOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;siteConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;linuxFxVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linuxFxVersion&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h5&gt;
  
  
  Azure Bicep - Advanced (with modules)
&lt;/h5&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;All the commands and templates that are required to create the &lt;em&gt;Azure App Service&lt;/em&gt; using &lt;em&gt;Azure Bicep&lt;/em&gt; can be found in the &lt;code&gt;iac/bicep/advanced&lt;/code&gt; folder that is part of the &lt;a href="https://github.com/drminnaar/graphql-dotnet-series/tree/main/iac" rel="noopener noreferrer"&gt;example github repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# file: iac/bicep/advanced/deploy.azcli&lt;/span&gt;

&lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"australiaeast"&lt;/span&gt;


&lt;span class="c"&gt;# STEP 1 - deploy template&lt;/span&gt;
&lt;span class="nv"&gt;$deploymentName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myview-deployment"&lt;/span&gt;

az deployment sub create &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$deploymentName&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$location&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--template-file&lt;/span&gt; ./main.bicep &lt;span class="sb"&gt;`&lt;/span&gt;
    &lt;span class="nt"&gt;--parameters&lt;/span&gt; &lt;span class="nv"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$location&lt;/span&gt;


&lt;span class="c"&gt;# STEP 2 - get outputs from deployment&lt;/span&gt;
az deployment sub show &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$deploymentName&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"properties.outputs"&lt;/span&gt;
&lt;span class="nv"&gt;$hostName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;az deployment sub show &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$deploymentName&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"properties.outputs.defaultHostName.value"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;az deployment sub show &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$deploymentName&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"properties.outputs.resourceGroupName.value"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$hostName&lt;/span&gt;, &lt;span class="nv"&gt;$rgName&lt;/span&gt;


&lt;span class="c"&gt;# STEP 3 - cleanup&lt;/span&gt;
az group delete &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$rgName&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// file: iac/bicep/advanced/modules/app-service.bicep&lt;/span&gt;

&lt;span class="c1"&gt;// parameters&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The name of app service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The name of app service plan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;aspName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The location of all resources&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resourceGroup&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The Runtime stack of current web app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;linuxFxVersion&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOTNETCORE|6.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;skuName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;


&lt;span class="c1"&gt;// define resources&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="nx"&gt;asp&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Microsoft.Web/serverfarms@2021-02-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;aspName&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="na"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;skuName&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nl"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;reserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Microsoft.Web/sites@2021-02-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;serverFarmId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="na"&gt;httpsOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;siteConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;linuxFxVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linuxFxVersion&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// define outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="nx"&gt;defaultHostName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultHostName&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// file: iac-src/bicep/advanced/main.bicep&lt;/span&gt;

&lt;span class="c1"&gt;// define scope&lt;/span&gt;
&lt;span class="nx"&gt;targetScope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subscription&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;


&lt;span class="c1"&gt;// define parameters&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The location of all resources&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deployment&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;


&lt;span class="c1"&gt;// define variables&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The name of resource group&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;rgName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myview-rg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The name of resource group&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;aspName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myview-asp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The name of app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myview-webapp-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;


&lt;span class="c1"&gt;// define resources&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="nx"&gt;resourceGroup&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Microsoft.Resources/resourceGroups@2021-04-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rgName&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// define modules&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="nx"&gt;appServiceModule&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;modules/app-service.bicep&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resourceGroup&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myview-module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;appName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt;
    &lt;span class="na"&gt;aspName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;aspName&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// define outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="nx"&gt;defaultHostName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;appServiceModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultHostName&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="nx"&gt;resourceGroupName&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rgName&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy GraphQL API to Azure App Service
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Publish GraphQL API Locally
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
dotnet publish &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--configuration&lt;/span&gt; Release &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--framework&lt;/span&gt; net6.0 &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; ./release &lt;span class="sb"&gt;`&lt;/span&gt;
  ./MyView.Api

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Deploy GraphQL API
&lt;/h4&gt;

&lt;p&gt; &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ./release

az webapp up &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--plan&lt;/span&gt; myview-asp &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; myview-webapp-api &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--resource-group&lt;/span&gt; myview-rg &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--os-type&lt;/span&gt; linux &lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--runtime&lt;/span&gt; &lt;span class="s2"&gt;"DOTNETCORE:6.0"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;




&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Where To Next?
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I have provided a number of &lt;a href="https://github.com/drminnaar/graphql-dotnet-series" rel="noopener noreferrer"&gt;examples&lt;/a&gt; that show how to build a GraphQL Server using &lt;a href="https://chillicream.com/docs/hotchocolate" rel="noopener noreferrer"&gt;ChilliCream Hot Chocolate&lt;/a&gt; GraphQL Server. If you would like to learn more, please view the following learning resources:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://chillicream.com/docs/hotchocolate/get-started" rel="noopener noreferrer"&gt;Official Getting Started Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ChilliCream/hotchocolate-examples" rel="noopener noreferrer"&gt;Official ChilliCream Hot Chocolate Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/shows/on-net/getting-started-with-hotchocolate" rel="noopener noreferrer"&gt;On.NET Show - Getting Started with HotChocolate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/GBvTRcV4PVA" rel="noopener noreferrer"&gt;Modern data APIs with EF Core and GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/3_4nt2QQSeE" rel="noopener noreferrer"&gt;Entity Framework Community Standup - Hot Chocolate 12 and GraphQL 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://youtu.be/HuN94qNwQmM" rel="noopener noreferrer"&gt;GraphQL API with .NET 5 and Hot Chocolate&lt;/a&gt; (Still applicable to .NET 6)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PLA8ZIAm2I03g9z705U3KWJjTv0Nccw9pj" rel="noopener noreferrer"&gt;GraphQL in .NET with HotChocolate (Playlist)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://microsoft.github.io/AzureTipsAndTricks/blog/tip287.html" rel="noopener noreferrer"&gt;Azure Tips &amp;amp; Tricks - How to use GraphQL on Azure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/_ncO6kUP-zs" rel="noopener noreferrer"&gt;Hot Chocolate: GraphQL Schema Stitching with ASP.Net Core - Michael Staib - NDC London 2021&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  HotChocolate Templates
&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;There are also a number of Hot Chocolate templates that can be installed using the &lt;code&gt;dotnet CLI&lt;/code&gt; tool.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install HotChocolate Templates:
 
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
  &lt;span class="c"&gt;# install Hot Chocolate GraphQL server templates (includes Azure function template)&lt;/span&gt;
  dotnet new &lt;span class="nt"&gt;-i&lt;/span&gt; HotChocolate.Templates

  &lt;span class="c"&gt;# install template that allows you to create a GraphQL Star Wars Demo&lt;/span&gt;
  dotnet new &lt;span class="nt"&gt;-i&lt;/span&gt; HotChocolate.Templates.StarWars

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List HotChocolate Templates
 
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
  &lt;span class="c"&gt;# list HotChocolate templates&lt;/span&gt;
  dotnet new &lt;span class="nt"&gt;--list&lt;/span&gt; HotChocolate

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  Template Name                        Short Name   Language  Tags
  -----------------------------------  -----------  --------  ------------------------------
  HotChocolate GraphQL Function        graphql-azf  [C#]      Web/GraphQL/Azure
  HotChocolate GraphQL Server          graphql      [C#]      Web/GraphQL
  HotChocolate GraphQL Star Wars Demo  starwars     [C#]      ChilliCream/HotChocolate/Demos

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create HotChocolate project using templates
 
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
  &lt;span class="c"&gt;# create ASP.NET GraphQL Server&lt;/span&gt;
  dotnet new graphql &lt;span class="nt"&gt;--name&lt;/span&gt; MyGraphQLDemo

  &lt;span class="c"&gt;# create graphql server using Azure Function&lt;/span&gt;
  dotnet new graphql-azf &lt;span class="nt"&gt;--name&lt;/span&gt; MyGraphQLAzfDemo

  &lt;span class="c"&gt;# create starwars GraphQL demo&lt;/span&gt;
  &lt;span class="nb"&gt;mkdir &lt;/span&gt;StarWars
  &lt;span class="nb"&gt;cd &lt;/span&gt;StarWars
  dotnet new starwars

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

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;




</description>
      <category>showdev</category>
      <category>dotnet</category>
      <category>graphql</category>
    </item>
    <item>
      <title>8 C#.NET Projects</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Sun, 02 May 2021 00:09:26 +0000</pubDate>
      <link>https://dev.to/drminnaar/8-c-net-projects-38li</link>
      <guid>https://dev.to/drminnaar/8-c-net-projects-38li</guid>
      <description>&lt;p&gt;I've recently been busy upgrading and creating a number of projects written in &lt;strong&gt;C#&lt;/strong&gt; using &lt;strong&gt;.NET5 Framework&lt;/strong&gt;. The projects range in difficulty from intermediate to advanced and cover a broad range of topics including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;using C# with database tech like &lt;strong&gt;Postgres&lt;/strong&gt; and &lt;strong&gt;MongoDB&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;API examples for &lt;strong&gt;REST&lt;/strong&gt;, &lt;strong&gt;GraphQL&lt;/strong&gt;, and &lt;strong&gt;gRPC&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS&lt;/strong&gt; examples covering services like &lt;strong&gt;DynamoDb&lt;/strong&gt;, &lt;strong&gt;Cognito&lt;/strong&gt;, &lt;strong&gt;S3&lt;/strong&gt;, &lt;strong&gt;SNS&lt;/strong&gt;, and &lt;strong&gt;SQS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;working with message brokers like &lt;strong&gt;Rabbit MQ&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;setting up your development stack using &lt;strong&gt;Docker&lt;/strong&gt; and &lt;strong&gt;Docker-Compose&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ASP.NET&lt;/strong&gt; and &lt;strong&gt;ASP.NET Identity&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;.NET Entity Framework Core&lt;/li&gt;
&lt;li&gt;working with &lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Redgate Flyway&lt;/a&gt; to manage database versioning and migrations&lt;/li&gt;
&lt;li&gt;architecture examples like modular monolith, onion architecture, clean architecture etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are 8 projects in total and can be summarised as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NoteWorx ASP.NET&lt;/li&gt;
&lt;li&gt;Identity Example&lt;/li&gt;
&lt;li&gt;Algorithms and Data Structures&lt;/li&gt;
&lt;li&gt;RabbitMQ for .NET Developers&lt;/li&gt;
&lt;li&gt;AWS for .NET Developers&lt;/li&gt;
&lt;li&gt;MFlix .NET&lt;/li&gt;
&lt;li&gt;Chinook .NET&lt;/li&gt;
&lt;li&gt;Ranker .NET (REST API Guide)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/noteworx-aspnetcore" rel="noopener noreferrer"&gt;NoteWorx ASP.NET&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F116779409-6e905300-aaca-11eb-8071-0fe013a7ac21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F116779409-6e905300-aaca-11eb-8071-0fe013a7ac21.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/noteworx-aspnetcore" rel="noopener noreferrer"&gt;NoteWorx ASP.NET&lt;/a&gt; is a basic note management web application that has been built using ASP.NET Core, ASP.NET Core Identity, Entity Framework Core, and Postgresql.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET5&lt;/li&gt;
&lt;li&gt;ASP.NET application using Identity&lt;/li&gt;
&lt;li&gt;Shows how to use &lt;em&gt;Gulp&lt;/em&gt; as an asset manager for javascript, css, and fonts etc&lt;/li&gt;
&lt;li&gt;Uses docker, docker-compose to manage stack (Postgres etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-aspnetcore" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/dotnet-identity-example" rel="noopener noreferrer"&gt;Identity Example&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F116623157-eb6fdf80-a999-11eb-8c1a-32e602da6cd2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F116623157-eb6fdf80-a999-11eb-8c1a-32e602da6cd2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/dotnet-identity-example" rel="noopener noreferrer"&gt;Identity Example&lt;/a&gt; is a project that shows how to use, customise, and configure Identity on Asp.Net Core with different backend stores (postgresql, mssql, sqlite). If you've ever wondered about how to take complete control over the way the Identity database is generated, then this is a good project to use as a guide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET5&lt;/li&gt;
&lt;li&gt;Focus on ASP.NET Identity customization&lt;/li&gt;
&lt;li&gt;Includes sample API project that demonstrates how to use &lt;strong&gt;ASP.NET Identity and Jwt Bearer Authentication&lt;/strong&gt;. The API project also demonstrates how to implement refresh tokens.&lt;/li&gt;
&lt;li&gt;Uses docker, docker-compose to manage stack for Postgres, MSSQL&lt;/li&gt;
&lt;li&gt;Uses powershel and bash scripts to automate spinning up and down of various stacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-identity-example" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/algorithms-and-data-structures" rel="noopener noreferrer"&gt;Algorithms and Data Structures&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F134303710%2Feb049280-a362-11eb-86d1-bb0c08ef19e4" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F134303710%2Feb049280-a362-11eb-86d1-bb0c08ef19e4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/algorithms-and-data-structures" rel="noopener noreferrer"&gt;Algorithms and Data Structures&lt;/a&gt; is a compilation of various algorithms and data structures that have been implemented using C# and Javascript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET5 and Javascript&lt;/li&gt;
&lt;li&gt;Covers &lt;strong&gt;Bubble Sort&lt;/strong&gt;, &lt;strong&gt;Shell Sort&lt;/strong&gt;, &lt;strong&gt;Selection Sort&lt;/strong&gt;, &lt;strong&gt;Insertion Sort&lt;/strong&gt;, &lt;strong&gt;Merge Sort&lt;/strong&gt;, &lt;strong&gt;Quick Sort&lt;/strong&gt;, &lt;strong&gt;Singly Linked List&lt;/strong&gt;, &lt;strong&gt;Doubly Linked List&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Accompanied by detailed README explaining various algorithms and data structures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/algorithms-and-data-structures" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/dotnet-rabbitmq" rel="noopener noreferrer"&gt;RabbitMQ for .NET Developers&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F114295409-344e1a00-9af9-11eb-87ef-96131e46fdcf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F114295409-344e1a00-9af9-11eb-87ef-96131e46fdcf.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq" rel="noopener noreferrer"&gt;RabbitMQ for .NET Developers&lt;/a&gt; is a composition of RabbitMQ examples for C# .NET developers. This project has a specific focus on demonstrating how to use &lt;em&gt;RabbitMQ&lt;/em&gt; with &lt;em&gt;C#.NET 5&lt;/em&gt;. This is achieved by providing a collection of practical examples (written in C#.NET 5) that highlight a number of &lt;em&gt;messaging patterns&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET5&lt;/li&gt;
&lt;li&gt;Demonstrates the following message patterns:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq/tree/master/Example1" rel="noopener noreferrer"&gt;One-Way Messaging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq/tree/master/Example2" rel="noopener noreferrer"&gt;Competing Consumers (Worker Queues)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq/tree/master/Example3" rel="noopener noreferrer"&gt;Publish/Subscribe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq/tree/master/Example4" rel="noopener noreferrer"&gt;Routing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq/tree/master/Example5" rel="noopener noreferrer"&gt;Topics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq/tree/master/Example6" rel="noopener noreferrer"&gt;Headers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Accompanied by detailed README files for each example demonstrating message pattern.&lt;/li&gt;

&lt;li&gt;Accompanied by a "getting started" guide that will help you learn a little more about RabbitMQ&lt;/li&gt;

&lt;li&gt;Manage entire &lt;strong&gt;RabbitMQ&lt;/strong&gt; stack using &lt;strong&gt;Docker&lt;/strong&gt; and &lt;strong&gt;Docker-Compose&lt;/strong&gt;
&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/dotnet-rabbitmq" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/aws-dotnet-examples" rel="noopener noreferrer"&gt;AWS for .NET Developers&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F114672166-f0595000-9d58-11eb-8240-65c0b06493b5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F114672166-f0595000-9d58-11eb-8240-65c0b06493b5.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples" rel="noopener noreferrer"&gt;AWS for .NET Developers&lt;/a&gt; is a collection of independent .NET projects written in &lt;strong&gt;C# .NET 5&lt;/strong&gt; that demonstrate how to integrate with various &lt;strong&gt;AWS&lt;/strong&gt; services using the &lt;strong&gt;AWS SDK for dotnet&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET5&lt;/li&gt;
&lt;li&gt;Demonstrates the following AWS services:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples/tree/master/cognito-mvc-api" rel="noopener noreferrer"&gt;Cognito with ASP.NET API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples/tree/master/cognito-mvc-web" rel="noopener noreferrer"&gt;Cognito with ASP.NET MVC Web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples/tree/master/dynamodb-console" rel="noopener noreferrer"&gt;DynamoDb with Console App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples/tree/master/sqs-console" rel="noopener noreferrer"&gt;SQS with Console App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples/tree/master/sns-console" rel="noopener noreferrer"&gt;SNS with Console App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples/tree/master/s3-console" rel="noopener noreferrer"&gt;S3 with Console App&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Accompanied by detailed README files for each AWS service example demonstrating how to use the &lt;strong&gt;.NET AWS SDK&lt;/strong&gt;.&lt;/li&gt;

&lt;li&gt;Demonstrates how to use &lt;strong&gt;.NET Secret Manager&lt;/strong&gt; by storing AWS config as "secrets"&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/mflix" rel="noopener noreferrer"&gt;MFlix .NET&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F114293752-d9aec100-9aec-11eb-8b5b-e04477d9dda0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F114293752-d9aec100-9aec-11eb-8b5b-e04477d9dda0.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/mflix" rel="noopener noreferrer"&gt;MFlix .NET&lt;/a&gt; is a showcase of how to build API's (&lt;strong&gt;REST&lt;/strong&gt;, &lt;strong&gt;gRPC&lt;/strong&gt;, &lt;strong&gt;GraphQL&lt;/strong&gt;) using &lt;strong&gt;C# .NET&lt;/strong&gt;.  I have created a contrived use-case that allows me to demonstrate how to build different API's for different needs. The high-level requirements cater to 3 types of developers as illustrated below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F111857121-550ccf00-8994-11eb-99a1-49e052e6c355.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F111857121-550ccf00-8994-11eb-99a1-49e052e6c355.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, the project is based on the following high-level architectural diagram that highlights&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the type of API's being built&lt;/li&gt;
&lt;li&gt;the way in which different API's will be accessed by different types of applications&lt;/li&gt;
&lt;li&gt;the scope of API's (public or private)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F111857444-58a15580-8996-11eb-8d3f-c3adea46a661.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F111857444-58a15580-8996-11eb-8d3f-c3adea46a661.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET5&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Dependency Injection&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;How to do paging, filtering, and sorting via the API&lt;/li&gt;
&lt;li&gt;Developing with MongoDB and C#&lt;/li&gt;
&lt;li&gt;Demonstrates how to seed a MongoDB database as part of docker-compose stack&lt;/li&gt;
&lt;li&gt;Preparing a local development environment using Docker and Docker-Compose&lt;/li&gt;
&lt;li&gt;Working with MongoDB database&lt;/li&gt;
&lt;li&gt;Working with SEQ as a log server&lt;/li&gt;
&lt;li&gt;Accompanied by detailed README that explains the project in more detail and also how to get started.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/chinook" rel="noopener noreferrer"&gt;Chinook .NET&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F234649268%2Fc108b300-99e7-11eb-8803-fe1e226e57c3" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frepository-images.githubusercontent.com%2F234649268%2Fc108b300-99e7-11eb-8803-fe1e226e57c3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/chinook" rel="noopener noreferrer"&gt;Chinook .NET&lt;/a&gt; is project designed to illustrate how to build a &lt;strong&gt;&lt;em&gt;&lt;a href="https://youtu.be/5OjqD-ow8GE" rel="noopener noreferrer"&gt;Modular Monolith&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; using the &lt;strong&gt;&lt;em&gt;&lt;a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/" rel="noopener noreferrer"&gt;Onion Architecture&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; as a guide. The motivation behind this project is to demonstrate an alternative to starting off with Microservices straight away.&lt;/p&gt;

&lt;p&gt;The high-level architecture for this &lt;strong&gt;&lt;em&gt;&lt;a href="https://youtu.be/5OjqD-ow8GE" rel="noopener noreferrer"&gt;Modular Monolith&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; is illustrated as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72651214-98ae2680-39e7-11ea-9117-f9a95477aa1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72651214-98ae2680-39e7-11ea-9117-f9a95477aa1f.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;3 primary modules&lt;/strong&gt;, where each module has it's own API. Each module should be constrained (though not a hard constraint for practical reasons) to a single schema within a shared database. Each module is based on the &lt;strong&gt;&lt;em&gt;&lt;a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/" rel="noopener noreferrer"&gt;Onion Architecture&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; with influences from &lt;strong&gt;&lt;em&gt;&lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;. Therefore, each module can be viewed in terms of the following illustration:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72653239-d2cef680-39ee-11ea-8215-e98386d32637.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72653239-d2cef680-39ee-11ea-8215-e98386d32637.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET5&lt;/li&gt;
&lt;li&gt;Working example of &lt;strong&gt;&lt;em&gt;&lt;a href="https://youtu.be/5OjqD-ow8GE" rel="noopener noreferrer"&gt;Modular Monolith&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Working example of &lt;strong&gt;&lt;em&gt;&lt;a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/" rel="noopener noreferrer"&gt;Onion Architecture&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Demonstrates how to use &lt;strong&gt;&lt;em&gt;&lt;a href="https://github.com/jbogard/MediatR" rel="noopener noreferrer"&gt;MediatR&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Demonstrates how to use &lt;strong&gt;&lt;em&gt;&lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Redgate Flyway&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; to manage database versioning and migrations&lt;/li&gt;
&lt;li&gt;Demonstrates how to setup a local development stack using Docker and Docker-Compose&lt;/li&gt;
&lt;li&gt;Accompanied by detailed README that goes into more detail about the project and how to get started&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/chinook" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Ranker .NET (REST API Guide)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/1aad52e50ae3e20061f3807c58d168131ad7712e445eacfce9ca5aea37d38577/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f692f68756d317670796b78343074336869323477346b2e706e67" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/1aad52e50ae3e20061f3807c58d168131ad7712e445eacfce9ca5aea37d38577/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f692f68756d317670796b78343074336869323477346b2e706e67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Ranker .NET (REST API Guide)&lt;/a&gt; is a guide with the goal of laying down foundational knowledge that is required when speaking about building REST API's. I decided to backup the theory with a practical example written in &lt;strong&gt;C#.NET5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST Constraints&lt;/li&gt;
&lt;li&gt;HATEOAS (Hypermedia As The Engine Of Application State)&lt;/li&gt;
&lt;li&gt;Richardson Maturity Model&lt;/li&gt;
&lt;li&gt;REST in Practice (Some practical guidelines)&lt;/li&gt;
&lt;li&gt;Example project (Written in &lt;strong&gt;C# .NET 5&lt;/strong&gt;) called &lt;strong&gt;Ranker&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Demonstrates how to setup a local development stack using Docker and Docker-Compose&lt;/li&gt;
&lt;li&gt;Accompanied by detailed README that goes into more detail about the project and how to get started. The README also forms the basis for the REST API Guide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Page:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Find the project with detailed README here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These projects are very much a labour of love. I create these projects so that I have something to point people to when I am explaining topics. I will continue to build on these projects and improve as I find more time to commit. But I would also like to share knowlege about my other love, namely, javascript/typescript. Therefore, I will most likely be building some React frontends for some of these API projects in the future. I'm also keen on demonstrating how to build a Microservices project by implementing services in both Typescript and C#. Also, people have been asking me if I'd consider producing some online videos about content relating to the aforementioned projects. I'm considering the idea, although my biggest concern is being able to make the time 🤷‍♂️&lt;/p&gt;




</description>
    </item>
    <item>
      <title>AWS For .NET</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Wed, 14 Apr 2021 09:48:48 +0000</pubDate>
      <link>https://dev.to/drminnaar/aws-for-net-5250</link>
      <guid>https://dev.to/drminnaar/aws-for-net-5250</guid>
      <description>&lt;h2&gt;
  
  
  AWS for .NET Developers
&lt;/h2&gt;

&lt;p&gt;I have created a &lt;a href="https://github.com/drminnaar/aws-dotnet-examples"&gt;github project&lt;/a&gt; that provides a collection of independent .NET projects written in C# .NET 5 that demonstrate how to integrate with various AWS services using the AWS SDK for dotnet.&lt;/p&gt;

&lt;p&gt;I summarise the project in the following sections. However, if you prefer going straight to the code then check out the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnet-examples"&gt;AWS .NET Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/s3-console"&gt;S3 ConsoleApp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/dynamodb-console"&gt;DynamoDb ConsoleApp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/sns-console"&gt;SNS ConsoleApp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/sqs-console"&gt;SQS ConsoleApp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/cognito-mvc-web"&gt;Cognito Mvc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/cognito-mvc-api"&gt;Cognito Api&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  AWS Services And Projects Summary
&lt;/h2&gt;

&lt;p&gt;So far, projects have been created for the following AWS Services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/s3"&gt;Amazon S3&lt;/a&gt; - An AWS service that provides authentication, authorization, and user management for your web and mobile apps.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/s3-console"&gt;S3 ConsoleApp&lt;/a&gt; - Console Application&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/sns/latest/dg/welcome.html"&gt;Amazon SNS&lt;/a&gt; - Amazon Simple Notification Service (Amazon SNS) is a web service that coordinates and manages the delivery or sending of messages to subscribing endpoints or clients.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/sns-console"&gt;SNS ConsoleApp&lt;/a&gt; - Console Application&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html"&gt;Amazon SQS&lt;/a&gt; - Amazon Simple Queue Service (SQS) is a fully managed message queuing service that enables you to decouple and scale microservices, distributed systems, and serverless applications.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/sqs-console"&gt;SQS ConsoleApp&lt;/a&gt; - Console Application&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/cognito/getting-started/"&gt;Amazon Cognito&lt;/a&gt; - Amazon Simple Notification Service (Amazon SNS) is a web service that coordinates and manages the delivery or sending of messages to subscribing endpoints or clients.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/cognito-mvc-web"&gt;Cognito Mvc&lt;/a&gt; - ASP.NET Core MVC Application&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/cognito-mvc-api"&gt;Cognito Api&lt;/a&gt; - ASP.NET Core WebAPI Application&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html"&gt;Amazon DynamoDb&lt;/a&gt; - Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/dynamodb-console"&gt;DynamoDb ConsoleApp&lt;/a&gt; - Console Application&lt;/li&gt;
&lt;/ul&gt;


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




&lt;h2&gt;
  
  
  Projects
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/cognito-mvc-web"&gt;Cognito Mvc&lt;/a&gt; - This project demonstrates how to integrate an ASP.NET Core MVC web application with Amazon Cognito using the Amazon SDK.&lt;/p&gt;

&lt;p&gt;The following features have been implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signup for a new account&lt;/li&gt;
&lt;li&gt;Confirm Signup (using confirmation code)&lt;/li&gt;
&lt;li&gt;Sign into account&lt;/li&gt;
&lt;li&gt;Sign out of account&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--h4rsrx3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114539975-20491a80-9ca9-11eb-8b68-95c45f879519.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h4rsrx3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114539975-20491a80-9ca9-11eb-8b68-95c45f879519.png" alt="cognito-signup-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/cognito-mvc-api"&gt;Cognito Api&lt;/a&gt; - This project demonstrates how to integrate a .NET Core Web Api application with Amazon Cognito using the Amazon SDK.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This Web Api application provides the following endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signups

&lt;ul&gt;
&lt;li&gt;POST api/signups - Allows an api consumer to signup for a new account&lt;/li&gt;
&lt;/ul&gt;


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

&lt;ul&gt;
&lt;li&gt;POST api/tokens - Provides JWT access token for valid account credentials&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;Values&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET api/values - An unauthorized endpoint that returns a list of values&lt;/li&gt;
&lt;li&gt;GET api/values/123 - An authorized endpoint (Requires JWT access token) that returns a single value&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/s3-console"&gt;S3 ConsoleApp&lt;/a&gt; - This project demonstrates how to integrate a .NET Core Console application with Amazon S3 using the Amazon SDK.&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;The following features have been implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List all S3 buckets&lt;/li&gt;
&lt;li&gt;Create new S3 bucket&lt;/li&gt;
&lt;li&gt;Delete S3 bucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nwSFhEo0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114326429-da953080-9b88-11eb-8ef0-aa4c1ec554bf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nwSFhEo0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114326429-da953080-9b88-11eb-8ef0-aa4c1ec554bf.png" alt="aws-s3-demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/dynamodb-console"&gt;DynamoDb ConsoleApp&lt;/a&gt; - This project demonstrates how to integrate a .NET Core console application with DynamoDb using the Amazon SDK. This application provides the functionality required to both manage DynamoDb tables, and manage the data stored in a DynamoDB table&lt;/p&gt;

&lt;p&gt;The following features have been implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage Tables&lt;/li&gt;
&lt;li&gt;Create table&lt;/li&gt;
&lt;li&gt;List and find tables&lt;/li&gt;
&lt;li&gt;Wait for tables to be described (eventually consistent)&lt;/li&gt;
&lt;li&gt;Delete table&lt;/li&gt;
&lt;li&gt;Manage Book Table Data&lt;/li&gt;
&lt;li&gt;Automatically creates Book table&lt;/li&gt;
&lt;li&gt;Add books to Book table&lt;/li&gt;
&lt;li&gt;Update books in Book table&lt;/li&gt;
&lt;li&gt;Delete books from Book table&lt;/li&gt;
&lt;li&gt;List and find books in Book table&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NOrZzrT1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114658257-a2871c80-9d45-11eb-9024-d5acde7d266e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NOrZzrT1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114658257-a2871c80-9d45-11eb-9024-d5acde7d266e.png" alt="dynamodb-1"&gt;&lt;/a&gt;&lt;/p&gt;


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

&lt;p&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/sns-console"&gt;SNS ConsoleApp&lt;/a&gt; - This project demonstrates how to integrate a .NET Core console application with SNS using the Amazon SDK. This application provides the functionality required to manage SNS topcs, subscriptions, and publications.&lt;/p&gt;

&lt;p&gt;The following features have been implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage Topics&lt;/li&gt;
&lt;li&gt;Create topic&lt;/li&gt;
&lt;li&gt;List and find topics
&lt;/li&gt;
&lt;li&gt;Delete topic&lt;/li&gt;
&lt;li&gt;Manage Subscriptions&lt;/li&gt;
&lt;li&gt;Create an email subscription&lt;/li&gt;
&lt;li&gt;Cancel a subscription&lt;/li&gt;
&lt;li&gt;List subscriptions&lt;/li&gt;
&lt;li&gt;Manage Publications&lt;/li&gt;
&lt;li&gt;An example showing how to publish a 'Game Ranking' to a 'game-ranking' topic&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--Ta70V6ix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114331020-32d32f00-9b97-11eb-8041-3a9a923df51b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ta70V6ix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114331020-32d32f00-9b97-11eb-8041-3a9a923df51b.png" alt="aws-sns-demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/drminnaar/aws-dotnetcore-examples/tree/master/sqs-console"&gt;SQS ConsoleApp&lt;/a&gt; - This project demonstrates how to integrate a .NET Core console application with SQS using the Amazon SDK.&lt;/p&gt;

&lt;p&gt;The following features have been implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage Queues&lt;/li&gt;
&lt;li&gt;Create queue&lt;/li&gt;
&lt;li&gt;List queues&lt;/li&gt;
&lt;li&gt;Delete queue&lt;/li&gt;
&lt;li&gt;Get queue url&lt;/li&gt;
&lt;li&gt;Manage Game Ranking Queue&lt;/li&gt;
&lt;li&gt;Enqueue game ranking to queue&lt;/li&gt;
&lt;li&gt;Dequeue game rankings from queue&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--21I3rTWz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114371324-7c8e3a80-9bd4-11eb-8e8d-5d4a126c9d2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--21I3rTWz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/114371324-7c8e3a80-9bd4-11eb-8e8d-5d4a126c9d2e.png" alt="aws-sqs-overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;-&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I have plans to extend this project by implementing the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improve existing examples (both code and documentation)&lt;/li&gt;
&lt;li&gt;Add additional examples for the current services that I have provisioned for (S3, DynamoDB, SQS, SNS, Cognito)&lt;/li&gt;
&lt;li&gt;Add examples for new services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all folks!&lt;/p&gt;




</description>
    </item>
    <item>
      <title>MFlix - A C# .NET 5 Project</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Tue, 06 Apr 2021 09:01:26 +0000</pubDate>
      <link>https://dev.to/drminnaar/mflix-a-c-net-5-project-4gck</link>
      <guid>https://dev.to/drminnaar/mflix-a-c-net-5-project-4gck</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I have created a project that demonstrates how to build 3 API's using 3 different API tehnologies, namely &lt;strong&gt;GraphQL&lt;/strong&gt;, &lt;strong&gt;gRPC&lt;/strong&gt;, and &lt;strong&gt;REST (HTTP)&lt;/strong&gt;. I have also chosen to use &lt;em&gt;MongoDB&lt;/em&gt; as my database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/drminnaar/mflix"&gt;You can find the project on github&lt;/a&gt;. The project has been built and tested on both &lt;em&gt;Linux&lt;/em&gt; and &lt;em&gt;Windows 10&lt;/em&gt; environments using &lt;em&gt;Visual Studio Code&lt;/em&gt; and &lt;em&gt;.NET 5&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I provide more detail about the project in the &lt;a href="https://github.com/drminnaar/mflix#readme"&gt;project README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The summary of the project thus far is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#1-purpose"&gt;Purpose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#2-description"&gt;Description&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/mflix#3-infrastructure"&gt;Infrastructure&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#31-mongo-seed"&gt;Mongo Seed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#32-the-docker-compose-file"&gt;The Docker Compose File&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/mflix#4-getting-started"&gt;Getting Started&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#41-get-the-code"&gt;Get The Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#42-manage-infrastructure"&gt;Manage Infrastructure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#43-start-mflix-grpc-api"&gt;Start MFlix gRpc API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#44-start-mflix-http-api"&gt;Start MFlix HTTP API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#45-start-mflix-graphql-api"&gt;Start MFlix GraphQL API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/drminnaar/mflix#5-test-mflix-grpc-services"&gt;Test MFlix gRPC services&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#51-grpcurl"&gt;gRPCurl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#52-grpcui"&gt;gRPCUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#53-bloomrpc"&gt;BloomRPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/mflix#54-insomnia"&gt;Insomnia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;The following diagram provides a high-level view of what I am building.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H4hzi7Eo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/111857444-58a15580-8996-11eb-8d3f-c3adea46a661.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H4hzi7Eo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/111857444-58a15580-8996-11eb-8d3f-c3adea46a661.png" alt="mflix-hla-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Initially, I thought about creating this project as part of a series of blog posts. However, I decided to instead build the application first. MFlix is by no means complete, but now is a good time to start sharing the work being done due to a number of interesting aspects that I am working on. In the coming months, I will continue to build out MFlix. Also, if there is interest, I would like to provide a series of blog posts where I discuss some of the more interesting aspects of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  About MFlix
&lt;/h2&gt;

&lt;p&gt;I chose &lt;em&gt;MFlix&lt;/em&gt; as the name for this project because I am using one of the sample databases provided by MongoDB called MFlix. The MFlix database is composed of collections of movie related data. I provide more detail in the &lt;a href="https://github.com/drminnaar/mflix#3-infrastructure"&gt;MongoDB section&lt;/a&gt; where I explain how to get a copy of the MFlix database. Therefore, because of the database name, and the fact that &lt;em&gt;MFlix&lt;/em&gt; is a short and catchy name, I decided to go with &lt;em&gt;MFlix&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The primary purpose of &lt;em&gt;MFlix&lt;/em&gt; is to demonstrate how to build gRPC, REST (http), and GraphQL API's using C# and the .NET Framework. In order to do this, I have created a &lt;a href="https://github.com/drminnaar/mflix#2-description"&gt;contrived use-case&lt;/a&gt; that will allow me to demonstrate how to build different API's for different needs. Each API demonstrates how to address the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Dependency Injection&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;How to do paging, filtering, and sorting via the API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The secondary purpose of &lt;em&gt;MFlix&lt;/em&gt; is to demonstrate how to work with different technologies, frameworks, and libraries using the C# .NET Framework. The different topics that will be demonstrated are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developing with MongoDB and C#&lt;/li&gt;
&lt;li&gt;Preparing a local development environment using Docker and Docker-Compose&lt;/li&gt;
&lt;li&gt;Working with MongoDB database&lt;/li&gt;
&lt;li&gt;Working with SEQ as a log server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, I cover a useful set of tools that can be used to test the various API's. Some of the tools covered are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP API

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.postman.com/"&gt;Postman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;gRPC API

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fullstorydev/grpcurl"&gt;gRPCurl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/fullstorydev/grpcui"&gt;gRPCUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/uw-labs/bloomrpc"&gt;BloomRPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;GraphQL API

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://chillicream.com/docs/bananacakepop"&gt;Banana Cake Pop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/APIs-guru/graphql-voyager"&gt;Voyager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;This was a quick introduction to &lt;a href="https://github.com/drminnaar/mflix"&gt;MFlix&lt;/a&gt;. I consider what I have done thus far as my &lt;em&gt;"MVP (Minimum Viable Product)"&lt;/em&gt;. Depending on the feedback, I may follow up with a series of blog posts and maybe a few videos on topics relating to technology and frameworks used within the project. If you like what you see so far, please star the &lt;a href="https://github.com/drminnaar/mflix"&gt;MFlix&lt;/a&gt; project.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>csharp</category>
      <category>api</category>
    </item>
    <item>
      <title>Jukenook Db</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Sat, 25 Jul 2020 10:46:56 +0000</pubDate>
      <link>https://dev.to/drminnaar/jukenook-db-4l7d</link>
      <guid>https://dev.to/drminnaar/jukenook-db-4l7d</guid>
      <description>&lt;p&gt;I have published &lt;a href="https://github.com/drminnaar/jukenook-db" rel="noopener noreferrer"&gt;a new project&lt;/a&gt; on my &lt;em&gt;Github&lt;/em&gt; account called &lt;a href="https://github.com/drminnaar/jukenook-db" rel="noopener noreferrer"&gt;Jukenook Db&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Jukenook Db&lt;/em&gt; is a reference project that demonstrates how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a &lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; environment using &lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; and &lt;a href="https://docs.docker.com/compose" rel="noopener noreferrer"&gt;Docker-Compose&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;configure database versioning and migration using &lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Jukenook Db&lt;/em&gt; is based on the &lt;em&gt;&lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook Database Project&lt;/a&gt;&lt;/em&gt;. The &lt;em&gt;&lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook Database Project&lt;/a&gt;&lt;/em&gt; is a sample database that is available to be used with a number of database engines such as Postgres, SQL Server, and MySQL for example. The Chinook data model represents a digital media store, including tables for artists, albums, media tracks, invoices and customers. To see the full description and supported databases, please visit the &lt;em&gt;&lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook Database Project&lt;/a&gt;&lt;/em&gt;. All credit goes to the &lt;em&gt;&lt;a href="https://github.com/cwoodruff" rel="noopener noreferrer"&gt;Chris Woodruff&lt;/a&gt;&lt;/em&gt; &lt;em&gt;&lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook Database Project&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The reason for creating this project is due to a continuous need for a consistent database structure that I can use when experimenting with different application development ideas. I searched for a data model that is simple, yet has the potential to evolve into something more sophisticated over time. After investigating a number of different options, I decided on the &lt;em&gt;&lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook Database Project&lt;/a&gt;&lt;/em&gt;. I have taken the original &lt;em&gt;&lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook Database Project&lt;/a&gt;&lt;/em&gt; and changed it to work specifically with a &lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt; database engine using &lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt; migrations. I will also continue to evolve &lt;em&gt;Jukenook Db&lt;/em&gt; as I experiment with different ideas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why The Name
&lt;/h2&gt;

&lt;p&gt;Firstly, I chose not to keep the original name &lt;em&gt;'Chinook (&lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook Database Project&lt;/a&gt;)'&lt;/em&gt;. This is primarily due to reasons involving the evolution of the database model over time.&lt;/p&gt;

&lt;p&gt;Secondly, Because the primary database concept is focused around music, I decided to take inspiration from a musical &lt;a href="https://en.wikipedia.org/wiki/Jukebox" rel="noopener noreferrer"&gt;Jukebox&lt;/a&gt;. Therefore, I combined the naming of &lt;a href="https://en.wikipedia.org/wiki/Jukebox" rel="noopener noreferrer"&gt;Jukebox&lt;/a&gt; and &lt;a href="https://github.com/cwoodruff/ChinookDatabase" rel="noopener noreferrer"&gt;Chinook&lt;/a&gt; to form the new name &lt;em&gt;'Jukenook'&lt;/em&gt;. A 'nook' also happens to be a corner or recess, and I think that makes a good place to locate a Jukebox 🤔&lt;/p&gt;




&lt;h2&gt;
  
  
  Purpose
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Primary Objective
&lt;/h3&gt;

&lt;p&gt;The primary objective for this project is to provide a &lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt; database that can be easily deployed into one's local development environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secondary Objectives
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Show how to use &lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt; to manage database versioning and migration&lt;/li&gt;
&lt;li&gt;Show how to setup a &lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt; database using &lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; and &lt;a href="https://docs.docker.com/compose" rel="noopener noreferrer"&gt;Docker-Compose&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Defining docker-compose file to create local &lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt; environment using the Postgres 12 and &lt;a href="https://www.pgadmin.org" rel="noopener noreferrer"&gt;pgAdmin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Defining docker-compose files that provide an easy way to work with &lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt; using &lt;a href="https://hub.docker.com/r/flyway/flyway" rel="noopener noreferrer"&gt;Flyway Docker Image&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Supported Platforms
&lt;/h2&gt;

&lt;p&gt;This project has been successfully tested on the following platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ubuntu.com/download/desktop" rel="noopener noreferrer"&gt;Ubuntu 20.04&lt;/a&gt; - Ubuntu is an open source software operating system that runs from the desktop, to the cloud, to all your internet connected things.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.microsoft.com/en-us/p/windows-10-pro/df77x4d43rkt" rel="noopener noreferrer"&gt;Windows 10 Professional (2004)&lt;/a&gt; - Latest version of Windows 10 operating system. For this particular platform I used &lt;a href="https://en.wikipedia.org/wiki/PowerShell" rel="noopener noreferrer"&gt;Powershell Command Line&lt;/a&gt; to execute project tasks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.toWindows%2010%20Professional%20(2004)"&gt;Windows Subsystem For Linux 2&lt;/a&gt; - WSL 2 is based on a new architecture that provides full Linux binary application compatibility and improved performance. WSL 2 is powered by a real Linux kernel in a lightweight virtual machine that boots in under two seconds. Specifically, the &lt;a href="https://ubuntu.com/download/desktop" rel="noopener noreferrer"&gt;Ubuntu 20.04&lt;/a&gt; distribution was used.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  General Tools
&lt;/h2&gt;

&lt;p&gt;The following list of tools are required in order to run this project correctly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; - Docker is a computer program that performs operating-system-level virtualization also known as containerization. In other words it allows one to containerize applications.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/compose" rel="noopener noreferrer"&gt;Docker-Compose&lt;/a&gt; - Compose is a tool for defining and running multi-container Docker applications.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt; - Version control for your database by making database migrations repeatable and easy&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt; - PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and technical standards compliance. It is designed to handle a range of workloads, from single machines to data warehouses or Web services with many concurrent users.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pgadmin.org" rel="noopener noreferrer"&gt;pgAdmin&lt;/a&gt; - Open Source administration and development platform for PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; - Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com" rel="noopener noreferrer"&gt;Npm&lt;/a&gt; - A package manager for the Javascript programming language. In this project it is used as a task runner to simplify running various infrastructural tasks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;In order to successfully run the &lt;em&gt;Jukenook&lt;/em&gt; database project, you will require the following tools and frameworks to be installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose" rel="noopener noreferrer"&gt;Docker-Compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com" rel="noopener noreferrer"&gt;Npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this project, every database definition will be described using a number of database migration scripts. The database migration scripts are defined as per the &lt;em&gt;&lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt;&lt;/em&gt; database versioning and migration tool guidelines. &lt;em&gt;&lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt;&lt;/em&gt; is an open-source database migration tool that favors simplicity and convention over configuration. For more information, please see the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://flywaydb.org/getstarted/" rel="noopener noreferrer"&gt;Official Flyway Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/flyway" rel="noopener noreferrer"&gt;Getting Started Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Get the repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/drminnaar/jukenook-db.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manage Database
&lt;/h3&gt;

&lt;p&gt;I have created &lt;em&gt;docker-compose&lt;/em&gt; files to help with the management of bringing up and taking down a PostgreSQL database environment. I also provide &lt;em&gt;docker-compose&lt;/em&gt; files to help manage the database migrations and versioning. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;docker-compose.yml - Defines the PostgreSQL and pgAdmin services&lt;/li&gt;
&lt;li&gt;docker-compose-dev-flyway:info.yml - Runs Flyway migration to obtain information about migrations&lt;/li&gt;
&lt;li&gt;docker-compose-dev-flyway:migrate.yml - Runs Flyway migration to do actual database migrations&lt;/li&gt;
&lt;li&gt;docker-compose-dev-flyway:validate.yml - - Runs Flyway migration to validate migrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to make it simpler to manage the environment, I have created an NPM package file wherein I have defined a number of tasks. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev-db:up"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker-compose up -d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev-db:down"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker-compose down --volumes &amp;amp;&amp;amp; docker-compose -f ./flyway/docker-compose-dev-flyway:info.yml -f ./flyway/docker-compose-dev-flyway:validate.yml -f ./flyway/docker-compose-dev-flyway:migrate.yml down"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev-db:migrate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker-compose -f ./flyway/docker-compose-dev-flyway:migrate.yml up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev-db:info"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker-compose -f ./flyway/docker-compose-dev-flyway:info.yml up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev-db:validate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker-compose -f ./flyway/docker-compose-dev-flyway:validate.yml up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run dev-db:down &amp;amp;&amp;amp; npm run dev-db:up"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I generally prefer using NPM as a task runner unless I have more advanced requirements.&lt;/p&gt;

&lt;h4&gt;
  
  
  Spinning Up
&lt;/h4&gt;

&lt;p&gt;This step will create an empty &lt;em&gt;Jukenook&lt;/em&gt; database running in a docker container. The &lt;code&gt;docker-compose.yml&lt;/code&gt; file is used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a Postgres12 (running on Alpine Linux) database in a docker container&lt;/li&gt;
&lt;li&gt;load pgAdmin application via docker container. The pgAdmin application is accessible at &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run dev-up

&amp;gt; jukenook-db@1.0.0 dev-db:up /home/dmin/projects/jukenook/jukenook-db
&amp;gt; docker-compose up -d

Creating network "jukenook_net" with the default driver
Creating jukenook_db    ... done
Creating jukenook_admin ... done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Tearing Down
&lt;/h4&gt;

&lt;p&gt;This step will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stop and remove all related docker containers&lt;/li&gt;
&lt;li&gt;remove all related docker volumes&lt;/li&gt;
&lt;li&gt;remove all related docker networks
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run dev-down

&amp;gt; jukenook-db@1.0.0 dev-db:down /home/dmin/projects/jukenook/jukenook-db
&amp;gt; docker-compose down --volumes &amp;amp;&amp;amp; docker-compose -f ./flyway/docker-compose-dev-flyway:info.yml -f ./flyway/docker-compose-dev-flyway:validate.yml -f ./flyway/docker-compose-dev-flyway:migrate.yml down

Stopping jukenook_admin ... done
Stopping jukenook_db    ... done
Removing jukenook_admin ... done
Removing jukenook_db    ... done
Removing network jukenook_net
Network jukenook_net is external, skipping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manage Database Migrations
&lt;/h3&gt;

&lt;p&gt;For the following commands, the &lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt; database versioning and migration tool is used.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get Database Migrations Info
&lt;/h4&gt;

&lt;p&gt;This command will return a list of migrations with relevant information like the migration state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run dev-db:info

&amp;gt; jukenook-db@1.0.0 dev-db:info /home/dmin/projects/jukenook/jukenook-db
&amp;gt; docker-compose -f ./flyway/docker-compose-dev-flyway:info.yml up

Creating jukenook_flyway ... done
Attaching to jukenook_flyway
Flyway Community Edition 6.4.4 by Redgate
Database: jdbc:postgresql://jukenook_db/jukenook (PostgreSQL 12.3)
Schema version: &amp;lt;&amp;lt; Empty Schema &amp;gt;&amp;gt;
+------------+---------+------------------------------+------+--------------+---------+
| Category   | Version | Description                  | Type | Installed On | State   |
+------------+---------+------------------------------+------+--------------+---------+
| Versioned  | 1.1     | Create operations schema     | SQL  |              | Pending |
| Versioned  | 1.2     | Create employee table        | SQL  |              | Pending |
| Versioned  | 1.3     | Create catalog schema        | SQL  |              | Pending |
| Versioned  | 1.4     | Create genre table           | SQL  |              | Pending |
| Versioned  | 1.5     | Create artist table          | SQL  |              | Pending |
| Versioned  | 1.6     | Create album table           | SQL  |              | Pending |
| Versioned  | 1.7     | Create media type table      | SQL  |              | Pending |
| Versioned  | 1.8     | Create track table           | SQL  |              | Pending |
| Versioned  | 1.9     | Create playlist table        | SQL  |              | Pending |
| Versioned  | 1.10    | Create composition table     | SQL  |              | Pending |
| Versioned  | 1.11    | Create sales schema          | SQL  |              | Pending |
| Versioned  | 1.12    | Create customer table        | SQL  |              | Pending |
| Versioned  | 1.13    | Create invoice table         | SQL  |              | Pending |
| Versioned  | 1.14    | Create invoice line table    | SQL  |              | Pending |
| Repeatable |         | 001 Install extensions       | SQL  |              | Pending |
| Repeatable |         | 002 Insert genre data        | SQL  |              | Pending |
| Repeatable |         | 003 Insert media type data   | SQL  |              | Pending |
| Repeatable |         | 004 Insert artist data       | SQL  |              | Pending |
| Repeatable |         | 005 Insert album data        | SQL  |              | Pending |
| Repeatable |         | 006 Insert track data        | SQL  |              | Pending |
| Repeatable |         | 007 Insert employee data     | SQL  |              | Pending |
| Repeatable |         | 008 Insert customer data     | SQL  |              | Pending |
| Repeatable |         | 009 Insert invoice data      | SQL  |              | Pending |
| Repeatable |         | 010 Insert invoice line data | SQL  |              | Pending |
+------------+---------+------------------------------+------+--------------+---------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Validate Database Migrations
&lt;/h4&gt;

&lt;p&gt;This command will validate pending migrations and return information relating to the validity thereof.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run dev-db:validate

&amp;gt; jukenook-db@1.0.0 dev-db:validate /home/dmin/projects/jukenook/jukenook-db
&amp;gt; docker-compose -f ./flyway/docker-compose-dev-flyway:validate.yml up

Recreating jukenook_flyway ... done
Attaching to jukenook_flyway
Flyway Community Edition 6.4.4 by Redgate
Database: jdbc:postgresql://jukenook_db/jukenook (PostgreSQL 12.3)
ERROR: Validate failed:
Detected resolved migration not applied to database: 1.1
Detected resolved migration not applied to database: 1.2
Detected resolved migration not applied to database: 1.3
Detected resolved migration not applied to database: 1.4
Detected resolved migration not applied to database: 1.5
Detected resolved migration not applied to database: 1.6
Detected resolved migration not applied to database: 1.7
Detected resolved migration not applied to database: 1.8
Detected resolved migration not applied to database: 1.9
Detected resolved migration not applied to database: 1.10
Detected resolved migration not applied to database: 1.11
Detected resolved migration not applied to database: 1.12
Detected resolved migration not applied to database: 1.13
Detected resolved migration not applied to database: 1.14
Detected resolved repeatable migration not applied to database: 001 Install extensions
Detected resolved repeatable migration not applied to database: 002 Insert genre data
Detected resolved repeatable migration not applied to database: 003 Insert media type data
Detected resolved repeatable migration not applied to database: 004 Insert artist data
Detected resolved repeatable migration not applied to database: 005 Insert album data
Detected resolved repeatable migration not applied to database: 006 Insert track data
Detected resolved repeatable migration not applied to database: 007 Insert employee data
Detected resolved repeatable migration not applied to database: 008 Insert customer data
Detected resolved repeatable migration not applied to database: 009 Insert invoice data
Detected resolved repeatable migration not applied to database: 010 Insert invoice line data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Run Database Migrations
&lt;/h4&gt;

&lt;p&gt;This command will run the actual migrations on the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run dev-db:migrate

&amp;gt; jukenook-db@1.0.0 dev-db:migrate /home/dmin/projects/jukenook/jukenook-db
&amp;gt; docker-compose -f ./flyway/docker-compose-dev-flyway:migrate.yml up

Recreating jukenook_flyway ... done
Attaching to jukenook_flyway
Flyway Community Edition 6.4.4 by Redgate
Database: jdbc:postgresql://jukenook_db/jukenook (PostgreSQL 12.3)
Successfully validated 24 migrations (execution time 00:00.264s)
Creating Schema History table "public"."flyway_schema_history" ...
Current version of schema "public": &amp;lt;&amp;lt; Empty Schema &amp;gt;&amp;gt;
Migrating schema "public" to version 1.1 - Create operations schema
Migrating schema "public" to version 1.2 - Create employee table
Migrating schema "public" to version 1.3 - Create catalog schema
Migrating schema "public" to version 1.4 - Create genre table
Migrating schema "public" to version 1.5 - Create artist table
Migrating schema "public" to version 1.6 - Create album table
Migrating schema "public" to version 1.7 - Create media type table
Migrating schema "public" to version 1.8 - Create track table
Migrating schema "public" to version 1.9 - Create playlist table
Migrating schema "public" to version 1.10 - Create composition table
Migrating schema "public" to version 1.11 - Create sales schema
Migrating schema "public" to version 1.12 - Create customer table
Migrating schema "public" to version 1.13 - Create invoice table
Migrating schema "public" to version 1.14 - Create invoice line table
Migrating schema "public" with repeatable migration 001 Install extensions
Migrating schema "public" with repeatable migration 002 Insert genre data
Migrating schema "public" with repeatable migration 003 Insert media type data
Migrating schema "public" with repeatable migration 004 Insert artist data
Migrating schema "public" with repeatable migration 005 Insert album data
Migrating schema "public" with repeatable migration 006 Insert track data
Migrating schema "public" with repeatable migration 007 Insert employee data
Migrating schema "public" with repeatable migration 008 Insert customer data
Migrating schema "public" with repeatable migration 009 Insert invoice data
Migrating schema "public" with repeatable migration 010 Insert invoice line data
Successfully applied 24 migrations to schema "public" (execution time 00:02.983s)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Connect Using pgAdmin
&lt;/h3&gt;

&lt;p&gt;As part of the database setup and configuration in the &lt;em&gt;docker-compose&lt;/em&gt; file. The web based PosrgreSQL database management tool is also run within a container.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1 - Open pgAdmin Tool
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Open browser and enter the address '&lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;' to access &lt;em&gt;pgAdmin&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;For username, enter '&lt;a href="mailto:admin@example.com"&gt;admin@example.com&lt;/a&gt;'&lt;/li&gt;
&lt;li&gt;For password, enter 'password'&lt;/li&gt;
&lt;li&gt;Logon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851208-999a2380-c94a-11ea-89d5-2e05acba5d20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851208-999a2380-c94a-11ea-89d5-2e05acba5d20.png" alt="1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You should be logged in with the following view open&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851210-9a32ba00-c94a-11ea-9f1c-e578ce28c98c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851210-9a32ba00-c94a-11ea-9f1c-e578ce28c98c.png" alt="2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2 - Create Server Group
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a server group called 'jukenook'&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851205-99018d00-c94a-11ea-8c10-48c3afbb9e25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851205-99018d00-c94a-11ea-8c10-48c3afbb9e25.png" alt="3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3 - Create new server
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a server called 'jukenook-docker'&lt;/li&gt;
&lt;li&gt;Select the 'jukenook' server group&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851204-9868f680-c94a-11ea-8022-41e1ab92eb3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851204-9868f680-c94a-11ea-8022-41e1ab92eb3a.png" alt="4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4 - Provide Connection Details
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Select 'Connection' tab&lt;/li&gt;
&lt;li&gt;For host, because we are using docker to run pgAdmin, we need to obtain the IP Address of the Postgres docker container. Therefore, open up a terminal and type the following commands:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  docker container inspect -f '{{ .NetworkSettings.Networks.jukenook_net.IPAddress }}' jukenook_db

  -- Result
  172.18.0.2 (you may recieve a different IP Address)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enter the connection details

&lt;ul&gt;
&lt;li&gt;Host - see above to obtain IPAddress&lt;/li&gt;
&lt;li&gt;Username - specified in docker-compose.yml file&lt;/li&gt;
&lt;li&gt;Password - specified in docker-compose.yml file&lt;/li&gt;
&lt;li&gt;Port - leave as the default 5432&lt;/li&gt;
&lt;li&gt;Role - enter 'admin'. The admin role is created as part of database initialization script &lt;em&gt;'create-jukenook-db (defined in entrypoint-scripts folder)'&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Select 'Save' connection&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851203-9868f680-c94a-11ea-9421-24d5027a9f84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851203-9868f680-c94a-11ea-9421-24d5027a9f84.png" alt="5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After saving connection, you should see a view similar to the following:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851209-999a2380-c94a-11ea-84ac-011cf20be56f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851209-999a2380-c94a-11ea-84ac-011cf20be56f.png" alt="6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851206-99018d00-c94a-11ea-974e-c3662a3f64bd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851206-99018d00-c94a-11ea-974e-c3662a3f64bd.png" alt="7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5 - Execute a Query
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a new query window by selecting the 'Query Tool' button.&lt;/li&gt;
&lt;li&gt;Enter a query and execute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851202-969f3300-c94a-11ea-9250-a1b56424950b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F87851202-969f3300-c94a-11ea-9250-a1b56424950b.png" alt="8"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Entrypoint Scripts
&lt;/h2&gt;

&lt;p&gt;You may be wondering where I create the database and configure users and roles. I make use of entrypoint scripts to perform onceoff database initialization. For example, I currently have a single entrypoint script called &lt;em&gt;'create-jukenook-db'&lt;/em&gt; that looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

psql &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;ON_ERROR_STOP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;--username&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt; &lt;span class="nt"&gt;--dbname&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOSQL&lt;/span&gt;&lt;span class="sh"&gt;
    -- create database
    CREATE DATABASE jukenook;

    -- restrict public access
    REVOKE CREATE ON SCHEMA public FROM PUBLIC;
    REVOKE ALL ON DATABASE jukenook FROM PUBLIC;

    -- create admin role
    CREATE ROLE admin;
    GRANT ALL PRIVILEGES ON DATABASE jukenook TO admin;

    -- create readonly role
    CREATE ROLE readonly;
    GRANT CONNECT ON DATABASE jukenook TO readonly;

    -- create readwrite role
    CREATE ROLE readwrite;
    GRANT CONNECT ON DATABASE jukenook TO readwrite;

    -- create admin users
    CREATE USER jukenookboss WITH PASSWORD 'password';
    GRANT admin TO jukenookboss;

    -- create reader user
    CREATE USER reader WITH PASSWORD 'password';
    GRANT readonly TO reader;

    -- create writer user
    CREATE USER writer WITH PASSWORD 'password';
    GRANT readwrite TO writer;
&lt;/span&gt;&lt;span class="no"&gt;EOSQL
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entrypoint scripts can be found in the &lt;em&gt;'entrypoint-scripts'&lt;/em&gt; folder as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F88454529-75978e80-cec4-11ea-9d7f-66eeb16e0ce5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F88454529-75978e80-cec4-11ea-9d7f-66eeb16e0ce5.png" alt="entrypoint-scripts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is also an entry added to the volumes section of the Postgres service in the &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.5'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;jukenook_db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="s"&gt;volumes&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./entrypoint-scripts:/docker-entrypoint-initdb.d/&lt;/span&gt;
    &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="s"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Schema
&lt;/h2&gt;

&lt;p&gt;The database schema is composed of 4 schemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;music_catalog (yellow)&lt;/li&gt;
&lt;li&gt;sales (green)&lt;/li&gt;
&lt;li&gt;operations (cyan)&lt;/li&gt;
&lt;li&gt;public (orange)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F88453517-bb038e00-cebb-11ea-9b22-bdc302d0ed94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F88453517-bb038e00-cebb-11ea-9b22-bdc302d0ed94.png" alt="Jukenook ERD"&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>database</category>
      <category>showdev</category>
      <category>docker</category>
    </item>
    <item>
      <title>gRPC Guide</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Sun, 09 Feb 2020 09:04:59 +0000</pubDate>
      <link>https://dev.to/drminnaar/grpc-guide-25mo</link>
      <guid>https://dev.to/drminnaar/grpc-guide-25mo</guid>
      <description>&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;In this guide, I aim to provide the salient points concerning &lt;em&gt;gRPC&lt;/em&gt; and &lt;em&gt;Protocol Buffers&lt;/em&gt;. If you know what &lt;em&gt;gRPC&lt;/em&gt; and &lt;em&gt;Protocol Buffers&lt;/em&gt; are, then this guide is not for you. This is a guide for the beginner or the mildly interested.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;gRPC&lt;/em&gt; is a framework for building API's and is an alternative to JSON and XML based services. gRPC has the following attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a free and open-source framework that was originally developed by Google but is now part of the Cloud Native Computing Foundation (CNCF)&lt;/li&gt;
&lt;li&gt;a cross-platform and language agnostic&lt;/li&gt;
&lt;li&gt;built on HTTP/2 and supports unary and streaming communication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Protocol Buffers&lt;/em&gt; serialize structured data and are used by default by gRPC. Protocol Buffers have the following attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;are language agnostic&lt;/li&gt;
&lt;li&gt;help structure information for serialization&lt;/li&gt;
&lt;li&gt;facilitates code generation&lt;/li&gt;
&lt;li&gt;results in small payloads and efficient serialization due to data being binary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of the concepts in this guide are language agnostic. However, for now, I only provide examples in C# using .NET Core 3.1. The examples have been tested on both Linux and Windows. All examples have been created using &lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; with the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp" rel="noopener noreferrer"&gt;C# for Visual Studio Code&lt;/a&gt; extension. Find the examples here,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/grpc-guide/tree/master/Examples/Messaging" rel="noopener noreferrer"&gt;Messenger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/grpc-guide/tree/master/Examples/Calculator" rel="noopener noreferrer"&gt;Calculator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;In a nutshell, gRPC can be summed up as follows,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A high performance, open-source universal RPC framework&lt;/p&gt;

&lt;p&gt;-- &lt;em&gt;&lt;a href="https://grpc.io" rel="noopener noreferrer"&gt;https://grpc.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before delving into gRPC, I'd like to take a step back and understand the problem that gRPC solves. For that I need to discuss the theory of communication fundamentals. Although this is a technical article, I won't be discussing communication theory as applied to computing systems. Instead, I will discuss an example of 2 people speaking.&lt;/p&gt;

&lt;p&gt;Let’s imagine 2 people having a discussion in the same room. Both people speak the same language and the communication medium is essentially the same shared space in which the 2 people are speaking. For now we will keep it simple and make the assumption that the communication is unidirectional (communication happens in one way at a time).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;Sender&lt;/em&gt; sends a message (request) to the &lt;em&gt;Receiver&lt;/em&gt; and waits for a response&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;Receiver&lt;/em&gt; receives the message (request) and returns a response as another message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the 2 people are in the same room speaking the same language, the communication is very simple. There is no need for anything special to enable successful communication. For clarity, the following attributes can be observed for this type of communication.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same language&lt;/li&gt;
&lt;li&gt;Same space (non-distributed)&lt;/li&gt;
&lt;li&gt;Same medium&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following diagram further illustrates how the communication occurs for this scenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73964490-28a41800-4977-11ea-877b-26542bb2f27f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73964490-28a41800-4977-11ea-877b-26542bb2f27f.png" alt="grpc-comms-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now imagine that we have 2 people that are in separate rooms, in different countries, and speak different languages. The following attributes contrast the difference to the example used above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different language&lt;/li&gt;
&lt;li&gt;Different space (distributed)&lt;/li&gt;
&lt;li&gt;Different medium&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, for successful communication to occur, we will need a mechanism to enable distributed communication. The mechanism will need to define some form of protocol (agreed upon rules) and will also need to do some form of encoding and decoding of messages sent between the &lt;em&gt;Sender&lt;/em&gt; and the &lt;em&gt;Receiver&lt;/em&gt;. This can be seen as illustrated in the diagram below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73964489-280b8180-4977-11ea-8691-bdfac793247d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73964489-280b8180-4977-11ea-8691-bdfac793247d.png" alt="grpc-comms-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now imagine that we simply replace the 2 people with 2 computing systems. A &lt;em&gt;Client&lt;/em&gt; and a &lt;em&gt;Server&lt;/em&gt;. The &lt;em&gt;Client&lt;/em&gt; may be a &lt;em&gt;NodeJS Console Application&lt;/em&gt; written in Javascript. The &lt;em&gt;Server&lt;/em&gt; could be running a &lt;em&gt;C# .NET&lt;/em&gt; application. We have 2 separate systems that are running in different data centers and connected via a network. In other words we have a distributed computing system. In order for the &lt;em&gt;Client&lt;/em&gt; and the &lt;em&gt;Server&lt;/em&gt; to communicate, a &lt;em&gt;mechanism&lt;/em&gt; with a &lt;em&gt;protocol&lt;/em&gt; will need to be used. &lt;em&gt;Protocol Buffers (Protobuf)&lt;/em&gt; and &lt;em&gt;gRPC&lt;/em&gt; are just such a mechanism. The diagram below illustrates how our basic communication model can be translated into gRPC clients and server. The clients and server can be completely distributed and running in different data centres in different locations throughout the world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F74091899-f2ef6280-4b21-11ea-9b3f-17588e5c8ae0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F74091899-f2ef6280-4b21-11ea-9b3f-17588e5c8ae0.png" alt="grpc-stub-server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There have been other solutions that solved this problem too. We are still using some of these at the time of this writing. Http services for example (REST) is still hugely popular. gRPC is simply an alternative to enable communication between distributed services and systems. It's important to remember that although there are different approaches to solving a common problem, the way in which we use these different approaches can be quite different. For example, building and using a Http service is entirely different from building and using a gRPC service.&lt;/p&gt;

&lt;p&gt;There is some really good online documentation that describes &lt;em&gt;gRPC&lt;/em&gt; and &lt;em&gt;Protocol Buffers&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://grpc.io/" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt; - The official gRPC website&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/protocol-buffers/docs/overview" rel="noopener noreferrer"&gt;Protocol Buffers&lt;/a&gt; - The official &lt;em&gt;Google&lt;/em&gt; developer guide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the online documentation is so good, I won't be repeating some of the great work that already been done. Instead, I'm going to focus on the salient points of &lt;em&gt;&lt;a href="https://grpc.io/" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href="https://developers.google.com/protocol-buffers/docs/overview" rel="noopener noreferrer"&gt;Protocol Buffers&lt;/a&gt;&lt;/em&gt;. I will also be providing some examples that illustrate how to get started with &lt;em&gt;gRPC&lt;/em&gt;. All examples will be provided using &lt;em&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-3.1" rel="noopener noreferrer"&gt;gRPC on .NET Core&lt;/a&gt;&lt;/em&gt;. For more specific documentation relating to building and consuming gRPC services on .NET Core, please see the following great online documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/csharp/" rel="noopener noreferrer"&gt;gRPC Tutorial: C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/protocol-buffers/docs/csharptutorial" rel="noopener noreferrer"&gt;Protocol Buffer Basics: C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/protocol-buffers/docs/reference/csharp-generated" rel="noopener noreferrer"&gt;Generated Code: C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-3.1" rel="noopener noreferrer"&gt;Introduction to gRPC on .NET Core&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Protocol Buffers
&lt;/h2&gt;

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

&lt;p&gt;&lt;em&gt;Protocol Buffers&lt;/em&gt; are a mechanism for serializing structured data. They are used by gRPC as the default serialization mechanism.&lt;/p&gt;

&lt;p&gt;For more information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/protocol-buffers/docs/overview" rel="noopener noreferrer"&gt;Protocol Buffers&lt;/a&gt; - The official &lt;em&gt;Google&lt;/em&gt; developer guide&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grpc.io/docs/guides#working-with-protocol-buffers" rel="noopener noreferrer"&gt;Working with Protocol Buffers&lt;/a&gt; - Protocol buffers explained on gRPC website&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How?
&lt;/h3&gt;

&lt;p&gt;Because &lt;em&gt;Protocol Buffers&lt;/em&gt; are used for serializing structured data, you need to define the structure of the information that you want serialized. We do this by defining protocol buffer message types in a &lt;em&gt;'.proto'&lt;/em&gt; file.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;AddressType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;HOME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="na"&gt;POSTAL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="na"&gt;WORK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;line1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;line2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;suburb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;AddressType&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="na"&gt;addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Practice Time
&lt;/h4&gt;

&lt;h5&gt;
  
  
  1. Setup protoc compiler
&lt;/h5&gt;

&lt;p&gt;The most basic way to compile the &lt;em&gt;'meetings.proto'&lt;/em&gt; file from above is to use the &lt;em&gt;'protoc'&lt;/em&gt; compiler. The &lt;em&gt;protoc&lt;/em&gt; compiler is available for a number of different platforms. &lt;a href="https://github.com/protocolbuffers/protobuf/releases" rel="noopener noreferrer"&gt;See the protobuf release page&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If, like me, you're a developer on Debian/Ubuntu and/or Windows, you will find the following online resources useful to install the &lt;em&gt;protobuf compiler&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# For Windows using Chocolatey&lt;/span&gt;
&lt;span class="p"&gt;
  -&lt;/span&gt; Install Chocolatey (https://chocolatey.org/install)
&lt;span class="p"&gt;
  -&lt;/span&gt; Install protoc (https://chocolatey.org/packages/protoc) &lt;span class="sb"&gt;

    choco install protoc

&lt;/span&gt;&lt;span class="gh"&gt;# For Debian Stretch using apt&lt;/span&gt;
&lt;span class="p"&gt;
  -&lt;/span&gt; Install protoc (https://packages.debian.org/stretch/protobuf-compiler)&lt;span class="sb"&gt;

    sudo apt install protobuf-compiler

&lt;/span&gt;&lt;span class="gh"&gt;# For Ubuntu Bionic using apt&lt;/span&gt;
&lt;span class="p"&gt;
  -&lt;/span&gt; Install protoc (https://launchpad.net/ubuntu/bionic/+package/protobuf-compiler)&lt;span class="sb"&gt;

    sudo apt install protobuf-compiler
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  2. Create 'meetings.proto' file
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;examples&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;AddressType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;HOME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="na"&gt;POSTAL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="na"&gt;WORK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;line1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;line2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;suburb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;AddressType&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="na"&gt;addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Meeting&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="na"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3. Compile 'meetings.proto' file
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# For Python&lt;/span&gt;
protoc -I . --python_out=. ./meetings.proto

&lt;span class="gh"&gt;# For Node/Javascript&lt;/span&gt;
protoc -I . --js_out=. ./meetings.proto

&lt;span class="gh"&gt;# For C#&lt;/span&gt;
protoc -I . --csharp_out=. ./meetings.proto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is to use the generated code with your programming language of choice. See more tutorials here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/android" rel="noopener noreferrer"&gt;Android&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/csharp" rel="noopener noreferrer"&gt;C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/cpp" rel="noopener noreferrer"&gt;C++&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/dart" rel="noopener noreferrer"&gt;Dart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/go" rel="noopener noreferrer"&gt;Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/java" rel="noopener noreferrer"&gt;Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/node" rel="noopener noreferrer"&gt;Node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/objective-c" rel="noopener noreferrer"&gt;Objective-C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/php" rel="noopener noreferrer"&gt;PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/ruby" rel="noopener noreferrer"&gt;Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/tutorials/basic/web" rel="noopener noreferrer"&gt;Web&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  gRPC
&lt;/h2&gt;

&lt;p&gt;gRPC is a free open-source RPC (Remote Procedure Call) framework for building distributed services. According to &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Remote_procedure_call" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;&lt;/em&gt;, RPC can be summarized as follows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In distributed computing, a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in a different address space (commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction. That is, the programmer writes essentially the same code whether the subroutine is local to the executing program, or remote. This is a form of client–server interaction (caller is client, executor is server), typically implemented via a request–response message-passing system.&lt;/p&gt;

&lt;p&gt;-- Wikipedia&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;gRPC&lt;/em&gt; uses &lt;em&gt;Protocol Buffers&lt;/em&gt; for communications. Furthermore, &lt;em&gt;gRPC&lt;/em&gt; is summarized as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designed by Google&lt;/li&gt;
&lt;li&gt;Opensourced in 2015 and now a &lt;em&gt;&lt;a href="https://cncf.io/" rel="noopener noreferrer"&gt;Cloud Native Computing Foundation&lt;/a&gt;&lt;/em&gt; incubating project&lt;/li&gt;
&lt;li&gt;Ample language support

&lt;ul&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;GO&lt;/li&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Android Java&lt;/li&gt;
&lt;li&gt;Dart&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A client can execute a method on a server application (on a different machine) as if it was a local object&lt;/li&gt;

&lt;li&gt;A gRPC service is defined by an interface composed of services (methods with parameters and return types) and messages (properties or data with specified types)&lt;/li&gt;

&lt;li&gt;The interface is implemented by the server and runs as a service that accepts calls from remote clients&lt;/li&gt;

&lt;li&gt;The client uses a stub (exact representation of the interface used by the server) to make remote calls to the server&lt;/li&gt;

&lt;li&gt;Servers and clients are platform and language agnostic. This means that one can have a server implemented in Java, but the server can be used by clients that have been implemented in other languages/platforms like Python, Node, C# etc.&lt;/li&gt;

&lt;li&gt;Uses &lt;em&gt;&lt;a href="https://developers.google.com/protocol-buffers/docs/overview" rel="noopener noreferrer"&gt;Protocol Buffers&lt;/a&gt;&lt;/em&gt; by default. The protocol buffers can be used as both &lt;em&gt;Interface Definition Language&lt;/em&gt; and the underlying message interchange format.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Should You Care About gRPC?
&lt;/h3&gt;

&lt;p&gt;I'm going to share a very opinionated perspective (my opinion) on why you should learn about gRPC.&lt;/p&gt;

&lt;p&gt;1. I think that gRPC is a natural fit for building API's. Because gRPC can help make connecting, executing and debugging distributed systems as easy as making local function calls, it doesn't feel like you're doing anything different to your usual code flow. And it's this ease of use and simplicity that I think makes it feel more natural and easy to use.&lt;/p&gt;

&lt;p&gt;2. gRPC is renowned for it's efficiency (serialization), speed and low latency. Therefore I think it is well suited to building Microservices.&lt;/p&gt;

&lt;p&gt;3. For discussion purposes, I list 3 types of API's that are typically developed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal - This means that your API's are accessible from anywhere within a service boundary of your choosing. In other words, internal API's are meant for internal consumption on your private network only.&lt;/li&gt;
&lt;li&gt;Partner - Partner API's are sort of internal and sort of public. But they are intended as integration points between your applications and services with your Partners applications and services. Typically these API's would be locked down using techniques like VPN and/or IP whitelisting.&lt;/li&gt;
&lt;li&gt;Public - Anyone on the public internet can access the API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the 3 types of API's in mind, I think that initially gRPC is ideal for internal API's. As more companies and developers get hooked on gRPC, I think that the mass adoption will begin to drive the development of gRPC services for Partner and Public API's too.&lt;/p&gt;

&lt;p&gt;4. Having the skills to build gRPC services will serve you well into the future. I think that the popularity of gRPC will continue to grow. Below, I provide a google trend on gRPC for the past 5 years (gRPC was open-sourced in 2015). Note the steady upward trend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://trends.google.com/trends/explore?date=today%205-y&amp;amp;q=grpc" rel="noopener noreferrer"&gt;View gRPC trend here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F74095914-804fa880-4b5c-11ea-8edc-1ec98c9ed369.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F74095914-804fa880-4b5c-11ea-8edc-1ec98c9ed369.png" alt="grpc-trend"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;Most developers that work with REST or HTTP services are familiar with the excellent [Postman] tool. &lt;em&gt;Postman&lt;/em&gt; is the ideal client tool for interacting with HTTP services. Unfortunately, &lt;em&gt;Postman&lt;/em&gt; does not offer support for gRPC .... yet. Luckily for all of us, there is one gRPC client tool worth mentioning. And that tool is &lt;em&gt;&lt;a href="https://github.com/uw-labs/bloomrpc" rel="noopener noreferrer"&gt;bloomRPC&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  bloomRPC
&lt;/h3&gt;

&lt;p&gt;GUI Client for gRPC Services &lt;/p&gt;

&lt;p&gt;Features&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native gRPC calls&lt;/li&gt;
&lt;li&gt;Unary Calls and Server Side Streaming Support&lt;/li&gt;
&lt;li&gt;Client side and Bi-directional Streaming&lt;/li&gt;
&lt;li&gt;Automatic Input recognition&lt;/li&gt;
&lt;li&gt;Multi tabs operations&lt;/li&gt;
&lt;li&gt;Metadata support&lt;/li&gt;
&lt;li&gt;Persistent Workspace&lt;/li&gt;
&lt;li&gt;Request Cancellation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please checkout the &lt;em&gt;&lt;a href="https://github.com/uw-labs/bloomrpc" rel="noopener noreferrer"&gt;bloomRPC&lt;/a&gt;&lt;/em&gt; repository and while you're at it, please give them a star. It is well deserving :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F74096133-94e17000-4b5f-11ea-81ea-605698d25eb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F74096133-94e17000-4b5f-11ea-81ea-605698d25eb1.png" alt="grpc-bloomgrpc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dotnet.microsoft.com/download/dotnet-core/3.1" rel="noopener noreferrer"&gt;.NET Core 3.1 SDK&lt;/a&gt; - .NET Core is a cross-platform version of .NET, for building apps that run on Linux, macOS, and Windows&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; - Visual Studio Code is a source-code editor developed by Microsoft for Windows, Linux and macOS&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp" rel="noopener noreferrer"&gt;C# for Visual Studio Code&lt;/a&gt; - C# for Visual Studio Code (powered by OmniSharp)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/zxh0/vscode-proto3" rel="noopener noreferrer"&gt;vscode-proto3&lt;/a&gt; &amp;amp;&amp;amp; &lt;a href="https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3" rel="noopener noreferrer"&gt;vscode-proto3-ext&lt;/a&gt; - Protobuf 3 support for Visual Studio Code&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dotnet.microsoft.com/download/dotnet-core/3.1" rel="noopener noreferrer"&gt;.NET Core 3.1 SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp" rel="noopener noreferrer"&gt;C# for Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tested On
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ubuntu.com/download/desktop" rel="noopener noreferrer"&gt;Ubuntu 18.04&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-manual" rel="noopener noreferrer"&gt;Ubuntu 18.04 WSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Windows 10&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Messaging Example
&lt;/h3&gt;

&lt;p&gt;This example is a simple messaging application that demonstrates how to create a .NET Core &lt;em&gt;gRPC Client&lt;/em&gt; and &lt;em&gt;gRPC Server&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;By the end of this example, you will have a gRPC Client Console application written in C# that is able to send and receive messages to and from a gRPC Server Console application written in C#. The following concepts will be demonstrated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a gRPC Client (C# Console Application)&lt;/li&gt;
&lt;li&gt;Create a gRPC Server (C# Console Application)&lt;/li&gt;
&lt;li&gt;Send messages from gRPC Client to gRPC Server&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  1. Create Solution
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir grpc-messaging
cd grpc-messaging
dotnet new sln -n Messaging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Create 'messaging.proto' file
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# for linux&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;messaging.proto

&lt;span class="c"&gt;# for powershell&lt;/span&gt;
New-Item &lt;span class="nt"&gt;-Name&lt;/span&gt; messaging.proto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define 'messaging.proto' file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;csharp_namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Messaging"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;MessageRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;MessageResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;Messenger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MessageRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Create gRPC Server
&lt;/h4&gt;

&lt;h5&gt;
  
  
  3.1 Create the Server Console application
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new console &lt;span class="nt"&gt;-n&lt;/span&gt; Messaging.ServerApp
dotnet sln Messaging.sln add Messaging.ServerApp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3.2 Add packages required to create gRPC Server
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Messaging.ServerApp
dotnet add package gRPC
dotnet add package gRPC.Tools
dotnet add package Google.Protobuf

dotnet list package

Project &lt;span class="s1"&gt;'Messaging.ServerApp'&lt;/span&gt; has the following package references
   &lt;span class="o"&gt;[&lt;/span&gt;netcoreapp3.1]:
   Top-level Package      Requested   Resolved
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Google.Protobuf      3.11.3      3.11.3
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; gRPC                 2.27.0      2.27.0
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; gRPC.Tools           2.27.0      2.27.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3.3 Create a 'Services' folder
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;Services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3.4 Edit Messaging.ServerApp.csproj file
&lt;/h5&gt;

&lt;p&gt;We need to add the following &lt;em&gt;'ItemGroup'&lt;/em&gt; to &lt;em&gt;Messaging.ServerApp.csproj&lt;/em&gt; to enable the appropriate code generation for our gRPC server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Protobuf&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"../*.proto"&lt;/span&gt; &lt;span class="na"&gt;GrpcServices=&lt;/span&gt;&lt;span class="s"&gt;"Server"&lt;/span&gt; &lt;span class="na"&gt;OutputDir=&lt;/span&gt;&lt;span class="s"&gt;"%(RelativePath)Services"&lt;/span&gt; &lt;span class="na"&gt;CompileOutputs=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; Include="../&lt;span class="err"&gt;*&lt;/span&gt;.proto" - Include all '.proto' files for code generation
&lt;span class="p"&gt;-&lt;/span&gt; GrpcServices="Server" - Only generate code relevant to server
&lt;span class="p"&gt;-&lt;/span&gt; OutputDir="%(RelativePath)Services" - path for generated files
&lt;span class="p"&gt;-&lt;/span&gt; CompileOutputs="false" - prevents compiling generated files into assembly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting &lt;em&gt;Messaging.ServerApp.csproj&lt;/em&gt; file should look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.NET.Sdk"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netcoreapp3.1&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Protobuf&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"../*.proto"&lt;/span&gt; &lt;span class="na"&gt;GrpcServices=&lt;/span&gt;&lt;span class="s"&gt;"Server"&lt;/span&gt; &lt;span class="na"&gt;OutputDir=&lt;/span&gt;&lt;span class="s"&gt;"%(RelativePath)Services"&lt;/span&gt; &lt;span class="na"&gt;CompileOutputs=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"Google.Protobuf"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"3.11.3"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"gRPC"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"2.27.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"gRPC.Tools"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"2.27.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;IncludeAssets&amp;gt;&lt;/span&gt;runtime; build; native; contentfiles; analyzers; buildtransitive&lt;span class="nt"&gt;&amp;lt;/IncludeAssets&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PrivateAssets&amp;gt;&lt;/span&gt;all&lt;span class="nt"&gt;&amp;lt;/PrivateAssets&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/PackageReference&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3.5 Build Solution
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build from the root of solution&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
dotnet build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the build, you should see a solution structure as follows. Take note of the 2 generate files in the 'Services' folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Messaging.cs&lt;/li&gt;
&lt;li&gt;MessagingGrpc.cs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73978257-dcfe6800-4990-11ea-8706-4a428f9fb64f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73978257-dcfe6800-4990-11ea-8706-4a428f9fb64f.png" alt="grpc-server-solution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  3.6 Create 'MessengerService'
&lt;/h5&gt;

&lt;p&gt;Create a Service that implements the generated gRPC 'MessengerBase' code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Grpc.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Messaging.ServerApp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessengerService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Messenger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MessengerBase&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MessageRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ServerCallContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageResponse&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"This is your friendly gRPC Server. Received message: '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'"&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3.7 Update 'Program.cs' to run server
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Grpc.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Messaging.ServerApp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;50050&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;try&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Messenger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BindService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MessengerService&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="n"&gt;Ports&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ServerPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ServerCredentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insecure&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;

                &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Messenger server listening on port &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Press any key to stop the server..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Server failed to start: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;finally&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ShutdownAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3.8 Run the gRPC Server
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run &lt;span class="nt"&gt;-p&lt;/span&gt; Messaging.ServerApp

&lt;span class="c"&gt;# You should see the following response&lt;/span&gt;
Messenger server listening on port 50050
Press any key to stop the server...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Create gRPC Client
&lt;/h4&gt;

&lt;h5&gt;
  
  
  4.1 Create the Client Console application
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# From the root of solution&lt;/span&gt;

dotnet new console &lt;span class="nt"&gt;-n&lt;/span&gt; Messaging.ClientApp
dotnet sln Messaging.sln add Messaging.ClientApp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  4.2 Add packages required to create gRPC Client
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Messaging.ClientApp
dotnet add package gRPC
dotnet add package gRPC.Tools
dotnet add package Google.Protobuf

dotnet list package

Project &lt;span class="s1"&gt;'Messaging.ClientApp'&lt;/span&gt; has the following package references
   &lt;span class="o"&gt;[&lt;/span&gt;netcoreapp3.1]:
   Top-level Package      Requested   Resolved
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Google.Protobuf      3.11.3      3.11.3
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; gRPC                 2.27.0      2.27.0
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; gRPC.Tools           2.27.0      2.27.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  4.3 Create a 'Services' folder
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;Services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  4.4 Edit Messaging.ClientApp.csproj file
&lt;/h5&gt;

&lt;p&gt;We need to add the following &lt;em&gt;'ItemGroup'&lt;/em&gt; to &lt;em&gt;Messaging.ClientApp.csproj&lt;/em&gt; to enable the appropriate code generation for our gRPC Client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Protobuf&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"../*.proto"&lt;/span&gt; &lt;span class="na"&gt;GrpcServices=&lt;/span&gt;&lt;span class="s"&gt;"Client"&lt;/span&gt; &lt;span class="na"&gt;OutputDir=&lt;/span&gt;&lt;span class="s"&gt;"%(RelativePath)Services"&lt;/span&gt; &lt;span class="na"&gt;CompileOutputs=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; Include="../&lt;span class="err"&gt;*&lt;/span&gt;.proto" - Include all '.proto' files for code generation
&lt;span class="p"&gt;-&lt;/span&gt; GrpcServices="Client" - Only generate code relevant to Client
&lt;span class="p"&gt;-&lt;/span&gt; OutputDir="%(RelativePath)Services" - path for generated files
&lt;span class="p"&gt;-&lt;/span&gt; CompileOutputs="false" - prevents compiling generated files into assembly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting &lt;em&gt;Messaging.ClientApp.csproj&lt;/em&gt; file should look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.NET.Sdk"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netcoreapp3.1&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Protobuf&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"../*.proto"&lt;/span&gt; &lt;span class="na"&gt;GrpcServices=&lt;/span&gt;&lt;span class="s"&gt;"Client"&lt;/span&gt; &lt;span class="na"&gt;OutputDir=&lt;/span&gt;&lt;span class="s"&gt;"%(RelativePath)Services"&lt;/span&gt; &lt;span class="na"&gt;CompileOutputs=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"Google.Protobuf"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"3.11.3"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"gRPC"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"2.27.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"gRPC.Tools"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"2.27.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;IncludeAssets&amp;gt;&lt;/span&gt;runtime; build; native; contentfiles; analyzers; buildtransitive&lt;span class="nt"&gt;&amp;lt;/IncludeAssets&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PrivateAssets&amp;gt;&lt;/span&gt;all&lt;span class="nt"&gt;&amp;lt;/PrivateAssets&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/PackageReference&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  4.5 Build Solution
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build from the root of solution&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
dotnet build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the build, you should see a solution structure as follows. Take note of the 2 generate files in the 'Services' folder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Messaging.cs&lt;/li&gt;
&lt;li&gt;MessagingGrpc.cs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73985150-4dac8100-499f-11ea-8d14-e8a97e28301d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73985150-4dac8100-499f-11ea-8d14-e8a97e28301d.png" alt="grpc-client-solution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  4.6 Update 'Program.cs' to run Client
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Grpc.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Messaging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Messaging.ClientApp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Channel&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:50050"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ChannelCredentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insecure&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Messenger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MessengerClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;MessageRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"These are not the droids you are looking for ..."&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Message: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ShutdownAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Press any key to exit..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  4.7 Run the gRPC Client
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run &lt;span class="nt"&gt;-p&lt;/span&gt; Messaging.ClientApp

&lt;span class="c"&gt;# You should see the following response&lt;/span&gt;
Message: This is your friendly gRPC Server. Received message: &lt;span class="s1"&gt;'These are not the droids you are looking for ...'&lt;/span&gt;
Press any key to exit...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The full solution can be found &lt;a href="https://github.com/drminnaar/grpc-guide/tree/master/Examples/Messaging" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculator Example
&lt;/h3&gt;

&lt;p&gt;Now it's your turn. Create a gRPC Calculator service that provides the following arithmetic operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add&lt;/li&gt;
&lt;li&gt;Subtract&lt;/li&gt;
&lt;li&gt;Multiply&lt;/li&gt;
&lt;li&gt;Divide&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;The full solution can be found &lt;a href="https://github.com/drminnaar/grpc-guide/tree/master/Examples/Calculator" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Proto File
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;calculators&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;csharp_namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Calculators"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;OperationRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;operands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;OperationResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;DivisionRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;dividend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;divisor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;DivisionResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Subtract&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Multiply&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Divide&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DivisionRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DivisionResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  gRPC Calculator Server
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// ########################&lt;/span&gt;
&lt;span class="c1"&gt;/// CalculatorService&lt;/span&gt;
&lt;span class="c1"&gt;/// ########################&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Grpc.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Linq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Calculators.ServerApp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CalculatorService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalculatorBase&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OperationResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ServerCallContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;OperationResponse&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DivisionResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DivisionRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ServerCallContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DivisionResponse&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dividend&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Divisor&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OperationResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ServerCallContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;OperationResponse&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Aggregate&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;operand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OperationResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OperationRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ServerCallContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;OperationResponse&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Aggregate&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;operand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// ########################&lt;/span&gt;
&lt;span class="c1"&gt;/// Program&lt;/span&gt;
&lt;span class="c1"&gt;/// ########################&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Grpc.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Calculators.ServerApp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;50050&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;try&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BindService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CalculatorService&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="n"&gt;Ports&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ServerPort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ServerCredentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insecure&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;

                &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Calculator server listening on port &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Press any key to stop the server..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Server failed to start: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;finally&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ShutdownAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h5&gt;
  
  
  gRPC Calculator Client
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// ########################&lt;/span&gt;
&lt;span class="c1"&gt;/// Program&lt;/span&gt;
&lt;span class="c1"&gt;/// ########################&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Grpc.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Calculators.ClientApp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Channel&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:50050"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ChannelCredentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insecure&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CalculatorClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;operands&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;1D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5D&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;addRequest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OperationRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;addRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operands&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;subtractRequest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OperationRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;subtractRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operands&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;multiplicationRequest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OperationRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;multiplicationRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operands&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;divisionRequest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DivisionRequest&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Dividend&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Divisor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SubtractAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtractRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MultiplyAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplicationRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;division&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DivideAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;divisionRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Sum: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Difference: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Product: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Division: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;division&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ShutdownAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Press any key to exit..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where To From Here?
&lt;/h2&gt;

&lt;p&gt;I've only introduced the gRPC and Protocol Buffer fundamentals in this guide. I'd recommend doing some online digging for information relating to your platform/language of choice. For example, I only spoke about &lt;em&gt;Unary&lt;/em&gt; communication in this guide. Be sure to do some research on other alternatives like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server streaming&lt;/li&gt;
&lt;li&gt;Client streaming&lt;/li&gt;
&lt;li&gt;Bi-directional streaming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm looking forward to feedback from the community to see if there is any way that I can help developers learn more about gRPC. I will then most likely explore a number of follow-up topics for future posts.&lt;/p&gt;

&lt;p&gt;gRPC for the win 🏆&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>REST API Guide</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Sun, 02 Feb 2020 07:23:26 +0000</pubDate>
      <link>https://dev.to/drminnaar/rest-api-guide-14n2</link>
      <guid>https://dev.to/drminnaar/rest-api-guide-14n2</guid>
      <description>&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;This is a guide with the goal of laying down foundational knowledge that is required when speaking about building REST API's. The following topics are covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST Constraints&lt;/li&gt;
&lt;li&gt;Richardson Maturity Model&lt;/li&gt;
&lt;li&gt;REST in Practice (Some practical guidelines)&lt;/li&gt;
&lt;li&gt;Example project (Written in C# using .Net Core 3.1) called &lt;em&gt;&lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Ranker&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main points that I would like to summarize with regards to REST are listed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST &lt;strong&gt;IS&lt;/strong&gt; an architectural style used to describe web architecture&lt;/li&gt;
&lt;li&gt;REST &lt;strong&gt;IS&lt;/strong&gt; protocol agnostic&lt;/li&gt;
&lt;li&gt;REST &lt;strong&gt;IS&lt;/strong&gt; about web architecture (REST != API)&lt;/li&gt;
&lt;li&gt;REST &lt;strong&gt;IS NOT&lt;/strong&gt; a design pattern&lt;/li&gt;
&lt;li&gt;REST &lt;strong&gt;IS NOT&lt;/strong&gt; a standard. However standards can be used to implement REST.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. REST Fundamentals
&lt;/h2&gt;

&lt;p&gt;This sections covers REST essentials. The goal of this section is to make the reader comfortable with the notion of REST. It is also intended to provide the minimum required theory to start talking about REST and building HTTP services that incorporate a REST architectural style.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;REST (REpresentational State Transfer)&lt;/em&gt; is an architectural style that was defined by &lt;em&gt;&lt;a href="https://roy.gbiv.com/" rel="noopener noreferrer"&gt;Roy Thomas Fielding&lt;/a&gt;&lt;/em&gt; in his PhD dissertation &lt;em&gt;"&lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf" rel="noopener noreferrer"&gt;Architectural Styles and the Design of Network-based Software Architectures&lt;/a&gt;"&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;According to &lt;em&gt;Fielding&lt;/em&gt;,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The name “Representational State Transfer” is intended to evoke an image of how a well-designed Web application behaves: a network of web pages (a virtual state-machine), where the user progresses through the application by selecting links (state transitions), resulting in the next page (representing the next state of the application) being transferred to the user and rendered for their use.&lt;/p&gt;

&lt;p&gt;(Fielding, 2000) pg 109&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Why REST?
&lt;/h3&gt;

&lt;p&gt;If you're someone that builds HTTP services for distributed systems, then understanding and applying REST principles will help you build services that are more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scalable&lt;/li&gt;
&lt;li&gt;reliable&lt;/li&gt;
&lt;li&gt;flexible&lt;/li&gt;
&lt;li&gt;portable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By building services based on REST principles, one is effectively building services that are more web friendly. This is because REST is an architectural style that describes web architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  REST Architectural Constraints
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Fielding&lt;/em&gt; describes REST as a hybrid style that is derived from several network-based architectural styles (&lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/net_arch_styles.htm" rel="noopener noreferrer"&gt;Chapter 3&lt;/a&gt;) combined with a number of additional constraints. In this section, the six architectural constraints as applied to REST are discussed. The key takeaway is that these constraints encourage design that will result in applications that easily scale, are faster, and more reliable.&lt;/p&gt;

&lt;p&gt;The 6 architectural REST constraints are as follows:&lt;/p&gt;

&lt;p&gt;1. Client-Server&lt;/p&gt;

&lt;p&gt;A guiding principle of &lt;em&gt;&lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/net_arch_styles.htm#sec_3_4_1" rel="noopener noreferrer"&gt;Client-Server&lt;/a&gt;&lt;/em&gt; is the &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Separation_of_concerns" rel="noopener noreferrer"&gt;separation of concerns&lt;/a&gt;&lt;/em&gt;. It's all about achieving high cohesion and loose coupling in order to improve portability and flexibility. It also allows systems to evolve independently of each other. As can be seen by the diagram below, a &lt;em&gt;Client&lt;/em&gt; sends a request, and a &lt;em&gt;Server&lt;/em&gt; receives the request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72971024-ba673d80-3e2d-11ea-963b-389138d424d5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72971024-ba673d80-3e2d-11ea-963b-389138d424d5.png" alt="rest-client-server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2. Statelessness&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;Server&lt;/em&gt; must not store any state during communications. All information required to understand a request must be contained within the &lt;em&gt;Request&lt;/em&gt;. Therefore, every &lt;em&gt;Request&lt;/em&gt; should be able to execute on its own and be self-contained. Also, a &lt;em&gt;Client&lt;/em&gt; must maintain it's own state. The benefit of this approach is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visibility - Everything required to understand the &lt;em&gt;Request&lt;/em&gt; is within the &lt;em&gt;Request&lt;/em&gt;. This makes monitoring a request easier.&lt;/li&gt;
&lt;li&gt;Reliability - Recovering from failures is easier because the &lt;em&gt;Server&lt;/em&gt; does not need to track/rollback/commit state because all the state is essentially captured within the message. If a &lt;em&gt;Request&lt;/em&gt; fails, it can be as simple as resending the &lt;em&gt;Request&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Scalability - Because there is no need to manage state and resources between requests, and because all &lt;em&gt;Requests&lt;/em&gt; are isolated,scalability is improved and simplified.&lt;/li&gt;
&lt;li&gt;Aligned with web architecture (the internet is designed this way)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72973703-9bb77580-3e32-11ea-9f3d-beba73f1b324.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F72973703-9bb77580-3e32-11ea-9f3d-beba73f1b324.png" alt="rest-stateless"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A disadvantage of this approach is that it decreases network efficiency because the &lt;em&gt;Requests&lt;/em&gt; need to contain all the information required for that interaction. The more information, the larger the &lt;em&gt;Request&lt;/em&gt; size, and therefore the more bandwidth is used. This will have a negative effect on latency as well.&lt;/p&gt;

&lt;p&gt;3. Cache   &lt;/p&gt;

&lt;p&gt;The primary reason for the &lt;em&gt;Cache&lt;/em&gt; constraint is to improve network efficiency. As noted above in the &lt;em&gt;Stateless&lt;/em&gt; constraint, the size of &lt;em&gt;Requests&lt;/em&gt; can decrease network efficiency due to the need for more bandwidth. Through caching, it is possible to reduce and sometimes remove the need for a &lt;em&gt;Client&lt;/em&gt; to interact with the &lt;em&gt;Server&lt;/em&gt;. In other words it's possible to reduce and/or eliminate the need for &lt;em&gt;Requests&lt;/em&gt;. Therefore, the &lt;em&gt;Cache&lt;/em&gt; constraint states that a &lt;em&gt;Server&lt;/em&gt; must include additional data in the response to indicate to the client whether the &lt;em&gt;Request&lt;/em&gt; is cacheable and for how long. A network &lt;em&gt;Client&lt;/em&gt; can then decide the appropriate action based on provided cache information in &lt;em&gt;Response&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Caching can improve performance. However, it comes with a number of disadvantages that impact the reliability of the system. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Integrity - Response data could be inaccurate due to stale or expired data&lt;/li&gt;
&lt;li&gt;Complexity - The implementation and use of caching mechanisms is renowned for it's complexity in the &lt;em&gt;Computer Science&lt;/em&gt; world&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4. Uniform Interface&lt;/p&gt;

&lt;p&gt;At the core of this constraint is the &lt;em&gt;principle of generality&lt;/em&gt; which is closely related to the &lt;em&gt;principle of anticipation&lt;/em&gt;. It stems from the fact that it is impossible to build the exact required interface for all network clients of a server service. Therefore, by providing a generic interface, one is able to provide a simplified interface with higher visibility that is able to satisfy the requirements of more clients. A disadvantage of this approach is that because the interface is so general, one is not able to satisfy specific client requirements. In other words, providing a generic interface can lead to a sub-optimal interface for many clients.&lt;/p&gt;

&lt;p&gt;There are four additional constraints that form part of the &lt;em&gt;Uniform Interface&lt;/em&gt; and are listed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Identification of resources&lt;/p&gt;

&lt;p&gt;A key abstraction of REST is a resource. According to &lt;em&gt;Fielding&lt;/em&gt; (&lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_2b" rel="noopener noreferrer"&gt;Resources and Resource Identifiers&lt;/a&gt;), a resource is any information that can be named. Furthermore, I personally like to think of a resource as a &lt;em&gt;"Noun"&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Noun - a word (other than a pronoun) used to identify any of a class of people, places, or things ( common noun ), or to name a particular one of these ( proper noun ).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is also better to think of a single resource as a collection of resources. For example, if we were to provide an API to allow a &lt;em&gt;Client&lt;/em&gt; to submit or retrieve a "rating", one would typically identify the resource as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ratings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Generally, there should only be a single way to access a resource. But this is more a guideline than a rule.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Manipulation of resources through representations&lt;/p&gt;

&lt;p&gt;This constraint states that the client should hold the representation of a resource that has enough information to create, modify or delete a resource. It's important that the representation of a resource is decoupled from the way the resource is identified. A resource can be represented in multiple formats or representations such as JSON, XML, HTML, PNG etc. A client should be able to specify the desired representation of a resource for any interaction with the server. Therefore, a &lt;em&gt;Client&lt;/em&gt; can specify to receive a resource in &lt;em&gt;JSON&lt;/em&gt; format, but send the resource as input in &lt;em&gt;XML&lt;/em&gt; format.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;For the retrieval of an Employees resource, we use XML format&lt;br&gt;
 by specifying a "Accept: application/xml" header.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="no"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ratings&lt;/span&gt;
 &lt;span class="nl"&gt;Accept:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;

 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ratings&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;7337&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;98765&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;movieId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;movieId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;ratings&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;For the creation of an Employees resource, we use&lt;br&gt;
 JSON format by specifying a "Content-Type: application/json" header&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ratings&lt;/span&gt;
 &lt;span class="nx"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;98765&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;movieId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;score&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;     
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Should a specific format not be supported, it is important for the &lt;em&gt;Server&lt;/em&gt; to provide an appropriate response to indicate that a specific format is not supported. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return a &lt;strong&gt;406 Not Acceptable&lt;/strong&gt; status code to indicate that the client specified a request with an &lt;em&gt;Accept&lt;/em&gt; header format that the &lt;em&gt;Server&lt;/em&gt; is unable to fulfill. [See here for more information]&lt;/li&gt;
&lt;li&gt;Return a &lt;strong&gt;415 Unsupported Media Type&lt;/strong&gt; when a response is specified in an unsupported content type. [See here for more information]&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Self descriptive messages&lt;/p&gt;

&lt;p&gt;Self descriptive messages enable intermediary communication by allowing intermediary components to transform the content of the message. In other words, the semantics of the message are exposed to the intermediaries. The implication of this constraint is that interactions are stateless, standard methods and media types are used to expose the semantics of message, and responses indicate cacheability.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Hypermedia as the engine of application state (HATEOAS)&lt;/p&gt;

&lt;p&gt;A key concept about HATEOAS is that it implies that a &lt;em&gt;Response&lt;/em&gt; sent from a &lt;em&gt;Server&lt;/em&gt; should include information that informs the &lt;em&gt;Client&lt;/em&gt; on how to interact with the &lt;em&gt;Server&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73115137-2d37fc00-3f87-11ea-925c-9ca21ba1e41c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73115137-2d37fc00-3f87-11ea-925c-9ca21ba1e41c.png" alt="rest-hateoas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The advantages of &lt;em&gt;HATEOAS&lt;/em&gt; are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improves discoverability of resources through published set of links (provided with response)&lt;/li&gt;
&lt;li&gt;Indicates to &lt;em&gt;Clients&lt;/em&gt; what actions can be taken next. In other words, without &lt;em&gt;HATEOAS&lt;/em&gt;, a &lt;em&gt;Client&lt;/em&gt; only has access to the data but no idea about what actions may be taken with that data&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;5. Layered System&lt;/p&gt;

&lt;p&gt;The key principle of this constraint is that the &lt;em&gt;Client&lt;/em&gt; cannot make any assumptions that it is communicating directly with the &lt;em&gt;Server&lt;/em&gt;. This constraint relates to the &lt;em&gt;Client-Server&lt;/em&gt; constraint (discussed above) in such a way that &lt;em&gt;Client&lt;/em&gt; and &lt;em&gt;Server&lt;/em&gt; are decoupled. Therefore the &lt;em&gt;Client&lt;/em&gt; makes no assumptions about any kind of hidden dependencies and this enables us to insert components and entire sub-systems between the &lt;em&gt;Client&lt;/em&gt; and the &lt;em&gt;Server&lt;/em&gt;. This allows one to add load balancers, DNS, caching servers and security (authentication and authorization) between &lt;em&gt;Client&lt;/em&gt; and &lt;em&gt;Server&lt;/em&gt; without disrupting the interaction.&lt;/p&gt;

&lt;p&gt;Layering allows one to evolve and improve ones architecture to improve scalability and reliability ones system.&lt;/p&gt;

&lt;p&gt;6. Code On Demand&lt;/p&gt;

&lt;p&gt;This is an optional constraint. The key concept about this constraint is that when a &lt;em&gt;Client&lt;/em&gt; makes a request to a resource on a &lt;em&gt;Server&lt;/em&gt;, it will receive the resource as well as the code to execute against that resource. The &lt;em&gt;Client&lt;/em&gt; knows nothing about the composition of the code and only needs to know how to execute it. Javascript is an example of where this is done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Richardson Maturity Model
&lt;/h3&gt;

&lt;p&gt;The &lt;em&gt;&lt;a href="https://dev.toRMM"&gt;Richardson Maturity Model&lt;/a&gt;&lt;/em&gt; is a heuristic maturity model that can be used to better understand how mature a service is in terms of the REST architectural style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73115617-7a1ed100-3f8d-11ea-87ed-7591e3be8b13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73115617-7a1ed100-3f8d-11ea-87ed-7591e3be8b13.png" alt="rest-rmm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Services at this level are described as having a single URI, and using a single HTTP verb (usually POST). This is very characteristic of most Web Services (WS-*) in that this services would have a single URI accepting an HTTP POST request having an XML payload.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Services at this level are described as having many URIs with a single HTTP verb. The primary difference between Level 0 and Level 1 is that Level 1 services expose multiple logical resources as opposed to a single resource.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Services at this level are described as having many URI-addressable resources. Each addressable resource supports both multiple HTTP verbs and HTTP status codes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Services at this level are like &lt;em&gt;Level 2&lt;/em&gt; services that additionally support &lt;em&gt;Hypermedia As The Engine Of Application State (HATEOAS)&lt;/em&gt;. Therefore, representations of a resource will also contain links to other resources (the actions that can be performed relating to current resource).&lt;/p&gt;

&lt;p&gt;When thinking about the &lt;em&gt;RMM&lt;/em&gt; applies to your API, please refrain from thinking in terms of having a &lt;em&gt;Level 2&lt;/em&gt; or &lt;em&gt;Level 3&lt;/em&gt; REST API. According to this model, an API cannot be called a REST API unless it at least satisfies a Level 3 of the &lt;em&gt;RMM&lt;/em&gt;. Therefore, it would be better to think of ones API as an HTTP API that satisfies a &lt;em&gt;Level 1,2, or 3&lt;/em&gt; on the &lt;em&gt;RMM&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. REST in Practice
&lt;/h2&gt;

&lt;p&gt;I have developed a simple Http Api to demonstrate some of the concepts that I discussed in Part 1 of this guide.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Ranker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;A REST API guide with and example project written in C# using .Net Core 3.1 &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've also started another project that I plan to use to demonstrate various technology concepts like REST API's.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/chinook" rel="noopener noreferrer"&gt;Chinook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;A playground for demonstrating concepts such as architecture, design, dotnet core, typescript, react, database and docker &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Defining A Contract
&lt;/h3&gt;

&lt;p&gt;In this example, we are going to define contracts for 3 types of resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users&lt;/li&gt;
&lt;li&gt;Movies&lt;/li&gt;
&lt;li&gt;Ratings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are 5 important aspects to defining a contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming a resource&lt;/li&gt;
&lt;li&gt;Http methods used to interact with resource&lt;/li&gt;
&lt;li&gt;Status codes used to describe the state of an interaction&lt;/li&gt;
&lt;li&gt;Content Negotiation&lt;/li&gt;
&lt;li&gt;Be consistent&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2.1 Naming Guidelines
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Resources should have names that are represented by nouns and not actions (behaviors)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# Incorrect naming&lt;/span&gt;

  &lt;span class="s"&gt;/getUsers&lt;/span&gt;
  &lt;span class="s"&gt;/getUserById/{userId}&lt;/span&gt;

  &lt;span class="s"&gt;# Correct Naming&lt;/span&gt;

  &lt;span class="s"&gt;/users&lt;/span&gt;
  &lt;span class="s"&gt;/users/{userId}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Resources should be named using plural form
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# Incorrect naming&lt;/span&gt;

  &lt;span class="s"&gt;/user&lt;/span&gt;
  &lt;span class="s"&gt;/movie&lt;/span&gt;
  &lt;span class="s"&gt;/rating&lt;/span&gt;

  &lt;span class="s"&gt;# Correct naming&lt;/span&gt;

  &lt;span class="s"&gt;/users&lt;/span&gt;
  &lt;span class="s"&gt;/movies&lt;/span&gt;
  &lt;span class="s"&gt;/ratings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Mapping RPC style methods to resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The naming guidelines seem to suit naming resources very well. However, what happens when one needs to name something that is more a behavior than a resource? For example, let's say we want to compute the average rating for a movie. How would we structure our naming?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;/movies/{movieId}/averageRating&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't think there is 100% consensus on what the correct naming strategy is for a scenario such as this one. However, when faced with defining a contract for something that feels more about behavior than resources, I like to define contracts based on the outcomes of those behaviors. Therefore, for the example above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;/averageMovieRatings&lt;/span&gt;
  &lt;span class="s"&gt;/averageMovieRatings/{movieId}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if we try to define a contract for a calculator? This is clearly an example of where defining a contract around a behavior is very difficult and "unnatural" to REST. The reason why it feels unnatural is because REST is an architectural style for describing web architecture. So if you imagined every endpoint as a webpage, then clearly the behaviors for a calculator don't map very well. My suggestion is to use an alternative technology like gRPC if you are building API's that are more about behavior than resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Represent hierarchy
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="s"&gt;/users/{userId}&lt;/span&gt;
  &lt;span class="s"&gt;/users/{userId}/ratings&lt;/span&gt;
  &lt;span class="s"&gt;/users/{userId}/ratings/{ratingId}&lt;/span&gt;

  &lt;span class="s"&gt;/movies/{movieId}&lt;/span&gt;
  &lt;span class="s"&gt;/movies/{movieId}/ratings&lt;/span&gt;
  &lt;span class="s"&gt;/movies/{movieId}/ratings/{ratingId}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Filtering, searching and sorting are not part of naming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For filtering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# Incorrect&lt;/span&gt;
  &lt;span class="s"&gt;/users/firstName/{firstName}&lt;/span&gt;

  &lt;span class="s"&gt;# Correct&lt;/span&gt;
  &lt;span class="s"&gt;/users?firstName={firstName}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For searching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# Incorrect&lt;/span&gt;
  &lt;span class="s"&gt;/users/search/{query}&lt;/span&gt;

  &lt;span class="s"&gt;# Correct&lt;/span&gt;
  &lt;span class="s"&gt;/users?q={query}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For ordering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# Incorrect&lt;/span&gt;
  &lt;span class="s"&gt;/users/orderBy/{firstName}&lt;/span&gt;

  &lt;span class="s"&gt;# Correct&lt;/span&gt;
  &lt;span class="s"&gt;/users?order={firstName}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.2 Http Methods
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Http Method&lt;/th&gt;
&lt;th&gt;Request Body&lt;/th&gt;
&lt;th&gt;Uri&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;/users&lt;/td&gt;
&lt;td&gt;List of users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;/users/{userId}&lt;/td&gt;
&lt;td&gt;Single user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;Single user&lt;/td&gt;
&lt;td&gt;/users&lt;/td&gt;
&lt;td&gt;Single user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;Single user&lt;/td&gt;
&lt;td&gt;/users/{userId}&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;Json Patch Document for user&lt;/td&gt;
&lt;td&gt;/users/{userId}&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;/users/{userId}&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HEAD&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;/users&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HEAD&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;/users/{userId}&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OPTIONS&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;/users&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  2.3 Status Codes
&lt;/h4&gt;

&lt;p&gt;In this section, a list of commonly used status codes is provided. Status codes help convey meaning in client/server interactions. They also help achieve consistency in terms of defining a contract.&lt;/p&gt;

&lt;p&gt;Level 200 - Success&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="noopener noreferrer"&gt;200 Ok&lt;/a&gt; - Request succeeded&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200" rel="noopener noreferrer"&gt;201 Create&lt;/a&gt; - Request succeeded and resource created&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204" rel="noopener noreferrer"&gt;204 No Content&lt;/a&gt; - Request succeeded and there is no additional content to send in response body&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level 300 - Redirection Responses&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/301" rel="noopener noreferrer"&gt;301 Moved Permanently&lt;/a&gt; - The URL of requested resourced has changed permanently. The new URL is provided in response&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302" rel="noopener noreferrer"&gt;302 Found&lt;/a&gt; - Indicates that the URI of requested resource changed, and can therefore use the same URI for future requests&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304" rel="noopener noreferrer"&gt;304 Not Modified&lt;/a&gt; - Used for caching. Indicates that the resource has not changed and that the same cached version can be used&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level 400 - Client Mistake&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400" rel="noopener noreferrer"&gt;400 Bad Request&lt;/a&gt; - The request could not be understood by the server due to malformed syntax. The client should not repeat the request without modifications&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401" rel="noopener noreferrer"&gt;401 Unauthorized&lt;/a&gt; - Request failed due to authentication failure&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403" rel="noopener noreferrer"&gt;403 Forbidden&lt;/a&gt; - Request failed due to authorization failure&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404" rel="noopener noreferrer"&gt;404 Not Found&lt;/a&gt; - The requested resource could not be found&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405" rel="noopener noreferrer"&gt;405 Method Not Allowed&lt;/a&gt; - The request method is understood by server but not supported. In other words, the server doesn't have an endpoint supporting requested method.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406" rel="noopener noreferrer"&gt;406 Not Acceptable&lt;/a&gt; - When a request is specified in an unsupported content type using the Accept header&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/409" rel="noopener noreferrer"&gt;409 Conflict&lt;/a&gt; - Indicates a conflict in terms of requested resource state. For a POST, it could mean that a resource already exists. For a PUT, it could mean that the state of resource changed thereby making current request data stale.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/415" rel="noopener noreferrer"&gt;415 Unsupported Media Type&lt;/a&gt; - When a response is specified in an unsupported content type&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422" rel="noopener noreferrer"&gt;422 Unprocessable Entity&lt;/a&gt; - Indicates the the request was correct and understood by server, but the data contained within request is invalid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level 500 - Server Mistake&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422" rel="noopener noreferrer"&gt;500 Internal Server Error&lt;/a&gt; - Indicates that something went wrong on the server that prevent the server from fulfilling the request.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503" rel="noopener noreferrer"&gt;503 Service Unavailable&lt;/a&gt; - Indicates that the server is functional but not able to deliver requested resource. This is usually a result of a server being overloaded, server is under maintenance, or a client side issue relating to DNS server (DND server could be unavailable).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504" rel="noopener noreferrer"&gt;504 Gateway Timeout&lt;/a&gt; - Indicates that a proxy server did not receive a timely response from the origin (upstream) server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2.4 Content Negotiation
&lt;/h4&gt;

&lt;p&gt;Implies the type of representation (Media Type) that will be used for request and response. The &lt;em&gt;Media Type&lt;/em&gt; is specified in header of request. Two popular Media Type formats that are used with Http Api's are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;application/json&lt;/li&gt;
&lt;li&gt;application/xml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typically, I would support at least the two aforementioned formats. For any media type format that is not supported, the Api should return a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406" rel="noopener noreferrer"&gt;406 Not Acceptable&lt;/a&gt; status code.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Send POST request to create a a new user.&lt;/span&gt;
&lt;span class="c1"&gt;# The request will use 'application/json' as input, but XML in return (application/xml)&lt;/span&gt;

&lt;span class="s"&gt;POST /users&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/xml&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;firstName"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lastName"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TheBuilder"&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# The response is returned as XML&lt;/span&gt;

&lt;span class="s"&gt;&amp;lt;User&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;Id&amp;gt;112233&amp;lt;/Id&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;FirstName&amp;gt;Bob&amp;lt;/FirstName&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;LastName&amp;gt;TheBuilder&amp;lt;/LastName&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;&amp;lt;/User&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Example Project
&lt;/h2&gt;

&lt;p&gt;To illustrate some of the topics that have been discussed, I created an example project called &lt;em&gt;&lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Ranker&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Ranker&lt;/a&gt;&lt;/em&gt; is an API that has been designed by using REST as a guide. In terms of the &lt;a href="https://www.crummy.com/writing/speaking/2008-QCon/act3.html" rel="noopener noreferrer"&gt;Richardson Maturity Model&lt;/a&gt;, I have implemented all endpoints to be at least a &lt;em&gt;Level 2&lt;/em&gt;. However, I have implemented some endpoints to a &lt;em&gt;Level 3&lt;/em&gt; (with HATEOAS). Conceptually, &lt;em&gt;&lt;a href="https://github.com/drminnaar/ranker" rel="noopener noreferrer"&gt;Ranker&lt;/a&gt;&lt;/em&gt; provides the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interface to manage &lt;em&gt;Users&lt;/em&gt; (with HATEOAS)&lt;/li&gt;
&lt;li&gt;Interface to manage &lt;em&gt;Movies&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Interface to manage &lt;em&gt;Ratings&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the following sections I provide more detail about the project and how to get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;p&gt;Although the focus of this example project is to illustrate an implementation of REST, I decided to provide a basic architecture to also illustrate a good separation of concerns so that the Api layer (Controllers) are kept very clean.&lt;/p&gt;

&lt;p&gt;I've chosen a architecture based on the &lt;a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/" rel="noopener noreferrer"&gt;Onion Architecture&lt;/a&gt;. Below, I provide 2 different views of what equates to exactly the same architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layered Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73599890-05135300-45ae-11ea-8f0f-2b684763235b.png" class="article-body-image-wrapper"&gt;&lt;img alt="Layered Architecture" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73599890-05135300-45ae-11ea-8f0f-2b684763235b.png"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Onion Architecture&lt;/strong&gt;&lt;/p&gt;


&lt;p&gt;&lt;br&gt;&lt;br&gt;
    &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73599926-7ce17d80-45ae-11ea-80f7-93181e65c86e.png" class="article-body-image-wrapper"&gt;&lt;img alt="Onion Architecture" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73599926-7ce17d80-45ae-11ea-80f7-93181e65c86e.png"&gt;&lt;/a&gt;&lt;br&gt;
  &lt;/p&gt;

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

&lt;p&gt;Primary Responsibility: Provides a distributed interface that gives access to application features&lt;/p&gt;

&lt;p&gt;This API has been implemented as a number of HTTP services based on REST guidelines. The API itself is based on an MVC (Model, View, and Controllers) architecture. The &lt;em&gt;Controllers&lt;/em&gt; are essentially the public facing API contract.&lt;/p&gt;

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

&lt;p&gt;Primary Responsibility: Provide the core of the system an interface to the "world".&lt;/p&gt;

&lt;p&gt;This layer is all about defining and configuring external dependencies such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;database access&lt;/li&gt;
&lt;li&gt;proxies to other API's&lt;/li&gt;
&lt;li&gt;logging&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;dependency injection&lt;/p&gt;

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

&lt;p&gt;Primary Responsibility: Application logic.&lt;/p&gt;

&lt;p&gt;This layer is typically where you would find "Application "Services".  &lt;/p&gt;

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

&lt;p&gt;Primary Responsibility: Enterprise domain logic.&lt;/p&gt;

&lt;p&gt;All domain logic relating to domain models and domain services are handled in this layer.&lt;/p&gt;
&lt;h3&gt;
  
  
  API Contract
&lt;/h3&gt;

&lt;p&gt;The API has been implemented with the Open Api Specification (OAS). Once you have the API up and running, you can browse to the following Url to get access to the OAS Swagger Document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Swagger document will look something like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73600055-1e1d0380-45b0-11ea-8e0c-43bf714f10e5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73600055-1e1d0380-45b0-11ea-8e0c-43bf714f10e5.png" alt="movies-oas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73600054-1e1d0380-45b0-11ea-8f7d-bde636b3b7f9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73600054-1e1d0380-45b0-11ea-8f7d-bde636b3b7f9.png" alt="ratings-oas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73600053-1d846d00-45b0-11ea-8986-472394f0d23c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73600053-1d846d00-45b0-11ea-8986-472394f0d23c.png" alt="users-oas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pagination
&lt;/h3&gt;

&lt;p&gt;For this project, any endpoint returning a collection of items has been implemented with paging. Use the following query parameters to control paging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page - the page number&lt;/li&gt;
&lt;li&gt;limit - the number of items per page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pagination has been implemented in two ways for this example project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pagination in Header
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/movies?page=2&amp;amp;limit=5&lt;/span&gt;

  &lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Pagination&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CurrentPageNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ItemCount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9742&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PageSize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PageCount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1949&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FirstPageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/movies?page=1&amp;amp;limit=5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LastPageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/movies?page=1949&amp;amp;limit=5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NextPageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/movies?page=3&amp;amp;limit=5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PreviousPageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/movies?page=1&amp;amp;limit=5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CurrentPageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/movies?page=2&amp;amp;limit=5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pagination as links (HATEOAS)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users?page=1&amp;amp;limit=1&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;links&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?page=1&amp;amp;limit=1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;current-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?page=2&amp;amp;limit=1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;previous-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?page=1&amp;amp;limit=1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?page=610&amp;amp;limit=1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filtering
&lt;/h3&gt;

&lt;p&gt;Where practical, I've tried to provide a filter per resource property. I've implemented filtering using 3 techniques:&lt;/p&gt;

&lt;p&gt;1. Basic&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// filter users by last name and age&lt;/span&gt;

   &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users?last-name=doe&amp;amp;gender=male&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. Range&lt;/p&gt;

&lt;p&gt;For numeric resource (and date) properties, I've implemented range filters as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// Possible input for age could be:&lt;/span&gt;
   &lt;span class="c1"&gt;// age=gt:30&lt;/span&gt;
   &lt;span class="c1"&gt;// age=gte:30&lt;/span&gt;
   &lt;span class="c1"&gt;// age=eq:30&lt;/span&gt;
   &lt;span class="c1"&gt;// age=lt:30&lt;/span&gt;
   &lt;span class="c1"&gt;// age=lte:30&lt;/span&gt;

   &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users?age=gte:30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Multiple (comma separated values)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// get a list of movies for the genres animation and sci-fi&lt;/span&gt;

   &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/movies?genres=animation,sci-fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ordering
&lt;/h3&gt;

&lt;p&gt;I've chosen to keep &lt;em&gt;ordering&lt;/em&gt; parameters very succinct. Therefore, ordering for a collection of resources may be executed in the following ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Order by a single resource property in ascending order
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// order by last name ascending&lt;/span&gt;

  &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users?order=last-name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Order by a single resource property in descending order
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// order by age descending&lt;/span&gt;

  &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users?order=-age&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Order by multiple resource properties using mixed sort orders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that we use comma separated values for the order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// order by last-name ascending then by age descending&lt;/span&gt;

  &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users?order=last-name,-age&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Caching
&lt;/h3&gt;

&lt;p&gt;I have implemented some basic client side caching behavior.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;The following endpoints use response caching where the cache expires after 10 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users&lt;/span&gt;

&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/movies&lt;/span&gt;
&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/movies/{movieId}&lt;/span&gt;

&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/ratings&lt;/span&gt;
&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/ratings/{ratingId}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following endpoint uses caching with an ETag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users/{userId}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HATEOAS
&lt;/h3&gt;

&lt;p&gt;The following endpoints have been implemented to return links as part of response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get links available from root&lt;/span&gt;

&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/movies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;movies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/movies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create-movie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create-rating&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get as single user, including a list of navigational links&lt;/span&gt;

&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Durham&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Franks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gender&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;durhamfranks@kog.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;links&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;delete-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?Page=1&amp;amp;Limit=10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPTIONS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PATCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;patch-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/10/ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for a collection of users (with links), we can use the request below. Please take note of the paging information that is returned as part of response&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get list of users (with links), and paging links&lt;/span&gt;

&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/v1/users&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Michele&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jacobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gender&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;michelejacobs@kineticut.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;links&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/23&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;delete-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/23&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?Page=1&amp;amp;Limit=10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPTIONS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/23&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PATCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;patch-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/23&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/23/ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Barnett&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Griffith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gender&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;barnettgriffith@corpulse.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;links&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/33&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;delete-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/33&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?Page=1&amp;amp;Limit=10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPTIONS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/33&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PATCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;patch-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/33&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users/33/ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ratings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;links&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?order=-age&amp;amp;page=1&amp;amp;limit=2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;current-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?order=-age&amp;amp;page=2&amp;amp;limit=2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;previous-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?order=-age&amp;amp;page=1&amp;amp;limit=2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/v1/users?order=-age&amp;amp;page=305&amp;amp;limit=2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Technology Used
&lt;/h2&gt;

&lt;h3&gt;
  
  
  OS
&lt;/h3&gt;

&lt;p&gt;I have developed and tested &lt;em&gt;Ranker&lt;/em&gt; on the following Operating Systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ubuntu.com/download/desktop" rel="noopener noreferrer"&gt;Ubuntu 18.04 LTS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ubuntu is an open source software operating system that runs from the desktop, to the cloud, to all your internet connected things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows 10 Professional&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to developing &lt;em&gt;Ranker&lt;/em&gt; on Windows 10, I have also tried and tested &lt;em&gt;Ranker&lt;/em&gt; using &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/about" rel="noopener noreferrer"&gt;Windows Subsystem For Linux&lt;/a&gt;. Specifically, I have used [WSL-Ubuntu]. See more about &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/about" rel="noopener noreferrer"&gt;WSL&lt;/a&gt; below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/wsl/about" rel="noopener noreferrer"&gt;Windows Subsystem For Linux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Windows Subsystem for Linux lets developers run a GNU/Linux environment -- including most command-line tools, utilities, and applications -- directly on Windows, unmodified, without the overhead of a virtual machine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/wsl/wsl2-install" rel="noopener noreferrer"&gt;Windows Subsystem For Linux 2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NOTE: I have not tested &lt;em&gt;Ranker&lt;/em&gt; on &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/wsl2-install" rel="noopener noreferrer"&gt;WSL2&lt;/a&gt; yet. I mention it here because I want to be clear that I've only tested on &lt;a href="https://dev.tonot%20to%20be%20confused%20with%20WSL2"&gt;WSL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WSL 2 is a new version of the architecture in WSL that changes how Linux distros interact with Windows. WSL 2 has the primary goals of increasing file system performance and adding full system call compatibility. Each Linux distro can run as a WSL 1, or a WSL 2 distro and can be switched between at any time. WSL 2 is a major overhaul of the underlying architecture and uses virtualization technology and a Linux kernel to enable its new features.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://visualstudio.microsoft.com/vs/community/" rel="noopener noreferrer"&gt;Visual Studio Community Edition&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A fully-featured, extensible, &lt;strong&gt;FREE&lt;/strong&gt; IDE for creating modern applications for Android, iOS, Windows, as well as web applications and cloud services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Kept things simple and only used an in-memory database&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Getting Started
&lt;/h2&gt;

&lt;p&gt;Before getting started, the following frameworks must be installed on your machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dotnet Core 3.1&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Get The Code
&lt;/h3&gt;

&lt;p&gt;Clone 'ranker' repository from GitHub&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# using https&lt;/span&gt;
git clone https://github.com/drminnaar/ranker.git

&lt;span class="c"&gt;# or using ssh&lt;/span&gt;
git clone git@github.com:drminnaar/ranker.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build The Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# change to project root&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ./ranker

&lt;span class="c"&gt;# build solution&lt;/span&gt;
dotnet build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running the API
&lt;/h3&gt;

&lt;p&gt;Run the API from the command line as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# change to project root&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ./ranker/Ranker.Api

&lt;span class="c"&gt;# To run 'Ranker Api' (http://localhost:5000)&lt;/span&gt;
dotnet watch run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Open Postman Collection
&lt;/h3&gt;

&lt;p&gt;I have provided a postman collection for the &lt;em&gt;Ranker&lt;/em&gt; API. Please find the Postman collection _'Ranker.postman_collection'_at the root of the solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73604546-5dbb0e00-45f7-11ea-9d3e-dcb8151bca82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F73604546-5dbb0e00-45f7-11ea-9d3e-dcb8151bca82.png" alt="ranker-postman-collection"&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>NoteWorx - Project 6</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Mon, 17 Sep 2018 07:31:39 +0000</pubDate>
      <link>https://dev.to/drminnaar/noteworx---project-6-58ei</link>
      <guid>https://dev.to/drminnaar/noteworx---project-6-58ei</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Over the past few months, I have been building a simple note taking application in 6 different ways. The goal of the project was to build something simple, but build it in different ways, and using different technologies. Up until now, the first 5 NoteWorx projects were all built using Javascript and Javascript frameworks with a MongoDB database. For the sixth NoteWorx project, I decided to use the cross-platform dotnetcore framework, C#, and a PostgreSQL database.&lt;/p&gt;

&lt;p&gt;This project is a reference project and will illustrate the following concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build end-to-end asp.net core web application using C#, ASP.NET Core Identity, and Entity Framework Core.&lt;/li&gt;
&lt;li&gt;Create a Cake build script to manage project build.&lt;/li&gt;
&lt;li&gt;Use Docker and Docker-Compose to manage containers used to host web application and postgres database.&lt;/li&gt;
&lt;li&gt;How to use NPM and Gulp to manage client side assets (css, javascript, etc).&lt;/li&gt;
&lt;li&gt;Use PostgreSQL as a database for all note and identity data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source code for NoteWorx (Project 6) can be found &lt;a href="https://github.com/drminnaar/noteworx-aspnetcore"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The previous NoteWorx projects are listed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-cli-fs"&gt;noteworx-cli-fs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic note application that uses a CLI (Command Line Interface) frontend to capture and manage notes, and a file system to store notes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-cli-mongodb"&gt;noteworx-cli-mongodb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic note application that uses a CLI (Command Line Interface) frontend to capture and manage notes, and mongodb to store notes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-cli-mongoose"&gt;noteworx-cli-mongoose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic note application that uses a CLI (Command Line Interface) frontend to capture and manage notes, Mongoose ODM to manage MongoDB interaction, and mongodb to store notes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-cli-couchbase"&gt;noteworx-cli-couchbase&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic note application that uses a CLI (Command Line Interface) frontend to capture and manage notes, and couchbase as a data store.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-cli-express-mongodb"&gt;noteworx-cli-express-mongodb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic note application that uses a CLI (Command Line Interface) frontend to capture and manage notes, an express note management API built using Express, and Mongodb to store notes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-expressui-mongodb"&gt;noteworx-expressui-mongodb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic note application that uses an Express frontend to capture and manage notes, and mongodb to store notes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/drminnaar/noteworx-react-mongodb"&gt;noteworx-react-mongodb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic note application that uses React frontend to capture and manage notes, an api written in ExpressJS, and mongodb to store notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is NoteWorx?
&lt;/h2&gt;

&lt;p&gt;NoteWorx is a basic note management web application. This version of NoteWorx (Project 6), has been built using the latest &lt;a href="https://www.asp.net/"&gt;ASP.NET Core 2.1&lt;/a&gt;, &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity"&gt;ASP.NET Core Identity&lt;/a&gt;, &lt;a href="https://docs.microsoft.com/en-us/ef/core/"&gt;Entity Framework Core&lt;/a&gt;, and &lt;a href="https://www.postgresql.org/"&gt;Postgresql&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;NoteWorx provides the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a note&lt;/li&gt;
&lt;li&gt;Edit a note&lt;/li&gt;
&lt;li&gt;Remove a note&lt;/li&gt;
&lt;li&gt;List all notes&lt;/li&gt;
&lt;li&gt;Find note by title or description&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Developed With
&lt;/h2&gt;

&lt;p&gt;The goal of this version of NoteWorx is to illustrate how one can build an end-to-end dotnetcore application entirely on a Linux OS. Therefore, the entire application was built using &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt; on &lt;a href="https://www.ubuntu.com/"&gt;Ubuntu 18.04&lt;/a&gt;. The following list is a summary of the primary tools, languages and frameworks used to build the application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.microsoft.com/net/download"&gt;.NET Core&lt;/a&gt; - .NET Core is a free and open-source managed software framework for Linux, Windows and macOS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/"&gt;C#&lt;/a&gt; - A multi-paradigm programming language encompassing strong typing, imperative, declarative, functional, generic, object-oriented (class-based), and component-oriented programming disciplines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.asp.net/"&gt;ASP.NET Core&lt;/a&gt; - ASP.NET Core is a free, cross-platform, and open-source web framework&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity"&gt;ASP.NET Core Identity&lt;/a&gt; - ASP.NET Core Identity is a membership system that adds login functionality to ASP.NET Core apps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/ef/core/"&gt;Entity Framework Core&lt;/a&gt; - EF Core is an object-relational mapper (O/RM) that enables .NET developers to work with a database using .NET objects. It eliminates the need for most of the data-access code that developers usually need to write.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.postgresql.org/"&gt;Postgresql&lt;/a&gt; - Is an object-relational database management system with an emphasis on extensibility and standards compliance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.docker.com"&gt;Docker&lt;/a&gt; - Used to host Postgresql database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/compose/"&gt;Docker-Compose&lt;/a&gt; - Compose is a tool for defining and running multi-container Docker applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://cakebuild.net/"&gt;Cake&lt;/a&gt; - Cake (C# Make) is a cross-platform build automation system with a C# DSL for tasks such as compiling code, copying files and folders, running unit tests, compressing files and building NuGet packages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://getbootstrap.com"&gt;Bootstrap 4&lt;/a&gt; - Build responsive, mobile-first projects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gulpjs.com/"&gt;Gulp&lt;/a&gt; - Gulp is a toolkit for automating painful or time-consuming tasks in your development workflow, so you can stop messing around and build something.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Notable Nuget Packages
&lt;/h3&gt;

&lt;p&gt;In addition to the aforementioned tools I want to make a special mention of 2 Nuget packages that I found very useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/OdeToCode/UseNodeModules"&gt;OdeToCode.UseNodeModules&lt;/a&gt; - ASP.NET Core middleware to serve files from the node_modules directory in the root of the project. This package enabled me to reference the &lt;em&gt;'node_modules'&lt;/em&gt; folder from within my Razor views. This is great for development. I have &lt;em&gt;'Gulp'&lt;/em&gt; tasks that copy the required packages from the &lt;em&gt;'node_modules'&lt;/em&gt; folder into the &lt;em&gt;'wwwroot'&lt;/em&gt; folder for production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/Humanizr/Humanizer"&gt;Humanizer.Core&lt;/a&gt; - Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities. This package enabled me to display date and times in a more "human friendly" manner. For example instead of display a date from 1 week ago in a date format, Humanizer takes the date and returns "1 Week ago" instead. Humanizer can be used for a whole lot more.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.&lt;/p&gt;

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

&lt;p&gt;The following software is required to be installed on your system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dotnet Core&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Version 2.1.402 is required.&lt;/p&gt;

&lt;p&gt;Run the following command from the terminal to verify version of dotnet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  dotnet &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The following version of Node and Npm are required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node 8.x&lt;/li&gt;
&lt;li&gt;Npm 3.x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Type the following commands in the terminal to verify your node and npm versions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  node &lt;span class="nt"&gt;-v&lt;/span&gt;
  npm &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Version 18.06 is required.&lt;/p&gt;

&lt;p&gt;Run the following command from the terminal to verify version of Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;

&lt;p&gt;Follow the following steps to get development environment running.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone 'noteworx-aspnetcore' repository from GitHub
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/drminnaar/noteworx-aspnetcore.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;or using ssh&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone git@github.com:drminnaar/noteworx-aspnetcore.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install node modules
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;cd &lt;/span&gt;noteworx-aspnetcore/src/NoteWorx.Web
   npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build
&lt;/h3&gt;

&lt;p&gt;There are 2 build options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build using dotnet CLI tool
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;noteworx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;aspnetcore&lt;/span&gt;
  &lt;span class="nx"&gt;dotnet&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Build using Cake build script
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;linux&lt;/span&gt; &lt;span class="nx"&gt;terminal&lt;/span&gt;
  &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;noteworx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;aspnetcore&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In both cases, &lt;em&gt;Gulp&lt;/em&gt; processes the &lt;em&gt;"gulpfile.js"&lt;/em&gt; file. The gulp process prepares client assets to be included in wwwroot folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run
&lt;/h3&gt;

&lt;p&gt;The NoteWorx application is configured to seed it's database with test data. Therefore, to sign into the NoteWorx application, one can use any of the users that are specified in the &lt;em&gt;'/NoteWorx.Web/Infrastructure/SeedFiles/users.json'&lt;/em&gt; file. The password for all users is &lt;em&gt;'P@ssword123!'&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Run NoteWorx Demo In Container Using Docker
&lt;/h4&gt;

&lt;p&gt;If you would like to simply see the application running in demo mode, type the following command in the terminal at the root of the solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;noteworx-aspnetcore
docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; ./docker-compose-demo.yml build
docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; ./docker-compose-demo.yml up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will build required image based on Dockerfile, setup a postgres database in a container, and setup pgAdmin (postges db tool) in a container.&lt;/p&gt;

&lt;p&gt;To view the demo, type the following in your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# To view the NoteWorx demo application&lt;/span&gt;
http://localhost:8080

&lt;span class="c"&gt;# To open the database admin tool (pgAdmin)&lt;/span&gt;
http://localhost:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're done running the demo, type the following command to stop and cleanup containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; ./docker-compose-demo.yml down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Run NoteWorx From Source
&lt;/h4&gt;

&lt;p&gt;Before running NoteWorx from source, you need to have a running Postgres database instance. For that you can type the following command to start a Postgres container and a pgAdmin container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;noteworx-aspnetcore
docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; ./docker-compose-data.yml &lt;span class="nt"&gt;-up&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, type the following to verify that the Postgres database has started in a container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# You should see a container having the name 'db-dev' by typing the following&lt;/span&gt;
docker container &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to ensure you have the correct IP Address configured in the connection-string setting of the &lt;em&gt;'appsettings.Development.json'&lt;/em&gt; file. Therefore, type the following command to determine the IP Address of postgres container (db-dev).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# use the following putput IP address in connection string&lt;/span&gt;
docker container inspect | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; IPAddress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, run the NoteWorx web applicatio&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;noteworx-aspnetcore/src/NoteWorx.Web
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the application starts, open the web browser and type the following address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;http://localhost:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're done running the application, type the following command to stop and cleanup containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; ./docker-compose-data.yml down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Other
&lt;/h2&gt;

&lt;p&gt;The online JSON data generator &lt;a href="https://www.json-generator.com/"&gt;www.json-generator.com&lt;/a&gt; was used to generate all data used to seed the NoteWorx application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Templates
&lt;/h3&gt;

&lt;p&gt;The following templates were used to generate data.&lt;/p&gt;

&lt;h4&gt;
  
  
  User Template
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{repeat(10)}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://placehold.it/32x32&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{integer(20, 40)}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{firstName()}} {{surname()}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{gender()}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;company&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{company().toUpperCase()}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{email()}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+1 {{phone()}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{integer(100, 999)}} {{street()}}, {{city()}}, {{state()}}, {{integer(100, 10000)}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;about&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{lorem(1, "paragraphs")}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Tag Template
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{repeat(100)}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{lorem(1, "words")}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Note Template
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{repeat(50)}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{lorem(random(3,4,5), "words")}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{lorem(1, "paragraph")}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{date(new Date(2018, 0, 1), new Date(), "ISODateTimeTZ")}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;modifiedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;createdDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;modifiedDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createdDate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;modifiedDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createdDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;modifiedDate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Next I will be building NoteWorx using an Angular frontend that connects to an ASP.NET Core API using JWT tokens.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Flyway - Getting Started</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Mon, 04 Jun 2018 20:30:51 +0000</pubDate>
      <link>https://dev.to/drminnaar/flyway---getting-started-3emm</link>
      <guid>https://dev.to/drminnaar/flyway---getting-started-3emm</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This guide is inspired by an article that I read a few years ago that describes the concept of evolutionary database design. The article can be found &lt;a href="https://www.martinfowler.com/articles/evodb.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. In the article, reference was made to a number of database migration tools. &lt;a href="https://flywaydb.org" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt; was one of the tools mentioned. As it turns out, it is &lt;em&gt;Flyway&lt;/em&gt; that I adopted in the end. Why &lt;em&gt;Flyway&lt;/em&gt;? Because it is powerful yet easy to learn and use.&lt;/p&gt;

&lt;p&gt;In this guide, I am going to explain how to use &lt;em&gt;Flyway&lt;/em&gt; by providing a working example using tools such as &lt;em&gt;Docker&lt;/em&gt;, &lt;em&gt;Docker-Compose&lt;/em&gt;, &lt;em&gt;PostgreSQL&lt;/em&gt;, &lt;em&gt;pgAdmin&lt;/em&gt;, and of course &lt;em&gt;Flyway&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://flywaydb.org/documentation/" rel="noopener noreferrer"&gt;official Flyway documentation&lt;/a&gt;, Flyway is an open-source database migration tool that strongly favors simplicity and convention over configuration.&lt;/p&gt;

&lt;p&gt;The key concept in the above definition is &lt;em&gt;"database migration"&lt;/em&gt;. Within the context of discussing &lt;em&gt;Flyway&lt;/em&gt;, a &lt;em&gt;"database migration"&lt;/em&gt; is a group of one or more database changes. In order to keep track of migrations, &lt;em&gt;Flyway&lt;/em&gt; creates a table (per schema) that maintains a history of all migrations for a specific schema.&lt;/p&gt;

&lt;p&gt;Flyway supports 2 forms of migration namely &lt;strong&gt;&lt;em&gt;versioned&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;repeatable&lt;/em&gt;&lt;/strong&gt; migrations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Versioned&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has a version number, checksum, and description. The version number ensures that migrations are unique. The checksum helps prevent accidental changes from being migrated. The description provides metadata about the migration.&lt;/li&gt;
&lt;li&gt;Versioned migrations are applied in order and only once&lt;/li&gt;
&lt;li&gt;An &lt;em&gt;"undo migration"&lt;/em&gt; having the same version number can be provided&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;em&gt;Repeatable&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has a description and checksum but a version number is not required.&lt;/li&gt;
&lt;li&gt;Repeatable migrations can be re-applied everytime their checksum changes.&lt;/li&gt;
&lt;li&gt;Always applied after &lt;em&gt;versioned&lt;/em&gt; migrations.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Migrations can be written in Java and SQL. However, in this guide I will be focusing on the SQL migrations. SQL migrations offer the most flexibility due to them being agnostic of any particular development platform. I will also be focusing on &lt;em&gt;versioned&lt;/em&gt; migrations.&lt;/p&gt;

&lt;p&gt;In this &lt;em&gt;getting started&lt;/em&gt; guide, the simplest scenario is to begin with a new database. This guide uses &lt;em&gt;Postgres&lt;/em&gt; to illustrate migrations. To make it simpler to view the changes in the database, &lt;em&gt;pgAdmin4&lt;/em&gt; will be used to connect to and inspect database changes. All migrations that will be created in this guide are available &lt;a href="https://github.com/drminnaar/flyway" rel="noopener noreferrer"&gt;in this repo&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technology Used
&lt;/h2&gt;

&lt;p&gt;The technology used to produce this guide is summarised as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker is a computer program that performs operating-system-level virtualization also known as containerization. It is developed by Docker, Inc.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/overview/" rel="noopener noreferrer"&gt;Docker-Compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compose is a tool for defining and running multi-container Docker applications.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PostgreSQL is an object-relational database management system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pgadmin.org/" rel="noopener noreferrer"&gt;pgAdmin4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open Source administration and development platform for PostgreSQL&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://flywaydb.org/" rel="noopener noreferrer"&gt;Flyway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flyway is an open source database migration tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;In order to follow this guide, a basic understanding of the following technologies is required:&lt;/p&gt;

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

&lt;p&gt;Git is a free and open source distributed version control system. Although not strictly mandatory, it is suggested to have Git installed on your local machine to make it simpler to retrieve the accompanying example repository. However, a zip file may also be downloaded.&lt;/p&gt;

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

&lt;p&gt;For this guide, I primarily use software hosted within Docker containers. Although I provide all the instructions to follow this guide, it is still recommended that one familiarise oneself with Docker. I have written a Docker guide that can be found &lt;em&gt;&lt;a href="https://github.com/drminnaar/guides/tree/master/docker-guide" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;. As part of the Docker guide, there is also a &lt;em&gt;&lt;a href="https://github.com/drminnaar/guides/blob/master/docker-guide/2-getting-started.md" rel="noopener noreferrer"&gt;getting started section&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In addition to Docker related technologies, the tool &lt;em&gt;docker-compose&lt;/em&gt; will also be used to run the containers. More specifically, &lt;em&gt;docker-compose&lt;/em&gt; is a tool for defining and running multi-container Docker applications.&lt;/p&gt;

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

&lt;p&gt;PostgreSQL is a free and open source object-relational database management system. In this guide, PostgreSQL will be run from a Docker container. For more information on PostgreSQL on Docker, please visit the &lt;a href="https://hub.docker.com/_/postgres/" rel="noopener noreferrer"&gt;official PostgreSQL Docker registry&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The tool &lt;em&gt;&lt;a href="https://www.pgadmin.org/" rel="noopener noreferrer"&gt;pgAdmin&lt;/a&gt;&lt;/em&gt;, is an open source administration and development platform for PostgreSQL. In this guide, &lt;em&gt;pgAdmin&lt;/em&gt; will be run from a Docker container. For more information on &lt;em&gt;pgAdmin&lt;/em&gt; on Docker, please visit the &lt;a href="https://hub.docker.com/r/dpage/pgadmin4/" rel="noopener noreferrer"&gt;official pgAdmin Docker registry&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Environment Setup
&lt;/h2&gt;

&lt;p&gt;At this point you should have &lt;em&gt;Docker&lt;/em&gt; and &lt;em&gt;Docker-Compose&lt;/em&gt; installed. This can be verified by running the following commands from the command line.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To verify Docker:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker version
  docker info
  docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To verify Docker-Compose:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker-compose &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all is well, the above commands should have run flawlessly.&lt;/p&gt;

&lt;p&gt;Next up, let's get the repository for this guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get Repository
&lt;/h3&gt;

&lt;p&gt;There are 3 ways to get the repository for this guide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone Repo Using HTTPS
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/drminnaar/flyway.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clone Repo Using SSH
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone git@github.com:drminnaar/flyway.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Download Zip File
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   wget https://github.com/drminnaar/flyway/archive/master.zip
   unzip ./master.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initialise Environment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;em&gt;'flyway'&lt;/em&gt; directory using the command line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once inside the &lt;em&gt;flyway&lt;/em&gt; directory, you will notice a file called &lt;em&gt;'docker-compose.yml'&lt;/em&gt;. This file contains all the instructions required to initialise our environment with all the required containerised software. In our case, the &lt;em&gt;docker-compose.yml&lt;/em&gt; files holds the instructions to run &lt;em&gt;postgresql&lt;/em&gt; and &lt;em&gt;pgadmin&lt;/em&gt; containers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type the following command to initialise environment to run Flyway code migrations:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Type the following command to verify that there are 2 containers running. One container will be our PostgreSQL server. The second container will be our pgAdmin web application.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker-compose ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command should display the running containers as specified in the &lt;em&gt;docker-compose&lt;/em&gt; file.&lt;/p&gt;




&lt;h2&gt;
  
  
  Create Database
&lt;/h2&gt;

&lt;p&gt;The first thing to be aware of when creating a migration, is that migrations do not create databases. Migrations only apply within the context of a database and do not create the database itself. Therefore, for my demonstration I will create an empty database from scratch and then create migrations for that database.&lt;/p&gt;

&lt;p&gt;In this example, I create a database called &lt;em&gt;"heroes"&lt;/em&gt;. It is a database that stores data related to, you guessed it, heroes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At this point, you should have a running PostgreSQL container instance. To verify this, run the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker-compose ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;List available databases by running the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-qf&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pg-dev&lt;span class="si"&gt;)&lt;/span&gt; psql &lt;span class="nt"&gt;-U&lt;/span&gt; postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'\l'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently, there is no &lt;em&gt;heroes&lt;/em&gt; database. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type the following command to create a &lt;em&gt;heroes&lt;/em&gt; database:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-qf&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pg-dev&lt;span class="si"&gt;)&lt;/span&gt; psql &lt;span class="nt"&gt;-U&lt;/span&gt; postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'CREATE DATABASE heroes OWNER postgres'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List available databases by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-qf&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pg-dev&lt;span class="si"&gt;)&lt;/span&gt; psql &lt;span class="nt"&gt;-U&lt;/span&gt; postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'\l'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Create Migrations
&lt;/h2&gt;

&lt;p&gt;For clarity sake, please take note that a migration is nothing more than a SQL file consisting of various SQL operations to be performed on the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding The Migrations
&lt;/h3&gt;

&lt;p&gt;The &lt;em&gt;heroes&lt;/em&gt; database now exists. We are now ready to run our migrations. Please take note of the &lt;em&gt;migrations&lt;/em&gt; folder that is part of the repo for this example. The &lt;em&gt;migrations&lt;/em&gt; folder consists of 7 migrations that are briefly described as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;V1_1_&lt;em&gt;Create_hero_schema.sql - Creates a new _hero_data&lt;/em&gt; schema
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;hero_data&lt;/span&gt; &lt;span class="k"&gt;AUTHORIZATION&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;V1_2_&lt;em&gt;Create_hero_table.sql - Create a new _hero&lt;/em&gt; table in the &lt;em&gt;hero_data&lt;/em&gt; schema
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;hero_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hero&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;BIGSERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;debut_year&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;appearances&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;special_powers&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;cunning&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;strength&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;technology&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;hero_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hero&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;pk_hero_id&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;V1_3_&lt;em&gt;Add_Destroyer_hero.sql - Inserts our first hero into _hero&lt;/em&gt; table
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;hero_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hero&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;debut_year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;appearances&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;special_powers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;cunning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;strength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;technology&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s1"&gt;'Destroyer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s1"&gt;'Created by Odin, locked in temple, brought to life by Loki'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;1965&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;V1_4_&lt;em&gt;Create_user_schema.sql - Create a _user_data&lt;/em&gt; schema
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt; &lt;span class="k"&gt;AUTHORIZATION&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;V1_5_&lt;em&gt;Create_user_table.sql - Create a new _user&lt;/em&gt; table in the &lt;em&gt;user_data&lt;/em&gt; schema
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;BIGSERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;pk_user_id&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;V1_6_&lt;em&gt;Add_unique_hero_name_contraint.sql - Alter _hero&lt;/em&gt; table by adding a unique name constraint
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;hero_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hero&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;uk_hero_name&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;V1_7_&lt;em&gt;Add_unique_user_email_constraint.sql - Alter _user&lt;/em&gt; table by adding a unique email constraint
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;uk_user_email&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will have noticed the strange naming convention. The way we name a migrations is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flywaydb.org/documentation/migrations#naming" rel="noopener noreferrer"&gt;According to the official Flyway documentation&lt;/a&gt;, the file name consists of the following parts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76oulk6mjsiyop1smeim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76oulk6mjsiyop1smeim.png" alt="flyway-naming-convention" width="800" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prefix:&lt;/strong&gt; V for versioned migrations, U for undo migrations, R for repeatable migrations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version:&lt;/strong&gt; Underscores (automatically replaced by dots at runtime) separate as many parts as you like (Not for repeatable migrations)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separator:&lt;/strong&gt; __ (two underscores)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Underscores (automatically replaced by spaces at runtime) separate the words&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Run Migrations
&lt;/h3&gt;

&lt;p&gt;Finally we get to run our migrations. To run the migrations, we will execute the &lt;a href="https://hub.docker.com/r/boxfuse/flyway/" rel="noopener noreferrer"&gt;&lt;em&gt;Flyway&lt;/em&gt; Docker container&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Before running the migration, we need to obtain the IP address of the postgres container as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container inspect &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"{{ .NetworkSettings.Networks.flyway_skynet.IPAddress}}"&lt;/span&gt; flyway_pg-dev_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We plug the obtained IP address from above into the command below. In my case, my IP address is &lt;em&gt;172.18.0.2&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--network&lt;/span&gt; docker_skynet &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;/migrations:/flyway/sql boxfuse/flyway &lt;span class="nt"&gt;-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;jdbc:postgresql://172.18.0.2:5432/heroes &lt;span class="nt"&gt;-user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres &lt;span class="nt"&gt;-password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;password migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see an output similar to the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjommcl9xtq2avvkewhij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjommcl9xtq2avvkewhij.png" alt="flyway-migration-result" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As can be seen from output above, all 7 migrations ran successfully.&lt;/p&gt;

&lt;p&gt;Run the following command to see a list of tables in the heroes database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-qf&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pg-dev&lt;span class="si"&gt;)&lt;/span&gt; psql &lt;span class="nt"&gt;-U&lt;/span&gt; postgres &lt;span class="nt"&gt;-d&lt;/span&gt; heroes &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"SELECT table_schema, table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema NOT IN ('pg_catalog', 'information_schema')"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a list of tables as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;table_schema&lt;/th&gt;
&lt;th&gt;table_name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;public&lt;/td&gt;
&lt;td&gt;flyway_schema_history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hero_data&lt;/td&gt;
&lt;td&gt;hero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;user_data&lt;/td&gt;
&lt;td&gt;user&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The database table &lt;em&gt;flyway_schema_history&lt;/em&gt; contains all the records for the database migrations that took place.&lt;/p&gt;

&lt;p&gt;Lastly, log into pgAdmin to view the &lt;em&gt;flyway_schema_history&lt;/em&gt; table.&lt;/p&gt;

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

&lt;p&gt;Navigate to &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; in your browser&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;email/username:&lt;/strong&gt; &lt;a href="mailto:iamhero@heroes.com"&gt;iamhero@heroes.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;password:&lt;/strong&gt; password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're wondering where the pgadmin credentials come from, you can find them specified in the &lt;em&gt;docker-compose.yml&lt;/em&gt; file. They're passed in as environment variables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdb8brhqbku6i7t6lhja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdb8brhqbku6i7t6lhja.png" alt="pgadmin-login" width="697" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once logged in, you can connect to the PostgreSQL server by adding a connection as follows:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa2awh0sv88ovzgax1eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa2awh0sv88ovzgax1eg.png" alt="pgadmin-create-server-1" width="697" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8odbqfcmenx79go2d1yz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8odbqfcmenx79go2d1yz.png" alt="pgadmin-create-server-2" width="697" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the &lt;em&gt;flyway_schema_history&lt;/em&gt; table that is located in the public schema of the heroes database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjkl18wpy6244v6t4fp7l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjkl18wpy6244v6t4fp7l.png" alt="pgadmin-flyway-table" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This has been a basic introduction into using the tool &lt;em&gt;Flyway&lt;/em&gt; for performing database migrations. Although basic, it doesn't really get much more complicated than this.&lt;/p&gt;

&lt;p&gt;I did not cover how to use &lt;em&gt;Flyway&lt;/em&gt; with an existing database, however, this is also supported by using the &lt;em&gt;baseline&lt;/em&gt; command with &lt;em&gt;Flyway&lt;/em&gt;. I will cover this in more detail in a next part to this guide.&lt;/p&gt;

</description>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Choosing a Programming Language</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Mon, 19 Mar 2018 07:23:45 +0000</pubDate>
      <link>https://dev.to/drminnaar/choosing-a-programming-language-493h</link>
      <guid>https://dev.to/drminnaar/choosing-a-programming-language-493h</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I recently came accross 2 videos on the &lt;a href="http://bigthink.com/" rel="noopener noreferrer"&gt;BigThink&lt;/a&gt; website that addresses the topic &lt;em&gt;'Five Programming Languages that Everyone Should Know'&lt;/em&gt;. The original videos can be found via the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://bigthink.com/videos/5-programming-languages-everyone-should-know" rel="noopener noreferrer"&gt;Larry Wall&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://bigthink.com/videos/the-5-programming-languages-you-need-to-know" rel="noopener noreferrer"&gt;Bjarne Stroustrup&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;a href="http://bigthink.com/videos/5-programming-languages-everyone-should-know" rel="noopener noreferrer"&gt;first video&lt;/a&gt;, &lt;a href="http://bigthink.com/experts/larrywall" rel="noopener noreferrer"&gt;Larry Wall&lt;/a&gt; (computer programmer responsible for creating Perl), begins by providing a very valid point. The point that he makes is that answering this question is very much influenced by context as well as the times. What may be good a few years ago may not necessarily hold true for current or future times. He then goes on to provide what he currently thinks are 5 programming languages that everyone should know and they are listed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Javascript&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Haskell&lt;/li&gt;
&lt;li&gt;C&lt;/li&gt;
&lt;li&gt;Perl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;a href="http://bigthink.com/videos/the-5-programming-languages-you-need-to-know" rel="noopener noreferrer"&gt;second video&lt;/a&gt;, &lt;a href="http://bigthink.com/experts/bjarnestroustrup" rel="noopener noreferrer"&gt;Bjarne Stroustrup&lt;/a&gt; (computer programmer who designed and implemented the computer programming language C++), begins by making a very strong statement. Bjarne says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Nobody should call themselves a professional if they only knew one language.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the rest of the video, Bjarne gets straight to the point and nominates the following computer programming languages as the 5 that he thinks you should know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Functional Programming Language (doesn't specify anything particular)&lt;/li&gt;
&lt;li&gt;High Performance Computing Programming Lanaguage (doesn't specify anything particular)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you would like to have your say, I have created a survey where you can nominate your top 5 programming languages. This survey is for fun and I allow anonymous access. You will also see the current results straight after making your picks. If you're interested, &lt;a href="https://www.surveymonkey.com/r/6NTMMY9" rel="noopener noreferrer"&gt;please access the survey here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next section I provide some detail into what "knowing" a programming language means.&lt;/p&gt;

&lt;p&gt;EDIT (2018-03-21) - Fixed inaccurate explanation of side effects as seen in functional programming section&lt;/p&gt;




&lt;h2&gt;
  
  
  "Knowing" a Programming Language
&lt;/h2&gt;

&lt;p&gt;I feel that it is important to provide some context and insight into what I perceive "knowing" a programming language entails. It is an opinion, therefore my thoughts on the matter should not be taken as 100% correct and applicable to all programming languages.&lt;/p&gt;

&lt;p&gt;Below I provide a list of concepts that I consider to be the pillars of "knowing" a programming language:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nuts and Bolts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By &lt;em&gt;"Nuts and Bolts"&lt;/em&gt;, I'm referring to the core features and mechanics that make the programming language work. These features have nothing to do with using libraries and frameworks. It is the language in it's purest form. More specifically, I am referring to things like compilation, type systems, memory managment, constructs, loops, evaluation mechanisms, variables, scope and closure to name a few. The &lt;em&gt;"Nuts and Bolts"&lt;/em&gt; are the building blocks of a programming language and one cannot effectively use the language unless one has a firm grasp in terms of understanding how to use and apply those building blocks. This is where everyone starts when learning a new language. It's also the easiest part in my opinion. For some, they may feel that once they know the &lt;em&gt;"Nuts and Bolts"&lt;/em&gt;, they know the language. But for me this is merely the beginning and but the tip of a very large iceberg.&lt;/p&gt;

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

&lt;p&gt;Most programming languages come packaged with a core set of libraries. These libraries are reusable bits of code that can be shared, adopted, extended, and applied to various programming problems. Typically, there are hundreds, actually thousands of libraries to choose from. This is especially more prevalent as a result of third party and open source development. It is impossible to learn about all libraries relating to a programming language. Though it is good practice to at least make oneself familiar with as many as possible. This takes a lot of time and commitment.&lt;/p&gt;

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

&lt;p&gt;I've often heard the terms "libraries" and "frameworks" used interchangeably. However, from my perspective, frameworks imply something far bigger than a simple library. Frameworks are usually created to help simplify development that may span multiple layers of an application architecture. Where libraries are easy to add, remove, or replace. Frameworks form an inherent part of ones architecture and cannot be easily removed or changed. Frameworks are big, and they require even more investment of time to fully understand and apply them. And often, just when you've achieved a good understanding of a framework, a new one comes along to replace it and one has to start all over again.&lt;/p&gt;

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

&lt;p&gt;So much about effective programming is about effective design. And the design of a programming language often determines how we design systems using that programming language. A good design is the key difference between a system that "works" over the long term and one that ultimately fails. A design that works in one programming language may not necessarily work for another programming language. Once again, it is only through time and experience that one is able to determine what designs work and what designs don't work at all. Also, different design patterns will emerge for different programming languages. This has a lot to do with the fact that some programming languages are imperative by nature and others are functional for example. As I've mentioned before, each programming language will have short-comings. For example, much to the dismay of many, the GO programming language currently does not support "generics". Therefore, one would need to use a different design than if one were programming in C#/Java (that do support generics). There is a constant tradeoff when designing programs for the real-world and it's different for each and every programming language.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application and Practice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each language will come with it's own set of good and bad practices. It is important to know about both. Each language will also come with subtle nuances and "traps" that one should be aware of. It's this practical side of working with a programming language that truly determines whether you know a programming language or not. It is knowledge only acquired by working continuously with the programming language and applying it in real-world scenarios that one can acquire a good sense of "knowing" what the programming language is all about.&lt;/p&gt;

&lt;p&gt;As one can see (and I'm sure many are aware of), learning a programming language is difficult. And for me it only get's harder with time as one is required to write ever increasingly sophisticated programs. But there's an interesting "little" problem that exists when learning a new programming language. And that "little" problem is time. You cannot shortcut time and therefore you cannot shortcut experience. To "know" a programming language takes a huge investment in time to gain sufficient experience in becoming adept at that programming language. I have approximately 15 years programming experience where I have programmed in C++, Java, C#, Javascript, and SQL. I can honestly say that I feel that I still don't "know" these languages. But that's what programming is all about for me. To continuously learn and improve.&lt;/p&gt;

&lt;p&gt;In the next section I am going to provide some insight into the programming languages that I think you should know. However, judging by what I have written in this section, you may have realised my subtle hint in that I don't think it is possible to "know" 5 programming languages. But I do think we should try because it makes us better thinkers and therefore better programmers.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 6 Programming Languages I Think You Should Know
&lt;/h2&gt;

&lt;p&gt;After watching the &lt;em&gt;"Big Think"&lt;/em&gt; videos, it got me thinking. What do I consider as the top 5 programming lanaguages that someone (by someone I mean anyone practicing or interested in programming) should know. After thinking about it I decided that there are actually 6 that I would like to recommend.&lt;/p&gt;

&lt;p&gt;Before answering the million dollar question, I would like to provide some of my working background as it does influence my choices. For the past 15 years, I have worked in 3 primary types of industry. Namely, financial services (banking and insurance), medical services industry, and the online gaming (gambling) and sports-betting industry (where I still work). The types of applications that I have been responsible for designing and building have always involved working within 3 primary areas of a system and they are listed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Databases&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One cannot build applications without some form of long-term persistent data store. If experience has taught me anything, it's that applications come and go but data is forever. It's the one software asset that tends to outlive everything else within a system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where there is data, there is a need to easily view, store, retrieve, and manage that data. Therefore, I have found that there is often a "one-to-many" relationship between databases and frontend applications. By that I mean that for each database there may be many applications built to interact with that database. The types of frontend applications that I have had to build involved using many different types of languages. For example, typically I would use one set of languages to build native applications and another set of languages to build web applications.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Very seldom have I been required to create simple CRUD (Create, Read, Update, and Delete) applications. There have always been business rules that govern the flows of different processes within a system. Some business rules are very complex and lead to the creation of many different kinds of domain models that involve integrating to databases and services (like API's for example). Often, I have been  required to expose domain models through API's. Once again there are certain programming languages that work better at this level than others.&lt;/p&gt;

&lt;p&gt;Based on my background and experience, I now provide what I feel are important programming lanaguages to know or learn. My top 6 programming lanaguages are listed as follows in no particular order:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Javascript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It feels like Javascript is everywhere these days, and it is. No longer being limited to clientside development, Javascript has matured into a language that can be used server side too. One only needs to read the job boards, and various blogs to realise that Javascript is very much here to stay. It always makes me think of &lt;a href="https://blog.codinghorror.com/the-principle-of-least-power" rel="noopener noreferrer"&gt;Atwoods Law&lt;/a&gt; that states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"any application that can be written in Javascript, will eventually be written in Javascript"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The fact of the matter is that there are very few jobs out there that do not benefit from someone having some Javascript knowledge. It is a very simple language to learn, however, it get's more complicated the more you learn. The Javascript language is full of subtle nuances that can trick even the most experienced Javascript developer.&lt;/p&gt;

&lt;p&gt;For me, knowing Javascript goes hand-in-hand with knowing a language that can easily transpile into Javascript. The reason why you would want to learn such a language is if you are building a large javascript codebase and want to improve maintainability. My preference is &lt;a href="https://www.typescriptlang.org" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; which is a superset of Javascript. There are also other Javascript alternatives out there like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://coffeescript.org/" rel="noopener noreferrer"&gt;Coffeescript&lt;/a&gt; - CoffeeScript is a programming language that transcompiles to JavaScript. It adds syntactic sugar inspired by Ruby, Python and Haskell in an effort to enhance JavaScript's brevity and readability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://elm-lang.org/" rel="noopener noreferrer"&gt;Elm&lt;/a&gt; - Elm is a domain-specific programming language for declaratively creating web browser-based graphical user interfaces. Elm is purely functional, and is developed with emphasis on usability, performance, and robustness.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also a "type checker" called &lt;a href="https://flow.org/" rel="noopener noreferrer"&gt;Flow&lt;/a&gt; that can be used with Javascript. Though I'm not seeing adoption anything close to Typescript at the moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Object Oriented Programming (OOP) Language&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At university, I majored in distributed computing using Java as my primary programming language. Although, I also done a fair amount of programming using C++ and a lesser known programming language called &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Eiffel_(programming_language)" rel="noopener noreferrer"&gt;Eiffel&lt;/a&gt;&lt;/strong&gt;. However, Java was always my favourite. Learning Java certainly enabled me to easily adapt to other programming languages. The only thing that I can say I hated about the Java programming language was "checked exceptions". And no, there is nothing you can do to convince me otherwise, despite any technical merit they may have.&lt;/p&gt;

&lt;p&gt;It is the C# programming language that I ended up spending most of my time with. I have been developing in C# as my primary language for more than 10 years now. The biggest drawback to me was that C# was never open-source or cross-platform. But thankfully that has all changed in recent years, and I am happily developing C# applications on a Linux OS. It's strange, but of late, the Javascript language has changed so much, that when I am writing Javascript, it often feels like I'm writing C# code. More recently for example, when the async/await feature was added to Javascript, I felt right at home because I had been writing multi-threaded asynchronous programs for years in C# using a very similar pattern. I must admit though, I am not a fan of introducing "class oriented" concepts into the Javascript language.&lt;/p&gt;

&lt;p&gt;So do I think you should learn C#, Java, or C++ etc? My personal feeling is that it doesn't matter all that much, but pick one. Like &lt;em&gt;Bjarne Stroustrup&lt;/em&gt; mentions in the video from above. These are a cluster of languages and knowing one helps you to know them all. As you can see from my personal experience, it started with Java and C++ but ended up mostly programming in Javascript and C#.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Python&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python has been around for a long time. Sometimes referred to as a scripting language, I will take it one step further and call it a general purpose programming language. Lately, circa 2017/2018, it has been gathering massive adoption. One cannot talk about data science without Python being mentioned in the discussion. The other one is of course R but for now my first choice is Python. I am mostly a Python hobbyist programmer and have not used it in any production environment. That doesn't mean that I think of it as a hobbysit language. On the contrary. Once again, one only needs to visit a job board or some trending stats to realise that Python is a clear favourite of many. With the rise of Machine Learning and Artificial Intelligence, it seems that Python has become a popular choice in those domains too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. SQL (Structure Query Language)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, SQL is a language. More specifically SQL is a fourth-generation language (4GL) that's closer to human language. I sometimes wonder if SQL is not the most omnipresent programming language in the world. SQL is everywhere, and in all my working experience, I have not once NOT had to work with SQL. Whether it was MSSQL, Postgres, MySQL, or Oracle, SQL existed in some shape or form. Of course SQL is not as sexy and shiny as the new NoSQL technologies out there, but SQL is here to stay for a long time yet. Interestingly, &lt;a href="https://www.couchbase.com/" rel="noopener noreferrer"&gt;Couchbase&lt;/a&gt;, a NoSql database, uses the &lt;a href="https://www.couchbase.com/products/n1ql" rel="noopener noreferrer"&gt;N1QL (pronounced "nickel")&lt;/a&gt; query language. The interesting thing about N1QL is that it adopts nearly full SQL ANSI-92 compliance. Even some tools like &lt;a href="https://mongobooster.com/blog/query-mongodb-with-sql/" rel="noopener noreferrer"&gt;NoSqlBooster&lt;/a&gt; allow one to write SQL queries over a MongoDB database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. BASH&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BASH is a scripting language and it is &lt;a href="https://en.wikipedia.org/wiki/Turing_completeness" rel="noopener noreferrer"&gt;Turing-Complete&lt;/a&gt;. Like my prior choices in programming languages to know, the reason BASH makes it onto my list is for reasons of it's massive adoption and community. For me, the difference between being a King or a God of Linux is ones ability to program in BASH. That and being able to work with VIM ;)&lt;/p&gt;

&lt;p&gt;Furthermore, Linux is by far the most used OS in server computing. Therefore, I think it is a good idea to master as much as possible about Linux as you're most likely bound to work with it sooner or later. Learning BASH scripts is part of mastering Linux. Knowing BASH will also help you to write repeatable and automated tasks that can be shared and used my many. Therefore, in addition to being a valuable sysadmin tool, I think it is a valuable devops tool too.&lt;/p&gt;

&lt;p&gt;When writing about Linux, I'm always reminded by the following picture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F37555299-0d5f94ca-29ee-11e8-8f2b-494848249ca0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33935506%2F37555299-0d5f94ca-29ee-11e8-8f2b-494848249ca0.jpg" alt="linux-cloud"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Functional Programming Language&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have no experience developing software using a purely (or close to pure) functional programming language. Therefore, I cannot make any recommendation based from experience. However, in the absence of experience, I turned to data to help drive my decision. For the past year I have been keeping a close eye on functional programming languages. The 3 functional programming languages that always seem to attract the most attention (in my experience) are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.haskell.org/" rel="noopener noreferrer"&gt;Haskell&lt;/a&gt; - Haskell is a standardized, general-purpose purely functional programming language, with non-strict semantics and strong static typing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scala-lang.org/" rel="noopener noreferrer"&gt;Scala&lt;/a&gt; - Scala is a general-purpose programming language providing support for functional programming and a strong static type system. Designed to be concise, many of Scala's design decisions aimed to address criticisms of Java.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://fsharp.org/" rel="noopener noreferrer"&gt;F#&lt;/a&gt; - F# is a strongly typed, multi-paradigm programming language that encompasses functional, imperative, and object-oriented programming methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I suspect that functional programming is going to become THE programming skill to have in the near future. The reason for me saying so is due to the increased demand to write concurrent and parallel programs. That demand is driven by the changing physical architecture of micro processors. In a nutshell, as programmers we have only had to worry about writing programs that work with a single core processor. Until a few years ago that is. If we needed more speed, we would increase the speed of the processor. In recent years, the processor industry reached the limits of providing higher processing speed. As a result, the processor architecture changed to provide 2, 4 and more cores per processor to help run programs faster. But programs didn't run faster because nobody had programming languages that could effectively utilise the additional cores to write truly concurrent programs without side-effects (more on that later). Nobody except those using functional programming languages that is. It turns out that functional programming languages are very good for multi-core, multi-threaded, and distributed system domains. One of the biggest advantages that one will often hear being advertised as a reason to use functional programming is to eliminate "side-effects". A "side-effect" is when you have some code that is accessing or changing the state of some data (like a variable) that is outside the scope of that code. The problems associated with side-effects are exacerbated in the presence of multiple threads. Another important concept to understand as it applies to parallel computing is Amdahl's Law. To explain Amdahl's Law would require an entire dedicated article, and I won't be providing that here. I would however like to direct you to an interesting explanation of Amdahl's Law that can be found &lt;a href="https://www.youtube.com/watch?v=WdRiZEwBhsM" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I should mention that programming languages like GO, Rust, Java and C# now have concurrency (the ability to write concurrent programs) baked into the language too and feel certain that this will only improve with time.&lt;/p&gt;

&lt;p&gt;I encourage anyone that is new or experienced with programming to invest time in learning a functional programming languages. If anything it will help one to think better about how to correctly write programs without side-effects. Also, functional paradigms are making their way into many popular languages like Java and C# too.&lt;/p&gt;

&lt;p&gt;It is Scala that holds the most interest to me in terms of functional programming languages. For me it is a rising star in the world of functional programming.&lt;/p&gt;

&lt;p&gt;That concludes my musings in terms of the programming languages that I think you should learn. In the next section I conclude this article and provide a few more programming languages that I feel are also important, and anyone of them could easily have taken the place of the one's I have already mentioned.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In my experience, there is no programming language to rule them all. I have mostly picked up languages out of necessity to get particular jobs done in the easiest way possible. The programming languages that I discussed are by no means the most popular languages. But they are languages that have massive communities, massive amounts of documentation and learning materials, and massive amounts of jobs.&lt;/p&gt;

&lt;p&gt;In closing I would like to mention a few programming languages that I would love to try. Anyone of them could easily have taken the place of the programming languages I discussed in previous sections. They are listed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;&lt;/strong&gt; - Rust is a systems programming language sponsored by Mozilla Research, which describes it as a "safe, concurrent, practical language", supporting functional and imperative-procedural paradigms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;GO&lt;/a&gt;&lt;/strong&gt; - Go is a programming language created at Google in 2009. It is a compiled, statically typed language in the tradition of Algol and C, with garbage collection, limited structural typing, memory safety features and CSP-style concurrent programming features added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://kotlinlang.org/" rel="noopener noreferrer"&gt;Kotlin&lt;/a&gt;&lt;/strong&gt; - Kotlin is a statically-typed programming language that runs on the Java virtual machine and also can be compiled to JavaScript source code or use the LLVM compiler infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I suspect that I will be exploring &lt;a href="https://www.scala-lang.org/" rel="noopener noreferrer"&gt;Scala&lt;/a&gt; or &lt;a href="https://kotlinlang.org/" rel="noopener noreferrer"&gt;Kotlin&lt;/a&gt; next as a potential "next skill".&lt;/p&gt;

&lt;p&gt;Don't forget that if you would like to have your say, you can access the survey that I am running for fun at &lt;a href="https://www.surveymonkey.com/r/6NTMMY9" rel="noopener noreferrer"&gt;this link&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>career</category>
      <category>languages</category>
    </item>
    <item>
      <title>MongoDB Guide - Getting Started</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Tue, 13 Mar 2018 08:07:29 +0000</pubDate>
      <link>https://dev.to/drminnaar/mongodb-guide---getting-started--22nk</link>
      <guid>https://dev.to/drminnaar/mongodb-guide---getting-started--22nk</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this guide, I am going to cover the essentials in terms of getting up and running with MongoDB. The best way to start learning new technology is to jump straight in and start using it. Therefore, after a brief introduction to MongoDB, the following sections are all about setting up your own MongoDB instance using 4 different hosting methods. Next, I introduce 5 tools that you can use to work with your MongoDB databases. The next section illustrates methods on creating your own database and collection with data. In this section I also provide a number of examples that illustrate some basic queries to query your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This guide is summarized as follows:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Is MongoDB&lt;/li&gt;
&lt;li&gt;MongoDB Setup

&lt;ul&gt;
&lt;li&gt;Install And Host Locally&lt;/li&gt;
&lt;li&gt;Install And Host Using Docker&lt;/li&gt;
&lt;li&gt;Host With MongoDB Atlas&lt;/li&gt;
&lt;li&gt;Host With MLab&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;MongoDB Tools

&lt;ul&gt;
&lt;li&gt;MongoDB Shell&lt;/li&gt;
&lt;li&gt;MongoDb Compass&lt;/li&gt;
&lt;li&gt;NoSqlBooster&lt;/li&gt;
&lt;li&gt;Robo 3T&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Basic MongoDB Commands&lt;/li&gt;

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

&lt;/ul&gt;

&lt;p&gt;Lastly, this guide does not cover the reasons to use MongoDB (perhaps a guide for another time). However, I would like to encourage readers to spend some time researching and understanding the rationale between choosing a NoSql database over a Sql database. MongoDB is not a replacement for SQL databases. It is merely an alternative that may (or may not) align better with ones specific requirements.&lt;/p&gt;

&lt;p&gt;The following question posted on Quora may be a good starting point:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.quora.com/What-are-some-reasons-to-use-traditional-RDBMS-over-NoSQL" rel="noopener noreferrer"&gt;What are some reasons to use traditional RDBMS over NoSQL?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From my personal experience and perspective, I will mention that one should think very carefully before committing to a NoSql database if your data is required to be agnostic. In this case I have found Sql databases to be a far better choice due to the simplicity of modelling data and exposing it in many different ways for many different applications.&lt;/p&gt;

&lt;p&gt;The original guide can be found on my &lt;a href="https://github.com/drminnaar/guides/tree/master/mongodb-guide" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;. Like my &lt;a href="https://github.com/drminnaar/guides/tree/master/docker-guide" rel="noopener noreferrer"&gt;Docker Guide&lt;/a&gt;, I will be updating and adding more content over time to this repository.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is MongoDB?
&lt;/h2&gt;

&lt;p&gt;MongoDB is a database. More specifically, it is an open source document-oriented database that has been designed for scalability and simplicity for both developers and sysadmins. Traditional relational database management systems (RDBMS) like MSSQL, Oracle, MySQL, and PostGreSQL store data in tables having a static schema composed of rows and columns. However, MongoDB stores it's data in JSON-like documents having dynamic schemas.&lt;/p&gt;




&lt;h2&gt;
  
  
  MongoDB Setup
&lt;/h2&gt;

&lt;p&gt;I will discuss 4 options to get up and running with MongoDB:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install and host locally&lt;/li&gt;
&lt;li&gt;Install and host in Docker&lt;/li&gt;
&lt;li&gt;Register for and use MongoDB Atlas (Database As A Service)&lt;/li&gt;
&lt;li&gt;Register for and use MLab (Database As A Service)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install And Host Locally
&lt;/h3&gt;

&lt;p&gt;Installing MongoDB is relatively straight forward. There are currently 3 platform (Windows, Linux, OSX) releases available and can be found &lt;a href="https://www.mongodb.com/download-center?jmp=homepage#community" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more specific installation instructions, please see the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.mongodb.com/v3.0/administration/install-on-linux" rel="noopener noreferrer"&gt;Install MongoDB On Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.mongodb.com/v3.0/tutorial/install-mongodb-on-windows" rel="noopener noreferrer"&gt;Install MongoDB On Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.mongodb.com/v3.0/tutorial/install-mongodb-on-os-x" rel="noopener noreferrer"&gt;Install MongoDB On OSX&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install And Host Using Docker
&lt;/h3&gt;

&lt;p&gt;If you have never used &lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; before, then this option is less suitable for you as it implies having some Docker knowledge and experience. However, if you are still interested in pursuing this option, then I recommend viewing my &lt;a href="(https://github.com/drminnaar/guides/tree/master/docker-guide)"&gt;Docker Guide&lt;/a&gt; as a starting point. I also have a &lt;a href="https://github.com/drminnaar/cheatsheets/blob/master/docker-cheatsheet.md" rel="noopener noreferrer"&gt;Docker Cheatsheet&lt;/a&gt; that you may find useful.&lt;/p&gt;

&lt;p&gt;The Docker image that will be used, is the &lt;a href="https://hub.docker.com/_/mongo" rel="noopener noreferrer"&gt;official Docker MongoDB image&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Run MongoDB
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Run MongoDB Using Named Volume
&lt;/h5&gt;

&lt;p&gt;For the following examples I map the Docker MongoDB port of &lt;em&gt;&lt;strong&gt;27017&lt;/strong&gt;&lt;/em&gt; to a local port of &lt;em&gt;&lt;strong&gt;37017&lt;/strong&gt;&lt;/em&gt;. The reason for this is because I have a local instance on MongoDB running that is already using the &lt;em&gt;&lt;strong&gt;27017&lt;/strong&gt;&lt;/em&gt; port.&lt;/p&gt;

&lt;p&gt;To run a new MongoDB container, execute the following command from the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;docker run --rm --name mongo-dev -p 37017:27017 -v mongo-dev-db:/data/db -d mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CLI Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;--rm&lt;/td&gt;
&lt;td&gt;remove container when stopped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--name mongo-dev&lt;/td&gt;
&lt;td&gt;give container a custom name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-p&lt;/td&gt;
&lt;td&gt;map container published port to local port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-v mongo-dev-db/data/db&lt;/td&gt;
&lt;td&gt;map the container volume 'data/db' to a custom name 'mongo-dev-db'&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-d mongo&lt;/td&gt;
&lt;td&gt;run mongo container as a daemon in the background&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h5&gt;
  
  
  Run MongoDB Using Bind Mount
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd
mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; mongodb/data/db
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; mongo-dev &lt;span class="nt"&gt;-p&lt;/span&gt; 37017:27017 &lt;span class="nt"&gt;-v&lt;/span&gt; ~/mongodb/data/db:/data/db &lt;span class="nt"&gt;-d&lt;/span&gt; mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CLI Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;--rm&lt;/td&gt;
&lt;td&gt;remove container when stopped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--name mongo-dev&lt;/td&gt;
&lt;td&gt;give container a custom name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-p&lt;/td&gt;
&lt;td&gt;map container published port to local port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-v ~/mongodb/data/db/data/db&lt;/td&gt;
&lt;td&gt;map the container volume 'data/db' to a bind mount '~/mongodb/data/db'&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-d mongo&lt;/td&gt;
&lt;td&gt;run mongo container as a daemon in the background&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Access MongoDB
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Access MongoDB From Local Machine
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;Type the following command to access MongoDB instance hosted within docker container:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;   mongo --host localhost --port 37017
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Access MongoDB Via Docker Interactive TTY
&lt;/h5&gt;

&lt;p&gt;There are 2 steps to accessing the MongoDB shell.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Firstly, access the MongoDB container shell by executing the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; mongo-dev bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open an interactive shell (bash) on the MongoDB container.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Secondly, once inside the container shell, access the MongoDB shell by executing the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   mongo localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Host With MongoDB Atlas
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/cloud/atlas" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt; is a &lt;em&gt;Data as a Service (DaaS)&lt;/em&gt; offering, and is hosted in the cloud. There is no installation of MongoDB required and a free tier is available.&lt;/p&gt;

&lt;p&gt;To get started, signup for free by registering for a free tier account &lt;a href="https://www.mongodb.com/cloud/atlas" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The free tier entitles you to 512MB storage.&lt;/p&gt;

&lt;p&gt;Please review the [MongoDB Atlas Documentation] for more information.&lt;/p&gt;

&lt;p&gt;Once you have registered and setup your MongoDB instance on &lt;em&gt;Atlas&lt;/em&gt;, you will be presented with a dashboard resembling the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn8q5ixkgkptt2530a50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn8q5ixkgkptt2530a50.png" alt="atlas" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Host With MLab
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mlab.com" rel="noopener noreferrer"&gt;MLab&lt;/a&gt; is a &lt;em&gt;Data as a Service (DaaS)&lt;/em&gt; offering, and is hosted in the cloud. There is no installation of MongoDB required and a free tier is available.&lt;/p&gt;

&lt;p&gt;To get started, signup for free account &lt;a href="https://mlab.com/signup/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The free tier entitles you to 500MB storage.&lt;/p&gt;

&lt;p&gt;Please review the &lt;a href="https://docs.mlab.com" rel="noopener noreferrer"&gt;MLab Documentation&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;Once you have registered and setup your MongoDB instance on &lt;em&gt;MLab&lt;/em&gt;, you will be presented with a dashboard resembling the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo3ygzkxtv0uoezm9vcx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo3ygzkxtv0uoezm9vcx.png" alt="mlab" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  MongoDB Tools
&lt;/h2&gt;

&lt;p&gt;The tooling for MongoDB has improved a lot of late and there are many options. I have worked with the following tools and I find them all quite good. It's really a matter of personal preference but I find that I tend to use them together.&lt;/p&gt;

&lt;h3&gt;
  
  
  MongoDB shell
&lt;/h3&gt;

&lt;p&gt;The MongoDB shell is the default way of interacting with MongoDB databases.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect to MongoDB
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  mongo localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;List Available Databases
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  show dbs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create Database
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  use message_db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create Collection
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  db.messages.insert&lt;span class="o"&gt;({&lt;/span&gt; message: &lt;span class="s1"&gt;'hello mongodb'&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;List Collections
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  show collections
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MongoDB Compass
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/products/compass" rel="noopener noreferrer"&gt;MongoDB Compass&lt;/a&gt; is a Graphical User Interface (GUI) tool that allows one to explore your MongoDB data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has a free addition available&lt;/li&gt;
&lt;li&gt;It is cross platform and is available for Linux, Windows, and Mac&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It supports the following primary features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run ad hoc queries&lt;/li&gt;
&lt;li&gt;Perform CRUD operations on data&lt;/li&gt;
&lt;li&gt;View and optimize query performance&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In the following screenshot, I am connected to MongoDB running on my local machine, using MongoDB Compass.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35owe9df6l0140z6ak4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35owe9df6l0140z6ak4x.png" alt="compass" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information on MongoDB Compass, go &lt;a href="https://www.mongodb.com/products/compass" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  NoSqlBooster
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nosqlBooster.com" rel="noopener noreferrer"&gt;NoSqlBooster&lt;/a&gt; is a Graphical User Interface (GUI) that provides an easy to use interface to work with your MongoDB database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has a free addition available&lt;/li&gt;
&lt;li&gt;It is cross platform and is available for Linux, Windows, and Mac&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It provides the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shell extensions&lt;/li&gt;
&lt;li&gt;Fluent Query API for MongoDB&lt;/li&gt;
&lt;li&gt;Query MongoDB with SQL&lt;/li&gt;
&lt;li&gt;Use Node Modules in your script&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In the following screenshot, I am connected to MongoDB running on Docker, using NoSqlBooster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5all70vs5h1vg5sqrk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5all70vs5h1vg5sqrk0.png" alt="nosqlbooster" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information, please visit the &lt;a href="https://nosqlbooster.com/" rel="noopener noreferrer"&gt;official NoSqlBooster website&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Robo 3T
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.toformerly%20RoboMongo"&gt;Robo 3T&lt;/a&gt;, is a free GUI tool that can be used to explore your MongoDB databases.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is free to use.&lt;/li&gt;
&lt;li&gt;It is cross platform and is available for Linux, Windows, and Mac&lt;/li&gt;
&lt;li&gt;It provides a MongoDB GUI with embedded shell&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the following screenshot, I am connected to a local instance of MongoDB using Robo 3T:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpy4r9cwg6k0jqb4nkwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpy4r9cwg6k0jqb4nkwf.png" alt="robo3t" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://robomongo.org" rel="noopener noreferrer"&gt;Robo 3T&lt;/a&gt; can be downloaded &lt;a href="https://robomongo.org/download" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information, go &lt;a href="https://robomongo.org/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Studio Code
&lt;/h3&gt;

&lt;p&gt;Using the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb" rel="noopener noreferrer"&gt;Azure CosmosDB Extension&lt;/a&gt;, one can connect to MongoDB databases in addition to &lt;a href="https://azure.microsoft.com/en-us/services/cosmos-db" rel="noopener noreferrer"&gt;Azure CosmosDB&lt;/a&gt; databases.&lt;/p&gt;

&lt;p&gt;For more information, see the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-azureextensionpack" rel="noopener noreferrer"&gt;Azure CosmosDB Extension on Market Place&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Microsoft/vscode-cosmosdb" rel="noopener noreferrer"&gt;Azure CosmosDB Extension on Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Install Azure CosmosDB Extension
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Launch VS Code&lt;/li&gt;
&lt;li&gt;Launch Quick Open (&lt;code&gt;ctrl+P&lt;/code&gt;) from within VS Code&lt;/li&gt;
&lt;li&gt;Paste the following command and press enter
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  ext &lt;span class="nb"&gt;install &lt;/span&gt;ms-vscode.vscode-azureextensionpack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configure User Settings
&lt;/h4&gt;

&lt;p&gt;Once you have the extension installed, you will need to ensure that you have a path to Mongo configured in your user settings. Press &lt;code&gt;Ctrl+,&lt;/code&gt; to open your user settings. Therefore, because I am using a Linux based OS, I had to add the following setting to the user settings json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"mongo.shell.path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/var/lib/mongodb"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Connect To Mongo On localhost
&lt;/h4&gt;

&lt;p&gt;To connect to MongoDB instance, follow the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expand &lt;em&gt;Azure Cosmos DB&lt;/em&gt; extension panel located in explorer&lt;/li&gt;
&lt;li&gt;Select the option to 'Attach Database Account'&lt;/li&gt;
&lt;li&gt;Select MongoDB&lt;/li&gt;
&lt;li&gt;Enter the connection details to MongoDB instance
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  mongodb://localhost:27017
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The steps are shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9m2mca6lekssena1rtb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9m2mca6lekssena1rtb.gif" alt="vs-code-cosmodb-ext" width="727" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Run Commands Using Mongo ScrapBooks
&lt;/h4&gt;

&lt;p&gt;To use the &lt;em&gt;'ScrapBook Feature'&lt;/em&gt;, follow the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach to your MongoDB instance as seen above&lt;/li&gt;
&lt;li&gt;Connect to database of your choice&lt;/li&gt;
&lt;li&gt;Select 'New MongoDB ScrapBook' option to open scrapbook editor&lt;/li&gt;
&lt;li&gt;Enter MongoDB command&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Ctrl+Shft+'&lt;/code&gt; to execute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The steps are shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvsi353xavl8521keur3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvsi353xavl8521keur3.gif" alt="vs-code-scrapbook" width="1201" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the time of this writing, there seems to be an &lt;a href="https://github.com/Microsoft/vscode-cosmosdb/issues/214" rel="noopener noreferrer"&gt;issue with Mongo ScrapBooks&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Basic MongoDB Commands
&lt;/h2&gt;

&lt;p&gt;Once you have your MongoDB instance running or hosted, open a mongo shell to your MongoDB server. For the purposes of this demonstration, I will be using my local installation 'localhost'.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect to MongoDB instance
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  mongo localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a 'zips_db' database
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  use zips_db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create 'zips' collection
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertMany&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AGAWAM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.622739&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.070206&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5338&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CUSHMAN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.51564999999999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.377017&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;36963&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01002&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BARRE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.10835400000001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.409698&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4546&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01005&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BELCHERTOWN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.41095300000001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.275103&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10579&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01007&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLANDFORD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.936114&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.182949&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01008&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BRIMFIELD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.188455&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.116543&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;706&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01010&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CHESTER&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.988761&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.279421&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;688&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01011&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CHESTERFIELD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.833309&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.38167&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  &lt;span class="mi"&gt;177&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01012&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CHICOPEE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.607962&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.162046&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3396&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01013&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CHICOPEE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.576142&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;42.176443&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1495&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;01020&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Search Queries&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get total collection count
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get all zip documents
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get 5 zip documents
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get zip having a city name of 'BLANDFORD'
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLANDFORD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get zip having a city name of 'BLANDFORD', ignore case
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$regex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;blandford&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get zip having a city names of 'BLANDFORD' and 'BRIMFIELD'
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLANDFORD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BRIMFIELD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get zip having a city names of 'BLANDFORD' and 'BRIMFIELD', ignore case
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="sr"&gt;/blandford/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/brimfield/i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;pretty &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get zip documents having a population greater than or equal to 30000
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$gte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;}}).&lt;/span&gt;&lt;span class="nf"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get all zip documents and use projection to only display city and population
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get all zip documents and use projection to only display city and population. Sort documents by city name in descending order
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Delete operations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete all cities called 'CHICOPEE'. Ignore case
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$regex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;chicopee&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;}})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Update operations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update the city of 'BLANDFORD' by setting its population to 10
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLANDFORD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$set&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This has been a quick introduction to getting started with MongoDB. In this guide we learned about 4 different ways to host your MongoDB instance. We also learned about 5 different tools that can be used to manage your MongoDB databases. Lastly, we explored some basic queries that can be used to create a database, create a collection, insert data, update data, and fetch data.&lt;/p&gt;

&lt;p&gt;MongoDB is an exciting and relatively new database that has a massive community and knowledgebase. I encourage all those that are interested to get involved by trying out the following learning resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.mongodb.com" rel="noopener noreferrer"&gt;MongoDB Docs&lt;/a&gt; - The official MongoDB documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://university.mongodb.com" rel="noopener noreferrer"&gt;MongoDB University&lt;/a&gt; - Free Online Classes on MongoDB from MongoDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following MongoDB book is my personal favourite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://shop.oreilly.com/product/0636920028031.do" rel="noopener noreferrer"&gt;MongoDB: The Definitive Guide, 2nd Edition&lt;/a&gt; - My personal&lt;/li&gt;
&lt;li&gt;&lt;a href="http://shop.oreilly.com/product/0636920049531.do" rel="noopener noreferrer"&gt;MongoDB: The Definitive Guide, 3rd Edition (Early Release)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in certification, please see the &lt;a href="https://university.mongodb.com/certification" rel="noopener noreferrer"&gt;MongoDB Professional&lt;br&gt;
Certification Program&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>beginners</category>
      <category>database</category>
      <category>introduction</category>
      <category>showdev</category>
    </item>
    <item>
      <title>React Redux Starter</title>
      <dc:creator>Douglas Minnaar</dc:creator>
      <pubDate>Mon, 26 Feb 2018 09:05:07 +0000</pubDate>
      <link>https://dev.to/drminnaar/react-redux-starter--4176</link>
      <guid>https://dev.to/drminnaar/react-redux-starter--4176</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Recently, I updated my &lt;a href="https://github.com/drminnaar/react-starter"&gt;react-starter&lt;/a&gt; project by adding the following notable changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accommodate multiple build configurations (dev and prod)&lt;/li&gt;
&lt;li&gt;allow one to specify addons (bundleanalyzer, bundlebuddy) as part of NPM scripts&lt;/li&gt;
&lt;li&gt;added webpack-dashboard as an optional NPM run script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was undecided between whether or not to introduce more advanced libraries like &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; and &lt;a href="https://reacttraining.com/react-router/"&gt;React-Router&lt;/a&gt; for example. In the end I decided to create a new starter project called &lt;a href="https://github.com/drminnaar/react-redux-starter"&gt;react-redux-starter&lt;/a&gt; that serves as more of an advanced starter project for those wanting to work with &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; and &lt;a href="https://reacttraining.com/react-router/"&gt;React-Router&lt;/a&gt; in addition to React. Therefore, in this post I will describe what is available in the &lt;a href="https://github.com/drminnaar/react-redux-starter"&gt;react-redux-starter&lt;/a&gt; project.&lt;/p&gt;

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

&lt;p&gt;The &lt;a href="https://github.com/drminnaar/react-redux-starter"&gt;react-redux-starter&lt;/a&gt; project is a basic template that consists of the essential elements that are required to start building a Single Page Application (SPA) using &lt;a href="https://reactjs.org"&gt;React&lt;/a&gt;, &lt;a href="https://reacttraining.com/react-router/"&gt;React Router&lt;/a&gt;, &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt;, &lt;a href="https://getbootstrap.com/docs/4.0/getting-started/introduction/"&gt;Bootstrap 4&lt;/a&gt;, &lt;a href="https://sass-lang.com/"&gt;Sass&lt;/a&gt;, and &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although I am calling this project a template of sorts, it is also a mini application in that it demonstrates a full vertical slice of the architecture. What this means, is that there is an example of Redux and React-Router in action. I provide a very simple component that fetches a list of zip codes. I kept the example simple by providing data via a &lt;em&gt;'Zip Code JSON file'&lt;/em&gt;. This simple component does however illustrate the use of Redux Actions, a Redux Container, and a Redux Store.&lt;/p&gt;

&lt;p&gt;The following diagram illustrates how data is fetched using Redux and a &lt;em&gt;Zip Code Service&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f_Ewt5pY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/36661103-035bd11a-1ae3-11e8-8c01-0224860801f8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f_Ewt5pY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/36661103-035bd11a-1ae3-11e8-8c01-0224860801f8.png" alt="react-redux-starter-zipcodes"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The template consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a typical project layout structure&lt;/li&gt;
&lt;li&gt;a Babel setup and configuration&lt;/li&gt;
&lt;li&gt;a Webpack setup and configuration&lt;/li&gt;
&lt;li&gt;an ESLint setup and configuration&lt;/li&gt;
&lt;li&gt;a SCSS setup and configuration&lt;/li&gt;
&lt;li&gt;a sample React component to display a list of zip codes&lt;/li&gt;
&lt;li&gt;a Redux setup to handle zip codes state&lt;/li&gt;
&lt;li&gt;a React Router setup to show basic navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, the template provides a development and production webpack configuration.&lt;/p&gt;

&lt;p&gt;The template also allows one to include specific plugins as part of build. Please see here for more detail&lt;/p&gt;




&lt;h2&gt;
  
  
  Showcase
&lt;/h2&gt;

&lt;p&gt;The following animated gifs illustrate what the application looks like.&lt;/p&gt;

&lt;h3&gt;
  
  
  Desktop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ap74-jMl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/33935506/36639642-ce08ea3a-1a19-11e8-8f97-0bcb29276aaf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ap74-jMl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/33935506/36639642-ce08ea3a-1a19-11e8-8f97-0bcb29276aaf.gif" alt="desktop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mobile
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C888TArI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/33935506/36639643-ce440ad4-1a19-11e8-9728-3a4b5f1bd800.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C888TArI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/33935506/36639643-ce440ad4-1a19-11e8-9728-3a4b5f1bd800.gif" alt="mobile"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Developed With
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt; - A source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt; - Javascript runtime&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; - A javascript library for building user interfaces&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://reacttraining.com/react-router/"&gt;React Router&lt;/a&gt; - Declarative routing for React&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; - Redux is a predictable state container for JavaScript apps.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/pburtchaell/redux-promise-middleware"&gt;Redux-Promise-Middleware&lt;/a&gt; - Redux middleware for promises, async functions and conditional optimistic updates&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/gaearon/redux-thunk"&gt;Redux-Thunk&lt;/a&gt; - Thunk middleware for Redux&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt; - A transpiler for javascript&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt; - A module bundler&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://sass-lang.com/"&gt;SCSS&lt;/a&gt; - A css metalanguage&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getbootstrap.com/"&gt;Bootstrap 4&lt;/a&gt; - Bootstrap is an open source toolkit for developing with HTML, CSS, and JS&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Find the &lt;a href="https://github.com/drminnaar/react-redux-starter.git"&gt;react-redux-starter project here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.&lt;/p&gt;

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

&lt;p&gt;The following software is required to be installed on your system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node 8.x&lt;/li&gt;
&lt;li&gt;Npm 3.x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Type the following commands in the terminal to verify your node and npm versions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  node &lt;span class="nt"&gt;-v&lt;/span&gt;
  npm &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;

&lt;p&gt;Follow the following steps to get development environment running.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone &lt;em&gt;'react-redux-starter'&lt;/em&gt; repository from GitHub
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  git clone https://github.com/drminnaar/react-redux-starter.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;OR USING SSH&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  git clone git@github.com:drminnaar/react-redux-starter.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install node modules
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;cd &lt;/span&gt;react-redux-starter
   npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Build Application
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;dev&lt;/th&gt;
&lt;th&gt;prod&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;npm run build:dev&lt;/td&gt;
&lt;td&gt;npm run build:prod&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Build Application And Watch For Changes
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;dev&lt;/th&gt;
&lt;th&gt;prod&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;npm run build:dev:watch&lt;/td&gt;
&lt;td&gt;npm run build:prod:watch&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Build Application With BundleAnalayzer Plugin Included
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;dev&lt;/th&gt;
&lt;th&gt;prod&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;npm run build:dev:bundleanalyze&lt;/td&gt;
&lt;td&gt;npm run build:prod:bundleanalyze&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After running the above command, a browser window will open displaying an interactive graph resembling the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--th6uJNAo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/36639476-30f9479c-1a16-11e8-9d09-1b80355a089b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--th6uJNAo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/36639476-30f9479c-1a16-11e8-9d09-1b80355a089b.png" alt="webpack bundle analyzer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Build Application With BundleBuddy Plugin Included
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;dev&lt;/th&gt;
&lt;th&gt;prod&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;npm run build:dev:bundlebuddy&lt;/td&gt;
&lt;td&gt;npm run build:prod:bundlebuddy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Run ESlint
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Lint Project Using ESLint
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npm run lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Lint Project Using ESLint, and autofix
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npm run lint:fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Run Start
&lt;/h4&gt;

&lt;p&gt;This will run the &lt;em&gt;'serve:dev'&lt;/em&gt; npm task&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Run Dev Server
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run serve:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Run Dev Server With Dashboard
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run serve:dev:dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will display a dashboard view in your console resembling the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0BCA8BuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/36639594-589409e8-1a18-11e8-84fe-29f7bdafcaa6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0BCA8BuN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33935506/36639594-589409e8-1a18-11e8-84fe-29f7bdafcaa6.png" alt="webpack-dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Run Prod Server
&lt;/h4&gt;

&lt;p&gt;This command will build application using production settings and start the application using &lt;em&gt;live-server&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run serve:prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It's always difficult providing a starting point that's simple but has enough detail to illustrate a few important concepts. I hope this project helps achieve that goal. I will be updating and tweaking over time to try and align the project as an ideal starting point to learning how to build React applications using Redux, Webpack and React Router.&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>webpack</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
