Giter Site home page Giter Site logo

john-cassidy / eshopping Goto Github PK

View Code? Open in Web Editor NEW
0.0 2.0 1.0 14.49 MB

.Net Core Microservices using Clean Architecture Implementation

C# 51.43% Dockerfile 1.48% HTML 13.57% CSS 10.33% SCSS 0.34% JavaScript 0.05% Less 10.79% Shell 0.06% TypeScript 7.31% Smarty 4.32% PowerShell 0.33%

eshopping's Introduction

eShopping

Based on Udemy Course: .Net Core Microservices using Clean Architecture Implementation

Medium Blog: Complete guid to build enterprise edition application end-to-end

Original Authors Github Repo: eShopping

GitHub Action Badges

build and test

Start Project

Create blank Solution and folder structure

dotnet new sln -n eShopping

mkdir ApiGateways
mkdir Infrastructure
mkdir Services

Build Command

dotnet build eShopping.sln /property:GenerateFullPaths=true /consoleloggerparameters:NoSummary

Catalog Microservice

cd Services
mkdir Catalog

create 4 projects following Clean Architecture:

  • Catalog.API
  • Catalog.Application
  • Catalog.Core
  • Catalog.Infrastructure

URLS

once hosts file updated: http://id-local.eshopping.com:44344

http://id-local.eshopping.com:44344/catalog.index.html http://id-local.eshopping.com:44344/basket.index.html http://id-local.eshopping.com:44344/order.index.html

Dockerfile

Build Catalog.API image: open prompt in solution folder and rull following command:

docker build --pull --rm -f "Services\Catalog\Catalog.API\Dockerfile" -t catalogapi:latest .

Docker Compose

Create docker compose project in Visual Studio after Services\Catalog\Catalog.API\Dockerfile created.

run docker-compose:

NOTE: REBUILD IMAGES TO INCLUDE CODE CHANGES AND START
docker-compose -f docker-compose.yml -f docker-compose.override.yml up --build
NOTE: START CONTAINERS FROM EXISTING IMAGES WITHOUT REBUILDING
docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d
NOTE: STOP RUNNING CONTAINERS AND REMOVE CONTAINERS
docker-compose -f docker-compose.yml -f docker-compose.override.yml down

PGAdmin4 running in Docker Desktop

Connect to running postgres container 'dicountdb'

Name: DiscountServer Hostname/address: host.docker.internal Port: 5432 Maintenance database: postgres Username: yourusername Password: yourpassword

Ordering

dotnet ef migrations (option 1)

When setting up development for first time with SqlServer container, run manual migration from command line in solution folder.

dotnet ef migrations add InitialCreate -p Services/Ordering/Ordering.Infrastructure -s Services/Ordering/Ordering.Api

Where InitialCreate is the name that we will give our migration, you can change this name with details of what your migration refers to, such as changing a field in a table, adding or removing fields, by convention we try to detail the update that the migration will do.

After -p (project) we pass the name of the solution that contains our DbContext in the case of Infrastructure and -s (solution) we pass our main project in the case of the API.

If everything went well after running the command you will get a message like this: 'Done. To undo this action, use ‘ef migrations remove’'

The migrations remove command is used to remove the created migration if it is not as you wanted.

dotnet ef migrations remove -p Services/Ordering/Ordering.Infrastructure -s Services/Ordering/Ordering.Api
dotnet ef database update -s Services/Ordering/Ordering.Api

Package Manager Console Commands (option 2)

Open Package Manager Console and select > Ordering.Infrastructure project

Run command:

Add-Migration InitialCreate

MessageBus / Message Queue

MassTransit RabbitMQ Transport Documentation

MassTransit RabbitMQ Bus Transport Configuration

MassTransit v8 is the first major release since the availability of .NET 6. MassTransit v8 works a significant portion of the underlying components into a more manageable solution structure. Focused on the developer experience, while maintaining compatibility with previous versions, this release brings together the entire MassTransit stack.

Upgrade Documentation for MassTransit v8

Documentation for MassTransit v8.1

RabbitMQ Management

Local Development URL: username: guest password: guest

