diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ConfigureServices.cs b/src/Sales/ConfigureServices.cs
new file mode 100644
index 0000000..7099c68
--- /dev/null
+++ b/src/Sales/ConfigureServices.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Sales
+{
+ public static class ConfigureServices
+ {
+ public static void AddSales(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddDbContext();
+ }
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ConfigureServices.cs b/src/Sales/ConfigureServices.cs
new file mode 100644
index 0000000..7099c68
--- /dev/null
+++ b/src/Sales/ConfigureServices.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Sales
+{
+ public static class ConfigureServices
+ {
+ public static void AddSales(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddDbContext();
+ }
+ }
+}
diff --git a/src/Sales/Endpoints.cs b/src/Sales/Endpoints.cs
new file mode 100644
index 0000000..857812f
--- /dev/null
+++ b/src/Sales/Endpoints.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Routing;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public static class Endpoints
+ {
+ public static void MapSales(this IEndpointRouteBuilder endpoints)
+ {
+
+ }
+
+ public static void MapSales(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderPlaced).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ConfigureServices.cs b/src/Sales/ConfigureServices.cs
new file mode 100644
index 0000000..7099c68
--- /dev/null
+++ b/src/Sales/ConfigureServices.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Sales
+{
+ public static class ConfigureServices
+ {
+ public static void AddSales(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddDbContext();
+ }
+ }
+}
diff --git a/src/Sales/Endpoints.cs b/src/Sales/Endpoints.cs
new file mode 100644
index 0000000..857812f
--- /dev/null
+++ b/src/Sales/Endpoints.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Routing;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public static class Endpoints
+ {
+ public static void MapSales(this IEndpointRouteBuilder endpoints)
+ {
+
+ }
+
+ public static void MapSales(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderPlaced).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Extensions.cs b/src/Sales/Extensions.cs
new file mode 100644
index 0000000..f940e11
--- /dev/null
+++ b/src/Sales/Extensions.cs
@@ -0,0 +1,14 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Sales
+{
+ public static class Extensions
+ {
+ public static async Task Deserialize(this HttpResponseMessage responseMessage)
+ {
+ return JsonConvert.DeserializeObject(await responseMessage.Content.ReadAsStringAsync());
+ }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ConfigureServices.cs b/src/Sales/ConfigureServices.cs
new file mode 100644
index 0000000..7099c68
--- /dev/null
+++ b/src/Sales/ConfigureServices.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Sales
+{
+ public static class ConfigureServices
+ {
+ public static void AddSales(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddDbContext();
+ }
+ }
+}
diff --git a/src/Sales/Endpoints.cs b/src/Sales/Endpoints.cs
new file mode 100644
index 0000000..857812f
--- /dev/null
+++ b/src/Sales/Endpoints.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Routing;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public static class Endpoints
+ {
+ public static void MapSales(this IEndpointRouteBuilder endpoints)
+ {
+
+ }
+
+ public static void MapSales(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderPlaced).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Extensions.cs b/src/Sales/Extensions.cs
new file mode 100644
index 0000000..f940e11
--- /dev/null
+++ b/src/Sales/Extensions.cs
@@ -0,0 +1,14 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Sales
+{
+ public static class Extensions
+ {
+ public static async Task Deserialize(this HttpResponseMessage responseMessage)
+ {
+ return JsonConvert.DeserializeObject(await responseMessage.Content.ReadAsStringAsync());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ExternalOrderIntegration.cs b/src/Sales/ExternalOrderIntegration.cs
new file mode 100644
index 0000000..a231126
--- /dev/null
+++ b/src/Sales/ExternalOrderIntegration.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using NServiceBus;
+
+namespace Sales
+{
+ public class ExternalOrderIntegration
+ {
+ private readonly IMessageSession _messageSession;
+ private readonly HttpClient _httpClient;
+
+ public ExternalOrderIntegration(IMessageSession messageSession, HttpClient httpClient)
+ {
+ _messageSession = messageSession;
+ _httpClient = httpClient;
+ }
+
+ public async Task PlaceOrder()
+ {
+ var response = await _httpClient.GetAsync("http://external.com/newOrders");
+ var externalOrder = await response.Deserialize();
+
+ var placeOrder = new PlaceOrder
+ {
+ OrderId = externalOrder!.Id,
+ // Translation to convert an external order or PlaceOrder command
+ };
+ await _messageSession.Send(placeOrder);
+ }
+ }
+
+ public class ExternalOrder
+ {
+ public Guid Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ConfigureServices.cs b/src/Sales/ConfigureServices.cs
new file mode 100644
index 0000000..7099c68
--- /dev/null
+++ b/src/Sales/ConfigureServices.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Sales
+{
+ public static class ConfigureServices
+ {
+ public static void AddSales(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddDbContext();
+ }
+ }
+}
diff --git a/src/Sales/Endpoints.cs b/src/Sales/Endpoints.cs
new file mode 100644
index 0000000..857812f
--- /dev/null
+++ b/src/Sales/Endpoints.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Routing;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public static class Endpoints
+ {
+ public static void MapSales(this IEndpointRouteBuilder endpoints)
+ {
+
+ }
+
+ public static void MapSales(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderPlaced).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Extensions.cs b/src/Sales/Extensions.cs
new file mode 100644
index 0000000..f940e11
--- /dev/null
+++ b/src/Sales/Extensions.cs
@@ -0,0 +1,14 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Sales
+{
+ public static class Extensions
+ {
+ public static async Task Deserialize(this HttpResponseMessage responseMessage)
+ {
+ return JsonConvert.DeserializeObject(await responseMessage.Content.ReadAsStringAsync());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ExternalOrderIntegration.cs b/src/Sales/ExternalOrderIntegration.cs
new file mode 100644
index 0000000..a231126
--- /dev/null
+++ b/src/Sales/ExternalOrderIntegration.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using NServiceBus;
+
+namespace Sales
+{
+ public class ExternalOrderIntegration
+ {
+ private readonly IMessageSession _messageSession;
+ private readonly HttpClient _httpClient;
+
+ public ExternalOrderIntegration(IMessageSession messageSession, HttpClient httpClient)
+ {
+ _messageSession = messageSession;
+ _httpClient = httpClient;
+ }
+
+ public async Task PlaceOrder()
+ {
+ var response = await _httpClient.GetAsync("http://external.com/newOrders");
+ var externalOrder = await response.Deserialize();
+
+ var placeOrder = new PlaceOrder
+ {
+ OrderId = externalOrder!.Id,
+ // Translation to convert an external order or PlaceOrder command
+ };
+ await _messageSession.Send(placeOrder);
+ }
+ }
+
+ public class ExternalOrder
+ {
+ public Guid Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Order.cs b/src/Sales/Order.cs
new file mode 100644
index 0000000..49417f4
--- /dev/null
+++ b/src/Sales/Order.cs
@@ -0,0 +1,23 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Sales
+{
+ [Table("Orders")]
+ public class Order
+ {
+ [Key]
+ public Guid OrderId { get; set; }
+
+ public OrderStatus Status { get; set; }
+ }
+
+ public enum OrderStatus
+ {
+ Pending = 0,
+ ReadyToShip = 1,
+ Shipped = 2,
+ Cancelled = 3
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ConfigureServices.cs b/src/Sales/ConfigureServices.cs
new file mode 100644
index 0000000..7099c68
--- /dev/null
+++ b/src/Sales/ConfigureServices.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Sales
+{
+ public static class ConfigureServices
+ {
+ public static void AddSales(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddDbContext();
+ }
+ }
+}
diff --git a/src/Sales/Endpoints.cs b/src/Sales/Endpoints.cs
new file mode 100644
index 0000000..857812f
--- /dev/null
+++ b/src/Sales/Endpoints.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Routing;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public static class Endpoints
+ {
+ public static void MapSales(this IEndpointRouteBuilder endpoints)
+ {
+
+ }
+
+ public static void MapSales(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderPlaced).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Extensions.cs b/src/Sales/Extensions.cs
new file mode 100644
index 0000000..f940e11
--- /dev/null
+++ b/src/Sales/Extensions.cs
@@ -0,0 +1,14 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Sales
+{
+ public static class Extensions
+ {
+ public static async Task Deserialize(this HttpResponseMessage responseMessage)
+ {
+ return JsonConvert.DeserializeObject(await responseMessage.Content.ReadAsStringAsync());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ExternalOrderIntegration.cs b/src/Sales/ExternalOrderIntegration.cs
new file mode 100644
index 0000000..a231126
--- /dev/null
+++ b/src/Sales/ExternalOrderIntegration.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using NServiceBus;
+
+namespace Sales
+{
+ public class ExternalOrderIntegration
+ {
+ private readonly IMessageSession _messageSession;
+ private readonly HttpClient _httpClient;
+
+ public ExternalOrderIntegration(IMessageSession messageSession, HttpClient httpClient)
+ {
+ _messageSession = messageSession;
+ _httpClient = httpClient;
+ }
+
+ public async Task PlaceOrder()
+ {
+ var response = await _httpClient.GetAsync("http://external.com/newOrders");
+ var externalOrder = await response.Deserialize();
+
+ var placeOrder = new PlaceOrder
+ {
+ OrderId = externalOrder!.Id,
+ // Translation to convert an external order or PlaceOrder command
+ };
+ await _messageSession.Send(placeOrder);
+ }
+ }
+
+ public class ExternalOrder
+ {
+ public Guid Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Order.cs b/src/Sales/Order.cs
new file mode 100644
index 0000000..49417f4
--- /dev/null
+++ b/src/Sales/Order.cs
@@ -0,0 +1,23 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Sales
+{
+ [Table("Orders")]
+ public class Order
+ {
+ [Key]
+ public Guid OrderId { get; set; }
+
+ public OrderStatus Status { get; set; }
+ }
+
+ public enum OrderStatus
+ {
+ Pending = 0,
+ ReadyToShip = 1,
+ Shipped = 2,
+ Cancelled = 3
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/PlaceOrderHandler.cs b/src/Sales/PlaceOrderHandler.cs
new file mode 100644
index 0000000..57bbf53
--- /dev/null
+++ b/src/Sales/PlaceOrderHandler.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Data.Common;
+using System.Net.Http;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using NServiceBus;
+using Sales.Contracts;
+using Shipping.Contracts;
+
+namespace Sales
+{
+ public class PlaceOrderController : Controller
+ {
+ private readonly IMessageSession _messageSession;
+
+ public PlaceOrderController(IMessageSession messageSession)
+ {
+ _messageSession = messageSession;
+ }
+
+ [HttpPost("/sales/orders/{orderId:Guid}")]
+ public async Task Action([FromRoute] Guid orderId)
+ {
+ await _messageSession.Send(new PlaceOrder
+ {
+ OrderId = orderId
+ });
+
+ return NoContent();
+ }
+ }
+
+ public class PlaceOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public PlaceOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(PlaceOrder message, IMessageHandlerContext context)
+ {
+ await _dbContext.Orders.AddAsync(new Order
+ {
+ OrderId = message.OrderId,
+ Status = OrderStatus.Pending
+ });
+ await _dbContext.SaveChangesAsync();
+
+ var orderPlaced = new OrderPlaced
+ {
+ OrderId = message.OrderId
+ };
+ await context.Publish(orderPlaced);
+ }
+ }
+
+ public class PlaceOrderSagaData : ContainSagaData
+ {
+ public Guid OrderId { get; set; }
+ }
+
+ public class PlaceOrderSaga :
+ Saga,
+ IAmStartedByMessages,
+ IHandleMessages,
+ IHandleMessages
+ {
+
+ protected override void ConfigureHowToFindSaga(SagaPropertyMapper mapper)
+ {
+ mapper.ConfigureMapping(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId);
+ mapper.ConfigureMapping(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId);
+ mapper.ConfigureMapping(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId);
+ }
+
+ public async Task Handle(OrderPlaced message, IMessageHandlerContext context)
+ {
+ await context.Send(new BillOrder
+ {
+ OrderId = message.OrderId
+ });
+ }
+
+ public async Task Handle(OrderBilled message, IMessageHandlerContext context)
+ {
+ await context.Send(new CreateShippingLabel
+ {
+ OrderId = message.OrderId
+ });
+ }
+
+ public async Task Handle(ShippingLabelCreated message, IMessageHandlerContext context)
+ {
+ await context.Send(new ReadyToShipOrder
+ {
+ OrderId = Data.OrderId
+ });
+
+ MarkAsComplete();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Billing.Contracts/OrderBilled.cs b/src/Billing.Contracts/OrderBilled.cs
new file mode 100644
index 0000000..e3a7bb8
--- /dev/null
+++ b/src/Billing.Contracts/OrderBilled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderBilled : IMessage
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/OrderRefunded.cs b/src/Billing.Contracts/OrderRefunded.cs
new file mode 100644
index 0000000..27ccf0b
--- /dev/null
+++ b/src/Billing.Contracts/OrderRefunded.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class OrderRefunded : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/RefundOrder.cs b/src/Billing.Contracts/RefundOrder.cs
new file mode 100644
index 0000000..9a7fac2
--- /dev/null
+++ b/src/Billing.Contracts/RefundOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class RefundOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/BillOrder.cs b/src/Billing/BillOrder.cs
new file mode 100644
index 0000000..3eb306e
--- /dev/null
+++ b/src/Billing/BillOrder.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Billing
+{
+ public class BillOrderHandler : IHandleMessages
+ {
+ public async Task Handle(BillOrder message, IMessageHandlerContext context)
+ {
+ // Do some work
+
+ // Reply
+ await context.Reply(new OrderBilled
+ {
+ OrderId = message.OrderId
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/Billing.csproj b/src/Billing/Billing.csproj
new file mode 100644
index 0000000..0e5a0a5
--- /dev/null
+++ b/src/Billing/Billing.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Billing/Endpoints.cs b/src/Billing/Endpoints.cs
new file mode 100644
index 0000000..a6609e2
--- /dev/null
+++ b/src/Billing/Endpoints.cs
@@ -0,0 +1,15 @@
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public static class Endpoints
+ {
+ public static void MapBilling(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderBilled).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing/RefundOrderHandler.cs b/src/Billing/RefundOrderHandler.cs
new file mode 100644
index 0000000..0e4afb4
--- /dev/null
+++ b/src/Billing/RefundOrderHandler.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Billing.Contracts;
+using NServiceBus;
+
+namespace Billing
+{
+ public class RefundOrderHandler : IHandleMessages
+ {
+ public async Task Handle(RefundOrder message, IMessageHandlerContext context)
+ {
+ await context.Publish(refunded =>
+ {
+ refunded.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/LooselyCoupledMonolith.sln b/src/LooselyCoupledMonolith.sln
new file mode 100644
index 0000000..de45722
--- /dev/null
+++ b/src/LooselyCoupledMonolith.sln
@@ -0,0 +1,176 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales", "Sales\Sales.csproj", "{018A96A1-C587-43C6-BB9C-12AB654F6CC6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Contracts", "Sales.Contracts\Sales.Contracts.csproj", "{FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Tests", "Sales.Tests\Sales.Tests.csproj", "{FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping", "Shipping\Shipping.csproj", "{18E2D615-2585-48C5-82A5-93CC798C54B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Contracts", "Shipping.Contracts\Shipping.Contracts.csproj", "{BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Tests", "Shipping.Tests\Shipping.Tests.csproj", "{F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales", "Sales", "{7D57F573-B99C-45B1-A5C3-5710F7E4083B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping", "Shipping", "{197792D6-E8EE-43E3-9330-6A15A518487E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker", "Worker\Worker.csproj", "{D1542A48-599D-46EA-A35D-24FE47649416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore", "AspNetCore\AspNetCore.csproj", "{4986376E-4D3C-4751-99FE-176F61A0BAA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing", "Billing\Billing.csproj", "{B179C1F1-86CB-4796-AE31-95EB314BA094}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing", "Billing", "{3A2E2769-EAF7-473B-9F32-2578709B911D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Contracts", "Billing.Contracts\Billing.Contracts.csproj", "{77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x64.Build.0 = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6}.Release|x86.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x64.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Debug|x86.Build.0 = Debug|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x64.Build.0 = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.ActiveCfg = Release|Any CPU
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D}.Release|x86.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x64.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x64.Build.0 = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975}.Release|x86.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Debug|x86.Build.0 = Debug|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x64.Build.0 = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {18E2D615-2585-48C5-82A5-93CC798C54B8}.Release|x86.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x64.Build.0 = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E}.Release|x86.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x64.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Debug|x86.Build.0 = Debug|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x64.Build.0 = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.ActiveCfg = Release|Any CPU
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1}.Release|x86.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x64.Build.0 = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.ActiveCfg = Release|Any CPU
+ {D1542A48-599D-46EA-A35D-24FE47649416}.Release|x86.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x64.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x64.Build.0 = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4986376E-4D3C-4751-99FE-176F61A0BAA2}.Release|x86.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x64.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Debug|x86.Build.0 = Debug|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x64.Build.0 = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.ActiveCfg = Release|Any CPU
+ {B179C1F1-86CB-4796-AE31-95EB314BA094}.Release|x86.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x64.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Debug|x86.Build.0 = Debug|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x64.Build.0 = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.ActiveCfg = Release|Any CPU
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {018A96A1-C587-43C6-BB9C-12AB654F6CC6} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FBC583E2-8BA8-4DD2-B9D4-BC76D13C347D} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {FDCEB20D-64A6-426E-9E5B-9FB8AC88B975} = {7D57F573-B99C-45B1-A5C3-5710F7E4083B}
+ {18E2D615-2585-48C5-82A5-93CC798C54B8} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {BAA655B9-BE4B-40E5-9A19-D8BEDFBDA31E} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {F61CB79C-4B4B-4D89-8047-C91C9EA7AEE1} = {197792D6-E8EE-43E3-9330-6A15A518487E}
+ {B179C1F1-86CB-4796-AE31-95EB314BA094} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ {77DCE1A7-64F0-49D8-9AC0-7DE397EF81D0} = {3A2E2769-EAF7-473B-9F32-2578709B911D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Sales.Contracts/CancelOrder.cs b/src/Sales.Contracts/CancelOrder.cs
new file mode 100644
index 0000000..f264adb
--- /dev/null
+++ b/src/Sales.Contracts/CancelOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class CancelOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderCancelled.cs b/src/Sales.Contracts/OrderCancelled.cs
new file mode 100644
index 0000000..d790bf8
--- /dev/null
+++ b/src/Sales.Contracts/OrderCancelled.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderCancelled : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/OrderPlaced.cs b/src/Sales.Contracts/OrderPlaced.cs
new file mode 100644
index 0000000..f99287b
--- /dev/null
+++ b/src/Sales.Contracts/OrderPlaced.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class OrderPlaced : IEvent
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/PlaceOrder.cs b/src/Sales.Contracts/PlaceOrder.cs
new file mode 100644
index 0000000..20ca626
--- /dev/null
+++ b/src/Sales.Contracts/PlaceOrder.cs
@@ -0,0 +1,7 @@
+using System;
+using NServiceBus;
+
+public class PlaceOrder : ICommand
+{
+ public Guid OrderId { get; set; }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/ReadyToShipOrder.cs b/src/Sales.Contracts/ReadyToShipOrder.cs
new file mode 100644
index 0000000..e6fa0f6
--- /dev/null
+++ b/src/Sales.Contracts/ReadyToShipOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Sales.Contracts
+{
+ public class ReadyToShipOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales.Contracts/Sales.Contracts.csproj b/src/Sales.Contracts/Sales.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Sales.Contracts/Sales.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/src/Sales.Tests/ConfigureServicesTests.cs b/src/Sales.Tests/ConfigureServicesTests.cs
new file mode 100644
index 0000000..73c3238
--- /dev/null
+++ b/src/Sales.Tests/ConfigureServicesTests.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Xunit;
+
+namespace Sales.Tests
+{
+ public class ConfigureServicesTests
+ {
+ [Fact]
+ public void DbContext_should_resolve()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSales();
+
+ var provider = serviceCollection.BuildServiceProvider();
+ var dbContext = provider.GetService();
+ dbContext.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/src/Sales.Tests/Sales.Tests.csproj b/src/Sales.Tests/Sales.Tests.csproj
new file mode 100644
index 0000000..b9b3995
--- /dev/null
+++ b/src/Sales.Tests/Sales.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Sales/CancelOrderHandler.cs b/src/Sales/CancelOrderHandler.cs
new file mode 100644
index 0000000..1c86008
--- /dev/null
+++ b/src/Sales/CancelOrderHandler.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public class CancelOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public CancelOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(CancelOrder message, IMessageHandlerContext context)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == message.OrderId);
+ order.Status = OrderStatus.Cancelled;
+ await _dbContext.SaveChangesAsync();
+
+ await context.Publish(cancelled =>
+ {
+ cancelled.OrderId = message.OrderId;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ConfigureServices.cs b/src/Sales/ConfigureServices.cs
new file mode 100644
index 0000000..7099c68
--- /dev/null
+++ b/src/Sales/ConfigureServices.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Sales
+{
+ public static class ConfigureServices
+ {
+ public static void AddSales(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddDbContext();
+ }
+ }
+}
diff --git a/src/Sales/Endpoints.cs b/src/Sales/Endpoints.cs
new file mode 100644
index 0000000..857812f
--- /dev/null
+++ b/src/Sales/Endpoints.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Routing;
+using NServiceBus;
+using Sales.Contracts;
+
+namespace Sales
+{
+ public static class Endpoints
+ {
+ public static void MapSales(this IEndpointRouteBuilder endpoints)
+ {
+
+ }
+
+ public static void MapSales(this RoutingSettings routing)
+ {
+ routing.RouteToEndpoint(
+ assembly: typeof(OrderPlaced).Assembly,
+ destination: "LooselyCoupledMonolith");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Extensions.cs b/src/Sales/Extensions.cs
new file mode 100644
index 0000000..f940e11
--- /dev/null
+++ b/src/Sales/Extensions.cs
@@ -0,0 +1,14 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Sales
+{
+ public static class Extensions
+ {
+ public static async Task Deserialize(this HttpResponseMessage responseMessage)
+ {
+ return JsonConvert.DeserializeObject(await responseMessage.Content.ReadAsStringAsync());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ExternalOrderIntegration.cs b/src/Sales/ExternalOrderIntegration.cs
new file mode 100644
index 0000000..a231126
--- /dev/null
+++ b/src/Sales/ExternalOrderIntegration.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using NServiceBus;
+
+namespace Sales
+{
+ public class ExternalOrderIntegration
+ {
+ private readonly IMessageSession _messageSession;
+ private readonly HttpClient _httpClient;
+
+ public ExternalOrderIntegration(IMessageSession messageSession, HttpClient httpClient)
+ {
+ _messageSession = messageSession;
+ _httpClient = httpClient;
+ }
+
+ public async Task PlaceOrder()
+ {
+ var response = await _httpClient.GetAsync("http://external.com/newOrders");
+ var externalOrder = await response.Deserialize();
+
+ var placeOrder = new PlaceOrder
+ {
+ OrderId = externalOrder!.Id,
+ // Translation to convert an external order or PlaceOrder command
+ };
+ await _messageSession.Send(placeOrder);
+ }
+ }
+
+ public class ExternalOrder
+ {
+ public Guid Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/Order.cs b/src/Sales/Order.cs
new file mode 100644
index 0000000..49417f4
--- /dev/null
+++ b/src/Sales/Order.cs
@@ -0,0 +1,23 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Sales
+{
+ [Table("Orders")]
+ public class Order
+ {
+ [Key]
+ public Guid OrderId { get; set; }
+
+ public OrderStatus Status { get; set; }
+ }
+
+ public enum OrderStatus
+ {
+ Pending = 0,
+ ReadyToShip = 1,
+ Shipped = 2,
+ Cancelled = 3
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/PlaceOrderHandler.cs b/src/Sales/PlaceOrderHandler.cs
new file mode 100644
index 0000000..57bbf53
--- /dev/null
+++ b/src/Sales/PlaceOrderHandler.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Data.Common;
+using System.Net.Http;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using NServiceBus;
+using Sales.Contracts;
+using Shipping.Contracts;
+
+namespace Sales
+{
+ public class PlaceOrderController : Controller
+ {
+ private readonly IMessageSession _messageSession;
+
+ public PlaceOrderController(IMessageSession messageSession)
+ {
+ _messageSession = messageSession;
+ }
+
+ [HttpPost("/sales/orders/{orderId:Guid}")]
+ public async Task Action([FromRoute] Guid orderId)
+ {
+ await _messageSession.Send(new PlaceOrder
+ {
+ OrderId = orderId
+ });
+
+ return NoContent();
+ }
+ }
+
+ public class PlaceOrderHandler : IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public PlaceOrderHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task Handle(PlaceOrder message, IMessageHandlerContext context)
+ {
+ await _dbContext.Orders.AddAsync(new Order
+ {
+ OrderId = message.OrderId,
+ Status = OrderStatus.Pending
+ });
+ await _dbContext.SaveChangesAsync();
+
+ var orderPlaced = new OrderPlaced
+ {
+ OrderId = message.OrderId
+ };
+ await context.Publish(orderPlaced);
+ }
+ }
+
+ public class PlaceOrderSagaData : ContainSagaData
+ {
+ public Guid OrderId { get; set; }
+ }
+
+ public class PlaceOrderSaga :
+ Saga,
+ IAmStartedByMessages,
+ IHandleMessages,
+ IHandleMessages
+ {
+
+ protected override void ConfigureHowToFindSaga(SagaPropertyMapper mapper)
+ {
+ mapper.ConfigureMapping(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId);
+ mapper.ConfigureMapping(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId);
+ mapper.ConfigureMapping(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId);
+ }
+
+ public async Task Handle(OrderPlaced message, IMessageHandlerContext context)
+ {
+ await context.Send(new BillOrder
+ {
+ OrderId = message.OrderId
+ });
+ }
+
+ public async Task Handle(OrderBilled message, IMessageHandlerContext context)
+ {
+ await context.Send(new CreateShippingLabel
+ {
+ OrderId = message.OrderId
+ });
+ }
+
+ public async Task Handle(ShippingLabelCreated message, IMessageHandlerContext context)
+ {
+ await context.Send(new ReadyToShipOrder
+ {
+ OrderId = Data.OrderId
+ });
+
+ MarkAsComplete();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Sales/ReadyToShipHandler.cs b/src/Sales/ReadyToShipHandler.cs
new file mode 100644
index 0000000..2b6541c
--- /dev/null
+++ b/src/Sales/ReadyToShipHandler.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using NServiceBus;
+using Sales.Contracts;
+using Shipping.Contracts;
+
+namespace Sales
+{
+ public class ReadyToShipHandler :
+ IHandleMessages,
+ IHandleMessages
+ {
+ private readonly SalesDbContext _dbContext;
+
+ public ReadyToShipHandler(SalesDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ private async Task SetStatus(Guid orderId)
+ {
+ var order = await _dbContext.Orders.SingleAsync(x => x.OrderId == orderId);
+ order.Status = OrderStatus.ReadyToShip;
+ await _dbContext.SaveChangesAsync();
+ }
+
+ public async Task Handle(ShippingLabelCreated message, IMessageHandlerContext context)
+ {
+ await SetStatus(message.OrderId);
+ }
+
+ public async Task Handle(ReadyToShipOrder message, IMessageHandlerContext context)
+ {
+ await SetStatus(message.OrderId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46aef81
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# JetBrains Rider
+.idea/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..752a6d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Derek Comartin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderCancelled/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
new file mode 100644
index 0000000..20ae4e6
--- /dev/null
+++ b/src/.learningtransport/.events/Sales.Contracts.OrderPlaced/LooselyCoupledMonolith.subscription
@@ -0,0 +1 @@
+LooselyCoupledMonolith
\ No newline at end of file
diff --git a/src/AspNetCore/AspNetCore.csproj b/src/AspNetCore/AspNetCore.csproj
new file mode 100644
index 0000000..d1bbf94
--- /dev/null
+++ b/src/AspNetCore/AspNetCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AspNetCore/Program.cs b/src/AspNetCore/Program.cs
new file mode 100644
index 0000000..0d02003
--- /dev/null
+++ b/src/AspNetCore/Program.cs
@@ -0,0 +1,42 @@
+using Billing;
+using Billing.Contracts;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using Sales;
+using Sales.Contracts;
+using Shipping;
+using Shipping.Contracts;
+
+namespace AspNetCore
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .UseNServiceBus(context =>
+ {
+ var endpointConfiguration = new EndpointConfiguration("LooselyCoupledMonolith");
+ var transport = endpointConfiguration.UseTransport();
+ var persistence = endpointConfiguration.UsePersistence();
+
+ var routing = transport.Routing();
+ routing.MapBilling();
+ routing.MapSales();
+ routing.MapShipping();
+
+ endpointConfiguration.SendOnly();
+
+ return endpointConfiguration;
+ })
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/src/AspNetCore/Properties/launchSettings.json b/src/AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000..ee51616
--- /dev/null
+++ b/src/AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:64790",
+ "sslPort": 44374
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/AspNetCore/Startup.cs b/src/AspNetCore/Startup.cs
new file mode 100644
index 0000000..c95df24
--- /dev/null
+++ b/src/AspNetCore/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sales;
+using Shipping;
+
+namespace AspNetCore
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSales();
+ services.AddShipping();
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSales();
+ endpoints.MapShipping();
+ });
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.Development.json b/src/AspNetCore/appsettings.Development.json
new file mode 100644
index 0000000..8983e0f
--- /dev/null
+++ b/src/AspNetCore/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/src/AspNetCore/appsettings.json b/src/AspNetCore/appsettings.json
new file mode 100644
index 0000000..d9d9a9b
--- /dev/null
+++ b/src/AspNetCore/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Billing.Contracts/BillOrder.cs b/src/Billing.Contracts/BillOrder.cs
new file mode 100644
index 0000000..c504a2d
--- /dev/null
+++ b/src/Billing.Contracts/BillOrder.cs
@@ -0,0 +1,10 @@
+using System;
+using NServiceBus;
+
+namespace Billing.Contracts
+{
+ public class BillOrder : ICommand
+ {
+ public Guid OrderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Billing.Contracts/Billing.Contracts.csproj b/src/Billing.Contracts/Billing.Contracts.csproj
new file mode 100644
index 0000000..7f31933
--- /dev/null
+++ b/src/Billing.Contracts/Billing.Contracts.csproj
@@ -0,0 +1,11 @@
+
+
+
+