[
  {
    "path": ".github/workflows/dotnet-core.yml",
    "content": "name: .NET Core\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v2\n    - name: Setup .NET Core\n      uses: actions/setup-dotnet@v1\n      with:\n        dotnet-version: 3.1.301\n    - name: Install dependencies\n      run: dotnet restore\n    - name: Build\n      run: dotnet build --configuration Release --no-restore\n    - name: Test\n      run: dotnet test --no-restore --verbosity normal\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n# NuGet v3's project.json files produces more ignoreable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n# CodeRush\n.cr/\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n\nNuGet.config\nappsettings.local.json"
  },
  {
    "path": ".postman_project/Dotnet_Istanbul.postman_collection.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"1ce3bc02-2070-441c-9d1a-386db626d78b\",\n\t\t\"name\": \"Dotnet_Istanbul\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"0-RegisterCustomer\",\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Content-Type\",\n\t\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\"value\": \"application/json\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"{\\n\\t\\\"FirstName\\\" :\\\"Suat\\\",\\n\\t\\\"LastName\\\" :\\\"Köse\\\",\\n\\t\\\"Address\\\" :\\\"Üsküdar\\\",\\n\\t\\\"Email\\\" :\\\"suadev@gmail.com\\\",\\n\\t\\\"Password\\\": \\\"12345\\\"\\n}\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"http://localhost:5000/api/customer\",\n\t\t\t\t\t\"protocol\": \"http\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"5000\",\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"api\",\n\t\t\t\t\t\t\"customer\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"1-GetToken\",\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Content-Type\",\n\t\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\"value\": \"application/json\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"{\\n\\t\\\"Email\\\" :\\\"suadev@gmail.com\\\",\\n\\t\\\"Password\\\" :\\\"12345\\\"\\n}\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"http://localhost:5000/api/token\",\n\t\t\t\t\t\"protocol\": \"http\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"5000\",\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"api\",\n\t\t\t\t\t\t\"token\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"2-AddToBasket-Success\",\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Content-Type\",\n\t\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Authorization\",\n\t\t\t\t\t\t\"value\": \"bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6InN1YWRldkBnbWFpbC5jb20iLCJDdXN0b21lcklkIjoiMDQ1NzFlNDQtMDJjYi00Mzc1LWE0MTMtN2NiYTMxZDk2NGMyIiwibmJmIjoxNTUzNjMxNDk5LCJleHAiOjE1NTM3MTc4OTksImlhdCI6MTU1MzYzMTQ5OSwiaXNzIjoid2l6bG8uYXBpLmRlbW8iLCJhdWQiOiJTb21lQ3VzdG9tQXBwIn0.cQOe_IVK8oYzjiDdaNOMo5aviiDMt_gX-PYL-n_NPjc\",\n\t\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"{\\n\\t\\\"ProductId\\\" :\\\"dc87e9ce-6d8d-4a01-a62d-2c2326472811\\\",\\n\\t\\\"Quantity\\\": 10\\n}\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"http://localhost:5000/api/basket\",\n\t\t\t\t\t\"protocol\": \"http\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"5000\",\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"api\",\n\t\t\t\t\t\t\"basket\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"3-CreateOrder\",\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Content-Type\",\n\t\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Authorization\",\n\t\t\t\t\t\t\"value\": \"bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6InN1YWRldkBnbWFpbC5jb20iLCJDdXN0b21lcklkIjoiMDQ1NzFlNDQtMDJjYi00Mzc1LWE0MTMtN2NiYTMxZDk2NGMyIiwibmJmIjoxNTUzNjMxNDk5LCJleHAiOjE1NTM3MTc4OTksImlhdCI6MTU1MzYzMTQ5OSwiaXNzIjoid2l6bG8uYXBpLmRlbW8iLCJhdWQiOiJTb21lQ3VzdG9tQXBwIn0.cQOe_IVK8oYzjiDdaNOMo5aviiDMt_gX-PYL-n_NPjc\",\n\t\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"{}\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"http://localhost:5000/api/order\",\n\t\t\t\t\t\"protocol\": \"http\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"5000\",\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"api\",\n\t\t\t\t\t\t\"order\"\n\t\t\t\t\t],\n\t\t\t\t\t\"query\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"\",\n\t\t\t\t\t\t\t\"value\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"GetAllProducts\",\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"http://localhost:5000/api/product\",\n\t\t\t\t\t\"protocol\": \"http\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"5000\",\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"api\",\n\t\t\t\t\t\t\"product\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"api\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build-api\",\n            \"program\": \"${workspaceFolder}/DotnetIst.Api/src/Api/bin/Debug/netcoreapp2.2/Api.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceFolder}/DotnetIst.Api/src/Api\",\n            \"stopAtEntry\": false,\n            \"internalConsoleOptions\": \"openOnSessionStart\",\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            },\n            \"env\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n                \"ASPNETCORE_URLS\": \"http://localhost:5000\"\n            },\n            \"sourceFileMap\": {\n                \"/Views\": \"${workspaceFolder}/Views\"\n            }\n        },\n        {\n            \"name\": \"customer\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build-customer\",\n            \"program\": \"${workspaceFolder}/DotnetIst.Services.Customers/src/Services.Customers/bin/Debug/netcoreapp2.2/Services.Customers.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceFolder}/DotnetIst.Services.Customers/src/Services.Customers\",\n            \"stopAtEntry\": false,\n            \"internalConsoleOptions\": \"openOnSessionStart\",\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            },\n            \"env\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n                \"ASPNETCORE_URLS\": \"http://localhost:5005\"\n            },\n            \"sourceFileMap\": {\n                \"/Views\": \"${workspaceFolder}/Views\"\n            }\n        },\n        {\n            \"name\": \"products\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build-product\",\n            \"program\": \"${workspaceFolder}/DotnetIst.Services.Products/src/Services.Products/bin/Debug/netcoreapp2.2/Services.Products.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceFolder}/DotnetIst.Services.Products/src/Services.Products\",\n            \"stopAtEntry\": false,\n            \"internalConsoleOptions\": \"openOnSessionStart\",\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            },\n            \"env\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n                \"ASPNETCORE_URLS\": \"http://localhost:5010\"\n            },\n            \"sourceFileMap\": {\n                \"/Views\": \"${workspaceFolder}/Views\"\n            }\n        },\n        {\n            \"name\": \"orders\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build-order\",\n            \"program\": \"${workspaceFolder}/DotnetIst.Services.Orders/src/Services.Orders/bin/Debug/netcoreapp2.2/Services.Orders.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceFolder}/DotnetIst.Services.Orders/src/Services.Orders\",\n            \"stopAtEntry\": false,\n            \"internalConsoleOptions\": \"openOnSessionStart\",\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            },\n            \"env\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n                \"ASPNETCORE_URLS\": \"http://localhost:5015\"\n            },\n            \"sourceFileMap\": {\n                \"/Views\": \"${workspaceFolder}/Views\"\n            }\n        },\n        {\n            \"name\": \"notifications\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build-notification\",\n            \"program\": \"${workspaceFolder}/DotnetIst.Services.Notifications/src/Services.Notifications/bin/Debug/netcoreapp2.2/Services.Notifications.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceFolder}/DotnetIst.Services.Notifications/src/Services.Notifications\",\n            \"stopAtEntry\": false,\n            \"internalConsoleOptions\": \"openOnSessionStart\",\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            },\n            \"env\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\",\n                \"ASPNETCORE_URLS\": \"http://localhost:5020\"\n            },\n            \"sourceFileMap\": {\n                \"/Views\": \"${workspaceFolder}/Views\"\n            }\n        },\n        {\n            \"name\": \".NET Core Attach\",\n            \"type\": \"coreclr\",\n            \"request\": \"attach\",\n            \"processId\": \"${command:pickProcess}\"\n        }\n    ],\n    \"compounds\": [\n        {\n            \"name\": \"All\",\n            \"configurations\": [\n                \"api\",\n                \"customer\",\n                \"products\",\n                \"orders\",\n                \"notifications\"\n            ]\n        },\n        {\n            \"name\": \"Api+Customer\",\n            \"configurations\": [\n                \"api\",\n                \"customer\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"build-api\",\n            \"command\": \"dotnet\",\n            \"type\": \"process\",\n            \"args\": [\n                \"build\",\n                \"${workspaceFolder}/DotnetIst.Api/src/Api/Api.csproj\"\n            ],\n            \"problemMatcher\": \"$msCompile\"\n        },\n        {\n            \"label\": \"build-customer\",\n            \"command\": \"dotnet\",\n            \"type\": \"process\",\n            \"args\": [\n                \"build\",\n                \"${workspaceFolder}/DotnetIst.Services.Customers/src/Services.Customers/Services.Customers.csproj\",\n            ],\n            \"problemMatcher\": \"$msCompile\"\n        },\n        {\n            \"label\": \"build-product\",\n            \"command\": \"dotnet\",\n            \"type\": \"process\",\n            \"args\": [\n                \"build\",\n                \"${workspaceFolder}/DotnetIst.Services.Products/src/Services.Products/Services.Products.csproj\",\n            ],\n            \"problemMatcher\": \"$msCompile\"\n        },\n        {\n            \"label\": \"build-order\",\n            \"command\": \"dotnet\",\n            \"type\": \"process\",\n            \"args\": [\n                \"build\",\n                \"${workspaceFolder}/DotnetIst.Services.Orders/src/Services.Orders/Services.Orders.csproj\",\n            ],\n            \"problemMatcher\": \"$msCompile\"\n        },\n        {\n            \"label\": \"build-notification\",\n            \"command\": \"dotnet\",\n            \"type\": \"process\",\n            \"args\": [\n                \"build\",\n                \"${workspaceFolder}/DotnetIst.Services.Notifications/src/Services.Notifications/Services.Notifications.csproj\",\n            ],\n            \"problemMatcher\": \"$msCompile\"\n        }\n    ]\n}"
  },
  {
    "path": "DotnetIst.Api/README.MD",
    "content": "## Api Gateway\n\ntodo: use ocelot\n\ntodo: create bffs for each channel type"
  },
  {
    "path": "DotnetIst.Api/src/Api/Api.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp2.2</TargetFramework>\n    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.App\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Razor.Design\" Version=\"2.2.0\" PrivateAssets=\"All\" />\n    <ProjectReference Include=\"..\\..\\..\\DotnetIst.Shared\\src\\Shared\\Shared.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/Authentication/AuthenticationExtensions.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Authentication.JwtBearer;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.IdentityModel.Tokens;\n\nnamespace Api.Authentication\n{\n    public static class AuthenticationExtensions\n    {\n        private const string SecretKey = \"SomeStaticAccessKey12345!\";\n        public static void AddJwtAuthentication(this IServiceCollection services)\n        {\n            services\n             .AddScoped<IHttpContextAccessor, HttpContextAccessor>()\n            .AddScoped<IAuthenticationService, AuthenticationService>()\n            .AddAuthentication(x =>\n            {\n                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;\n                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;\n            })\n            .AddJwtBearer(x =>\n            {\n                x.Audience = \"SomeCustomApp\";\n                x.RequireHttpsMetadata = false;\n                x.SaveToken = true;\n                x.ClaimsIssuer = \"dotnetist.api.demo\";\n                x.TokenValidationParameters = new TokenValidationParameters\n                {\n                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey)),\n                    ValidateLifetime = true,\n                    ValidateIssuerSigningKey = true,\n                    ValidateIssuer = false,\n                    ValidateAudience = true\n                };\n                x.Events = new JwtBearerEvents()\n                {\n                    OnTokenValidated = (context) =>\n                    {\n                        var name = context.Principal.Identity.Name;\n                        if (string.IsNullOrEmpty(name))\n                        {\n                            context.Fail(\"Unauthorized. Please re-login\");\n                        }\n                        context.HttpContext.Items.Add(\"CurrentCustomer\",\n                            new TokenModel\n                            {\n                                Email = context.Principal.Identity.Name,\n                                CustomerId = Guid.Parse(\n                                    context.Principal.Claims.First(s => s.Type == \"CustomerId\").Value),\n                            });\n                        return Task.CompletedTask;\n                    }\n                };\n            });\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Authentication/AuthenticationService.cs",
    "content": "using System;\nusing System.IdentityModel.Tokens.Jwt;\nusing System.Security.Claims;\nusing System.Text;\nusing Api.Models;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.IdentityModel.Tokens;\nnamespace Api.Authentication\n{\n    public class AuthenticationService : IAuthenticationService\n    {\n        private IHttpContextAccessor _contextAccessor;\n\n        public AuthenticationService(IHttpContextAccessor contextAccessor)\n        {\n            _contextAccessor = contextAccessor;\n        }\n\n        public TokenModel GetCurrentUser()\n            => _contextAccessor.HttpContext?.Items?[\"CurrentCustomer\"] != null ?\n                    _contextAccessor.HttpContext.Items[\"CurrentCustomer\"] as TokenModel : null;\n\n        public string GetToken(Customer customer)\n        {\n            var tokenHandler = new JwtSecurityTokenHandler();\n            var key = Encoding.ASCII.GetBytes(\"SomeStaticAccessKey12345!\");\n            var tokenDescriptor = new SecurityTokenDescriptor\n            {\n                Audience = \"SomeCustomApp\",\n                Issuer = \"wizlo.api.demo\",\n                Subject = new ClaimsIdentity(new Claim[]\n                {\n                    new Claim(ClaimTypes.Name, customer.Email),\n                    new Claim(\"CustomerId\", customer.Id.ToString())\n                }),\n                Expires = DateTime.UtcNow.AddDays(1),\n                SigningCredentials = new SigningCredentials(\n                        new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)\n            };\n            var token = tokenHandler.CreateToken(tokenDescriptor);\n            return tokenHandler.WriteToken(token);\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Authentication/IAuthenticationService.cs",
    "content": "using Api.Models;\n\nnamespace Api.Authentication\n{\n    public interface IAuthenticationService\n    {\n        string GetToken(Customer customer);\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Authentication/Model/LoginModel.cs",
    "content": "namespace Api.Authentication\n{\n    public class LoginModel\n    {\n        public string Email { get; set; }\n        public string Password { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Authentication/Model/TokenModel.cs",
    "content": "using System;\n\nnamespace Api.Authentication\n{\n    public class TokenModel\n    {\n        public Guid CustomerId { get; set; }\n        public string Email { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Commands/Baskets/AddProductToBasket.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Api.Commands.Baskets\n{\n    [MessageNamespace(\"customers\")]\n    public class AddProductToBasket : ICommand\n    {\n        public Guid ProductId { get; }\n        public int Quantity { get; }\n\n        public AddProductToBasket(Guid productId, int quantity)\n        {\n            ProductId = productId;\n            Quantity = quantity;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Commands/Customers/CreateCustomer.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Api.Commands.Customers\n{\n    [MessageNamespace(\"customers\")]\n    public class CreateCustomer : ICommand\n    {\n        public Guid Id { get; set; }\n        public string Email { get; set; }\n        public string Password { get; set; }\n        public string FirstName { get; set; }\n        public string LastName { get; set; }\n        public string Address { get; set; }\n\n        public CreateCustomer(string email, string password, string firstName, string lastName, string address)\n        {\n            this.Id = Guid.NewGuid();\n            this.Email = email;\n            this.Password = password;\n            this.FirstName = firstName;\n            this.LastName = lastName;\n            this.Address = address;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Commands/Orders/CreateOrder.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Api.Commands.Orders\n{\n    [MessageNamespace(\"orders\")]\n    public class CreateOrder : ICommand\n    {\n        public Guid Id { get; private set; }\n\n        public CreateOrder()\n        {\n            Id = Guid.NewGuid();\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Controllers/BaseController.cs",
    "content": "using System;\nusing Api.Authentication;\nusing Shared.Messages;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Api.Controllers\n{\n    public class BaseController : ControllerBase\n    {\n        protected readonly IBusPublisher BusPublisher;\n        public BaseController(IBusPublisher busPublisher)\n        {\n            BusPublisher = busPublisher;\n        }\n\n        protected TokenModel CurrentUser\n        {\n            get\n            {\n                return HttpContext.Items[\"CurrentCustomer\"] != null ?\n                    HttpContext.Items[\"CurrentCustomer\"] as TokenModel : null;\n            }\n        }\n\n        protected ICorrelationContext GetContext()\n        {\n            return GetContext(CurrentUser.CustomerId);\n        }\n\n        //This method is only for AllowAnonymus CustomerController\n        protected ICorrelationContext GetContext(Guid customerId)\n        {\n            return CorrelationContext.Create(Guid.NewGuid(), customerId);\n        }\n\n        // protected IActionResult Accepted(ICorrelationContext context)\n        // {        //     \n        //     // Response.Headers.Add(OperationHeader, $\"checktransactionstatus/{context.Id}\");\n        //     return base.Accepted();\n        // }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Controllers/BasketController.cs",
    "content": "﻿using System.Threading.Tasks;\nusing Api.Commands.Baskets;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Api.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    [Authorize]\n    public class BasketController : BaseController\n    {\n        public BasketController(IBusPublisher busPublisher) : base(busPublisher)\n        {\n\n        }\n\n        [HttpPost]\n        public async Task<IActionResult> Post(AddProductToBasket command)\n        {\n            var context = GetContext();\n            await BusPublisher.SendAsync(command, context);\n            return Accepted();\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/Controllers/CustomerController.cs",
    "content": "﻿using System.Threading.Tasks;\nusing Api.Commands.Customers;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Api.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    public class CustomerController : BaseController\n    {\n        public CustomerController(IBusPublisher busPublisher) : base(busPublisher)\n        {\n\n        }\n\n        [HttpPost]\n        public async Task<IActionResult> Post(CreateCustomer command)\n        {\n            var context = GetContext(command.Id);\n            await BusPublisher.SendAsync(command, context);\n            return Accepted();\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/Controllers/HomeController.cs",
    "content": "using Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Api.Controllers\n{\n    [Route(\"\")]\n    public class HomeController : ControllerBase\n    {\n        [HttpGet]\n        [AllowAnonymous]\n        public IActionResult Get()\n        {\n            return Ok(\"Api is up.\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Controllers/OrderController.cs",
    "content": "﻿using System.Threading.Tasks;\nusing Api.Commands.Orders;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Api.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    [Authorize]\n    public class OrderController : BaseController\n    {\n        public OrderController(IBusPublisher busPublisher) : base(busPublisher)\n        {\n\n        }\n\n        [HttpPost]\n        public async Task<IActionResult> Post(CreateOrder command)\n        {\n            var context = GetContext();\n            await BusPublisher.SendAsync(command, context);\n            return Accepted();\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/Controllers/ProductController.cs",
    "content": "﻿using System.Threading.Tasks;\nusing Api.Commands.Customers;\nusing Api.HttpServices;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Api.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    public class ProductController : ControllerBase\n    {\n        private readonly IProductHttpService _productHttpService;\n\n        public ProductController(IProductHttpService productHttpService)\n        {\n            _productHttpService = productHttpService;\n        }\n\n        [HttpGet]\n        public async Task<IActionResult> Get()\n        {\n            return Ok(await _productHttpService.GetList());\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/Controllers/TokenController.cs",
    "content": "using System.Threading.Tasks;\nusing Api.Authentication;\nusing Api.HttpServices;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Api.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    public class TokenController : ControllerBase\n    {\n        private readonly IAuthenticationService _authService;\n        private readonly ICustomerHttpService _customerHttpService;\n\n        public TokenController(IAuthenticationService authService,\n                ICustomerHttpService customerHttpService)\n        {\n            _authService = authService;\n            _customerHttpService = customerHttpService;\n        }\n\n        [HttpPost]\n        [AllowAnonymous]\n        public async Task<IActionResult> GenerateToken(LoginModel reqeust)\n        {\n            var customer = await _customerHttpService.GetCustomerByEmail(reqeust.Email);\n\n            if (customer == null)\n            {\n                return BadRequest(\"Customer not found.\");\n            }\n            if (customer.Password != reqeust.Password)\n            {\n                return BadRequest(\"Wrong password.\");\n            }\n\n            return Ok(_authService.GetToken(customer));\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/HttpServices/CustomerHttpService.cs",
    "content": "using System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Api.Models;\nusing Newtonsoft.Json;\n\n\nnamespace Api.HttpServices\n{\n    public class CustomerHttpService : ICustomerHttpService\n    {\n        private HttpClient _client { get; }\n\n        public CustomerHttpService(HttpClient client)\n        {\n            _client = client;\n        }\n\n        public async Task<Customer> GetCustomerByEmail(string email)\n        {\n            var request = new HttpRequestMessage(HttpMethod.Get, $\"customer/customerbyemail/{email}\");\n            var response = await _client.SendAsync(request);\n\n            var content = await response.Content.ReadAsStringAsync();\n            if (response.IsSuccessStatusCode)\n            {\n                response.Content.Dispose();\n                return JsonConvert.DeserializeObject<Customer>(content);\n            }\n            throw new Exception(\"Customer service connection error\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/HttpServices/ICustomerHttpService.cs",
    "content": "using System;\nusing System.Threading.Tasks;\nusing Api.Models;\n\nnamespace Api.HttpServices\n{\n    public interface ICustomerHttpService\n    {\n        Task<Customer> GetCustomerByEmail(string CustomerId);\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/HttpServices/IProductHttpService.cs",
    "content": "using System.Collections.Generic;\nusing System.Threading.Tasks;\n\n\nnamespace Api.HttpServices\n{\n    public interface IProductHttpService\n    {\n        Task<object> GetList();\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/HttpServices/ProductHttpService.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\n\nnamespace Api.HttpServices\n{\n    public class ProductHttpService : IProductHttpService\n    {\n        private HttpClient _client { get; }\n\n        public ProductHttpService(HttpClient client)\n        {\n            _client = client;\n        }\n\n        public async Task<object> GetList()\n        {\n            var request = new HttpRequestMessage(HttpMethod.Get, $\"product\");\n            var response = await _client.SendAsync(request);\n\n            var content = await response.Content.ReadAsStringAsync();\n            if (response.IsSuccessStatusCode)\n            {\n                response.Content.Dispose();\n                return JsonConvert.DeserializeObject<List<object>>(content);\n            }\n            throw new Exception(\"Product service connection error\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Models/Customer.cs",
    "content": "using System;\n\nnamespace Api.Models\n{\n    public class Customer\n    {\n        public Guid Id { get; set; }\n        public string Email { get; set; }\n        public string Password { get; set; }\n        public string FirstName { get; set; }\n        public string LastName { get; set; }\n        public string Address { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Program.cs",
    "content": "﻿using Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Hosting;\nusing Shared.Logging;\n\nnamespace Api\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            CreateWebHostBuilder(args).Build().Run();\n        }\n\n        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>\n            WebHost.CreateDefaultBuilder(args)\n                .UseStartup<Startup>()\n                .UseLogging(\"Api\");\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/Properties/launchSettings.json",
    "content": "﻿{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55301\",\n      \"sslPort\": 44356\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"Api\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Api/src/Api/Startup.cs",
    "content": "﻿using System;\nusing System.Net.Http.Headers;\nusing System.Reflection;\nusing Api.Authentication;\nusing Api.HttpServices;\nusing Autofac;\nusing Autofac.Extensions.DependencyInjection;\nusing Shared.Models;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Shared;\n\nnamespace Api\n{\n    public class Startup\n    {\n        public Startup(IConfiguration configuration)\n        {\n            Configuration = configuration;\n        }\n\n        public IConfiguration Configuration { get; }\n\n        // This method gets called by the runtime. Use this method to add services to the container.\n        public IServiceProvider ConfigureServices(IServiceCollection services)\n        {\n            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);\n            services.AddJwtAuthentication();\n\n            var httpServices = Configuration.GetOptions<HttpServiceOptions>(\"HttpServices\");\n            services.AddHttpClient<ICustomerHttpService, CustomerHttpService>(client =>\n            {\n                client.BaseAddress = new Uri(httpServices.CustomerHttpServiceUrl);\n                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(\"application/json\"));\n            });\n            services.AddHttpClient<IProductHttpService, ProductHttpService>(client =>\n            {\n                client.BaseAddress = new Uri(httpServices.ProductHttpServiceUrl);\n                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(\"application/json\"));\n            });\n\n            return services.BuildContainer();\n        }\n\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            if (env.IsDevelopment())\n            {\n                app.UseDeveloperExceptionPage();\n            }\n\n            app.UseAuthentication();\n            app.UseMvc();\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Debug\",\n      \"System\": \"Information\",\n      \"Microsoft\": \"Information\"\n    }\n  }\n}\n"
  },
  {
    "path": "DotnetIst.Api/src/Api/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\",\n  \"HttpServices\": {\n    \"CustomerHttpServiceUrl\": \"http://localhost:5005/api/\",\n    \"ProductHttpServiceUrl\": \"http://localhost:5010/api/\"\n  },\n  \"rabbitMq\": {\n    \"namespace\": \"api\",\n    \"retries\": 3,\n    \"retryInterval\": 2,\n    \"username\": \"guest\",\n    \"password\": \"guest\",\n    \"virtualHost\": \"/\",\n    \"port\": 5672,\n    \"hostnames\": [\n      \"localhost\"\n    ],\n    \"requestTimeout\": \"00:00:10\",\n    \"publishConfirmTimeout\": \"00:00:01\",\n    \"recoveryInterval\": \"00:00:10\",\n    \"persistentDeliveryMode\": true,\n    \"autoCloseConnection\": true,\n    \"automaticRecovery\": true,\n    \"topologyRecovery\": true,\n    \"exchange\": {\n      \"durable\": true,\n      \"autoDelete\": false,\n      \"type\": \"Topic\"\n    },\n    \"queue\": {\n      \"autoDelete\": false,\n      \"durable\": true,\n      \"exclusive\": false\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/README.MD",
    "content": "**Migration**\n\n0- cd src/Services.Customers\n\n1- *dotnet ef migrations add \"migration_name\" -o ./Data/Migrations*\n\n2- *dotnet ef database update*"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Commands/AddProductToBasket.cs",
    "content": "\nusing System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Customers.Commands\n{\n    public class AddProductToBasket : ICommand\n    {\n        public Guid ProductId { get; }\n        public int Quantity { get; }\n\n        public AddProductToBasket(Guid productId,\n            int quantity)\n        {\n            ProductId = productId;\n            Quantity = quantity;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Commands/CreateCustomer.cs",
    "content": "\nusing System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Customers.Commands\n{\n    public class CreateCustomer : ICommand\n    {\n        public Guid Id { get; set; }\n        public string Email { get; set; }\n        public string Password { get; set; }\n        public string FirstName { get; set; }\n        public string LastName { get; set; }\n        public string Address { get; set; }\n\n        public CreateCustomer(Guid id, string email, string password, string firstName, string lastName, string address)\n        {\n            this.Id = id;\n            this.Password = password;\n            this.Email = email;\n            this.FirstName = firstName;\n            this.LastName = lastName;\n            this.Address = address;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Controllers/BasketController.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.EntityFrameworkCore;\nusing Services.Customers.Data;\n\nnamespace Services.Customers.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    public class BasketController : ControllerBase\n    {\n        private readonly CustomerDBContext _dbContext;\n\n        public BasketController(CustomerDBContext dbContext)\n        {\n            _dbContext = dbContext;\n        }\n        [HttpGet(\"{customerId}\")]\n        public async Task<ActionResult> Get(Guid customerId)\n        {\n            return Ok(await _dbContext.Baskets.Include(i => i.Items)\n                    .FirstOrDefaultAsync(s => s.CustomerId == customerId));\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Controllers/CustomerController.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.EntityFrameworkCore;\nusing Services.Customers.Data;\n\nnamespace Services.Customers.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    public class CustomerController : ControllerBase\n    {\n        private readonly CustomerDBContext _dbContext;\n\n        public CustomerController(CustomerDBContext dbContext)\n        {\n            _dbContext = dbContext;\n        }\n        [HttpGet(\"customerbyemail/{email}\")]\n        public async Task<ActionResult> Get(string email)\n        {\n            return Ok(await _dbContext.Customers\n                    .FirstOrDefaultAsync(s => s.Email == email));\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Controllers/HomeController.cs",
    "content": "using Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Services.Customers.Controllers\n{\n    [Route(\"\")]\n    public class HomeController : ControllerBase\n    {\n        [HttpGet]\n        [AllowAnonymous]\n        public IActionResult Get()\n        {\n            return Ok(\"Customer service is up.\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/CustomerDBContext.cs",
    "content": "using Microsoft.EntityFrameworkCore;\n\nnamespace Services.Customers.Data\n{\n    public class CustomerDBContext : DbContext\n    {\n        public CustomerDBContext(DbContextOptions<CustomerDBContext> options) : base(options)\n        {\n        }\n        public DbSet<Basket> Baskets { get; set; }\n        public DbSet<BasketItem> BasketItems { get; set; }\n        public DbSet<Customer> Customers { get; set; }\n\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            modelBuilder.Entity<Basket>().ToTable(\"Basket\");\n            modelBuilder.Entity<Basket>().HasMany(x => x.Items);\n\n\n            modelBuilder.Entity<BasketItem>().ToTable(\"BasketItem\");\n\n            modelBuilder.Entity<Customer>().ToTable(\"Customer\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Entity/Basket.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing Shared.Models;\n\nnamespace Services.Customers.Data\n{\n    public class Basket : BaseEntity\n    {\n        public Guid CustomerId { get; set; }\n        public List<BasketItem> Items { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Entity/BasketItem.cs",
    "content": "using System;\nusing Shared.Models;\n\nnamespace Services.Customers.Data\n{\n    public class BasketItem : BaseEntity\n    {\n        public Guid BasketId { get; set; }\n        public Guid ProductId { get; set; }\n        public string ProductName { get; set; }\n        public int Quantity { get; set; }\n        public decimal UnitPrice { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Entity/Customer.cs",
    "content": "using System;\nusing Shared.Models;\n\nnamespace Services.Customers.Data\n{\n    public class Customer : BaseEntity\n    {\n        public string Email { get; set; }\n        public string Password { get; set; }\n        public string FirstName { get; set; }\n        public string LastName { get; set; }\n        public string Address { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Migrations/20190308211118_initial.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Customers.Data.Migrations\n{\n    [DbContext(typeof(CustomerDBContext))]\n    [Migration(\"20190308211118_initial\")]\n    partial class initial\n    {\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Customers.Data.Basket\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<DateTime>(\"CreatedAt\");\n\n                    b.Property<Guid>(\"CustomerId\");\n\n\n\n                    b.ToTable(\"Basket\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.BasketItem\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"BasketId\");\n\n                    b.Property<long>(\"ProductId\");\n\n                    b.Property<string>(\"ProductName\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<decimal>(\"UnitPrice\");\n\n\n\n                    b.HasIndex(\"BasketId\");\n\n                    b.ToTable(\"BasketItem\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.Customer\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Address\");\n\n                    b.Property<string>(\"Email\");\n\n                    b.Property<string>(\"FirstName\");\n\n                    b.Property<string>(\"LastName\");\n\n                    b.Property<string>(\"Password\");\n\n\n\n                    b.ToTable(\"Customer\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.BasketItem\", b =>\n                {\n                    b.HasOne(\"Services.Customers.Data.Basket\")\n                        .WithMany(\"Items\")\n                        .HasForeignKey(\"BasketId\")\n                        .OnDelete(DeleteBehavior.Cascade);\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Migrations/20190308211118_initial.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Services.Customers.Data.Migrations\n{\n    public partial class initial : Migration\n    {\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.CreateTable(\n                name: \"Basket\",\n                columns: table => new\n                {\n                    Id = table.Column<Guid>(nullable: false),\n                    CustomerId = table.Column<Guid>(nullable: false),\n                    CreatedAt = table.Column<DateTime>(nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Basket\", x => x.Id);\n                });\n\n            migrationBuilder.CreateTable(\n                name: \"Customer\",\n                columns: table => new\n                {\n                    Id = table.Column<Guid>(nullable: false),\n                    Email = table.Column<string>(nullable: true),\n                    Password = table.Column<string>(nullable: true),\n                    FirstName = table.Column<string>(nullable: true),\n                    LastName = table.Column<string>(nullable: true),\n                    Address = table.Column<string>(nullable: true)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Customer\", x => x.Id);\n                });\n\n            migrationBuilder.CreateTable(\n                name: \"BasketItem\",\n                columns: table => new\n                {\n                    Id = table.Column<Guid>(nullable: false),\n                    BasketId = table.Column<Guid>(nullable: false),\n                    ProductId = table.Column<long>(nullable: false),\n                    ProductName = table.Column<string>(nullable: true),\n                    Quantity = table.Column<int>(nullable: false),\n                    UnitPrice = table.Column<decimal>(nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_BasketItem\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_BasketItem_Basket_BasketId\",\n                        column: x => x.BasketId,\n                        principalTable: \"Basket\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                });\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_BasketItem_BasketId\",\n                table: \"BasketItem\",\n                column: \"BasketId\");\n        }\n\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropTable(\n                name: \"BasketItem\");\n\n            migrationBuilder.DropTable(\n                name: \"Customer\");\n\n            migrationBuilder.DropTable(\n                name: \"Basket\");\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Migrations/20190308222102_base_entity.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Customers.Data.Migrations\n{\n    [DbContext(typeof(CustomerDBContext))]\n    [Migration(\"20190308222102_base_entity\")]\n    partial class base_entity\n    {\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Customers.Data.Basket\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"CustomerId\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.ToTable(\"Basket\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.BasketItem\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"BasketId\");\n\n                    b.Property<long>(\"ProductId\");\n\n                    b.Property<string>(\"ProductName\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<decimal>(\"UnitPrice\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.HasIndex(\"BasketId\");\n\n                    b.ToTable(\"BasketItem\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.Customer\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Address\");\n\n                    b.Property<string>(\"Email\");\n\n                    b.Property<string>(\"FirstName\");\n\n                    b.Property<string>(\"LastName\");\n\n                    b.Property<string>(\"Password\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.ToTable(\"Customer\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.BasketItem\", b =>\n                {\n                    b.HasOne(\"Services.Customers.Data.Basket\")\n                        .WithMany(\"Items\")\n                        .HasForeignKey(\"BasketId\")\n                        .OnDelete(DeleteBehavior.Cascade);\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Migrations/20190308222102_base_entity.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Services.Customers.Data.Migrations\n{\n    public partial class base_entity : Migration\n    {\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.RenameColumn(\n                name: \"CreatedAt\",\n                table: \"Basket\",\n                newName: \"UpdateDate\");\n\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"UpdateDate\",\n                table: \"Customer\",\n                nullable: false,\n                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));\n\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"UpdateDate\",\n                table: \"BasketItem\",\n                nullable: false,\n                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));\n        }\n\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"UpdateDate\",\n                table: \"Customer\");\n\n            migrationBuilder.DropColumn(\n                name: \"UpdateDate\",\n                table: \"BasketItem\");\n\n            migrationBuilder.RenameColumn(\n                name: \"UpdateDate\",\n                table: \"Basket\",\n                newName: \"CreatedAt\");\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/Migrations/CustomerDBContextModelSnapshot.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Customers.Data.Migrations\n{\n    [DbContext(typeof(CustomerDBContext))]\n    partial class CustomerDBContextModelSnapshot : ModelSnapshot\n    {\n        protected override void BuildModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Customers.Data.Basket\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"CustomerId\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.ToTable(\"Basket\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.BasketItem\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"BasketId\");\n\n                    b.Property<long>(\"ProductId\");\n\n                    b.Property<string>(\"ProductName\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<decimal>(\"UnitPrice\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.HasIndex(\"BasketId\");\n\n                    b.ToTable(\"BasketItem\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.Customer\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Address\");\n\n                    b.Property<string>(\"Email\");\n\n                    b.Property<string>(\"FirstName\");\n\n                    b.Property<string>(\"LastName\");\n\n                    b.Property<string>(\"Password\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.ToTable(\"Customer\");\n                });\n\n            modelBuilder.Entity(\"Services.Customers.Data.BasketItem\", b =>\n                {\n                    b.HasOne(\"Services.Customers.Data.Basket\")\n                        .WithMany(\"Items\")\n                        .HasForeignKey(\"BasketId\")\n                        .OnDelete(DeleteBehavior.Cascade);\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Data/SeedData.cs",
    "content": "using System;\nusing System.Linq;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Services.Customers.Data\n{\n    public static class SeedData\n    {\n        public static void Initialize(IServiceProvider serviceProvider)\n        {\n            var context = serviceProvider.GetRequiredService<CustomerDBContext>();\n            context.Database.EnsureCreated();\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Events/OrderCompleted.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Customers.Events\n{\n    public class OrderCompleted : IEvent\n    {\n        public Guid Id { get; }\n\n        public OrderCompleted(Guid id)\n        {\n            Id = id;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Events/ProductAddedToBasket.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Customers.Events\n{\n    public class ProductAddedToBasket : IEvent\n    {\n        public Guid ProductId { get; }\n        public int Quantity { get; }\n\n        public ProductAddedToBasket(Guid productId, int quantity)\n        {\n            ProductId = productId;\n            Quantity = quantity;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Handlers/AddProductToBasketHandler.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.Logging;\nusing Services.Customers.Commands;\nusing Services.Customers.Data;\nusing Services.Customers.Events;\nusing Services.Customers.HttpServices;\n\nnamespace Services.Customers.Handlers\n{\n    public class AddProductToBasketHandler : ICommandHandler<AddProductToBasket>\n    {\n        private readonly IBusPublisher _busPublisher;\n        private readonly CustomerDBContext _dbContext;\n        private readonly IProductHttpService _productHttpService;\n        private readonly ILogger<AddProductToBasketHandler> _logger;\n\n        public AddProductToBasketHandler(IBusPublisher busPublisher,\n            CustomerDBContext dbContext,\n            IProductHttpService productHttpService,\n            ILogger<AddProductToBasketHandler> logger\n            )\n        {\n            _productHttpService = productHttpService;\n            _logger = logger;\n            _busPublisher = busPublisher;\n            _dbContext = dbContext;\n        }\n\n        public async Task HandleAsync(AddProductToBasket command, ICorrelationContext context)\n        {\n            // Warning: Customer service needs Product service's data.\n            // What if Product service can't response for a while? (assume no retry policy)\n            // DDD - sharing data betwwen bounded cotext\n\n            var product = await _productHttpService.GetAsync(command.ProductId);\n            if (product == null)\n                throw new Exception($\"Product not found. Id: {command.ProductId}\");\n\n            var basket = await _dbContext.Baskets.FirstOrDefaultAsync(q => q.CustomerId == context.CustomerId);\n            if (basket == null)\n                throw new Exception($\"Basket not found for customer: {context.CustomerId}\");\n\n            var basketItem = await _dbContext.BasketItems.FirstOrDefaultAsync(q => q.ProductId == command.ProductId);\n\n            if (basketItem != null)\n            {\n                basketItem.Quantity += command.Quantity;\n            }\n            else\n            {\n                _dbContext.BasketItems.Add(\n                    new BasketItem\n                    {\n                        BasketId = basket.Id,\n                        ProductId = command.ProductId,\n                        Quantity = command.Quantity,\n                        ProductName = product.Name,\n                        UnitPrice = product.Price\n                    });\n            }\n\n            await _dbContext.SaveChangesAsync();\n\n            // no event, just logging.\n            _logger.LogInformation($\"[Local Transaction] : {command.Quantity} {product.Name} added to basket. CorrelationId: {context.CorrelationId}\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Handlers/CreateCustomerdHandler.cs",
    "content": "using System;\nusing System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Logging;\nusing Services.Customers.Commands;\nusing Services.Customers.Data;\n\nnamespace Services.Customers.Handlers\n{\n    public class CreateCustomerdHandler : ICommandHandler<CreateCustomer>\n    {\n        private readonly IBusPublisher _busPublisher;\n        private readonly CustomerDBContext _dbContext;\n        private readonly ILogger<CreateCustomerdHandler> _logger;\n\n        public CreateCustomerdHandler(IBusPublisher busPublisher,\n                                        CustomerDBContext dbContext,\n                                        ILogger<CreateCustomerdHandler> logger)\n        {\n            _logger = logger;\n            _busPublisher = busPublisher;\n            _dbContext = dbContext;\n        }\n        public async Task HandleAsync(CreateCustomer _event, ICorrelationContext context)\n        {\n            _dbContext.Customers.Add(new Customer\n            {\n                Id = _event.Id,\n                Password = _event.Password,\n                Email = _event.Email,\n                FirstName = _event.FirstName,\n                LastName = _event.LastName,\n                Address = _event.Address\n            });\n\n            _dbContext.Baskets.Add(new Basket\n            {\n                CustomerId = _event.Id\n            });\n\n            await _dbContext.SaveChangesAsync();\n            _logger.LogInformation($\"[Local Transaction] : Customer created. CorrelataionId: {context.CorrelationId}\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Handlers/OrderCompletedHandler.cs",
    "content": "using System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.Logging;\nusing Services.Customers.Data;\nusing Services.Customers.Events;\n\nnamespace Services.Customers.Handlers\n{\n    public class OrderCompletedHandler : IEventHandler<OrderCompleted>\n    {\n        private readonly IBusPublisher _busPublisher;\n        private readonly CustomerDBContext _dbContext;\n        private readonly ILogger<OrderCompletedHandler> _logger;\n\n        public OrderCompletedHandler(IBusPublisher busPublisher,\n                                    CustomerDBContext dbContext,\n                                    ILogger<OrderCompletedHandler> logger)\n        {\n            _logger = logger;\n            _busPublisher = busPublisher;\n            _dbContext = dbContext;\n        }\n        public async Task HandleAsync(OrderCompleted _event, ICorrelationContext context)\n        {\n            var basket = await _dbContext.Baskets\n                .Include(i => i.Items)\n                .FirstOrDefaultAsync(q => q.CustomerId == context.CustomerId);\n\n            _dbContext.BasketItems.RemoveRange(basket.Items);\n            await _dbContext.SaveChangesAsync();\n            //no event, just logging\n            _logger.LogInformation($\"[Local Transaction] : Basket items cleared. CorrelationId: {context.CorrelationId}\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/HttpServices/IProductHttpService.cs",
    "content": "using System;\nusing System.Threading.Tasks;\nusing Services.Customers.Data;\nusing Services.Customers.Models;\n\nnamespace Services.Customers.HttpServices\n{\n    public interface IProductHttpService\n    {\n        Task<Product> GetAsync(Guid id);\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/HttpServices/ProductHttpService.cs",
    "content": "using System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\nusing Services.Customers.Data;\nusing Services.Customers.Models;\n\nnamespace Services.Customers.HttpServices\n{\n    public class ProductHttpService : IProductHttpService\n    {\n        private HttpClient _client { get; }\n\n        public ProductHttpService(HttpClient client)\n        {\n            _client = client;\n        }\n\n        public async Task<Product> GetAsync(Guid id)\n        {\n            var request = new HttpRequestMessage(HttpMethod.Get, $\"product/{id}\");\n            var response = await _client.SendAsync(request);\n\n            var content = await response.Content.ReadAsStringAsync();\n            if (response.IsSuccessStatusCode)\n            {\n                response.Content.Dispose();\n                return JsonConvert.DeserializeObject<Product>(content);\n            }\n            throw new Exception(\"Product service connection error\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Models/Product.cs",
    "content": "using System;\n\nnamespace Services.Customers.Models\n{\n    public class Product\n    {\n        public Guid Id { get; set; }\n        public string Name { get; set; }\n        public decimal Price { get; set; }\n        public int Quantity { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Program.cs",
    "content": "﻿using Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Hosting;\nusing Shared.Logging;\n\nnamespace Services.Customers\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            CreateWebHostBuilder(args).Build().Run();\n        }\n        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>\n            WebHost.CreateDefaultBuilder(args)\n                .UseStartup<Startup>()\n                .UseLogging(\"Customer.Service\");\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Properties/launchSettings.json",
    "content": "﻿{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:5834\",\n      \"sslPort\": 44386\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"src\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"http://localhost:5005\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Services.Customers.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp2.2</TargetFramework>\n    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.App\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Razor.Design\" Version=\"2.2.0\" PrivateAssets=\"All\" />\n    <ProjectReference Include=\"..\\..\\..\\DotnetIst.Shared\\src\\Shared\\Shared.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/Startup.cs",
    "content": "﻿using System;\nusing System.Net.Http.Headers;\nusing Shared.Models;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Services.Customers.Commands;\nusing Services.Customers.Data;\nusing Shared;\nusing Services.Customers.HttpServices;\nusing Services.Customers.Events;\n\nnamespace Services.Customers\n{\n    public class Startup\n    {\n        public Startup(IConfiguration configuration)\n        {\n            Configuration = configuration;\n        }\n\n        public IConfiguration Configuration { get; }\n\n        // This method gets called by the runtime. Use this method to add services to the container.\n        public IServiceProvider ConfigureServices(IServiceCollection services)\n        {\n            services.AddDbContext<CustomerDBContext>(options =>\n                options.UseNpgsql(Configuration.GetConnectionString(\"DefaultConnection\"))\n            );\n\n            var httpServices = Configuration.GetOptions<HttpServiceOptions>(\"HttpServices\");\n            services.AddHttpClient<IProductHttpService, ProductHttpService>(client =>\n            {\n                client.BaseAddress = new Uri(httpServices.ProductHttpServiceUrl);\n                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(\"application/json\"));\n            });\n\n            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);\n\n            return services.BuildContainer();\n        }\n\n\n\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            if (env.IsDevelopment())\n            {\n                app.UseDeveloperExceptionPage();\n            }\n\n            app.UseMvc();\n            app.UseRabbitMq()\n               .SubscribeCommand<CreateCustomer>()\n               .SubscribeCommand<AddProductToBasket>()\n               .SubscribeEvent<OrderCompleted>();\n\n            SeedData.Initialize(app.ApplicationServices);\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Debug\",\n      \"System\": \"Information\",\n      \"Microsoft\": \"Information\"\n    }\n  }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Customers/src/Services.Customers/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\",\n  \"ConnectionStrings\": {\n    \"DefaultConnection\": \"Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=Customers;\"\n  },\n  \"HttpServices\": {\n    \"ProductHttpServiceUrl\": \"http://localhost:5010/api/\"\n  },\n  \"rabbitMq\": {\n    \"namespace\": \"customers\",\n    \"retries\": 3,\n    \"retryInterval\": 2,\n    \"username\": \"guest\",\n    \"password\": \"guest\",\n    \"virtualHost\": \"/\",\n    \"port\": 5672,\n    \"hostnames\": [\n      \"localhost\"\n    ],\n    \"requestTimeout\": \"00:00:10\",\n    \"publishConfirmTimeout\": \"00:00:01\",\n    \"recoveryInterval\": \"00:00:10\",\n    \"persistentDeliveryMode\": true,\n    \"autoCloseConnection\": true,\n    \"automaticRecovery\": true,\n    \"topologyRecovery\": true,\n    \"exchange\": {\n      \"durable\": true,\n      \"autoDelete\": false,\n      \"type\": \"Topic\"\n    },\n    \"queue\": {\n      \"autoDelete\": false,\n      \"durable\": true,\n      \"exclusive\": false\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Notifications/README.MD",
    "content": "**NotificationService**"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Controllers/HomeController.cs",
    "content": "using Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Services.Notifications.Controllers\n{\n    [Route(\"\")]\n    public class HomeController : ControllerBase\n    {\n        [HttpGet]\n        [AllowAnonymous]\n        public IActionResult Get()\n        {\n            return Ok(\"Notification service is up.\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Events/OrderCompleted.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Notifications.Events\n{\n    [MessageNamespace(\"customers\")]\n    public class OrderCompleted : IEvent\n    {\n        public Guid Id { get; }\n\n        public OrderCompleted(Guid id)\n        {\n            Id = id;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Events/OrderFailed.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Notifications.Events\n{\n    public class OrderFailed : IEvent\n    {\n        public Guid Id { get; }\n\n        public OrderFailed(Guid id)\n        {\n            Id = id;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Handlers/OrderCompletedHandler.cs",
    "content": "using System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Logging;\nusing Services.Notifications.Events;\n\nnamespace Services.Notifications.Handlers\n{\n    public class OrderCompletedHandler : IEventHandler<OrderCompleted>\n    {\n        private readonly ILogger<OrderCompletedHandler> _logger;\n        public OrderCompletedHandler(ILogger<OrderCompletedHandler> logger)\n        {\n            _logger = logger;\n        }\n        public async Task HandleAsync(OrderCompleted _event, ICorrelationContext context)\n        {\n            // Order completed sms/mail/push...\n            _logger.LogInformation($\"[Local Transaction] : Notification sent for Created Order. CorrelationId: {context.CorrelationId}\");\n            await Task.CompletedTask;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Handlers/OrderFailedHandler.cs",
    "content": "using System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Logging;\nusing Services.Notifications.Events;\n\nnamespace Services.Notifications.Handlers\n{\n    public class OrderFailedHandler : IEventHandler<OrderFailed>\n    {\n        private readonly ILogger<OrderFailedHandler> _logger;\n        public OrderFailedHandler(ILogger<OrderFailedHandler> logger)\n        {\n            _logger = logger;\n        }\n        public async Task HandleAsync(OrderFailed _event, ICorrelationContext context)\n        {\n            // Order failed sms/mail/push...\n            _logger.LogInformation($\"[Local Transaction] : Notification sent for Failed Order. CorrelationId: {context.CorrelationId}\");\n            await Task.CompletedTask;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Program.cs",
    "content": "﻿using Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Hosting;\nusing Shared.Logging;\n\nnamespace Services.Notifications\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            CreateWebHostBuilder(args).Build().Run();\n        }\n\n        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>\n            WebHost.CreateDefaultBuilder(args)\n                .UseStartup<Startup>()\n                .UseLogging(\"Notification.Service\");\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Properties/launchSettings.json",
    "content": "﻿{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:34801\",\n      \"sslPort\": 44346\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"Services.Notifications\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"http://localhost:5020\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Services.Notifications.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp2.2</TargetFramework>\n    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.App\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Razor.Design\" Version=\"2.2.0\" PrivateAssets=\"All\" />\n    <ProjectReference Include=\"..\\..\\..\\DotnetIst.Shared\\src\\Shared\\Shared.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/Startup.cs",
    "content": "﻿using System;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Services.Notifications.Events;\nusing Shared;\n\nnamespace Services.Notifications\n{\n    public class Startup\n    {\n        public Startup(IConfiguration configuration)\n        {\n            Configuration = configuration;\n        }\n\n        public IConfiguration Configuration { get; }\n\n        // This method gets called by the runtime. Use this method to add services to the container.\n        public IServiceProvider ConfigureServices(IServiceCollection services)\n        {\n            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);\n\n            return services.BuildContainer();\n        }\n\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            if (env.IsDevelopment())\n            {\n                app.UseDeveloperExceptionPage();\n            }\n\n            app.UseMvc();\n            app.UseRabbitMq()\n               .SubscribeEvent<OrderCompleted>(_namespace: \"customers\")\n               .SubscribeEvent<OrderFailed>();\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Debug\",\n      \"System\": \"Information\",\n      \"Microsoft\": \"Information\"\n    }\n  }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Notifications/src/Services.Notifications/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\",\n  \"rabbitMq\": {\n    \"namespace\": \"notifications\",\n    \"retries\": 3,\n    \"retryInterval\": 2,\n    \"username\": \"guest\",\n    \"password\": \"guest\",\n    \"virtualHost\": \"/\",\n    \"port\": 5672,\n    \"hostnames\": [\n      \"localhost\"\n    ],\n    \"requestTimeout\": \"00:00:10\",\n    \"publishConfirmTimeout\": \"00:00:01\",\n    \"recoveryInterval\": \"00:00:10\",\n    \"persistentDeliveryMode\": true,\n    \"autoCloseConnection\": true,\n    \"automaticRecovery\": true,\n    \"topologyRecovery\": true,\n    \"exchange\": {\n      \"durable\": true,\n      \"autoDelete\": false,\n      \"type\": \"Topic\"\n    },\n    \"queue\": {\n      \"autoDelete\": false,\n      \"durable\": true,\n      \"exclusive\": false\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/README.md",
    "content": "**Migration**\n\n0- cd src/Services.Products\n\n1- *dotnet ef migrations add \"migration_name\" -o ./Data/Migrations*\n\n2- *dotnet ef database update*"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Commands/CreateOrder.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Orders.Commands\n{\n    public class CreateOrder : ICommand\n    {\n        public Guid Id { get; }\n\n        public CreateOrder(Guid id)\n        {\n            this.Id = id;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Controllers/HomeController.cs",
    "content": "using Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Services.Orders.Controllers\n{\n    [Route(\"\")]\n    public class HomeController : ControllerBase\n    {\n        [HttpGet]\n        [AllowAnonymous]\n        public IActionResult Get()\n        {\n            return Ok(\"Order service is up.\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Entity/Order.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Shared.Models;\n\nnamespace Services.Orders.Data\n{\n    public class Order : BaseEntity\n    {\n        public Guid CustomerId { get; set; }\n        public List<OrderItem> Items { get; set; }\n        public decimal TotalAmount { get; set; }\n        public OrderStatus Status { get; set; }\n    }\n}\n\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Entity/OrderItem.cs",
    "content": "using System;\nusing Shared.Models;\n\nnamespace Services.Orders.Data\n{\n    public class OrderItem : BaseEntity\n    {\n        public Guid OrderId { get; set; }\n        public Guid ProductId { get; set; }\n        public string Name { get; set; }\n        public int Quantity { get; set; }\n        public decimal UnitPrice { get; set; }\n        public decimal TotalPrice => Quantity * UnitPrice;\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Entity/OrderStatus.cs",
    "content": "namespace Services.Orders.Data\n{\n    public enum OrderStatus\n    {\n        Created = 0,\n        Completed = 1,\n        Failed = 2\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Migrations/20190308211841_initial.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Orders.Data.Migrations\n{\n    [DbContext(typeof(OrderDBContext))]\n    [Migration(\"20190308211841_initial\")]\n    partial class initial\n    {\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Orders.Data.Order\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"CustomerId\");\n\n                    b.Property<int>(\"Status\");\n\n                    b.Property<decimal>(\"TotalAmount\");\n\n\n\n                    b.ToTable(\"Order\");\n                });\n\n            modelBuilder.Entity(\"Services.Orders.Data.OrderItem\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Name\");\n\n                    b.Property<Guid>(\"OrderId\");\n\n                    b.Property<long>(\"ProductId\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<decimal>(\"UnitPrice\");\n\n\n\n                    b.HasIndex(\"OrderId\");\n\n                    b.ToTable(\"OrderItem\");\n                });\n\n            modelBuilder.Entity(\"Services.Orders.Data.OrderItem\", b =>\n                {\n                    b.HasOne(\"Services.Orders.Data.Order\")\n                        .WithMany(\"Items\")\n                        .HasForeignKey(\"OrderId\")\n                        .OnDelete(DeleteBehavior.Cascade);\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Migrations/20190308211841_initial.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Services.Orders.Data.Migrations\n{\n    public partial class initial : Migration\n    {\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.CreateTable(\n                name: \"Order\",\n                columns: table => new\n                {\n                    Id = table.Column<Guid>(nullable: false),\n                    CustomerId = table.Column<Guid>(nullable: false),\n                    TotalAmount = table.Column<decimal>(nullable: false),\n                    Status = table.Column<int>(nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Order\", x => x.Id);\n                });\n\n            migrationBuilder.CreateTable(\n                name: \"OrderItem\",\n                columns: table => new\n                {\n                    Id = table.Column<Guid>(nullable: false),\n                    OrderId = table.Column<Guid>(nullable: false),\n                    ProductId = table.Column<long>(nullable: false),\n                    Name = table.Column<string>(nullable: true),\n                    Quantity = table.Column<int>(nullable: false),\n                    UnitPrice = table.Column<decimal>(nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_OrderItem\", x => x.Id);\n                    table.ForeignKey(\n                        name: \"FK_OrderItem_Order_OrderId\",\n                        column: x => x.OrderId,\n                        principalTable: \"Order\",\n                        principalColumn: \"Id\",\n                        onDelete: ReferentialAction.Cascade);\n                });\n\n            migrationBuilder.CreateIndex(\n                name: \"IX_OrderItem_OrderId\",\n                table: \"OrderItem\",\n                column: \"OrderId\");\n        }\n\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropTable(\n                name: \"OrderItem\");\n\n            migrationBuilder.DropTable(\n                name: \"Order\");\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Migrations/20190308222202_base_entity.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Orders.Data.Migrations\n{\n    [DbContext(typeof(OrderDBContext))]\n    [Migration(\"20190308222202_base_entity\")]\n    partial class base_entity\n    {\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Orders.Data.Order\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"CustomerId\");\n\n                    b.Property<int>(\"Status\");\n\n                    b.Property<decimal>(\"TotalAmount\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.ToTable(\"Order\");\n                });\n\n            modelBuilder.Entity(\"Services.Orders.Data.OrderItem\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Name\");\n\n                    b.Property<Guid>(\"OrderId\");\n\n                    b.Property<long>(\"ProductId\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<decimal>(\"UnitPrice\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.HasIndex(\"OrderId\");\n\n                    b.ToTable(\"OrderItem\");\n                });\n\n            modelBuilder.Entity(\"Services.Orders.Data.OrderItem\", b =>\n                {\n                    b.HasOne(\"Services.Orders.Data.Order\")\n                        .WithMany(\"Items\")\n                        .HasForeignKey(\"OrderId\")\n                        .OnDelete(DeleteBehavior.Cascade);\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Migrations/20190308222202_base_entity.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Services.Orders.Data.Migrations\n{\n    public partial class base_entity : Migration\n    {\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"UpdateDate\",\n                table: \"OrderItem\",\n                nullable: false,\n                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));\n\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"UpdateDate\",\n                table: \"Order\",\n                nullable: false,\n                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));\n        }\n\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"UpdateDate\",\n                table: \"OrderItem\");\n\n            migrationBuilder.DropColumn(\n                name: \"UpdateDate\",\n                table: \"Order\");\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/Migrations/OrderDBContextModelSnapshot.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Orders.Data.Migrations\n{\n    [DbContext(typeof(OrderDBContext))]\n    partial class OrderDBContextModelSnapshot : ModelSnapshot\n    {\n        protected override void BuildModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Orders.Data.Order\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<Guid>(\"CustomerId\");\n\n                    b.Property<int>(\"Status\");\n\n                    b.Property<decimal>(\"TotalAmount\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.ToTable(\"Order\");\n                });\n\n            modelBuilder.Entity(\"Services.Orders.Data.OrderItem\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Name\");\n\n                    b.Property<Guid>(\"OrderId\");\n\n                    b.Property<long>(\"ProductId\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<decimal>(\"UnitPrice\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.HasIndex(\"OrderId\");\n\n                    b.ToTable(\"OrderItem\");\n                });\n\n            modelBuilder.Entity(\"Services.Orders.Data.OrderItem\", b =>\n                {\n                    b.HasOne(\"Services.Orders.Data.Order\")\n                        .WithMany(\"Items\")\n                        .HasForeignKey(\"OrderId\")\n                        .OnDelete(DeleteBehavior.Cascade);\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/OrderDBContext.cs",
    "content": "using Microsoft.EntityFrameworkCore;\nusing Services.Orders.Data;\n\nnamespace Services.Customers.Data\n{\n    public class OrderDBContext : DbContext\n    {\n        public OrderDBContext(DbContextOptions<OrderDBContext> options) : base(options)\n        {\n        }\n        public DbSet<Order> Orders { get; set; }\n\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            modelBuilder.Entity<Order>().ToTable(\"Order\");\n            modelBuilder.Entity<Order>().HasMany(x => x.Items);\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Data/SeedData.cs",
    "content": "using System;\nusing System.Linq;\nusing Microsoft.Extensions.DependencyInjection;\nusing Services.Customers.Data;\n\nnamespace Services.Orders.Data\n{\n    public static class SeedData\n    {\n        public static void Initialize(IServiceProvider serviceProvider)\n        {\n            var context = serviceProvider.GetRequiredService<OrderDBContext>();\n            context.Database.EnsureCreated();\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Events/OrderCompleted.cs",
    "content": "using System;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Orders.Events\n{\n    [MessageNamespace(\"customers\")]\n    public class OrderCompleted : IEvent\n    {\n        public Guid Id { get; }\n\n        public OrderCompleted(Guid id)\n        {\n            Id = id;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Events/OrderCreated.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Orders.Events\n{\n    [MessageNamespace(\"products\")]\n    public class OrderCreated : IEvent\n    {\n        public Guid Id { get; }\n        public IDictionary<Guid, int> Products { get; } // id, quantity\n\n        public OrderCreated(Guid id, IDictionary<Guid, int> products)\n        {\n            Id = id;\n            Products = products;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Events/OrderFailed.cs",
    "content": "using System;\nusing Shared.Messages;\n\nnamespace Services.Orders.Events\n{\n    [MessageNamespace(\"notifications\")]\n    public class OrderFailed : IEvent\n    {\n        public Guid OrderId { get; set; }\n        public OrderFailed(Guid orderId)\n        {\n            this.OrderId = orderId;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Events/ProductsReserveFailed.cs",
    "content": "using System;\nusing Shared.Messages;\n\nnamespace Services.Orders.Events\n{\n    public class ProductsReserveFailed : IEvent\n    {\n        public Guid OrderId { get; set; }\n        public ProductsReserveFailed(Guid orderId)\n        {\n            this.OrderId = orderId;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Events/ProductsReserved.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing Shared.Messages;\n\nnamespace Services.Orders.Events\n{\n    public class ProductsReserved : IEvent\n    {\n        public Guid OrderId { get; set; }\n        public IDictionary<Guid, int> Products { get; set; }\n\n        public ProductsReserved(Guid orderId, IDictionary<Guid, int> products)\n        {\n            OrderId = orderId;\n            Products = products;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Handlers/CreateOrderHandler.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Logging;\nusing Services.Customers.Data;\nusing Services.Orders.Commands;\nusing Services.Orders.Data;\nusing Services.Orders.Events;\nusing Services.Orders.HttpServices;\n\nnamespace Services.Orders.Handlers\n{\n    public class CreateOrderHandler : ICommandHandler<CreateOrder>\n    {\n        private readonly IBusPublisher _busPublisher;\n        private readonly ICustomerHttpService _customerHttpService;\n        private readonly OrderDBContext _dbContext;\n        private readonly ILogger<CreateOrderHandler> _logger;\n\n        public CreateOrderHandler(IBusPublisher busPublisher,\n               ICustomerHttpService customerHttpService,\n               OrderDBContext dbContext,\n               ILogger<CreateOrderHandler> logger)\n        {\n            _busPublisher = busPublisher;\n            _customerHttpService = customerHttpService;\n            _dbContext = dbContext;\n            _logger = logger;\n        }\n\n        public async Task HandleAsync(CreateOrder command, ICorrelationContext context)\n        {\n            // Warning: Order service needs Customer service's data.\n            // What if Customer service can't response for a while? (assume no retry policy)   \n\n            var basket = await _customerHttpService.GetBasket(context.CustomerId);\n\n            var items = basket.Items.Select(i =>\n                new OrderItem\n                {\n                    Id = Guid.NewGuid(),\n                    OrderId = command.Id,\n                    ProductId = i.ProductId,\n                    Name = i.ProductName,\n                    Quantity = i.Quantity,\n                    UnitPrice = i.UnitPrice\n                }).ToList();\n\n            var order = new Order\n            {\n                Status = OrderStatus.Created,\n                Id = command.Id,\n                CustomerId = context.CustomerId,\n                Items = items,\n                TotalAmount = items.Sum(s => s.TotalPrice)\n            };\n\n            _dbContext.Orders.Add(order);\n            await _dbContext.SaveChangesAsync();\n\n            _logger.LogInformation($\"[Local Transaction] : Order created. CorrelationId: {context.CorrelationId}\");\n            await _busPublisher.PublishAsync(new OrderCreated(\n                command.Id, items.ToDictionary(i => i.ProductId, i => i.Quantity)), context);\n\n\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Handlers/ProductsReserveFailedHandler.cs",
    "content": "using System;\nusing System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Logging;\nusing Services.Customers.Data;\nusing Services.Orders.Data;\nusing Services.Orders.Events;\n\nnamespace Services.Orders.Handlers\n{\n    public class ProductsReserveFailedHandler : IEventHandler<ProductsReserveFailed>\n    {\n        private readonly IBusPublisher _busPublisher;\n        private readonly OrderDBContext _dbContext;\n        private readonly ILogger<ProductsReserveFailedHandler> _logger;\n\n        public ProductsReserveFailedHandler(IBusPublisher busPublisher,\n                                         OrderDBContext dbContext,\n                                         ILogger<ProductsReserveFailedHandler> logger)\n        {\n            _logger = logger;\n            _busPublisher = busPublisher;\n            _dbContext = dbContext;\n        }\n        public async Task HandleAsync(ProductsReserveFailed _event, ICorrelationContext context)\n        {\n            var order = await _dbContext.Orders.FindAsync(_event.OrderId);\n            order.Status = OrderStatus.Failed;\n            order.UpdateDate = DateTime.Now;\n\n            await _dbContext.SaveChangesAsync();\n            _logger.LogInformation($\"[Local Transaction] : Order failed. CorrelationId: {context.CorrelationId}\");\n            await _busPublisher.PublishAsync(new OrderFailed(_event.OrderId), context);\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Handlers/ProductsReservedHandler.cs",
    "content": "using System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Logging;\nusing Services.Customers.Data;\nusing Services.Orders.Data;\nusing Services.Orders.Events;\n\nnamespace Services.Orders.Handlers\n{\n    public class ProductsReservedHandler : IEventHandler<ProductsReserved>\n    {\n        private readonly IBusPublisher _busPublisher;\n        private readonly OrderDBContext _dbContext;\n        private readonly ILogger<ProductsReservedHandler> _logger;\n\n        public ProductsReservedHandler(IBusPublisher busPublisher,\n                         OrderDBContext dbContext,\n                         ILogger<ProductsReservedHandler> logger)\n        {\n            _logger = logger;\n            _busPublisher = busPublisher;\n            _dbContext = dbContext;\n        }\n        public async Task HandleAsync(ProductsReserved _event, ICorrelationContext context)\n        {\n            var order = await _dbContext.Orders.FindAsync(_event.OrderId);\n            order.Status = OrderStatus.Completed;\n\n            await _dbContext.SaveChangesAsync();\n            _logger.LogInformation($\"[Local Transaction] : Order completed. CorrelationId: {context.CorrelationId}\");\n            await _busPublisher.PublishAsync(new OrderCompleted(_event.OrderId), context);\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/HttpServices/CustomerHttpService.cs",
    "content": "using System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\nusing Services.Orders.Models;\n\nnamespace Services.Orders.HttpServices\n{\n    public class CustomerHttpService : ICustomerHttpService\n    {\n        private HttpClient _client { get; }\n\n        public CustomerHttpService(HttpClient client)\n        {\n            _client = client;\n        }\n\n        public async Task<Basket> GetBasket(Guid customerId)\n        {\n            var request = new HttpRequestMessage(HttpMethod.Get, $\"basket/{customerId}\");\n            var response = await _client.SendAsync(request);\n\n            var content = await response.Content.ReadAsStringAsync();\n            if (response.IsSuccessStatusCode)\n            {\n                response.Content.Dispose();\n                return JsonConvert.DeserializeObject<Basket>(content);\n            }\n            throw new Exception(\"Customer service connection error\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/HttpServices/ICustomerHttpService.cs",
    "content": "using System;\nusing System.Threading.Tasks;\nusing Services.Orders.Models;\n\nnamespace Services.Orders.HttpServices\n{\n    public interface ICustomerHttpService\n    {\n        Task<Basket> GetBasket(Guid CustomerId);\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Models/Basket.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace Services.Orders.Models\n{\n    public class Basket\n    {\n        public Guid Id { get; set; }\n        public Guid CustomerId { get; set; }\n        public DateTime CreatedAt { get; set; }\n        public List<BasketItem> Items { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Models/BasketItem.cs",
    "content": "using System;\n\nnamespace Services.Orders.Models\n{\n    public class BasketItem\n    {\n        public Guid Id { get; set; }\n        public Guid BasketId { get; set; }\n        public Guid ProductId { get; set; }\n        public string ProductName { get; set; }\n        public int Quantity { get; set; }\n        public decimal UnitPrice { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Program.cs",
    "content": "﻿using Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Hosting;\nusing Shared.Logging;\n\nnamespace Services.Orders\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            CreateWebHostBuilder(args).Build().Run();\n        }\n\n        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>\n            WebHost.CreateDefaultBuilder(args)\n                .UseStartup<Startup>()\n                .UseLogging(\"Order.Service\");\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Properties/launchSettings.json",
    "content": "﻿{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:35766\",\n      \"sslPort\": 44314\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"Services.Orders\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"http://localhost:5015\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Services.Orders.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp2.2</TargetFramework>\n    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.App\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Razor.Design\" Version=\"2.2.0\" PrivateAssets=\"All\" />\n    <ProjectReference Include=\"..\\..\\..\\DotnetIst.Shared\\src\\Shared\\Shared.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/Startup.cs",
    "content": "﻿using System;\nusing System.Net.Http.Headers;\nusing Shared.Models;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Services.Orders.Commands;\nusing Services.Orders.Data;\nusing Shared;\nusing Services.Orders.HttpServices;\nusing Services.Customers.Data;\nusing Services.Orders.Events;\n\nnamespace Services.Orders\n{\n    public class Startup\n    {\n        public Startup(IConfiguration configuration)\n        {\n            Configuration = configuration;\n        }\n\n        public IConfiguration Configuration { get; }\n\n        // This method gets called by the runtime. Use this method to add services to the container.\n        public IServiceProvider ConfigureServices(IServiceCollection services)\n        {\n            services.AddDbContext<OrderDBContext>(options =>\n                options.UseNpgsql(Configuration.GetConnectionString(\"DefaultConnection\"))\n            );\n\n            var httpServices = Configuration.GetOptions<HttpServiceOptions>(\"HttpServices\");\n            services.AddHttpClient<ICustomerHttpService, CustomerHttpService>(client =>\n            {\n                client.BaseAddress = new Uri(httpServices.CustomerHttpServiceUrl);\n                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(\"application/json\"));\n            });\n\n            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);\n\n            return services.BuildContainer();\n        }\n\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            if (env.IsDevelopment())\n            {\n                app.UseDeveloperExceptionPage();\n            }\n\n            app.UseMvc();\n            app.UseRabbitMq()\n               .SubscribeCommand<CreateOrder>()\n               .SubscribeEvent<ProductsReserved>()\n               .SubscribeEvent<ProductsReserveFailed>();\n\n            SeedData.Initialize(app.ApplicationServices);\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Debug\",\n      \"System\": \"Information\",\n      \"Microsoft\": \"Information\"\n    }\n  }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Orders/src/Services.Orders/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\",\n  \"ConnectionStrings\": {\n    \"DefaultConnection\": \"Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=Orders;\"\n  },\n  \"HttpServices\": {\n    \"CustomerHttpServiceUrl\": \"http://localhost:5005/api/\"\n  },\n  \"rabbitMq\": {\n    \"namespace\": \"orders\",\n    \"retries\": 3,\n    \"retryInterval\": 2,\n    \"username\": \"guest\",\n    \"password\": \"guest\",\n    \"virtualHost\": \"/\",\n    \"port\": 5672,\n    \"hostnames\": [\n      \"localhost\"\n    ],\n    \"requestTimeout\": \"00:00:10\",\n    \"publishConfirmTimeout\": \"00:00:01\",\n    \"recoveryInterval\": \"00:00:10\",\n    \"persistentDeliveryMode\": true,\n    \"autoCloseConnection\": true,\n    \"automaticRecovery\": true,\n    \"topologyRecovery\": true,\n    \"exchange\": {\n      \"durable\": true,\n      \"autoDelete\": false,\n      \"type\": \"Topic\"\n    },\n    \"queue\": {\n      \"autoDelete\": false,\n      \"durable\": true,\n      \"exclusive\": false\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/README.md",
    "content": "**Migration**\n\n0- .csproj path\n\n1- *dotnet ef migrations add \"migration_name\" -o ./Data/Migrations*\n\n2- *dotnet ef database update*"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Controllers/HomeController.cs",
    "content": "using Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Services.Products.Controllers\n{\n    [Route(\"\")]\n    public class HomeController : ControllerBase\n    {\n        [HttpGet]\n        [AllowAnonymous]\n        public IActionResult Get()\n        {\n            return Ok(\"Product service is up.\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Controllers/ProductController.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.EntityFrameworkCore;\nusing Services.Customers.Data;\nusing Services.Products.Data;\n\nnamespace Services.Products.Controllers\n{\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    public class ProductController : ControllerBase\n    {\n        private readonly ProductDBContext _dbContext;\n\n        public ProductController(ProductDBContext dbContext)\n        {\n            _dbContext = dbContext;\n        }\n        [HttpGet(\"{id}\")]\n        public async Task<ActionResult> Get(Guid id)\n        {\n            return Ok(await _dbContext.Products.FindAsync(id));\n        }\n\n        [HttpGet]\n        public async Task<ActionResult> Get()\n        {\n            return Ok(await _dbContext.Products.ToListAsync());\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/Entity/Product.cs",
    "content": "using System;\nusing Shared.Models;\n\nnamespace Services.Products.Data\n{\n    public class Product : BaseEntity\n    {\n        public string Name { get; set; }\n        public decimal Price { get; set; }\n        public int Quantity { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/Migrations/20190308212022_initial.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Products.Data.Migrations\n{\n    [DbContext(typeof(ProductDBContext))]\n    [Migration(\"20190308212022_initial\")]\n    partial class initial\n    {\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Products.Data.Product\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Name\");\n\n                    b.Property<decimal>(\"Price\");\n\n                    b.Property<int>(\"Quantity\");\n\n\n\n                    b.ToTable(\"Product\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/Migrations/20190308212022_initial.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Services.Products.Data.Migrations\n{\n    public partial class initial : Migration\n    {\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.CreateTable(\n                name: \"Product\",\n                columns: table => new\n                {\n                    Id = table.Column<Guid>(nullable: false),\n                    Name = table.Column<string>(nullable: true),\n                    Price = table.Column<decimal>(nullable: false),\n                    Quantity = table.Column<int>(nullable: false)\n                },\n                constraints: table =>\n                {\n                    table.PrimaryKey(\"PK_Product\", x => x.Id);\n                });\n        }\n\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropTable(\n                name: \"Product\");\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/Migrations/20190308222331_base_entity.Designer.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Migrations;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Products.Data.Migrations\n{\n    [DbContext(typeof(ProductDBContext))]\n    [Migration(\"20190308222331_base_entity\")]\n    partial class base_entity\n    {\n        protected override void BuildTargetModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Products.Data.Product\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Name\");\n\n                    b.Property<decimal>(\"Price\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n\n\n                    b.ToTable(\"Product\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/Migrations/20190308222331_base_entity.cs",
    "content": "﻿using System;\nusing Microsoft.EntityFrameworkCore.Migrations;\n\nnamespace Services.Products.Data.Migrations\n{\n    public partial class base_entity : Migration\n    {\n        protected override void Up(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.AddColumn<DateTime>(\n                name: \"UpdateDate\",\n                table: \"Product\",\n                nullable: false,\n                defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));\n        }\n\n        protected override void Down(MigrationBuilder migrationBuilder)\n        {\n            migrationBuilder.DropColumn(\n                name: \"UpdateDate\",\n                table: \"Product\");\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/Migrations/ProductDBContextModelSnapshot.cs",
    "content": "﻿// <auto-generated />\nusing System;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\nusing Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;\nusing Services.Customers.Data;\n\nnamespace Services.Products.Data.Migrations\n{\n    [DbContext(typeof(ProductDBContext))]\n    partial class ProductDBContextModelSnapshot : ModelSnapshot\n    {\n        protected override void BuildModel(ModelBuilder modelBuilder)\n        {\n#pragma warning disable 612, 618\n            modelBuilder\n                .HasAnnotation(\"Npgsql:ValueGenerationStrategy\", NpgsqlValueGenerationStrategy.SerialColumn)\n                .HasAnnotation(\"ProductVersion\", \"2.2.1-servicing-10028\")\n                .HasAnnotation(\"Relational:MaxIdentifierLength\", 63);\n\n            modelBuilder.Entity(\"Services.Products.Data.Product\", b =>\n                {\n                    b.Property<Guid>(\"Id\")\n                        .ValueGeneratedOnAdd();\n\n                    b.Property<string>(\"Name\");\n\n                    b.Property<decimal>(\"Price\");\n\n                    b.Property<int>(\"Quantity\");\n\n                    b.Property<DateTime?>(\"UpdateDate\");\n\n                    b.ToTable(\"Product\");\n                });\n#pragma warning restore 612, 618\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/ProductDBContext.cs",
    "content": "using Microsoft.EntityFrameworkCore;\nusing Services.Products.Data;\n\nnamespace Services.Customers.Data\n{\n    public class ProductDBContext : DbContext\n    {\n        public ProductDBContext(DbContextOptions<ProductDBContext> options) : base(options)\n        {\n        }\n        public DbSet<Product> Products { get; set; }\n\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            modelBuilder.Entity<Product>().ToTable(\"Product\");\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Data/SeedData.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Microsoft.Extensions.DependencyInjection;\nusing Services.Customers.Data;\nusing Services.Products.Data;\n\nnamespace Services.Products.Data\n{\n    public static class SeedData\n    {\n        public static void Initialize(IServiceProvider serviceProvider)\n        {\n            var context = serviceProvider.GetRequiredService<ProductDBContext>();\n            context.Database.EnsureCreated();\n            if (!context.Products.Any())\n            {\n                var products = new List<Product>()\n                {\n                    new Product { Name = \"Printer\", Price = 200, Quantity = 500 },\n                    new Product() { Name = \"Mouse\", Price = 20, Quantity = 500 },\n                    new Product() { Name = \"Keyboard\", Price = 50, Quantity = 500 }\n                };\n\n                context.Products.AddRange(products);\n                context.SaveChanges();\n            }\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Events/OrderCreated.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing Shared.Messages;\nusing Newtonsoft.Json;\n\nnamespace Services.Products.Events\n{\n    public class OrderCreated : IEvent\n    {\n        public Guid Id { get; }\n        public IDictionary<Guid, int> Products { get; } // id, quantity\n\n        public OrderCreated(Guid id, IDictionary<Guid, int> products)\n        {\n            Id = id;\n            Products = products;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Events/ProductsReserveFailed.cs",
    "content": "using System;\nusing Shared.Messages;\n\nnamespace Services.Products.Events\n{\n    [MessageNamespace(\"orders\")]\n    public class ProductsReserveFailed : IEvent\n    {\n        public Guid OrderId { get; set; }\n        public ProductsReserveFailed(Guid orderId)\n        {\n            this.OrderId = orderId;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Events/ProductsReserved.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing Shared.Messages;\n\nnamespace Services.Products.Events\n{\n    [MessageNamespace(\"orders\")]\n    public class ProductsReserved : IEvent\n    {\n        public Guid OrderId { get; set; }\n        public IDictionary<Guid, int> Products { get; set; }\n        public ProductsReserved(Guid orderId, IDictionary<Guid, int> products)\n        {\n            OrderId = orderId;\n            Products = products;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Handlers/OrderCreatedHandler.cs",
    "content": "using System;\nusing System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Logging;\nusing Services.Customers.Data;\nusing Services.Products.Events;\n\nnamespace Services.Products.Handlers\n{\n    public class OrderCreatedHandler : IEventHandler<OrderCreated>\n    {\n        private readonly ProductDBContext _dbContext;\n        private readonly IBusPublisher _busPublisher;\n        private readonly ILogger<OrderCreatedHandler> _logger;\n\n        public OrderCreatedHandler(ProductDBContext dbContext,\n                            IBusPublisher busPublisher,\n                            ILogger<OrderCreatedHandler> logger)\n        {\n            _logger = logger;\n            _dbContext = dbContext;\n            _busPublisher = busPublisher;\n        }\n        public async Task HandleAsync(OrderCreated _event, ICorrelationContext context)\n        {\n            var isReserved = true;\n\n            foreach ((Guid productId, int quantity) in _event.Products)\n            {\n                var product = await _dbContext.Products.FindAsync(productId);\n\n                if (product == null)\n                {\n                    isReserved = false;\n                    _logger.LogInformation($\"[Local Transaction] : Product '{productId}' not found. CorrelationId: {context.CorrelationId}\");\n                    break;\n                }\n\n                if (quantity > product.Quantity)\n                {\n                    isReserved = false;\n                    _logger.LogInformation($\"[Local Transaction] : Not available {product.Quantity} {product.Name}. CorrelationId: {context.CorrelationId}\");\n                    break;\n                }\n                else\n                {\n                    product.Quantity -= quantity;\n                    product.UpdateDate = DateTime.Now;\n                }\n            }\n\n            if (isReserved)\n            {\n                await _dbContext.SaveChangesAsync();\n                _logger.LogInformation($\"[Local Transaction] : Products reserved. CorrelationId: {context.CorrelationId}\");\n                await _busPublisher.PublishAsync(new ProductsReserved(_event.Id, _event.Products), context);\n            }\n            else\n            {\n                _logger.LogInformation($\"[Local Transaction] : Products could not be reserved. CorrelationId: {context.CorrelationId}\");\n                await _busPublisher.PublishAsync(new ProductsReserveFailed(_event.Id), context);\n            }\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Program.cs",
    "content": "﻿using Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Hosting;\nusing Shared.Logging;\n\nnamespace Services.Products\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            CreateWebHostBuilder(args).Build().Run();\n        }\n\n        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>\n            WebHost.CreateDefaultBuilder(args)\n                .UseStartup<Startup>()\n                .UseLogging(\"Product.Service\");\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Properties/launchSettings.json",
    "content": "﻿{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:29904\",\n      \"sslPort\": 44329\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"Services.Products\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"applicationUrl\": \"http://localhost:5010\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Services.Products.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp2.2</TargetFramework>\n    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.App\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Razor.Design\" Version=\"2.2.0\" PrivateAssets=\"All\" />\n    <ProjectReference Include=\"..\\..\\..\\DotnetIst.Shared\\src\\Shared\\Shared.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/Startup.cs",
    "content": "﻿using System;\nusing Shared;\nusing Shared.RabbitMq;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Services.Customers.Data;\nusing Services.Products.Data;\nusing Services.Products.Events;\n\nnamespace Services.Products\n{\n    public class Startup\n    {\n        public Startup(IConfiguration configuration)\n        {\n            Configuration = configuration;\n        }\n\n        public IConfiguration Configuration { get; }\n\n        // This method gets called by the runtime. Use this method to add services to the container.\n        public IServiceProvider ConfigureServices(IServiceCollection services)\n        {\n            services.AddDbContext<ProductDBContext>(options =>\n                options.UseNpgsql(Configuration.GetConnectionString(\"DefaultConnection\"))\n            );\n            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);\n\n            return services.BuildContainer();\n        }\n\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            if (env.IsDevelopment())\n            {\n                app.UseDeveloperExceptionPage();\n            }\n\n            app.UseMvc();\n            app.UseRabbitMq()\n               .SubscribeEvent<OrderCreated>();\n\n            SeedData.Initialize(app.ApplicationServices);\n        }\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/appsettings.Development.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Debug\",\n      \"System\": \"Information\",\n      \"Microsoft\": \"Information\"\n    }\n  }\n}\n"
  },
  {
    "path": "DotnetIst.Services.Products/src/Services.Products/appsettings.json",
    "content": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\",\n  \"ConnectionStrings\": {\n    \"DefaultConnection\": \"Host=localhost;Port=5432;Username=postgres;Password=postgres;Database=Products;\"\n  },\n  \"rabbitMq\": {\n    \"namespace\": \"products\",\n    \"retries\": 3,\n    \"retryInterval\": 2,\n    \"username\": \"guest\",\n    \"password\": \"guest\",\n    \"virtualHost\": \"/\",\n    \"port\": 5672,\n    \"hostnames\": [\n      \"localhost\"\n    ],\n    \"requestTimeout\": \"00:00:10\",\n    \"publishConfirmTimeout\": \"00:00:01\",\n    \"recoveryInterval\": \"00:00:10\",\n    \"persistentDeliveryMode\": true,\n    \"autoCloseConnection\": true,\n    \"automaticRecovery\": true,\n    \"topologyRecovery\": true,\n    \"exchange\": {\n      \"durable\": true,\n      \"autoDelete\": false,\n      \"type\": \"Topic\"\n    },\n    \"queue\": {\n      \"autoDelete\": false,\n      \"durable\": true,\n      \"exclusive\": false\n    }\n  }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Extensions.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Reflection;\nusing Autofac;\nusing Autofac.Extensions.DependencyInjection;\nusing Shared.RabbitMq;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Shared\n{\n    public static class Extensions\n    {\n        public static string Underscore(this string value)\n            => string.Concat(value.Select((x, i) => i > 0 && char.IsUpper(x) ? \"_\" + x.ToString() : x.ToString()));\n\n        public static TModel GetOptions<TModel>(this IConfiguration configuration, string section) where TModel : new()\n        {\n            var model = new TModel();\n            configuration.GetSection(section).Bind(model);\n            return model;\n        }\n\n        public static IServiceProvider BuildContainer(this IServiceCollection services)\n        {\n            var builder = new ContainerBuilder();\n            builder.RegisterAssemblyTypes(Assembly.GetCallingAssembly())\n                .AsImplementedInterfaces();\n            builder.Populate(services);\n            builder.AddRabbitMq();\n            return new AutofacServiceProvider(builder.Build());\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Logging/LoggingExtensions.cs",
    "content": "using System;\nusing Microsoft.AspNetCore.Hosting;\nusing Serilog;\nusing Serilog.Sinks.Elasticsearch;\n\nnamespace Shared.Logging\n{\n    public static class Extensions\n    {\n        public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder, string applicationName)\n        {\n            return webHostBuilder.UseSerilog((context, loggerConfiguration) =>\n            {\n                loggerConfiguration.Enrich.FromLogContext()\n                    .Enrich.WithProperty(\"Environment\", context.HostingEnvironment.EnvironmentName)\n                    .Enrich.WithProperty(\"ApplicationName\", applicationName);\n\n                loggerConfiguration\n                .WriteTo.Console()\n                .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(\"http://localhost:9200/\"))\n                {\n                    AutoRegisterTemplate = true,\n                    IndexFormat = \"logstash-{0:yyyy.MM.dd}\"\n                });\n            });\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/MessageHandlers/ICommandHandler.cs",
    "content": "using System.Threading.Tasks;\nusing Shared.Messages;\nusing Shared.RabbitMq;\n\nnamespace Shared.MessageHandlers\n{\n    public interface ICommandHandler<in TCommand> where TCommand : ICommand\n    {\n        Task HandleAsync(TCommand command, ICorrelationContext context);\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/MessageHandlers/IEventHandler.cs",
    "content": "using System.Threading.Tasks;\nusing Shared.Messages;\nusing Shared.RabbitMq;\n\nnamespace Shared.MessageHandlers\n{\n    public interface IEventHandler<in TEvent> where TEvent : IEvent\n    {\n        Task HandleAsync(TEvent _event, ICorrelationContext context);\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Messages/ICommand.cs",
    "content": "namespace Shared.Messages\n{\n    public interface ICommand\n    {\n\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Messages/IEvent.cs",
    "content": "namespace Shared.Messages\n{\n    public interface IEvent\n    {\n\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Messages/MessageNamespaceAttribute.cs",
    "content": "using System;\n\nnamespace Shared.Messages\n{\n    public class MessageNamespaceAttribute : Attribute\n    {\n        public string Namespace { get; }\n\n        public MessageNamespaceAttribute(string _namespace)\n        {\n            Namespace = _namespace?.ToLowerInvariant();\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Models/BaseEntity.cs",
    "content": "using System;\n\nnamespace Shared.Models\n{\n    public class BaseEntity\n    {\n        public Guid Id { get; set; }\n        public DateTime CreateDate { get; set; }\n        public DateTime? UpdateDate { get; set; }\n        public BaseEntity()\n        {\n            this.CreateDate = DateTime.Now;\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Models/HttpServiceOptions.cs",
    "content": "namespace Shared.Models\n{\n    public class HttpServiceOptions\n    {\n        public string ProductHttpServiceUrl { get; set; }\n        public string CustomerHttpServiceUrl { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/BusPublisher.cs",
    "content": "using System.Reflection;\nusing System.Threading.Tasks;\nusing Shared.Messages;\nusing Microsoft.Extensions.Logging;\nusing RawRabbit;\nusing RawRabbit.Enrichers.MessageContext;\n\nnamespace Shared.RabbitMq\n{\n    public class BusPublisher : IBusPublisher\n    {\n        private readonly IBusClient _busClient;\n        private readonly ILogger<IBusPublisher> _logger;\n        private readonly string _defaultNamespace;\n\n        public BusPublisher(IBusClient busClient, RabbitMqOptions options, ILogger<IBusPublisher> logger)\n        {\n            _busClient = busClient;\n            _logger = logger;\n            _defaultNamespace = options.Namespace;\n        }\n\n        public async Task SendAsync<TCommand>(TCommand command, ICorrelationContext context)\n            where TCommand : ICommand\n        {\n            var commandName = command.GetType().Name;\n            _logger.LogInformation($\"[Sent a command] : '{commandName}' Correlation id: '{context.CorrelationId}'\");\n\n            await _busClient.PublishAsync(command, ctx => ctx.UseMessageContext(context)\n                 .UsePublishConfiguration(p => p.WithRoutingKey(GetRoutingKey(command))));\n        }\n\n        public async Task PublishAsync<TEvent>(TEvent _event, ICorrelationContext context)\n            where TEvent : IEvent\n        {\n            var eventName = _event.GetType().Name;\n            _logger.LogInformation($\"[Published an event] : '{eventName}' Correlation id: '{context.CorrelationId}'\");\n\n            await _busClient.PublishAsync(_event, ctx => ctx.UseMessageContext(context)\n                 .UsePublishConfiguration(p => p.WithRoutingKey(GetRoutingKey(_event))));\n        }\n\n        private string GetRoutingKey<T>(T message)\n        {\n            var _namespace = message.GetType().GetCustomAttribute<MessageNamespaceAttribute>()?.Namespace ?? _defaultNamespace;\n            _namespace = string.IsNullOrWhiteSpace(_namespace) ? string.Empty : $\"{_namespace}.\";\n\n            return $\"{_namespace}{typeof(T).Name.Underscore()}\".ToLowerInvariant();\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/BusSubscriber.cs",
    "content": "﻿using System;\nusing System.Reflection;\nusing System.Threading.Tasks;\nusing Shared.MessageHandlers;\nusing Shared.Messages;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\nusing Polly;\nusing RawRabbit;\nusing RawRabbit.Common;\n\nnamespace Shared.RabbitMq\n{\n    public class BusSubscriber : IBusSubscriber\n    {\n        private readonly ILogger _logger;\n        private readonly IBusClient _busClient;\n        private readonly IServiceProvider _serviceProvider;\n        private readonly string _defaultNamespace;\n        private readonly int _retries;\n        private readonly int _retryInterval;\n\n        public BusSubscriber(IApplicationBuilder app)\n        {\n            _logger = app.ApplicationServices.GetService<ILogger<BusSubscriber>>();\n            _serviceProvider = app.ApplicationServices.GetService<IServiceProvider>();\n            _busClient = _serviceProvider.GetService<IBusClient>();\n\n            var options = _serviceProvider.GetService<RabbitMqOptions>();\n            _defaultNamespace = options.Namespace;\n            _retries = options.Retries >= 0 ? options.Retries : 3;\n            _retryInterval = options.RetryInterval > 0 ? options.RetryInterval : 2;\n        }\n\n        public IBusSubscriber SubscribeCommand<TCommand>(string _namespace = null)\n            where TCommand : ICommand\n        {\n            _busClient.SubscribeAsync<TCommand, CorrelationContext>(async (command, correlationContext) =>\n                {\n                    var commandHandler = _serviceProvider.GetService<ICommandHandler<TCommand>>();\n\n                    return await TryHandleAsync(command, correlationContext,\n                        () => commandHandler.HandleAsync(command, correlationContext));\n                },\n                ctx => ctx.UseSubscribeConfiguration(cfg =>\n                    cfg.FromDeclaredQueue(q => q.WithName(GetQueueName<TCommand>(_namespace)))));\n\n            return this;\n        }\n\n        public IBusSubscriber SubscribeEvent<TEvent>(string _namespace = null)\n            where TEvent : IEvent\n        {\n            _busClient.SubscribeAsync<TEvent, CorrelationContext>(async (_event, correlationContext) =>\n                {\n                    var eventHandler = _serviceProvider.GetService<IEventHandler<TEvent>>();\n\n                    return await TryHandleAsync(_event, correlationContext,\n                        () => eventHandler.HandleAsync(_event, correlationContext));\n                },\n                ctx => ctx.UseSubscribeConfiguration(cfg =>\n                    cfg.FromDeclaredQueue(q => q.WithName(GetQueueName<TEvent>(_namespace)))));\n\n            return this;\n        }\n\n        private async Task<Acknowledgement> TryHandleAsync<TMessage>(TMessage message,\n            CorrelationContext correlationContext, Func<Task> handle)\n        {\n            var currentRetry = 0;\n            var retryPolicy = Policy\n                .Handle<Exception>()\n                .WaitAndRetryAsync(_retries, i => TimeSpan.FromSeconds(_retryInterval));\n\n            var messageName = message.GetType().Name;\n\n            return await retryPolicy.ExecuteAsync<Acknowledgement>(async () =>\n            {\n                var retryMessage = currentRetry == 0 ? string.Empty : $\"Retry: {currentRetry}'.\";\n                var messageType = message is IEvent ? \"n event\" : \" command\";\n\n                _logger.LogInformation($\"[Handled a{messageType}] : '{messageName}' \" +\n                                     $\"Correlation id: '{correlationContext.CorrelationId}'. {retryMessage}\");\n                await handle();\n\n                return new Ack();\n            });\n        }\n\n        private string GetQueueName<T>(string _namespace = null)\n        {\n            _namespace = string.IsNullOrWhiteSpace(_namespace)\n                ? (string.IsNullOrWhiteSpace(_defaultNamespace) ? string.Empty : _defaultNamespace)\n                : _namespace;\n            var separatedNamespace = string.IsNullOrWhiteSpace(_namespace) ? string.Empty : $\"{_namespace}.\";\n            return $\"{Assembly.GetEntryAssembly().GetName().Name}/{separatedNamespace}{typeof(T).Name.Underscore()}\";\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/CorrelationContext.cs",
    "content": "using System;\nusing Newtonsoft.Json;\n\nnamespace Shared.RabbitMq\n{\n    public class CorrelationContext : ICorrelationContext\n    {\n        public Guid CorrelationId { get; }\n        public Guid CustomerId { get; }\n\n        public CorrelationContext()\n        {\n        }\n\n        [JsonConstructor]\n        private CorrelationContext(Guid correlationId, Guid customerId)\n        {\n            CorrelationId = correlationId;\n            CustomerId = customerId;\n        }\n\n        public static ICorrelationContext Create(Guid id, Guid customerId)\n        {\n            return new CorrelationContext(id, customerId);\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/IBusPublisher.cs",
    "content": "using System.Threading.Tasks;\nusing Shared.Messages;\n\nnamespace Shared.RabbitMq\n{\n    public interface IBusPublisher\n    {\n        Task SendAsync<TCommand>(TCommand command, ICorrelationContext context)\n            where TCommand : ICommand;\n\n        Task PublishAsync<TEvent>(TEvent _event, ICorrelationContext context)\n            where TEvent : IEvent;\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/IBusSubscriber.cs",
    "content": "﻿using System;\nusing Shared.Messages;\n\nnamespace Shared.RabbitMq\n{\n    public interface IBusSubscriber\n    {\n        IBusSubscriber SubscribeCommand<TCommand>(string _namespace = null)\n            where TCommand : ICommand;\n\n        IBusSubscriber SubscribeEvent<TEvent>(string _namespace = null)\n            where TEvent : IEvent;\n    }\n}\n"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/ICorrelationContext.cs",
    "content": "using System;\n\nnamespace Shared.RabbitMq\n{\n    public interface ICorrelationContext\n    {\n        Guid CorrelationId { get; }\n        Guid CustomerId { get; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/RabbitMqExtensions.cs",
    "content": "using System.Reflection;\nusing Autofac;\nusing Shared.MessageHandlers;\nusing Shared.Messages;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.Extensions.Configuration;\nusing RawRabbit;\nusing RawRabbit.Common;\nusing RawRabbit.Configuration;\nusing RawRabbit.Enrichers.MessageContext;\nusing RawRabbit.Instantiation;\n\nnamespace Shared.RabbitMq\n{\n    public static class RabbitMqExtensions\n    {\n        public static IBusSubscriber UseRabbitMq(this IApplicationBuilder app)\n            => new BusSubscriber(app);\n\n        public static void AddRabbitMq(this ContainerBuilder builder)\n        {\n            builder.Register(context =>\n            {\n                var configuration = context.Resolve<IConfiguration>();\n                var options = configuration.GetOptions<RabbitMqOptions>(\"rabbitMq\");\n                return options;\n            }).SingleInstance();\n\n            builder.Register(context =>\n            {\n                var configuration = context.Resolve<IConfiguration>();\n                var options = configuration.GetOptions<RawRabbitConfiguration>(\"rabbitMq\");\n                return options;\n            }).SingleInstance();\n\n            var assembly = Assembly.GetCallingAssembly();\n            builder.RegisterAssemblyTypes(assembly)\n                .AsClosedTypesOf(typeof(IEventHandler<>))\n                .InstancePerDependency();\n            builder.RegisterAssemblyTypes(assembly)\n                .AsClosedTypesOf(typeof(ICommandHandler<>))\n                .InstancePerDependency();\n            builder.RegisterType<BusPublisher>().As<IBusPublisher>()\n                .InstancePerDependency();\n            ConfigureBus(builder);\n        }\n\n        private static void ConfigureBus(ContainerBuilder builder)\n        {\n            builder.Register<IInstanceFactory>(context =>\n            {\n                var options = context.Resolve<RabbitMqOptions>();\n                var configuration = context.Resolve<RawRabbitConfiguration>();\n                var namingConventions = new CustomNamingConventions(options.Namespace);\n\n                return RawRabbitFactory.CreateInstanceFactory(new RawRabbitOptions\n                {\n                    DependencyInjection = ioc =>\n                    {\n                        ioc.AddSingleton(options);\n                        ioc.AddSingleton(configuration);\n                        ioc.AddSingleton<INamingConventions>(namingConventions);\n\n                    },\n                    Plugins = p => p\n                        .UseAttributeRouting()\n                        .UseRetryLater()\n                        .UseMessageContext<CorrelationContext>()\n                        .UseContextForwarding()\n                });\n            }).SingleInstance();\n            builder.Register(context => context.Resolve<IInstanceFactory>().Create());\n        }\n\n        private class CustomNamingConventions : NamingConventions\n        {\n            public CustomNamingConventions(string defaultNamespace)\n            {\n                ExchangeNamingConvention = type => (type.GetCustomAttribute<MessageNamespaceAttribute>()?.Namespace ??\n                     defaultNamespace).ToLowerInvariant();\n                RoutingKeyConvention = type =>\n                    $\"#.{type.GetCustomAttribute<MessageNamespaceAttribute>()?.Namespace ?? defaultNamespace}.{type.Name.Underscore()}\"\n                    .ToLowerInvariant();\n            }\n        }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/RabbitMq/RabbitMqOptions.cs",
    "content": "using RawRabbit.Configuration;\n\nnamespace Shared.RabbitMq\n{\n    public class RabbitMqOptions : RawRabbitConfiguration\n    {\n        public string Namespace { get; set; }\n        public int Retries { get; set; }\n        public int RetryInterval { get; set; }\n    }\n}"
  },
  {
    "path": "DotnetIst.Shared/src/Shared/Shared.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore\" Version=\"2.2.0\" />\n    <PackageReference Include=\"Newtonsoft.Json\" Version=\"13.0.2\" />\n\n    <PackageReference Include=\"RawRabbit\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.DependencyInjection.ServiceCollection\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.Enrichers.Attributes\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.Enrichers.Polly\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.Enrichers.MessageContext\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.Enrichers.MessageContext.Subscribe\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.DependencyInjection.Autofac\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.Enrichers.RetryLater\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.Operations.Publish\" Version=\"2.0.0-rc5\" />\n    <PackageReference Include=\"RawRabbit.Operations.Subscribe\" Version=\"2.0.0-rc5\" />\n\n    <PackageReference Include=\"Autofac\" Version=\"4.8.1\" />\n    <PackageReference Include=\"Autofac.Extensions.DependencyInjection\" Version=\"4.3.1\" />\n\n    <PackageReference Include=\"Npgsql.EntityFrameworkCore.PostgreSQL\" Version=\"2.2.0\" />\n    <PackageReference Include=\"NpgSql.EntityFrameworkCore.PostgreSQL.Design\" Version=\"1.1.1\" />\n\n    <PackageReference Include=\"Serilog\" Version=\"2.7.1\" />\n    <PackageReference Include=\"Serilog.AspNetCore\" Version=\"2.1.1\" />\n    <PackageReference Include=\"Serilog.Extensions.Logging\" Version=\"2.0.2\" />\n    <PackageReference Include=\"Serilog.Sinks.Console\" Version=\"3.1.1\" />\n    <PackageReference Include=\"Serilog.Sinks.Elasticsearch\" Version=\"6.5.0\" />\n        \n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "README.md",
    "content": "Presentation : https://speakerdeck.com/suadev/microservice-architecture-and-implementation-with-asp-dot-net-core\n\nThe aim of the demo is showing ***event-driven and eventual consistent communication*** between the microservices. \n\n<img src=\"https://speakerd.s3.amazonaws.com/presentations/d74133b1f0d1409ab6093806e005f64e/preview_slide_17.jpg\" />\n\n\n## Prerequities\n\n* DotNet Core SDK 2.2\n\n* Docker\n\n* pgAdmin or Azure Data Studio (Needs PostgreSQL extension - https://github.com/Microsoft/azuredatastudio-postgresql/ )\n\n\n## Running in Debug Mode\n\n* Run 'docker-compose up'\n\n* Wait all services to up and running. ( rabbitmq, postgres, elasticsearch and kibana )\n\n* Select 'All' debug option and start debuging.\n\n* Wait until all microservices are up and running.\n\nP.S. You can use ***.postman_project/Dotnet_Istanbul.postman_collection.json*** file for a quick test from Postman.\n\n\n## Tool Set\n\n* Asp.Net Core 2.2 \n* Entity Framework Core 2.2\n* PostgreSQL - Npgsql\n* Serilog - Elasticsearch - Kibana\n* RabbitMQ - RawRabbit\n* Docker Containers ( PostgreSQL, RabbitMQ, Elasticsearch and Kibana )\n* pgAdmin or Azure Data Studio\n* VS Code\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '3.7'\n\nservices:\n\n  rabbitmq:\n    image: rabbitmq:3-management\n    container_name: myrabbitmq\n    ports:\n      - \"15672:15672\"\n      - \"5672:5672\"\n    environment:\n      - RABBITMQ_DEFAULT_USER=guest\n      - RABBITMQ_DEFAULT_PASS=guest\n\n  postgres:\n    image: postgres\n    container_name: mypostgres\n    ports:\n      - \"5432:5432\"\n    environment:\n      - POSTGRES_PASSWORD=postgres\n\n  elasticsearch:\n    image: docker.elastic.co/elasticsearch/elasticsearch:6.6.1\n    container_name: myelastic\n    environment:\n      - cluster.name=docker-cluster\n      - bootstrap.memory_lock=true\n      - \"ES_JAVA_OPTS=-Xms512m -Xmx512m\"\n    ulimits:\n      memlock:\n        soft: -1\n        hard: -1\n    ports:\n      - \"9200:9200\"\n      - \"9300:9300\"\n\n  kibana:\n    image: docker.elastic.co/kibana/kibana:6.6.1\n    container_name: mykibana\n    ports:\n      - \"5601:5601\""
  },
  {
    "path": "dotnet-istanbul-microservices-demo.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.26124.0\nMinimumVisualStudioVersion = 15.0.26124.0\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"DotnetIst.Api\", \"DotnetIst.Api\", \"{674A9DD4-F9DA-4F9F-81E3-AB6A24C5149D}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{CA1A4673-F703-4C40-B44E-AE28673B4A71}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Api\", \"DotnetIst.Api\\src\\Api\\Api.csproj\", \"{2BCBD3FB-715D-45A5-96DB-346608043045}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"DotnetIst.Shared\", \"DotnetIst.Shared\", \"{A14724F1-AE75-45BE-AFF2-F46603C797DE}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{7FC87A4C-7F67-49D8-A702-9CC75F9910FB}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Shared\", \"DotnetIst.Shared\\src\\Shared\\Shared.csproj\", \"{DCF6A908-B7C2-412C-924D-A598647F7540}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"DotnetIst.Services.Customers\", \"DotnetIst.Services.Customers\", \"{6806424F-4261-4347-8CDE-5F6399BBC6BF}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{EA331B36-EF9B-4C04-B52F-0192A629A229}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Services.Customers\", \"DotnetIst.Services.Customers\\src\\Services.Customers\\Services.Customers.csproj\", \"{FA617103-F493-4FDD-96FA-0E83B881E0B0}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"DotnetIst.Services.Notifications\", \"DotnetIst.Services.Notifications\", \"{3B87C5C6-314D-4101-B233-A196403845AB}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{84EC4F28-DC06-4F42-90B1-F7C8D57B6C1B}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Services.Notifications\", \"DotnetIst.Services.Notifications\\src\\Services.Notifications\\Services.Notifications.csproj\", \"{577857E0-19A7-406C-8495-7BCF71886F71}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"DotnetIst.Services.Orders\", \"DotnetIst.Services.Orders\", \"{8E520BD8-B6D7-4205-93FC-7F9BFA99A4A7}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{28BA3B30-1F93-4907-B6BB-32D09A038CC9}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Services.Orders\", \"DotnetIst.Services.Orders\\src\\Services.Orders\\Services.Orders.csproj\", \"{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"DotnetIst.Services.Products\", \"DotnetIst.Services.Products\", \"{020A54F8-7DC3-4148-8797-7534A89B32F7}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{B5E52D90-0C27-4D1C-9DCE-B614658969FA}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Services.Products\", \"DotnetIst.Services.Products\\src\\Services.Products\\Services.Products.csproj\", \"{83E22247-7E48-429B-83B7-979263473F36}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Release|x64.Build.0 = Release|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045}.Release|x86.Build.0 = Release|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Release|x64.Build.0 = Release|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540}.Release|x86.Build.0 = Release|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Release|x64.Build.0 = Release|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0}.Release|x86.Build.0 = Release|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Release|x64.Build.0 = Release|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71}.Release|x86.Build.0 = Release|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Release|x64.Build.0 = Release|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0}.Release|x86.Build.0 = Release|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Release|x64.Build.0 = Release|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{83E22247-7E48-429B-83B7-979263473F36}.Release|x86.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(NestedProjects) = preSolution\n\t\t{CA1A4673-F703-4C40-B44E-AE28673B4A71} = {674A9DD4-F9DA-4F9F-81E3-AB6A24C5149D}\n\t\t{2BCBD3FB-715D-45A5-96DB-346608043045} = {CA1A4673-F703-4C40-B44E-AE28673B4A71}\n\t\t{7FC87A4C-7F67-49D8-A702-9CC75F9910FB} = {A14724F1-AE75-45BE-AFF2-F46603C797DE}\n\t\t{DCF6A908-B7C2-412C-924D-A598647F7540} = {7FC87A4C-7F67-49D8-A702-9CC75F9910FB}\n\t\t{EA331B36-EF9B-4C04-B52F-0192A629A229} = {6806424F-4261-4347-8CDE-5F6399BBC6BF}\n\t\t{FA617103-F493-4FDD-96FA-0E83B881E0B0} = {EA331B36-EF9B-4C04-B52F-0192A629A229}\n\t\t{84EC4F28-DC06-4F42-90B1-F7C8D57B6C1B} = {3B87C5C6-314D-4101-B233-A196403845AB}\n\t\t{577857E0-19A7-406C-8495-7BCF71886F71} = {84EC4F28-DC06-4F42-90B1-F7C8D57B6C1B}\n\t\t{28BA3B30-1F93-4907-B6BB-32D09A038CC9} = {8E520BD8-B6D7-4205-93FC-7F9BFA99A4A7}\n\t\t{3AF46C68-DA51-4CFE-B9D1-BA247AF2C9C0} = {28BA3B30-1F93-4907-B6BB-32D09A038CC9}\n\t\t{B5E52D90-0C27-4D1C-9DCE-B614658969FA} = {020A54F8-7DC3-4148-8797-7534A89B32F7}\n\t\t{83E22247-7E48-429B-83B7-979263473F36} = {B5E52D90-0C27-4D1C-9DCE-B614658969FA}\n\tEndGlobalSection\nEndGlobal\n"
  }
]