Application Gateway

use Ocelot Nuget Package to setup API Gateway. Ocelot API Gateway Documentation Microsoft Learn - Implement API Gateways with Ocelot

use Copilot Chat to create the Routes in ocelot.Development.json and ocelot.Local.json

Basket API

open ocelot.Development.json open BasketController.cs and keep file selected paste following command in Copilot Chat: you can modify the text below to generate routes for: Catalog.API, Ordering.API, and Discount.API


in ocelot.Development.json file create Routes for each of the route in Basket.API BasketController.cs. for DownstreamHostAndPorts section Include Host: host.docker.internal and port 9001 from basket.api in docker-compose.override.yml. for DownstreamPathTemplate section Include /api/v1/Basket/. stringify value for "Port": 9001. for UpstreamPathTemplate do not include /api/v1. for DownstreamScheme key set value="http"

Ocelot API Gateway

Setup project to route requests to apis.

Copilot Request input on how to test Ocelot API Gateway

How to create and run tests for Ocelot.APIGateway project that is hosted in docker container with port 9010. this api runs api that routes requests to Catalog.API, Basket.API, Discount.API, and Order.API with configurations in file ocelot.Development.json. To accomplish this it configures the gateway using nuget packages: Ocelot v22.01 and Ocelot.Cache.CacheManager v22.01.

Copilot Reponse

To create and run tests for the Ocelot.APIGateway project, you can use a testing framework like xUnit. Here's a step-by-step guide:

  1. Create a new xUnit Test Project: In Visual Studio, create a new xUnit Test Project in the same solution as your Ocelot.APIGateway project.

  2. Add necessary NuGet packages: Add the Microsoft.AspNetCore.TestHost and Microsoft.AspNetCore.Mvc.Testing NuGet packages to your test project. These packages will allow you to create a test server and make HTTP requests to it.

  3. Create a custom WebApplicationFactory: This class will create a TestServer that shares the same configuration and service registrations as your Ocelot.APIGateway project.

  4. Write your tests: Create test methods that send HTTP requests to your API gateway and assert the responses.

  5. Run your tests: Use the dotnet test command to run your tests.

Here's an example of how you can do this:

Step 1: Create a new xUnit Test Project

dotnet new xunit -n Ocelot.APIGateway.Tests

Step 2: Add necessary NuGet packages

dotnet add package Microsoft.AspNetCore.TestHost
dotnet add package Microsoft.AspNetCore.Mvc.Testing

Step 3: Create a custom WebApplicationFactory

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseStartup<TStartup>();
    }
}

Step 4: Write your tests

public class GatewayTests : IClassFixture<CustomWebApplicationFactory<Startup>>
{
    private readonly HttpClient _client;

    public GatewayTests(CustomWebApplicationFactory<Startup> factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task GetCatalog_ReturnsSuccessStatusCode()
    {
        // Arrange
        var request = new HttpRequestMessage(HttpMethod.Get, "/Catalog");

        // Act
        var response = await _client.SendAsync(request);

        // Assert
        response.EnsureSuccessStatusCode();
    }
}

Step 5: Run your tests

dotnet test

This will run your tests and display the results in the terminal.

Duende IdentityServer v7 for .NET 8

Duende Software company offers IdentityServer dotnet project templates as a flexible and standards-compliant OpenID Connect and OAuth 2.x framework for ASP.NET Core.

IdentityServer v7 Documentation

GitHub Repo

Templates

Install Templates

> dotnet new install Duende.IdentityServer.Templates

The following template packages will be installed:
   Duende.IdentityServer.Templates

Success: Duende.IdentityServer.Templates::6.3.1 installed the following templates:
Template Name                                               Short Name     Language  Tags
----------------------------------------------------------  -------------  --------  ------------------
Duende BFF Host using a Remote API                          bff-remoteapi  [C#]      Web/IdentityServer
Duende BFF using a Local API                                bff-localapi   [C#]      Web/IdentityServer
Duende IdentityServer Empty                                 isempty        [C#]      Web/IdentityServer
Duende IdentityServer Quickstart UI (UI assets only)        isui           [C#]      Web/IdentityServer
Duende IdentityServer with ASP.NET Core Identity            isaspid        [C#]      Web/IdentityServer
Duende IdentityServer with Entity Framework Stores          isef           [C#]      Web/IdentityServer
Duende IdentityServer with In-Memory Stores and Test Users  isinmem        [C#]      Web/IdentityServer

Uninstall with: dotnet new uninstall Duende.IdentityServer.Templates

Project Creation

run following command from Infrastructure folder:

dotnet new isinmem -n EShopping.Identity

this will install v6. after creation update:

  • project net8
  • identityserver nuget package to v7 preview 3
  • update other nuget packages to net8 version respectively

Steps when upgrading v6 to v7 Notes on 7.0.0-preview2

Client Credential Flow

The Client Credentials Flow involves an application exchanging its application credentials, such as clientId and clientSecret, for an access_token.

Nginx ApiGateway

create nginx.local.conf file to configure nginx api gateway and reverse proxy create nginx.Dockerfile to build image add sections to docker-compose.yml and docker-compose.override.yml for:

  • nginx reverseproxy @port=9200
  • identityserver @port=9009

build/run docker-compose test nginx with route: id-local.eshopping.com:9200

Update hosts file

Update hosts file to include resolution to URI: 127.0.0.1 id-local.eshopping.com

Create Cert with OpenSSL

Article on how to Create Self Signed Certificate Article on how to Create Self Signed Certificate

create id-local.conf file run bash command from nginx folder: NOTE: modify password before running script!

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout id-local.key -out id-local.crt -config id-local.conf -passin pass:[password]

this will create id-local.key, id-local.crt

run bash command from nginx folder and enter password:

openssl pkcs12 -export -out id-local.pfx -inkey id-local.key -in id-local.crt

This will create id-local.pfx file. Import certificate into on your machine.

Elastic (ELK) Stack

ELK Stack is a collection of three open-source products: Elasticsearch, Logstash, and Kibana, all developed, managed and maintained by the company Elastic.

Elasticsearch: It is a NoSQL database that is based on the Lucene search engine. Elasticsearch is a highly scalable product that enables you to store, search, and analyze big volumes of data in real time.

Logstash: It is a data collection pipeline tool. It collects data inputs and feeds it into Elasticsearch. Logstash has a variety of filters that transform and shape the data as it’s ingested into Elasticsearch.

Kibana: It is a data visualization tool that is used to visualize the data in Elasticsearch. Kibana provides a wide variety of visualizations and dashboards for data analysis.

Together, these three different products provide a powerful stack for data ingestion, storage, and visualization. It's particularly popular for log and event data, but can be used for other types of data as well.

Project Enhancements

Enhance Common.Logging Library to implement ELK Stack with Elasticsearch, Logstash, and Kibana.

Enhance with CorrelationID.

  • Add to APIs
  • Update elasticsearch fields to include correlationId
  • Publish correlationId through Basket Checkout to Order via Service Bus

HealthChecks

API Versioning

REST API versioning is a critical aspect of maintaining a successful and well-designed API. By including a version number in the URL or headers of an HTTP request, developers can ensure that clients of the API are using the correct version and can make changes to the API without breaking existing clients. There are several different approaches to versioning REST APIs, including using the version number in the URL, using the Accept header, and using custom headers.

Article: Managing Multiple Versions of Your API with .NET and Swagger

In this article, they will explore the different approaches to REST API versioning and discuss the pros and cons of each approach. They will also look at some best practices for implementing REST API versioning in your own projects.

Angular

This project was generated with Angular CLI version 17.0.9.

The front-end application is built with Angular v17 standalone option that allows the application to use Standalone Components.

Article on Standalone Components Article on Standalone Components

Prerequisites

Commands:

node --version
v20.10.0

npm --version
10.2.3

npx --version
10.2.3
#NPX comes along with the NPM installation by default

Create Project

Use npx to instead of Angular CLI to create projects, components, etc... Article on Using npx

npx @angular/cli new client --dry-run
# or use this
npx -p @angular/cli ng new client --dry-run

Need to install the following packages:
@angular/cli@17.0.9
Ok to proceed? (y) y
? Which stylesheet format would you like to use? SCSS   [
https://sass-lang.com/documentation/syntax#scss                ]
? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)?
No
CREATE client/angular.json (2867 bytes)
CREATE client/package.json (1075 bytes)
CREATE client/README.md (1087 bytes)
CREATE client/tsconfig.json (936 bytes)
CREATE client/.editorconfig (290 bytes)
CREATE client/.gitignore (590 bytes)
CREATE client/tsconfig.app.json (277 bytes)
CREATE client/tsconfig.spec.json (287 bytes)
CREATE client/.vscode/extensions.json (134 bytes)
CREATE client/.vscode/launch.json (490 bytes)
CREATE client/.vscode/tasks.json (980 bytes)
CREATE client/src/main.ts (256 bytes)
CREATE client/src/favicon.ico (15086 bytes)
CREATE client/src/index.html (305 bytes)
CREATE client/src/styles.scss (81 bytes)
CREATE client/src/app/app.component.html (21220 bytes)
CREATE client/src/app/app.component.spec.ts (945 bytes)
CREATE client/src/app/app.component.ts (379 bytes)
CREATE client/src/app/app.component.scss (0 bytes)
CREATE client/src/app/app.config.ts (235 bytes)
CREATE client/src/app/app.routes.ts (80 bytes)
CREATE client/src/assets/.gitkeep (0 bytes)
✔ Packages installed successfully.
    Directory is already under version control. Skipping initialization of git.

Commands

Angular Project Commands from client folder (See README in client folder for more detailed list)

Install Packages

ngx-bootstrap

GitHub Repo

ngx-bootstrap Angular Bootstrap CSS
12.x.x 17.x.x 5.x.x or 4.x.x
npx ng add ngx-bootstrap

ℹ Using package manager: npm
✔ Found compatible package version: ngx-bootstrap@12.0.0.
✔ Package information loaded.

The package ngx-bootstrap@12.0.0 will be installed and executed.
Would you like to proceed? Yes
✔ Packages successfully installed.
    ✅️ Added "bootstrap
    ✅️ Added "ngx-bootstrap
'ERROR: Could not find the project main file inside of the workspace config (src)'
npm i bootstrap
npm i font-awesome

Update angular.json: projects > client > architect > options > styles:

"styles": [
              "./node_modules/bootstrap/dist/css/bootstrap.min.css",
              "./node_modules/ngx-bootstrap/datepicker/bs-datepicker.css",
              "./node_modules/font-awesome/css/font-awesome.min.css",
              "src/styles.scss"
            ],

Other Considerations

How to Setup ESLint and Prettier in an Angular Project

Development Notes

List of commands used to develop project

npx ng g c navbar --skip-tests --dry-run

Observable Sequence Diagram

Observable Sequence Diagram

Tranform Json to TypeScript

Vercel Website where you can input json and create TypeScript models

SharedComponents without using SharedModule

How to use Shared Elements without using a Module

A Shared module enables the centralization and organization of common directives, pipes, and components into a single module, which can be imported as needed in other sections of the application.

Alternatively, a SharedComponent can be created to do the same for applications using Standalone components.

See client app README.md for informatino on how this project configured SharedComponents used by Standalone Components.

NGX-Bootstrap Pagination

Documentation

UI Components

xng-breadcrumb

Angular 17 functional HTTP interceptors

NGX-Bootstrap Carousel

Documentation

Identity Server Client Implementation

Integrate IdentityServer into UI:

  • Account Component, Account Service

  • Account Routing

  • Server Side Changes

  • Checkout Flow

  • Can Activate Route Guard

  • Package.json changes

  • Silent Callback

  • Changes to:

    • Basket Service
    • Checkout Component
    • NavBar
  • 401 Error Interceptor

  • Checkout giving 400 Error

Kubernetes & AKS

kubectl Quick Reference

kubectl Context and Configuration

Generate kubernetes secret

Following powershell script will encode/decode secret used by kubernetes secrets:

$Text = 'username'
# base64 encode
$EncodedText = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Text))
# base64 decode
$DecodedText = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedText))
# output
Write-Host $EncodedText # = dXNlcm5hbWU=
Write-Host $DecodedText # = username

$Text = 'password'
# base64 encode
$EncodedText = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Text))
# base64 decode
$DecodedText = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedText))
# output
Write-Host $EncodedText # = cGFzc3dvcmQ=
Write-Host $DecodedText # = password

Tag docker image: catalogapi:latest

create tag for this image and upload to docker hub

jpcassidy/eshopping-catalogapi:latest

Install and connect to kubernetes dashboard

Instructions for installing kubernetes dashboard v3.0.0.alpha

kubernetes dashboard v3.0.0.alpha Instructions

kubernetes dashboard v3.0.0.alpha - suggests installing with helm

Instructions for installing kubernetes dashboard v2.7.0

Reference /kubernetes/Kubernetes.md

kubectl apply

cd .\Deployments\k8s\catalog\catalog-db\

kubectl apply -f mongo-secret.yaml

kubectl apply -f mongo-configmap.yaml

kubectl apply -f catalog-db.yaml

cd ..\catalog-api\

kubectl apply -f catalog-api.yaml

kubectl delete

cd .\Deployments\k8s\catalog\catalog-api\

kubectl delete -f catalog-api.yaml

cd ..\catalog-db\

kubectl delete -f catalog-db.yaml

kubectl delete -f mongo-configmap.yaml

kubectl delete -f mongo-secret.yaml

Catalog API Swagger Access

run kubectl get all

NAME                          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/catalog-api-service   NodePort    10.101.138.221   <none>        9000:31000/TCP   6m58s

The service catalog-api-service is exposed as a NodePort service at port 31000.

To access the API in your browser, you need the IP address of one of your Kubernetes nodes (you can use either the internal or external IP, depending on where you are accessing from) and the NodePort (31000 in this case).

If you're running Kubernetes locally (like minikube), you can usually use localhost or 127.0.0.1 as the IP.

So, the URL to access the API would look something like this:

http://<node-ip>:31000

Replace with the IP address of your Kubernetes node.

If you don't know your node IP, you can get it by running:

kubectl get nodes -o wide

NAME             STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE         KERNEL-VERSION                       CONTAINER-RUNTIME
docker-desktop   Ready    control-plane   77d   v1.28.2   192.168.65.3   <none>        Docker Desktop   5.15.133.1-microsoft-standard-WSL2   docker://24.0.7

The IP addresses will be listed in the INTERNAL-IP or EXTERNAL-IP column.

http://192.168.65.3:31000

Helm

Quickstart

Install

Create / Tag docker images and upload to container repository

Image Repository
basketapi jpcassidy/eshopping-basketapi:latest
catalogapi jpcassidy/eshopping-catalogapi:latest
discountapi jpcassidy/eshopping-discountapi:latest
orderingapi jpcassidy/eshopping-orderingapi:latest
ocelotapigw jpcassidy/eshopping-ocelotapigw:latest

Note: ocelotapigw will need ocelot.k8s.json created and configured to work with kubernetes deployment.

Create / Configure helm charts

Create Helm Charts in .\Deployments\helm folder.

# basketdb
helm create basketdb
# basket
helm create basket
# catalogdb
helm create catalogdb
# catalog
helm create catalog
# discountdb
helm create discountdb
# discount
helm create discount
# elasticsearch
helm create elasticsearch
# kibana
helm create kibana
# ocelotapigw
helm create ocelotapigw
# orderdb
helm create orderdb
# ordering
helm create ordering
# rabbitmq
helm create rabbitmq

Configure values.yaml with properties from docker-compose files. Use the repository image names uploaded to container registry.

Create configure.yaml files to store env variables in the templates folder of each helm chart.

install / uninstall helm charts

# run scripts from /Deployment/helm/ folder
.\install-helm.ps1
~~~~
.\uninstall-helm.ps1

# check context
kubectl config current-context
kubectl get all

How to Build & Push Helm Chart to Docker Hub

Documentation

eshopping's People

Contributors

john-cassidy avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.