├── .gitattributes
├── .gitignore
├── LICENSE.txt
├── README.md
├── activities
├── 01-InstallTooling.md
├── 02-CreateEmptyWebProject.md
├── 03-CreateControllerAndAction.md
├── 04-ReturningJsonData.md
├── 05-BindingFromQueryString.md
├── 06-BindingFromRouteParameters.md
├── 07-AcceptingPostedData.md
├── 08-Configuration.md
├── 09-Logging.md
├── 10-InitialDockerfile.md
├── 11-ProductionDockerfile.md
├── 12-DockerCompose.md
├── 13-UnitTests.md
└── 14-IntegrationTests.md
├── images
├── 0-EditSampleApiProject.png
├── 1-PostmanRequest.png
├── 2-LoggingOutput.png
├── 3-AddTestProject.png
├── 4-TestProjectReferenceViaUi.png
├── 5-TestProjectMoq.png
├── 6-EditTestProject.png
└── 7-AppSettingsJson.png
├── resources
└── .dockerignore
└── steps
├── 02-Create-Solution-And-Project
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ └── Startup.cs
├── 03-Create-Controller-And-Action
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Controllers
│ └── SampleController.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ └── Startup.cs
├── 04-Returning-JSON-Data
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Controllers
│ └── SampleController.cs
│ ├── OutputModels
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ └── Startup.cs
├── 05-Binding-Data-From-Query-String
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Controllers
│ └── SampleController.cs
│ ├── OutputModels
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ └── Startup.cs
├── 06-Binding-From-Route-Parameters
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Controllers
│ └── SampleController.cs
│ ├── OutputModels
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ └── Startup.cs
├── 07-Accepting-Posted-Data
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Controllers
│ └── SampleController.cs
│ ├── InputModels
│ └── CalculateInputModel.cs
│ ├── OutputModels
│ ├── CalculateOutputModel.cs
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ └── Startup.cs
├── 08-Configuration
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Configuration
│ └── MessagesConfiguration.cs
│ ├── Controllers
│ └── SampleController.cs
│ ├── InputModels
│ └── CalculateInputModel.cs
│ ├── OutputModels
│ ├── CalculateOutputModel.cs
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── 09-Logging
├── SampleApi.sln
├── global.json
└── src
│ └── SampleApi
│ ├── Configuration
│ └── MessagesConfiguration.cs
│ ├── Controllers
│ └── SampleController.cs
│ ├── InputModels
│ └── CalculateInputModel.cs
│ ├── OutputModels
│ ├── CalculateOutputModel.cs
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── 10-Initial-Dockerfile
├── .dockerignore
├── SampleApi.sln
├── dockerfile
├── global.json
└── src
│ └── SampleApi
│ ├── Configuration
│ └── MessagesConfiguration.cs
│ ├── Controllers
│ └── SampleController.cs
│ ├── InputModels
│ └── CalculateInputModel.cs
│ ├── OutputModels
│ ├── CalculateOutputModel.cs
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── 11-Production-Dockerfile
├── .dockerignore
├── SampleApi.sln
├── dockerfile
├── global.json
└── src
│ └── SampleApi
│ ├── Configuration
│ └── MessagesConfiguration.cs
│ ├── Controllers
│ └── SampleController.cs
│ ├── InputModels
│ └── CalculateInputModel.cs
│ ├── OutputModels
│ ├── CalculateOutputModel.cs
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── 12-Docker-Compose
├── .dockerignore
├── SampleApi.sln
├── docker-compose.yml
├── dockerfile
├── global.json
└── src
│ └── SampleApi
│ ├── Configuration
│ └── MessagesConfiguration.cs
│ ├── Controllers
│ └── SampleController.cs
│ ├── InputModels
│ └── CalculateInputModel.cs
│ ├── OutputModels
│ ├── CalculateOutputModel.cs
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── 13-Unit-Tests
├── .dockerignore
├── SampleApi.sln
├── docker-compose.yml
├── dockerfile
├── global.json
├── src
│ └── SampleApi
│ │ ├── Configuration
│ │ └── MessagesConfiguration.cs
│ │ ├── Controllers
│ │ └── SampleController.cs
│ │ ├── InputModels
│ │ └── CalculateInputModel.cs
│ │ ├── OutputModels
│ │ ├── CalculateOutputModel.cs
│ │ └── HelloOutputModel.cs
│ │ ├── Program.cs
│ │ ├── Properties
│ │ └── launchSettings.json
│ │ ├── SampleApi.csproj
│ │ ├── Startup.cs
│ │ ├── appsettings.Development.json
│ │ └── appsettings.json
└── test
│ └── SampleApi.Test
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.Test.csproj
│ └── SampleControllerTests.cs
├── 14-Integration-Tests
├── .dockerignore
├── SampleApi.sln
├── docker-compose.yml
├── dockerfile
├── global.json
├── src
│ └── SampleApi
│ │ ├── Configuration
│ │ └── MessagesConfiguration.cs
│ │ ├── Controllers
│ │ └── SampleController.cs
│ │ ├── InputModels
│ │ └── CalculateInputModel.cs
│ │ ├── OutputModels
│ │ ├── CalculateOutputModel.cs
│ │ └── HelloOutputModel.cs
│ │ ├── Program.cs
│ │ ├── Properties
│ │ └── launchSettings.json
│ │ ├── SampleApi.csproj
│ │ ├── Startup.cs
│ │ ├── appsettings.development.json
│ │ └── appsettings.json
└── test
│ ├── SampleApi.IntegrationTest
│ ├── Properties
│ │ └── launchSettings.json
│ ├── SampleApi.IntegrationTest.csproj
│ ├── SampleControllerIntegrationTests.cs
│ └── xunit.runner.json
│ └── SampleApi.Test
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.Test.csproj
│ └── SampleControllerTests.cs
└── 15-Testing-In-Docker
├── .dockerignore
├── SampleApi.sln
├── docker-compose.yml
├── dockerfile
├── global.json
├── src
└── SampleApi
│ ├── Configuration
│ └── MessagesConfiguration.cs
│ ├── Controllers
│ └── SampleController.cs
│ ├── InputModels
│ └── CalculateInputModel.cs
│ ├── OutputModels
│ ├── CalculateOutputModel.cs
│ └── HelloOutputModel.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── SampleApi.csproj
│ ├── Startup.cs
│ ├── appsettings.development.json
│ └── appsettings.json
└── test
├── SampleApi.IntegrationTest
├── Properties
│ └── launchSettings.json
├── SampleApi.IntegrationTest.csproj
├── SampleControllerIntegrationTests.cs
└── xunit.runner.json
└── SampleApi.Test
├── Properties
└── launchSettings.json
├── SampleApi.Test.csproj
└── SampleControllerTests.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Steve J Gordon (https://www.stevejgordon.co.uk)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ASP.NET Core and Docker Workshop
2 |
3 | ## Pre-requisite Setup
4 |
5 | 1. Clone this repository locally
6 | 1. Install Postman for Windows - [Download Postman](https://www.getpostman.com/apps)
7 |
8 | ## What You'll Be Building
9 |
10 | In this workshop you will build a simple ASP.NET Core API from scratch, initially using the .NET SDK CLI. The finished API will have two endpoints, one returning data via HTTP GET and the other accepting data via HTTP POST. It will make use of ASP.NET Core configuration.
11 |
12 | You'll then create a Docker image for your API and run it as a Docker container.
13 |
14 | ## Activities
15 |
16 | | Activity | Topics |
17 | | ----- | ---- |
18 | | [Activity #1](/activities/01-InstallTooling.md) | Install the .NET Core SDK and Docker tooling |
19 | | [Activity #2](/activities/02-CreateEmptyWebProject.md) | Create an empty web project via the command line |
20 | | [Activity #3](/activities/03-CreateControllerAndAction.md) | Create a controller and action |
21 | | [Activity #4](/activities/04-ReturningJsonData.md) | Returning JSON Data |
22 | | [Activity #5](/activities/05-BindingFromQueryString.md) | Binding data from the query string |
23 | | [Activity #6](/activities/06-BindingFromRouteParameters.md) | Binding data from route parameters |
24 | | [Activity #7](/activities/07-AcceptingPostedData.md) | Accepting posted data |
25 | | [Activity #8](/activities/08-Configuration.md) | Application configuration |
26 | | [Activity #9](/activities/09-Logging.md) | Working with logging |
27 | | [Activity #10](/activities/10-InitialDockerfile.md) | Initial Dockerfile |
28 | | [Activity #11](/activities/11-ProductionDockerfile.md) | Production Dockerfile |
29 | | [Activity #12](/activities/12-DockerCompose.md) | Working with Docker Compose |
30 | | [Activity #13](/activities/13-UnitTests.md) | Adding some unit tests |
31 | | [Activity #14](/activities/14-IntegrationTests.md) | Adding an integration test |
--------------------------------------------------------------------------------
/activities/01-InstallTooling.md:
--------------------------------------------------------------------------------
1 | # Install .NET SDK
2 |
3 | ## What's the plan?
4 |
5 | We're going make sure the correct version of the SDK for .NET Core is installed and if not, install it.
6 |
7 | ## Activity Steps
8 |
9 | 1. Verify the .NET SDK version installed on your PC. Open a command prompt and run the following command...
10 |
11 | ```dotnet --version```
12 |
13 | The version should be **2.1.403** or higher.
14 |
15 | 2. If you require a newer version, you can download and install it from [.NET SDK for Visual Studio](https://www.microsoft.com/net/download/visual-studio-sdks)
16 |
17 | 3. You can view additional information with the following command...
18 |
19 | ```dotnet --info```
20 |
21 | This command lists all of the SDK and runtime versions installed on your PC.
22 |
23 | ## End of Activity
24 |
25 | Continue to [Activity 2](02-CreateEmptyWebProject.md).
26 |
27 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/02-CreateEmptyWebProject.md:
--------------------------------------------------------------------------------
1 | # Creating an Empty Web Project
2 |
3 | For this activity, please ensure you have completed [Activity 1](01-InstallTooling.md) to install the required tooling.
4 |
5 | ## What's the plan?
6 |
7 | We're going to use the command line and dotnet CLI to create the structure for our API project and solution.
8 |
9 | We could use the Visual Studio UI and tooling for this also, but let's see how easily the cross platform CLI supports working with projects and templates.
10 |
11 | ## Activity Steps
12 |
13 | 1. Open a command prompt from your preferred project directory e.g. 'C:\Projects\'.
14 | 2. Create a 'SampleApi' folder.
15 |
16 | ```md SampleApi```
17 |
18 | 3. Change to the 'SampleApi' folder.
19 |
20 | ```cd SampleApi```
21 |
22 | 4. Pin the SDK version for these activies to 2.1.403
23 |
24 | ```dotnet new globaljson --sdk-version 2.1.403```
25 |
26 | 5. Use the dotnet CLI to create an empty web project called SampleApi under a directory called 'src'.
27 |
28 | ```dotnet new web --name SampleApi --no-https -o src/SampleApi```
29 |
30 | 6. Use the dotnet CLI to create a new empty solution
31 |
32 | ```dotnet new sln```
33 |
34 | 7. Add the SampleApi project to the solution.
35 |
36 | ```dotnet sln add .\src\SampleApi\SampleApi.csproj```
37 |
38 | 8. Use the dotnet CLI to build the solution.
39 |
40 | ```dotnet build```
41 |
42 | 9. Use the dotnet CLI to run the application
43 |
44 | ```dotnet run --project src/SampleApi/SampleApi.csproj```
45 |
46 | *NOTE: By default the application will be hosted on port 5000. If this conflicts with anything you can override the port using the switch --urls "http://localhost:PORT"*
47 |
48 | 10. Open a browser to test the application by navigating to http://localhost:5000
49 |
50 | To finish, we'll clean up some items added by the default web project template which we do not need. This is not absolutely required but keeps everything clean.
51 |
52 | 11. Explore to the 'src/SampleApi' directory from Windows Explorer.
53 | 12. Open the src/SampleApi/SampleApi.csproj file in the text editor of your choosing.
54 |
55 | 13. Remove the entire ItemGroup which specified the folder include for the wwwroot folder.
56 | 14. Remove the package reference to 'Microsoft.AspNetCore.Razor.Design' which is not needed for an API project.
57 |
58 | The csproj file for SampleApi should look like this once you have finished...
59 |
60 | ```xml
61 |
62 |
63 |
64 | netcoreapp2.1
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | ```
73 |
74 | 15. In Windows Explorer, delete the 'wwwroot' folder. This is not needed for an API project since we will not serve any static files.
75 |
76 | ## End of Activity
77 |
78 | By this point you should be able to double click the solution file to open the SampleApi project in Visual Studio 2017.
79 |
80 | The completed example for this activity can be found in the '/steps/02-Create-Solution-And-Project' folder.
81 |
82 | Continue to [Activity 3](03-CreateControllerAndAction.md).
83 |
84 | [Return to README and activity links](../README.md)
85 |
--------------------------------------------------------------------------------
/activities/03-CreateControllerAndAction.md:
--------------------------------------------------------------------------------
1 | # Creating a Controller and Action
2 |
3 | For this activity, please ensure you have completed [Activity 2](02-CreateEmptyWebProject.md).
4 |
5 | ## What's the plan?
6 |
7 | We're going to create our first ASP.NET Core MVC controller and an action to handle requests to the root path for the API.
8 |
9 | ## Activity Steps
10 |
11 | 1. Open your SampleApi.sln in Visual Studio 2017.
12 | 1. Create a new folder call 'Controllers' under the SampleApi project.
13 | 1. Create a class called 'SampleController' in the Controllers folder.
14 | 1. Update the class to inherit from the ControllerBase abstract class.
15 |
16 | ``` csharp
17 | public class SampleController : ControllerBase
18 | ```
19 |
20 | *NOTE: This will require the a using statement for 'Microsoft.AspNetCore.Mvc'.*
21 |
22 | 5. Add the [ApiController] attribute to the class.
23 |
24 | ``` csharp
25 | [ApiController]
26 | public class SampleController : ControllerBase
27 | ```
28 |
29 | 6. Create a method as follows...
30 |
31 | ``` csharp
32 | [Route("")]
33 | public string Hello()
34 | {
35 | return "Hello";
36 | }
37 | ```
38 |
39 | 7. Open the Startup class.
40 | 8. Add the following line to the ConfigureServices method to register the MVC services with DI.
41 |
42 | ```csharp
43 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
44 | ```
45 |
46 | *NOTE: A using statement will be required for 'Microsoft.AspNetCore.Mvc'.*
47 |
48 | 9. Replace the app.Run call in the 'Configure' method with the following...
49 |
50 | ```csharp
51 | app.UseMvc();
52 | ```
53 |
54 | 7. Run the application by pressing F5.
55 |
56 | ## End of Activity
57 |
58 | The completed example for this activity can be found in the '/steps/03-Create-Controller-And-Action' folder.
59 |
60 | Continue to [Activity 4](04-ReturningJsonData.md).
61 |
62 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/04-ReturningJsonData.md:
--------------------------------------------------------------------------------
1 | # Returning JSON Data
2 |
3 | For this activity, please ensure you have completed [Activity 3](03-CreateControllerAndAction.md) and have your solution open in Visual Studio 2017.
4 |
5 | ## What's the plan?
6 |
7 | We're going to update our action to return a JSON result.
8 |
9 | ## Activity Steps
10 |
11 | 1. Create a new folder call 'OutputModels' inside the SampleApi project.
12 | 2. Create a class called 'HelloOutputModel' in the OutputModels folder.
13 | 3. Add the following Property declaration to the class...
14 |
15 | ``` csharp
16 | public string WelcomeMessage { get; set; } = "Hello";
17 | ```
18 |
19 | 4. Update the 'Hello' method in the 'SampleController' so that the method returns `ActionResult`
20 |
21 | ``` csharp
22 | public ActionResult Hello()
23 | ```
24 |
25 | 5. Update the 'Hello' method to instantiate an instance of the HelloOutputModel before the return statement.
26 |
27 | ``` csharp
28 | var model = new HelloOutputModel();
29 | ```
30 | *NOTE: You'll need to include a using statement for 'SampleApi.OutputModels'*
31 |
32 | 6. Update the return statement to return the object.
33 |
34 | ``` csharp
35 | return Ok(model);
36 | ```
37 |
38 | 7. Run the application by pressing F5.
39 |
40 | ## End of Activity
41 |
42 | By the end of this activity your completed action method should now look like this...
43 | ``` csharp
44 | [Route("")]
45 | public ActionResult Hello()
46 | {
47 | var model = new HelloOutputModel();
48 | return Ok(model);
49 | }
50 | ```
51 |
52 | The completed example for this activity can be found in the '/steps/04-Returning-JSON-Data' folder.
53 |
54 | Continue to [Activity 5](05-BindingFromQueryString.md).
55 |
56 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/05-BindingFromQueryString.md:
--------------------------------------------------------------------------------
1 | # Binding Data from the QueryString
2 |
3 | For this activity, please ensure you have completed [Activity 4](04-ReturningJsonData.md) and have your solution open in Visual Studio 2017.
4 |
5 | ## What's the plan?
6 |
7 | We're going to explore binding data from the query string.
8 |
9 | ## Activity Steps
10 |
11 | 1. Update the method signature of the Hello method to accept a string argument called 'name'.
12 |
13 | ``` csharp
14 | public ActionResult Hello(string name)
15 | ```
16 |
17 | 2. After the line which creates the HelloOutputModel, before the return statement, add the following line to update the WelcomeMessage on the model...
18 |
19 | ``` csharp
20 | model.WelcomeMessage = $"{model.WelcomeMessage} {name ?? "whoever you are!"}";
21 | ```
22 |
23 | 3. Run the application by pressing F5.
24 | 4. Append a query string parameter called 'name' with any value you want to the URL in your address bar.
25 |
26 | > ?name=Steve
27 |
28 | 5. Press Enter to navigate to the updated URL.
29 |
30 | ## End of Activity
31 |
32 | By the end of this activity your completed action method should now look like this...
33 | ``` csharp
34 | [Route("")]
35 | public ActionResult Hello(string name)
36 | {
37 | var model = new HelloOutputModel();
38 | model.WelcomeMessage = $"{model.WelcomeMessage} {name ?? "whoever you are!"}";
39 | return Ok(model);
40 | }
41 | ```
42 |
43 | The completed example for this activity can be found in the '/steps/05-Binding-Data-From-Query-String' folder.
44 |
45 | Continue to [Activity 6](06-BindingFromRouteParameters.md).
46 |
47 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/06-BindingFromRouteParameters.md:
--------------------------------------------------------------------------------
1 | # Binding Data from the Route Parameters
2 |
3 | For this activity, please ensure you have completed [Activity 5](05-BindingFromQueryString.md) and have your solution open in Visual Studio 2017.
4 |
5 | ## What's the plan?
6 |
7 | We're going to explore binding data from route parameters.
8 |
9 | ## Activity Steps
10 |
11 | 1. Update the route attribute to include an optional route parameter.
12 |
13 | ``` csharp
14 | [Route("{name?}")]
15 | ```
16 |
17 | 2. Run the application by pressing F5.
18 | 3. Add a suffix to the path of the URL to pass your name which will be bound to the action argument. e.g. '/Steve'.
19 | 4. Press Enter to navigate to the updated URL.
20 |
21 | ## End of Activity
22 |
23 | The completed example for this activity can be found in the '/steps/06-Binding-From-Route-Parameters' folder.
24 |
25 | Continue to [Activity 7](07-AcceptingPostedData.md).
26 |
27 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/07-AcceptingPostedData.md:
--------------------------------------------------------------------------------
1 | # Accepting Posted Data
2 |
3 | For this activity, please ensure you have completed [Activity 6](06-BindingFromRouteParameters.md) and have your solution open in Visual Studio 2017.
4 |
5 | ## What's the plan?
6 |
7 | We're going to add an action which will accept and handle POSTed data to a new endpoint on our API.
8 |
9 | ## Activity Steps
10 |
11 | 1. Create a new class called 'CalculateOutputModel' in the 'OutputModels' folder.
12 |
13 | ``` csharp
14 | public class CalculateOutputModel
15 | {
16 | public int Result { get; set; }
17 | }
18 | ```
19 |
20 | 2. Create a new folder called 'InputModels'
21 | 3. Create a new class called 'CalculateInputModel' in the 'InputModels' folder.
22 | 4. Add to properties as follows...
23 |
24 | ``` csharp
25 | public int Number1 { get; set; }
26 | public int Number2 { get; set; }
27 | ```
28 |
29 | 4. Add a new method to the SampleController called 'Calculate'...
30 |
31 | ``` csharp
32 | [HttpPost]
33 | [Route("calculate")]
34 | public ActionResult Calculate(CalculateInputModel input)
35 | {
36 | var result = new CalculateOutputModel { Result = input.Number1 + input.Number2 };
37 | return Ok(result);
38 | }
39 | ```
40 | *NOTE: You will require a using statement for 'SampleApi.InputModels'.*
41 |
42 | 5. Run the application by pressing F5.
43 |
44 | 6. Copy the URL from the address bar.
45 |
46 | 7. Open Postman (or your application of choice) and create a POST request to your copied URL, adding a path of '/Calculate'.
47 | 8. Add the following body to the POST request...
48 |
49 | ``` javascript
50 | {
51 | "number1": 10,
52 | "number2": 20
53 | }
54 | ```
55 |
56 | *NOTE: If using postman, your UI should be similar to the following, although your port will likely differ.*
57 |
58 | 
59 |
60 | 9. Send the request and check the response.
61 | 10. Change your request body to include invalid data such as a string value...
62 |
63 | ``` javascript
64 | {
65 | "number1": 10,
66 | "number2": 'this is invalid'
67 | }
68 | ```
69 |
70 | 11. Send the request and check the response.
71 |
72 | ## End of Activity
73 |
74 | The completed example for this activity can be found in the '/steps/07-Accepting-Posted-Data' folder.
75 |
76 | Continue to [Activity 8](08-Configuration.md).
77 |
78 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/08-Configuration.md:
--------------------------------------------------------------------------------
1 |
2 | # Configuration
3 |
4 | For this activity, please ensure you have completed [Activity 7](07-AcceptingPostedData.md) and have your solution open in Visual Studio 2017.
5 |
6 | ## What's the plan?
7 |
8 | We're going to add the concept of configuration to our API. We'll configure the application using an appsettings.json file. We'll use the Options pattern in our SampleController to retrieve the configured value which we'll use to control the output from an endpoint in our API.
9 |
10 | ## Activity Steps
11 |
12 | 1. Create a JSON file called 'appsettings.json' at the root of the project.
13 |
14 | 
15 |
16 | 2. Add a 'Messages' section to the configuration file. Include a setting called 'WelcomeMessage' with a value of 'Hey'. Once complete, the contents of your appsettings.json file should be as follows...
17 |
18 | ``` javascript
19 | {
20 | "Messages": {
21 | "WelcomeMessage": "Hey"
22 | }
23 | }
24 | ```
25 |
26 | 3. Create a new folder called 'Configuration'
27 | 4. Create a new class called 'MessagesConfiguration' in the 'Configuration' folder with a single `string` property called 'WelcomeMessage'.
28 |
29 | ``` csharp
30 | public class MessagesConfiguration
31 | {
32 | public string WelcomeMessage { get; set; }
33 | }
34 | ```
35 |
36 | 5. At the top of the Startup class, add a public constructor accepting an IConfiguration object. Store this into a public read-only property.
37 |
38 | ``` csharp
39 | public IConfiguration Configuration { get; }
40 |
41 | public Startup(IConfiguration configuration)
42 | {
43 | Configuration = configuration;
44 | }
45 | ```
46 |
47 | 6. In the ConfigureServices method of the Startup class; add a line to bind the configuration to our typed configuration class. Call the `Configure` on the `IServiceCollection` passing the type for the 'MessagesConfiguration' into the generic parameter. This method accepts an `IConfig` object which we get by calling `GetSection` on the `IConfiguration` property, passing the section name to read and bind. Once complete the ConfigureServices method should be as follows...
48 |
49 | ``` csharp
50 | public void ConfigureServices(IServiceCollection services)
51 | {
52 | services.Configure(Configuration.GetSection("Messages"));
53 |
54 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
55 | }
56 | ```
57 |
58 | *NOTE: This will require a using statement for 'SampleApi.Configuration'.*
59 |
60 | 7. Add a constructor to the SampleController accepting an `IOptions` and store the object in a private read-only field.
61 |
62 | *NOTE: This will require a using statement for 'SampleApi.Configuration' and 'Microsoft.Extensions.Options'.*
63 |
64 | ``` csharp
65 | private readonly IOptions _messagesConfig;
66 |
67 | public SampleController(IOptions messagesConfig)
68 | {
69 | _messagesConfig = messagesConfig;
70 | }
71 | ```
72 |
73 | 8. Update the 'Hello' method to use the welcome message from the configuration.
74 |
75 | ``` csharp
76 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
77 | ```
78 |
79 | 9. Run the application by pressing F5.
80 | 10. Create a JSON file called 'appsettings.development.json' at the root of the project.
81 | 11. Copy in the 'Messages' section from appsettings.json' into the new configuration file.
82 | 12. Update the value of the 'WelcomeMessage' setting to 'Hey from dev'. Once complete the contents of your appsettings.json file should be as follows...
83 |
84 | ``` javascript
85 | {
86 | "Messages": {
87 | "WelcomeMessage": "Hey from dev"
88 | }
89 | }
90 | ```
91 |
92 | 13. Run the application by pressing F5.
93 |
94 | ## End of Activity
95 |
96 | The completed example for this activity can be found in the '/steps/08-Configuration' folder.
97 |
98 | Continue to [Activity 9](09-Logging.md).
99 |
100 | [Return to README and activity links](../README.md)
101 |
--------------------------------------------------------------------------------
/activities/09-Logging.md:
--------------------------------------------------------------------------------
1 |
2 | # Logging
3 |
4 | For this activity, please ensure you have completed [Activity 8](08-Configuration.md) and have your solution open in Visual Studio 2017.
5 |
6 | ## What's the plan?
7 |
8 | We're going to use the default ASP.NET Core logging (Microsoft.Extensions.Logging) library to log a message to the console from our 'Calculate' action.
9 |
10 | ## Activity Steps
11 |
12 | 1. Update the constructor of the SampleController to accept an `ILogger` and store the object in a private field.
13 |
14 | ``` csharp
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 | ```
23 |
24 | *NOTE: This will require a using statement for 'Microsoft.Extensions.Logging'.*
25 |
26 | 2. Update the Calculate method to make use of logging as follows...
27 |
28 | ``` csharp
29 | public ActionResult Calculate(CalculateInputModel input)
30 | {
31 | var result = new CalculateOutputModel();
32 |
33 | try
34 | {
35 | result.Result = input.Number1 + input.Number2;
36 | _logger.LogInformation("Successfully calculated a result");
37 | }
38 | catch (Exception ex)
39 | {
40 | _logger.LogError(ex, "Unable to calculate a result");
41 | }
42 | return Ok(result);
43 | }
44 | ```
45 | *NOTE: This will require a using statement for 'System'.*
46 |
47 | 3. Run the application by pressing F5.
48 | 4. Send a post request using Postman. Use the same steps found in [Activity 6](6-AcceptingPostedData.md)
49 | 5. In Visual Studio, check the output window, showing out from "ASP.NET Core Web Server".
50 |
51 | 
52 |
53 | 6. Add a development logging section to your appsettings.development.json file with the following values...
54 |
55 | ``` javascript
56 | "Logging": {
57 | "LogLevel": {
58 | "Default": "Debug",
59 | "System": "Information",
60 | "Microsoft": "Information"
61 | }
62 | },
63 | ```
64 |
65 | 7. Add a production logging section to your appsettings.json file with the following values...
66 |
67 | ``` javascript
68 | "Logging": {
69 | "LogLevel": {
70 | "Default": "Warning"
71 | }
72 | },
73 | ```
74 |
75 | ## End of Activity
76 |
77 | The completed example for this activity can be found in the '/steps/09-Logging' folder.
78 |
79 | Continue to [Activity 10](10-InitialDockerfile.md).
80 |
81 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/10-InitialDockerfile.md:
--------------------------------------------------------------------------------
1 |
2 | # Initial Dockerfile
3 |
4 | For this activity, please ensure you have completed [Activity 9](09-Logging.md).
5 |
6 | ## What's the plan?
7 |
8 | We're going to create a dockerfile to containerise our application. We'll use the dockerfile to build a Docker image for the application so that it can be distributed and used to launch a container.
9 |
10 | ## Activity Steps
11 |
12 | 1. Copy the '.dockerignore' file from the 'resources' folder of this workshop repository and paste it into the root of your solution. *The same folder where your .sln file exists*
13 | 2. Create a new text document in the your root directory called 'dockerfile'. **It is important that you do not include an extension for this file**
14 | 3. Edit the 'dockerfile' in VS Code or Notepad (or your text editor of choice) and add the following...
15 |
16 | ```
17 | FROM microsoft/dotnet:2.1-sdk
18 |
19 | WORKDIR /app
20 |
21 | COPY src/SampleApi .
22 |
23 | RUN dotnet build
24 |
25 | EXPOSE 80
26 |
27 | ENTRYPOINT ["dotnet", "run"]
28 | ```
29 |
30 | 4. Save the file.
31 | 5. Open a command prompt window in the same directory as the dockerfile.
32 | 6. Build a docker image using the 'docker build' command...
33 |
34 |
35 | ```
36 | docker build -t aspnetcore-workshop .
37 | ```
38 |
39 | 7. Once the build completes, run a docker container from the image using the 'docker run' command...
40 |
41 |
42 | ```
43 | docker run -p 7001:80 aspnetcore-workshop
44 | ```
45 | *NOTE: If the above fails because the port 7001 is use on your PC, try another port number.*
46 |
47 | 8. At this point, you should see some output from the ASP.NET Core logging after the application starts.
48 | 9. Open a browser window and navigate to [http://localhost:7001](http://localhost:7001/).
49 | 10. In the command prompt, press CTRL + C to detach from the container.
50 | 11. View the running containers with the 'docker container ps' command.
51 |
52 |
53 | ```
54 | docker container ps
55 | ```
56 |
57 | 12. A single entry should exist for the container we have just been running. The first column will be the container ID.
58 | 13. Kill the container using the 'docker stop' command. It accepts a container ID. You only need to provide the first 2 or 3 characters.
59 |
60 | ```
61 | docker stop
62 | ```
63 |
64 | 14. View the size of the image we created using the 'docker images' command.
65 |
66 | ```
67 | docker images aspnetcore-workshop
68 | ```
69 |
70 | ## End of Activity
71 |
72 | The completed example for this activity can be found in the '/steps/10-Initial-Dockerfile' folder.
73 |
74 | Continue to [Activity 11](11-ProductionDockerfile.md).
75 |
76 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/11-ProductionDockerfile.md:
--------------------------------------------------------------------------------
1 |
2 | # Production Dockerfile
3 |
4 | For this activity, please ensure you have completed [Activity 10](10-InitialDockerfile.md).
5 |
6 | ## What's the plan?
7 |
8 | We're going to improve our dockerfile, using a multistage build to produce a runtime based production image.
9 |
10 | ## Activity Steps
11 |
12 | 1. Edit the 'dockerfile' in VS Code or Notepad (or your text editor of choice) and add the following...
13 |
14 | ```
15 | # Build image
16 |
17 | FROM microsoft/dotnet:2.1-sdk as publish
18 |
19 | WORKDIR /publish
20 |
21 | COPY src/SampleApi/*.csproj ./src/SampleApi/
22 |
23 | RUN dotnet restore src/SampleApi/SampleApi.csproj --verbosity quiet
24 |
25 | COPY ./src ./src
26 |
27 | RUN dotnet publish src/SampleApi/SampleApi.csproj --output ../../out -c Release --no-restore --verbosity quiet /clp:ErrorsOnly
28 |
29 | # Optimised final image
30 |
31 | FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine
32 |
33 | ENTRYPOINT ["dotnet", "SampleApi.dll"]
34 |
35 | WORKDIR /app
36 |
37 | EXPOSE 80
38 |
39 | COPY --from=publish /publish/out .
40 | ```
41 |
42 | 2. Save the file.
43 | 3. Open a command prompt window in the same directory as the dockerfile.
44 | 4. Build a docker image using the 'docker build' command...
45 |
46 |
47 | ```
48 | docker build -t aspnetcore-workshop-prod .
49 | ```
50 |
51 | 5. Once the build completes, run a docker container from the image using the 'docker run' command...
52 |
53 |
54 | ```
55 | docker run -p 7001:80 aspnetcore-workshop-prod
56 | ```
57 | *NOTE: If the above fails because the port 7001 is use on your PC, try another port number.*
58 |
59 | 6. At this point, you should see some output from the ASP.NET Core logging after the application starts.
60 | 7. Open a browser window and navigate to [http://localhost:7001](http://localhost:7001/).
61 | 8. In the command prompt, press CTRL + C to detach from the container.
62 | 9. View the running containers with the 'docker container ps' command.
63 |
64 |
65 | ```
66 | docker container ps
67 | ```
68 |
69 | 10. A single entry should exist for the container we have just been running. The first column will be the container ID.
70 | 11. Kill the container using the 'docker stop' command. It accepts a container ID. You only need to provide the first 2 or 3 characters.
71 |
72 | ```
73 | docker stop
74 | ```
75 |
76 | 12. View the size of the image we created using the 'docker images' command.
77 |
78 | ```
79 | docker images aspnetcore-workshop-prod
80 | ```
81 |
82 | ## End of Activity
83 |
84 | The completed example for this activity can be found in the '/steps/11-Production-Dockerfile' folder.
85 |
86 | Continue to [Activity 12](12-DockerCompose.md).
87 |
88 | [Return to README and activity links](../README.md)
89 |
--------------------------------------------------------------------------------
/activities/12-DockerCompose.md:
--------------------------------------------------------------------------------
1 |
2 | # Docker Compose
3 |
4 | For this activity, please ensure you have completed [Activity 11](11-ProductionDockerfile.md).
5 |
6 | ## What's the plan?
7 |
8 | We're going to add a docker-compose file to support running our application without having to recall the docker switch to expose ports. We'll also override the configuration for the application at runtime of the container by passing in an environment variable.
9 |
10 | ## Activity Steps
11 |
12 | 1. Create a new text document in the root directory called 'docker-compose.yml'.
13 | 2. Edit the 'docker-compose.yml' in VS Code or Notepad (or your text editor of choice) and add the following...
14 |
15 | ```
16 | version: '3'
17 |
18 | services:
19 |
20 | api-service:
21 | build:
22 | context: .
23 | ports:
24 | - "10001:80"
25 | environment:
26 | - "Messages__WelcomeMessage=Hello from Docker"
27 | container_name: sample-api-service
28 | ```
29 |
30 | 3. Save the file.
31 | 4. Open a command prompt window in the same directory as the Docker compose file.
32 | 5. Run the compose file using the docker-compose command...
33 |
34 |
35 | ```
36 | docker-compose up -d
37 | ```
38 | *The -d switch starts in detached mode*
39 |
40 | 6. Open a browser window and navigate to [http://localhost:10001](http://localhost:10001/).
41 |
42 | *Note that the welcome message has been loaded from the environment variable set in the compose file*
43 |
44 | 7. In the command prompt, view the running containers
45 |
46 | ```
47 | docker-compose ps
48 | ```
49 |
50 | 8. Stop the container...
51 |
52 | ```
53 | docker-compose stop
54 | ```
55 |
56 | ## End of Activity
57 |
58 | The completed example for this activity can be found in the '/steps/12-Docker-Compose' folder.
59 |
60 | Continue to [Activity 13](13-UnitTests.md).
61 |
62 | [Return to README and activity links](../README.md)
63 |
--------------------------------------------------------------------------------
/activities/13-UnitTests.md:
--------------------------------------------------------------------------------
1 |
2 | # Adding Unit Test Project
3 |
4 | For this activity, please ensure you have completed [Activity 12](12-DockerCompose.md).
5 |
6 | ## What's the plan?
7 |
8 | We're going to add a unit test project with a simple test against the 'Hello' action of our 'SampleController'. We'll run the tests via the UI and/or the command line via the dotnet CLI. Finally we'll update the dockerfile so that tests are run during the Docker image build process.
9 |
10 | ## Activity Steps
11 |
12 | 1. Create a new Solution Folder called 'Test'.
13 | 2. Add a new XUnit based unit test project called 'SampleApi.Test', ensuring the location places the new project into a physical directory called 'Test' under your solution root directory.
14 |
15 | 
16 |
17 | 3. Add a project reference to the SampleApi project from the new SampleApi.Test project.
18 |
19 | 
20 |
21 | *If you prefer to do this via the command line you can run the following command from your solution root directory*
22 |
23 | ```dotnet add test/SampleApi.Test/SampleApi.Test.csproj reference src/SampleApi/SampleApi.csproj```
24 |
25 | 4. Add a NuGet package for the 'Moq' mocking library
26 |
27 | 
28 |
29 | *If you prefer to do this via the command line you can run the following command from your solution root directory*
30 |
31 | ```dotnet add test/SampleApi.Test/SampleApi.Test.csproj package Moq```
32 |
33 | 5. Add a NuGet package for the 'FluentAssertions' library
34 |
35 | *If you prefer to do this via the command line you can run the following command from your solution root directory*
36 |
37 | ```dotnet add test/SampleApi.Test/SampleApi.Test.csproj package FluentAssertions```
38 |
39 | 6. Edit your SampleApi.Test project
40 |
41 | 
42 |
43 | 7. Change the SDK at the top of the project file from 'Microsoft.NET.Sdk' to 'Microsoft.NET.Sdk.Web'.
44 |
45 | 8. Add an implicit reference to the aspnetcore metapackages to the PackageReference ItemGroup section
46 |
47 | ``````
48 |
49 | At this point your project file should look like this...
50 |
51 | ```xml
52 |
53 |
54 |
55 | netcoreapp2.1
56 | false
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | ```
74 |
75 | 9. Rename the default 'UnitTest1' class to 'SampleControllerTests' using your preferred refactoring approach (also updating the file name).
76 |
77 | 10. Rename the 'Test1' method to 'Hello_Should_ReturnExpectedWelcomeMessage'
78 |
79 | 11. Update your test so that it looks like the block below. This will exercise the 'Hello' action method...
80 |
81 | ```csharp
82 | [Fact]
83 | public void Hello_Should_ReturnExpectedWelcomeMessage()
84 | {
85 | const string welcomeMessage = "TEST";
86 | const string name = "Bob";
87 |
88 | var expectedWelcome = $"{welcomeMessage} {name}";
89 |
90 | var mockOptions = new Mock>();
91 | mockOptions.Setup(x => x.Value).Returns(new MessagesConfiguration { WelcomeMessage = welcomeMessage });
92 |
93 | var sut = new SampleController(mockOptions.Object, new NullLogger());
94 |
95 | var actionResult = sut.Hello(name);
96 |
97 | var okResult = actionResult.Result.Should().BeAssignableTo()
98 | .Which.Value.Should().BeAssignableTo()
99 | .Which.WelcomeMessage.Should().Be(expectedWelcome);
100 | }
101 | ```
102 |
103 | 12. Include any required Using statements.
104 |
105 | 13. Run the unit test via your preferred test runner.
106 |
107 | 14. You can also execute the test via the dotnet CLI. Run the following command from your solution root directory...
108 |
109 | ```dotnet test test/SampleApi.Test/SampleApi.Test.csproj```
110 |
111 | ## End of Activity
112 |
113 | The completed example for this activity can be found in the '/steps/13-Unit-Tests' folder.
114 |
115 | Continue to [Activity 14](14-IntegrationTests.md).
116 |
117 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/activities/14-IntegrationTests.md:
--------------------------------------------------------------------------------
1 |
2 | # Adding In Memory Integration Tests
3 |
4 | For this activity, please ensure you have completed [Activity 13](12-UnitTests.md).
5 |
6 | ## What's the plan?
7 |
8 | We're going to add an integration test project with a simple test against the 'Hello' endpoint of our API.
9 |
10 | ## Activity Steps
11 |
12 | 1. Create a new Solution Folder called 'Test'.
13 | 2. Within your 'Test' solution folder, add a new XUnit based unit test project called 'SampleApi.IntegrationTest', ensuring the location places the new project into the physical 'Test' directory under your solution root directory (the same folder as we used for Step 13).
14 |
15 | 3. Add a project reference to the SampleApi project from the new SampleApi.IntegrationTest project.
16 |
17 | *If you prefer to do this via the command line you can run the following command from your solution root directory*
18 |
19 | ```dotnet add test/SampleApi.IntegrationTest/SampleApi.IntegrationTest.csproj reference src/SampleApi/SampleApi.csproj```
20 |
21 | 4. Add a NuGet package for the 'Microsoft.AspNetCore.Mvc.Testing' library
22 |
23 | *If you prefer to do this via the command line you can run the following command from your solution root directory*
24 |
25 | ```dotnet add test/SampleApi.IntegrationTest/SampleApi.IntegrationTest.csproj package Microsoft.AspNetCore.Mvc.Testing```
26 |
27 | 5. Add a NuGet package for the 'FluentAssertions' library
28 |
29 | *If you prefer to do this via the command line you can run the following command from your solution root directory*
30 |
31 | ```dotnet add test/SampleApi.IntegrationTest/SampleApi.IntegrationTest.csproj package FluentAssertions```
32 |
33 | 6. Edit your SampleApi.Test project by right clicking and choosing 'Edit SampleApi.IntegrationTest.csproj'.
34 |
35 | 7. Change the SDK at the top of the project file from 'Microsoft.NET.Sdk' to 'Microsoft.NET.Sdk.Web'.
36 |
37 | 8. Add an implicit reference to the aspnetcore metapackages to the PackageReference ItemGroup section.
38 |
39 | ``````
40 |
41 | At this point your project file should look like this (although your package reference order may differ)...
42 |
43 | ```xml
44 |
45 |
46 |
47 | netcoreapp2.1
48 | false
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | ```
66 |
67 | 9. Rename the default 'UnitTest1' class to 'SampleControllerIntegrationTests' using your preferred refactoring approach (also updating the file name).
68 |
69 | 10. Update your class to implement 'IClassFixture>'.
70 |
71 | ```csharp
72 | public class SampleControllerIntegrationTests : IClassFixture>
73 | ```
74 |
75 | 11. Add a constructor which accepts a 'WebApplicationFactory' and store this to a private read-only field.
76 |
77 | ```csharp
78 | private readonly WebApplicationFactory _factory;
79 |
80 | public SampleControllerIntegrationTests(WebApplicationFactory factory)
81 | {
82 | _factory = factory;
83 | }
84 | ```
85 |
86 | 12. Add a private constant string called 'JsonContentType' with a value of "application/json; charset=utf-8" to the top of your class.
87 |
88 | ```csharp
89 | private const string JsonContentType = "application/json; charset=utf-8";
90 | ```
91 |
92 | 13. Rename the 'Test1' method to 'Hello_ReturnsExpectedContentType'
93 |
94 | 14. Update your test so that it looks like the block below. This will spin up a host and in-memory test web server before using the client to make a request to the 'Hello' endpoint. We are asserting some quite basic checks here but the tests can be far more involved.
95 |
96 | ```csharp
97 | [Fact]
98 | public async Task Hello_ReturnsExpectedContentType()
99 | {
100 | var client = _factory.CreateClient();
101 |
102 | var response = await client.GetAsync("/Steve");
103 |
104 | response.EnsureSuccessStatusCode(); // Status Code 200-299
105 | response.Content.Headers.ContentType.ToString().Should().Be(JsonContentType);
106 | }
107 | ```
108 |
109 | 15. Include any required Using statements.
110 |
111 | 16. Run the unit test via your preferred test runner.
112 |
113 | 17. You can also execute the test via the dotnet CLI. Run the following command from your solution root directory...
114 |
115 | ```dotnet test test/SampleApi.IntegrationTest/SampleApi.IntegrationTest.csproj```
116 |
117 | ## End of Activity
118 |
119 | The completed example for this activity can be found in the '/steps/14-Integration-Tests' folder.
120 |
121 | [Return to README and activity links](../README.md)
--------------------------------------------------------------------------------
/images/0-EditSampleApiProject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/0-EditSampleApiProject.png
--------------------------------------------------------------------------------
/images/1-PostmanRequest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/1-PostmanRequest.png
--------------------------------------------------------------------------------
/images/2-LoggingOutput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/2-LoggingOutput.png
--------------------------------------------------------------------------------
/images/3-AddTestProject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/3-AddTestProject.png
--------------------------------------------------------------------------------
/images/4-TestProjectReferenceViaUi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/4-TestProjectReferenceViaUi.png
--------------------------------------------------------------------------------
/images/5-TestProjectMoq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/5-TestProjectMoq.png
--------------------------------------------------------------------------------
/images/6-EditTestProject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/6-EditTestProject.png
--------------------------------------------------------------------------------
/images/7-AppSettingsJson.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevejgordon/AspNetCoreDockerWorkshop/db6c9dc8523ea255a76d674739ba5096686e89e9/images/7-AppSettingsJson.png
--------------------------------------------------------------------------------
/resources/.dockerignore:
--------------------------------------------------------------------------------
1 | **/obj
2 | **/bin
3 | .vs
4 | *.sh
5 | .git
6 | .gitignore
7 | **/launchSettings.json
--------------------------------------------------------------------------------
/steps/02-Create-Solution-And-Project/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/02-Create-Solution-And-Project/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/02-Create-Solution-And-Project/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/02-Create-Solution-And-Project/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/02-Create-Solution-And-Project/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/02-Create-Solution-And-Project/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Builder;
6 | using Microsoft.AspNetCore.Hosting;
7 | using Microsoft.AspNetCore.Http;
8 | using Microsoft.Extensions.DependencyInjection;
9 |
10 | namespace SampleApi
11 | {
12 | public class Startup
13 | {
14 | // This method gets called by the runtime. Use this method to add services to the container.
15 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
16 | public void ConfigureServices(IServiceCollection services)
17 | {
18 | }
19 |
20 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
21 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
22 | {
23 | if (env.IsDevelopment())
24 | {
25 | app.UseDeveloperExceptionPage();
26 | }
27 |
28 | app.Run(async (context) =>
29 | {
30 | await context.Response.WriteAsync("Hello World!");
31 | });
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/steps/03-Create-Controller-And-Action/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/03-Create-Controller-And-Action/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/03-Create-Controller-And-Action/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 |
3 | namespace SampleApi.Controllers
4 | {
5 | [ApiController]
6 | public class SampleController : ControllerBase
7 | {
8 | [Route("")]
9 | public string Hello()
10 | {
11 | return "Hello";
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/steps/03-Create-Controller-And-Action/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/03-Create-Controller-And-Action/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/03-Create-Controller-And-Action/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/03-Create-Controller-And-Action/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace SampleApi
7 | {
8 | public class Startup
9 | {
10 | // This method gets called by the runtime. Use this method to add services to the container.
11 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
12 | public void ConfigureServices(IServiceCollection services)
13 | {
14 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
15 | }
16 |
17 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
18 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
19 | {
20 | if (env.IsDevelopment())
21 | {
22 | app.UseDeveloperExceptionPage();
23 | }
24 |
25 | app.UseMvc();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using SampleApi.OutputModels;
3 |
4 | namespace SampleApi.Controllers
5 | {
6 | [ApiController]
7 | public class SampleController : ControllerBase
8 | {
9 | [Route("")]
10 | public ActionResult Hello()
11 | {
12 | var model = new HelloOutputModel();
13 | return Ok(model);
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/04-Returning-JSON-Data/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace SampleApi
7 | {
8 | public class Startup
9 | {
10 | // This method gets called by the runtime. Use this method to add services to the container.
11 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
12 | public void ConfigureServices(IServiceCollection services)
13 | {
14 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
15 | }
16 |
17 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
18 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
19 | {
20 | if (env.IsDevelopment())
21 | {
22 | app.UseDeveloperExceptionPage();
23 | }
24 |
25 | app.UseMvc();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using SampleApi.OutputModels;
3 |
4 | namespace SampleApi.Controllers
5 | {
6 | [ApiController]
7 | public class SampleController : ControllerBase
8 | {
9 | [Route("")]
10 | public ActionResult Hello(string name)
11 | {
12 | var model = new HelloOutputModel();
13 | model.WelcomeMessage = $"{model.WelcomeMessage} {name ?? "whoever you are!"}";
14 | return Ok(model);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/05-Binding-Data-From-Query-String/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace SampleApi
7 | {
8 | public class Startup
9 | {
10 | // This method gets called by the runtime. Use this method to add services to the container.
11 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
12 | public void ConfigureServices(IServiceCollection services)
13 | {
14 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
15 | }
16 |
17 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
18 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
19 | {
20 | if (env.IsDevelopment())
21 | {
22 | app.UseDeveloperExceptionPage();
23 | }
24 |
25 | app.UseMvc();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using SampleApi.OutputModels;
3 |
4 | namespace SampleApi.Controllers
5 | {
6 | [ApiController]
7 | public class SampleController : ControllerBase
8 | {
9 | [Route("{name?}")]
10 | public ActionResult Hello(string name)
11 | {
12 | var model = new HelloOutputModel();
13 | model.WelcomeMessage = $"{model.WelcomeMessage} {name ?? "whoever you are!"}";
14 | return Ok(model);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/06-Binding-From-Route-Parameters/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace SampleApi
7 | {
8 | public class Startup
9 | {
10 | // This method gets called by the runtime. Use this method to add services to the container.
11 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
12 | public void ConfigureServices(IServiceCollection services)
13 | {
14 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
15 | }
16 |
17 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
18 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
19 | {
20 | if (env.IsDevelopment())
21 | {
22 | app.UseDeveloperExceptionPage();
23 | }
24 |
25 | app.UseMvc();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using SampleApi.InputModels;
3 | using SampleApi.OutputModels;
4 |
5 | namespace SampleApi.Controllers
6 | {
7 | [ApiController]
8 | public class SampleController : ControllerBase
9 | {
10 | [Route("{name?}")]
11 | public ActionResult Hello(string name)
12 | {
13 | var model = new HelloOutputModel();
14 | model.WelcomeMessage = $"{model.WelcomeMessage} {name ?? "whoever you are!"}";
15 | return Ok(model);
16 | }
17 |
18 | [HttpPost]
19 | [Route("calculate")]
20 | public ActionResult Calculate(CalculateInputModel input)
21 | {
22 | var result = new CalculateOutputModel { Result = input.Number1 + input.Number2 };
23 | return Ok(result);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/07-Accepting-Posted-Data/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace SampleApi
7 | {
8 | public class Startup
9 | {
10 | // This method gets called by the runtime. Use this method to add services to the container.
11 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
12 | public void ConfigureServices(IServiceCollection services)
13 | {
14 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
15 | }
16 |
17 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
18 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
19 | {
20 | if (env.IsDevelopment())
21 | {
22 | app.UseDeveloperExceptionPage();
23 | }
24 |
25 | app.UseMvc();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/steps/08-Configuration/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/08-Configuration/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using Microsoft.Extensions.Options;
3 | using SampleApi.Configuration;
4 | using SampleApi.InputModels;
5 | using SampleApi.OutputModels;
6 |
7 | namespace SampleApi.Controllers
8 | {
9 | [ApiController]
10 | public class SampleController : ControllerBase
11 | {
12 | private readonly IOptions _messagesConfig;
13 |
14 | public SampleController(IOptions messagesConfig)
15 | {
16 | _messagesConfig = messagesConfig;
17 | }
18 |
19 | [Route("{name?}")]
20 | public ActionResult Hello(string name)
21 | {
22 | var model = new HelloOutputModel();
23 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
24 | return Ok(model);
25 | }
26 |
27 | [HttpPost]
28 | [Route("calculate")]
29 | public ActionResult Calculate(CalculateInputModel input)
30 | {
31 | var result = new CalculateOutputModel { Result = input.Number1 + input.Number2 };
32 | return Ok(result);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Messages": {
3 | "WelcomeMessage": "Hey from dev"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/steps/08-Configuration/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Messages": {
3 | "WelcomeMessage": "Hey"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/steps/09-Logging/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/09-Logging/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using SampleApi.Configuration;
6 | using SampleApi.InputModels;
7 | using SampleApi.OutputModels;
8 |
9 | namespace SampleApi.Controllers
10 | {
11 | [ApiController]
12 | public class SampleController : ControllerBase
13 | {
14 | private readonly IOptions _messagesConfig;
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 |
23 | [Route("{name?}")]
24 | public ActionResult Hello(string name)
25 | {
26 | var model = new HelloOutputModel();
27 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
28 | return Ok(model);
29 | }
30 |
31 | [HttpPost]
32 | [Route("calculate")]
33 | public ActionResult Calculate(CalculateInputModel input)
34 | {
35 | var result = new CalculateOutputModel();
36 |
37 | try
38 | {
39 | result.Result = input.Number1 + input.Number2;
40 | _logger.LogInformation("Successfully calculated a result");
41 | }
42 | catch (Exception ex)
43 | {
44 | _logger.LogError(ex, "Unable to calculate a result");
45 | }
46 | return Ok(result);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "Messages": {
10 | "WelcomeMessage": "Hey from dev"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/09-Logging/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "Messages": {
8 | "WelcomeMessage": "Hey"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/.dockerignore:
--------------------------------------------------------------------------------
1 | **/obj
2 | **/bin
3 | .vs
4 | *.sh
5 | .git
6 | .gitignore
7 | **/launchSettings.json
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/dockerfile:
--------------------------------------------------------------------------------
1 | FROM microsoft/dotnet:2.1-sdk
2 |
3 | WORKDIR /app
4 |
5 | COPY src/SampleApi .
6 |
7 | RUN dotnet build
8 |
9 | EXPOSE 80
10 |
11 | ENTRYPOINT ["dotnet", "run"]
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using SampleApi.Configuration;
6 | using SampleApi.InputModels;
7 | using SampleApi.OutputModels;
8 |
9 | namespace SampleApi.Controllers
10 | {
11 | [ApiController]
12 | public class SampleController : ControllerBase
13 | {
14 | private readonly IOptions _messagesConfig;
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 |
23 | [Route("{name?}")]
24 | public ActionResult Hello(string name)
25 | {
26 | var model = new HelloOutputModel();
27 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
28 | return Ok(model);
29 | }
30 |
31 | [HttpPost]
32 | [Route("calculate")]
33 | public ActionResult Calculate(CalculateInputModel input)
34 | {
35 | var result = new CalculateOutputModel();
36 |
37 | try
38 | {
39 | result.Result = input.Number1 + input.Number2;
40 | _logger.LogInformation("Successfully calculated a result");
41 | }
42 | catch (Exception ex)
43 | {
44 | _logger.LogError(ex, "Unable to calculate a result");
45 | }
46 | return Ok(result);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "Messages": {
10 | "WelcomeMessage": "Hey from dev"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/10-Initial-Dockerfile/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "Messages": {
8 | "WelcomeMessage": "Hey"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/.dockerignore:
--------------------------------------------------------------------------------
1 | **/obj
2 | **/bin
3 | .vs
4 | *.sh
5 | .git
6 | .gitignore
7 | **/launchSettings.json
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/dockerfile:
--------------------------------------------------------------------------------
1 | # Build image
2 |
3 | FROM microsoft/dotnet:2.1-sdk as publish
4 |
5 | WORKDIR /publish
6 |
7 | COPY src/SampleApi/*.csproj ./src/SampleApi/
8 |
9 | RUN dotnet restore src/SampleApi/SampleApi.csproj --verbosity quiet
10 |
11 | COPY ./src ./src
12 |
13 | RUN dotnet publish src/SampleApi/SampleApi.csproj --output ../../out -c Release --no-restore --verbosity quiet /clp:ErrorsOnly
14 |
15 | # Optimised final image
16 |
17 | FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine
18 |
19 | ENTRYPOINT ["dotnet", "SampleApi.dll"]
20 |
21 | WORKDIR /app
22 |
23 | EXPOSE 80
24 |
25 | COPY --from=publish /publish/out .
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using SampleApi.Configuration;
6 | using SampleApi.InputModels;
7 | using SampleApi.OutputModels;
8 |
9 | namespace SampleApi.Controllers
10 | {
11 | [ApiController]
12 | public class SampleController : ControllerBase
13 | {
14 | private readonly IOptions _messagesConfig;
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 |
23 | [Route("{name?}")]
24 | public ActionResult Hello(string name)
25 | {
26 | var model = new HelloOutputModel();
27 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
28 | return Ok(model);
29 | }
30 |
31 | [HttpPost]
32 | [Route("calculate")]
33 | public ActionResult Calculate(CalculateInputModel input)
34 | {
35 | var result = new CalculateOutputModel();
36 |
37 | try
38 | {
39 | result.Result = input.Number1 + input.Number2;
40 | _logger.LogInformation("Successfully calculated a result");
41 | }
42 | catch (Exception ex)
43 | {
44 | _logger.LogError(ex, "Unable to calculate a result");
45 | }
46 | return Ok(result);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "Messages": {
10 | "WelcomeMessage": "Hey from dev"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/11-Production-Dockerfile/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "Messages": {
8 | "WelcomeMessage": "Hey"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/.dockerignore:
--------------------------------------------------------------------------------
1 | **/obj
2 | **/bin
3 | .vs
4 | *.sh
5 | .git
6 | .gitignore
7 | **/launchSettings.json
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
38 | EndGlobalSection
39 | EndGlobal
40 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | api-service:
6 | build:
7 | context: .
8 | ports:
9 | - "10001:80"
10 | environment:
11 | - "Messages__WelcomeMessage=Hello from Docker"
12 | container_name: sample-api-service
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/dockerfile:
--------------------------------------------------------------------------------
1 | # Build image
2 |
3 | FROM microsoft/dotnet:2.1-sdk as publish
4 |
5 | WORKDIR /publish
6 |
7 | COPY src/SampleApi/*.csproj ./src/SampleApi/
8 |
9 | RUN dotnet restore src/SampleApi/SampleApi.csproj --verbosity quiet
10 |
11 | COPY ./src ./src
12 |
13 | RUN dotnet publish src/SampleApi/SampleApi.csproj --output ../../out -c Release --no-restore --verbosity quiet /clp:ErrorsOnly
14 |
15 | # Optimised final image
16 |
17 | FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine
18 |
19 | ENTRYPOINT ["dotnet", "SampleApi.dll"]
20 |
21 | WORKDIR /app
22 |
23 | EXPOSE 80
24 |
25 | COPY --from=publish /publish/out .
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using SampleApi.Configuration;
6 | using SampleApi.InputModels;
7 | using SampleApi.OutputModels;
8 |
9 | namespace SampleApi.Controllers
10 | {
11 | [ApiController]
12 | public class SampleController : ControllerBase
13 | {
14 | private readonly IOptions _messagesConfig;
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 |
23 | [Route("{name?}")]
24 | public ActionResult Hello(string name)
25 | {
26 | var model = new HelloOutputModel();
27 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
28 | return Ok(model);
29 | }
30 |
31 | [HttpPost]
32 | [Route("calculate")]
33 | public ActionResult Calculate(CalculateInputModel input)
34 | {
35 | var result = new CalculateOutputModel();
36 |
37 | try
38 | {
39 | result.Result = input.Number1 + input.Number2;
40 | _logger.LogInformation("Successfully calculated a result");
41 | }
42 | catch (Exception ex)
43 | {
44 | _logger.LogError(ex, "Unable to calculate a result");
45 | }
46 | return Ok(result);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "Messages": {
10 | "WelcomeMessage": "Hey from dev"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/12-Docker-Compose/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "Messages": {
8 | "WelcomeMessage": "Hey"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/.dockerignore:
--------------------------------------------------------------------------------
1 | **/obj
2 | **/bin
3 | .vs
4 | *.sh
5 | .git
6 | .gitignore
7 | **/launchSettings.json
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2F277387-CAB6-421C-8757-3F48F313CB78}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi.Test", "test\SampleApi.Test\SampleApi.Test.csproj", "{79216D43-8936-4929-9366-F87686373282}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Debug|x64 = Debug|x64
18 | Debug|x86 = Debug|x86
19 | Release|Any CPU = Release|Any CPU
20 | Release|x64 = Release|x64
21 | Release|x86 = Release|x86
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
35 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
36 | {79216D43-8936-4929-9366-F87686373282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {79216D43-8936-4929-9366-F87686373282}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {79216D43-8936-4929-9366-F87686373282}.Debug|x64.ActiveCfg = Debug|Any CPU
39 | {79216D43-8936-4929-9366-F87686373282}.Debug|x64.Build.0 = Debug|Any CPU
40 | {79216D43-8936-4929-9366-F87686373282}.Debug|x86.ActiveCfg = Debug|Any CPU
41 | {79216D43-8936-4929-9366-F87686373282}.Debug|x86.Build.0 = Debug|Any CPU
42 | {79216D43-8936-4929-9366-F87686373282}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {79216D43-8936-4929-9366-F87686373282}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {79216D43-8936-4929-9366-F87686373282}.Release|x64.ActiveCfg = Release|Any CPU
45 | {79216D43-8936-4929-9366-F87686373282}.Release|x64.Build.0 = Release|Any CPU
46 | {79216D43-8936-4929-9366-F87686373282}.Release|x86.ActiveCfg = Release|Any CPU
47 | {79216D43-8936-4929-9366-F87686373282}.Release|x86.Build.0 = Release|Any CPU
48 | EndGlobalSection
49 | GlobalSection(SolutionProperties) = preSolution
50 | HideSolutionNode = FALSE
51 | EndGlobalSection
52 | GlobalSection(NestedProjects) = preSolution
53 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
54 | {79216D43-8936-4929-9366-F87686373282} = {2F277387-CAB6-421C-8757-3F48F313CB78}
55 | EndGlobalSection
56 | GlobalSection(ExtensibilityGlobals) = postSolution
57 | SolutionGuid = {E1435368-2E74-447C-A722-8BD1CE4E8B22}
58 | EndGlobalSection
59 | EndGlobal
60 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | api-service:
6 | build:
7 | context: .
8 | ports:
9 | - "10001:80"
10 | environment:
11 | - "Messages__WelcomeMessage=Hello from Docker"
12 | container_name: sample-api-service
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/dockerfile:
--------------------------------------------------------------------------------
1 | # Build image
2 |
3 | FROM microsoft/dotnet:2.1-sdk as publish
4 |
5 | WORKDIR /publish
6 |
7 | COPY src/SampleApi/*.csproj ./src/SampleApi/
8 |
9 | RUN dotnet restore src/SampleApi/SampleApi.csproj --verbosity quiet
10 |
11 | COPY ./src ./src
12 |
13 | RUN dotnet publish src/SampleApi/SampleApi.csproj --output ../../out -c Release --no-restore --verbosity quiet /clp:ErrorsOnly
14 |
15 | # Optimised final image
16 |
17 | FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine
18 |
19 | ENTRYPOINT ["dotnet", "SampleApi.dll"]
20 |
21 | WORKDIR /app
22 |
23 | EXPOSE 80
24 |
25 | COPY --from=publish /publish/out .
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using SampleApi.Configuration;
6 | using SampleApi.InputModels;
7 | using SampleApi.OutputModels;
8 |
9 | namespace SampleApi.Controllers
10 | {
11 | [ApiController]
12 | public class SampleController : ControllerBase
13 | {
14 | private readonly IOptions _messagesConfig;
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 |
23 | [Route("{name?}")]
24 | public ActionResult Hello(string name)
25 | {
26 | var model = new HelloOutputModel();
27 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
28 | return Ok(model);}
29 |
30 | [HttpPost]
31 | [Route("calculate")]
32 | public ActionResult Calculate(CalculateInputModel input)
33 | {
34 | var result = new CalculateOutputModel();
35 |
36 | try
37 | {
38 | result.Result = input.Number1 + input.Number2;
39 | _logger.LogInformation("Successfully calculated a result");
40 | }
41 | catch (Exception ex)
42 | {
43 | _logger.LogError(ex, "Unable to calculate a result");
44 | }
45 | return Ok(result);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "Messages": {
10 | "WelcomeMessage": "Hey from dev"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "Messages": {
8 | "WelcomeMessage": "Hey"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/test/SampleApi.Test/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:55988/",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi.Test": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "environmentVariables": {
22 | "ASPNETCORE_ENVIRONMENT": "Development"
23 | },
24 | "applicationUrl": "http://localhost:55989/"
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/test/SampleApi.Test/SampleApi.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/steps/13-Unit-Tests/test/SampleApi.Test/SampleControllerTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FluentAssertions;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Logging.Abstractions;
5 | using Microsoft.Extensions.Options;
6 | using Moq;
7 | using SampleApi.Configuration;
8 | using SampleApi.Controllers;
9 | using SampleApi.OutputModels;
10 | using Xunit;
11 |
12 | namespace SampleApi.Test
13 | {
14 | public class SampleControllerTests
15 | {
16 | [Fact]
17 | public void Hello_Should_ReturnExpectedWelcomeMessage()
18 | {
19 | const string welcomeMessage = "TEST";
20 | const string name = "Bob";
21 |
22 | var expectedWelcome = $"{welcomeMessage} {name}";
23 |
24 | var mockOptions = new Mock>();
25 | mockOptions.Setup(x => x.Value).Returns(new MessagesConfiguration { WelcomeMessage = welcomeMessage });
26 |
27 | var sut = new SampleController(mockOptions.Object, new NullLogger());
28 |
29 | var actionResult = sut.Hello(name);
30 |
31 | var okResult = actionResult.Result.Should().BeAssignableTo()
32 | .Which.Value.Should().BeAssignableTo()
33 | .Which.WelcomeMessage.Should().Be(expectedWelcome);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/.dockerignore:
--------------------------------------------------------------------------------
1 | **/obj
2 | **/bin
3 | .vs
4 | *.sh
5 | .git
6 | .gitignore
7 | **/launchSettings.json
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2F277387-CAB6-421C-8757-3F48F313CB78}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApi.Test", "test\SampleApi.Test\SampleApi.Test.csproj", "{79216D43-8936-4929-9366-F87686373282}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi.IntegrationTest", "test\SampleApi.IntegrationTest\SampleApi.IntegrationTest.csproj", "{09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Debug|x64 = Debug|x64
20 | Debug|x86 = Debug|x86
21 | Release|Any CPU = Release|Any CPU
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
35 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
36 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
38 | {79216D43-8936-4929-9366-F87686373282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {79216D43-8936-4929-9366-F87686373282}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {79216D43-8936-4929-9366-F87686373282}.Debug|x64.ActiveCfg = Debug|Any CPU
41 | {79216D43-8936-4929-9366-F87686373282}.Debug|x64.Build.0 = Debug|Any CPU
42 | {79216D43-8936-4929-9366-F87686373282}.Debug|x86.ActiveCfg = Debug|Any CPU
43 | {79216D43-8936-4929-9366-F87686373282}.Debug|x86.Build.0 = Debug|Any CPU
44 | {79216D43-8936-4929-9366-F87686373282}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {79216D43-8936-4929-9366-F87686373282}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {79216D43-8936-4929-9366-F87686373282}.Release|x64.ActiveCfg = Release|Any CPU
47 | {79216D43-8936-4929-9366-F87686373282}.Release|x64.Build.0 = Release|Any CPU
48 | {79216D43-8936-4929-9366-F87686373282}.Release|x86.ActiveCfg = Release|Any CPU
49 | {79216D43-8936-4929-9366-F87686373282}.Release|x86.Build.0 = Release|Any CPU
50 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x64.ActiveCfg = Debug|Any CPU
53 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x64.Build.0 = Debug|Any CPU
54 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x86.ActiveCfg = Debug|Any CPU
55 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x86.Build.0 = Debug|Any CPU
56 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x64.ActiveCfg = Release|Any CPU
59 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x64.Build.0 = Release|Any CPU
60 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x86.ActiveCfg = Release|Any CPU
61 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x86.Build.0 = Release|Any CPU
62 | EndGlobalSection
63 | GlobalSection(SolutionProperties) = preSolution
64 | HideSolutionNode = FALSE
65 | EndGlobalSection
66 | GlobalSection(NestedProjects) = preSolution
67 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
68 | {79216D43-8936-4929-9366-F87686373282} = {2F277387-CAB6-421C-8757-3F48F313CB78}
69 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547} = {2F277387-CAB6-421C-8757-3F48F313CB78}
70 | EndGlobalSection
71 | GlobalSection(ExtensibilityGlobals) = postSolution
72 | SolutionGuid = {E1435368-2E74-447C-A722-8BD1CE4E8B22}
73 | EndGlobalSection
74 | EndGlobal
75 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | api-service:
6 | build:
7 | context: .
8 | ports:
9 | - "10001:80"
10 | environment:
11 | - "Messages__WelcomeMessage=Hello from Docker"
12 | container_name: sample-api-service
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/dockerfile:
--------------------------------------------------------------------------------
1 | # Build image
2 |
3 | FROM microsoft/dotnet:2.1-sdk as publish
4 |
5 | WORKDIR /publish
6 |
7 | COPY src/SampleApi/*.csproj ./src/SampleApi/
8 |
9 | RUN dotnet restore src/SampleApi/SampleApi.csproj --verbosity quiet
10 |
11 | COPY ./src ./src
12 |
13 | RUN dotnet publish src/SampleApi/SampleApi.csproj --output ../../out -c Release --no-restore --verbosity quiet /clp:ErrorsOnly
14 |
15 | # Optimised final image
16 |
17 | FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine
18 |
19 | ENTRYPOINT ["dotnet", "SampleApi.dll"]
20 |
21 | WORKDIR /app
22 |
23 | EXPOSE 80
24 |
25 | COPY --from=publish /publish/out .
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using SampleApi.Configuration;
6 | using SampleApi.InputModels;
7 | using SampleApi.OutputModels;
8 |
9 | namespace SampleApi.Controllers
10 | {
11 | [ApiController]
12 | public class SampleController : ControllerBase
13 | {
14 | private readonly IOptions _messagesConfig;
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 |
23 | [Route("{name?}")]
24 | public ActionResult Hello(string name)
25 | {
26 | var model = new HelloOutputModel();
27 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
28 | return Ok(model);}
29 |
30 | [HttpPost]
31 | [Route("calculate")]
32 | public ActionResult Calculate(CalculateInputModel input)
33 | {
34 | var result = new CalculateOutputModel();
35 |
36 | try
37 | {
38 | result.Result = input.Number1 + input.Number2;
39 | _logger.LogInformation("Successfully calculated a result");
40 | }
41 | catch (Exception ex)
42 | {
43 | _logger.LogError(ex, "Unable to calculate a result");
44 | }
45 | return Ok(result);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/appsettings.development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "Messages": {
10 | "WelcomeMessage": "Hey from dev"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "Messages": {
8 | "WelcomeMessage": "Hey"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/test/SampleApi.IntegrationTest/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:59827/",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi.IntegrationTest": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "environmentVariables": {
22 | "ASPNETCORE_ENVIRONMENT": "Development"
23 | },
24 | "applicationUrl": "http://localhost:59828/"
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/test/SampleApi.IntegrationTest/SampleApi.IntegrationTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/test/SampleApi.IntegrationTest/SampleControllerIntegrationTests.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using FluentAssertions;
3 | using Microsoft.AspNetCore.Mvc.Testing;
4 | using Xunit;
5 |
6 | namespace SampleApi.IntegrationTest
7 | {
8 | public class SampleControllerIntegrationTests : IClassFixture>
9 | {
10 | private const string JsonContentType = "application/json; charset=utf-8";
11 |
12 | private readonly WebApplicationFactory _factory;
13 |
14 | public SampleControllerIntegrationTests(WebApplicationFactory factory)
15 | {
16 | _factory = factory;
17 | }
18 |
19 | [Fact]
20 | public async Task Hello_ReturnsExpectedContentType()
21 | {
22 | var client = _factory.CreateClient();
23 |
24 | var response = await client.GetAsync("/Steve");
25 |
26 | response.EnsureSuccessStatusCode(); // Status Code 200-299
27 | response.Content.Headers.ContentType.ToString().Should().Be(JsonContentType);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/test/SampleApi.IntegrationTest/xunit.runner.json:
--------------------------------------------------------------------------------
1 | {
2 | "shadowCopy": false
3 | }
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/test/SampleApi.Test/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:55988/",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi.Test": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "environmentVariables": {
22 | "ASPNETCORE_ENVIRONMENT": "Development"
23 | },
24 | "applicationUrl": "http://localhost:55989/"
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/test/SampleApi.Test/SampleApi.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/steps/14-Integration-Tests/test/SampleApi.Test/SampleControllerTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FluentAssertions;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Logging.Abstractions;
5 | using Microsoft.Extensions.Options;
6 | using Moq;
7 | using SampleApi.Configuration;
8 | using SampleApi.Controllers;
9 | using SampleApi.OutputModels;
10 | using Xunit;
11 |
12 | namespace SampleApi.Test
13 | {
14 | public class SampleControllerTests
15 | {
16 | [Fact]
17 | public void Hello_Should_ReturnExpectedWelcomeMessage()
18 | {
19 | const string welcomeMessage = "TEST";
20 | const string name = "Bob";
21 |
22 | var expectedWelcome = $"{welcomeMessage} {name}";
23 |
24 | var mockOptions = new Mock>();
25 | mockOptions.Setup(x => x.Value).Returns(new MessagesConfiguration { WelcomeMessage = welcomeMessage });
26 |
27 | var sut = new SampleController(mockOptions.Object, new NullLogger());
28 |
29 | var actionResult = sut.Hello(name);
30 |
31 | var okResult = actionResult.Result.Should().BeAssignableTo()
32 | .Which.Value.Should().BeAssignableTo()
33 | .Which.WelcomeMessage.Should().Be(expectedWelcome);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/.dockerignore:
--------------------------------------------------------------------------------
1 | **/obj
2 | **/bin
3 | .vs
4 | *.sh
5 | .git
6 | .gitignore
7 | **/launchSettings.json
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/SampleApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{61C50D69-0377-4212-9E88-E329C797284C}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApi", "src\SampleApi\SampleApi.csproj", "{D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2F277387-CAB6-421C-8757-3F48F313CB78}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApi.Test", "test\SampleApi.Test\SampleApi.Test.csproj", "{79216D43-8936-4929-9366-F87686373282}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi.IntegrationTest", "test\SampleApi.IntegrationTest\SampleApi.IntegrationTest.csproj", "{09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Debug|x64 = Debug|x64
20 | Debug|x86 = Debug|x86
21 | Release|Any CPU = Release|Any CPU
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.ActiveCfg = Debug|Any CPU
29 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x64.Build.0 = Debug|Any CPU
30 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.ActiveCfg = Debug|Any CPU
31 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Debug|x86.Build.0 = Debug|Any CPU
32 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.ActiveCfg = Release|Any CPU
35 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x64.Build.0 = Release|Any CPU
36 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.ActiveCfg = Release|Any CPU
37 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C}.Release|x86.Build.0 = Release|Any CPU
38 | {79216D43-8936-4929-9366-F87686373282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {79216D43-8936-4929-9366-F87686373282}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {79216D43-8936-4929-9366-F87686373282}.Debug|x64.ActiveCfg = Debug|Any CPU
41 | {79216D43-8936-4929-9366-F87686373282}.Debug|x64.Build.0 = Debug|Any CPU
42 | {79216D43-8936-4929-9366-F87686373282}.Debug|x86.ActiveCfg = Debug|Any CPU
43 | {79216D43-8936-4929-9366-F87686373282}.Debug|x86.Build.0 = Debug|Any CPU
44 | {79216D43-8936-4929-9366-F87686373282}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {79216D43-8936-4929-9366-F87686373282}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {79216D43-8936-4929-9366-F87686373282}.Release|x64.ActiveCfg = Release|Any CPU
47 | {79216D43-8936-4929-9366-F87686373282}.Release|x64.Build.0 = Release|Any CPU
48 | {79216D43-8936-4929-9366-F87686373282}.Release|x86.ActiveCfg = Release|Any CPU
49 | {79216D43-8936-4929-9366-F87686373282}.Release|x86.Build.0 = Release|Any CPU
50 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x64.ActiveCfg = Debug|Any CPU
53 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x64.Build.0 = Debug|Any CPU
54 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x86.ActiveCfg = Debug|Any CPU
55 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Debug|x86.Build.0 = Debug|Any CPU
56 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x64.ActiveCfg = Release|Any CPU
59 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x64.Build.0 = Release|Any CPU
60 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x86.ActiveCfg = Release|Any CPU
61 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547}.Release|x86.Build.0 = Release|Any CPU
62 | EndGlobalSection
63 | GlobalSection(SolutionProperties) = preSolution
64 | HideSolutionNode = FALSE
65 | EndGlobalSection
66 | GlobalSection(NestedProjects) = preSolution
67 | {D18B7B47-6C35-4A99-9B6F-9A904A2F7A9C} = {61C50D69-0377-4212-9E88-E329C797284C}
68 | {79216D43-8936-4929-9366-F87686373282} = {2F277387-CAB6-421C-8757-3F48F313CB78}
69 | {09CDBB7A-4EF9-4EEF-A8D9-6446CFE1A547} = {2F277387-CAB6-421C-8757-3F48F313CB78}
70 | EndGlobalSection
71 | GlobalSection(ExtensibilityGlobals) = postSolution
72 | SolutionGuid = {E1435368-2E74-447C-A722-8BD1CE4E8B22}
73 | EndGlobalSection
74 | EndGlobal
75 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | api-service:
6 | build:
7 | context: .
8 | ports:
9 | - "10001:80"
10 | environment:
11 | - "Messages__WelcomeMessage=Hello from Docker"
12 | container_name: sample-api-service
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/dockerfile:
--------------------------------------------------------------------------------
1 | # Build image
2 |
3 | FROM microsoft/dotnet:2.1-sdk as publish
4 |
5 | WORKDIR /publish
6 |
7 | COPY SampleApi.sln .
8 | COPY src/SampleApi/*.csproj ./src/SampleApi/
9 | COPY test/SampleApi.Test/*.csproj ./test/SampleApi.Test/
10 | COPY test/SampleApi.IntegrationTest/*.csproj ./test/SampleApi.IntegrationTest/
11 |
12 | RUN dotnet restore --verbosity quiet
13 |
14 | COPY ./src ./src
15 | COPY ./test ./test
16 |
17 | RUN dotnet build -c Release --no-restore /clp:ErrorsOnly
18 | RUN dotnet test test/SampleApi.Test/SampleApi.Test.csproj -c Release --no-build --no-restore --verbosity minimal
19 | RUN dotnet test test/SampleApi.IntegrationTest/SampleApi.IntegrationTest.csproj -c Release --no-build --no-restore --verbosity minimal
20 | RUN dotnet publish src/SampleApi/SampleApi.csproj --output ../../out -c Release --no-restore --verbosity quiet /clp:ErrorsOnly
21 |
22 | # Optimised final image
23 |
24 | FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine
25 |
26 | ENTRYPOINT ["dotnet", "SampleApi.dll"]
27 |
28 | WORKDIR /app
29 |
30 | EXPOSE 80
31 |
32 | COPY --from=publish /publish/out .
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "2.1.403"
4 | }
5 | }
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/Configuration/MessagesConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.Configuration
3 | {
4 | public class MessagesConfiguration
5 | {
6 | public string WelcomeMessage { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/Controllers/SampleController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using SampleApi.Configuration;
6 | using SampleApi.InputModels;
7 | using SampleApi.OutputModels;
8 |
9 | namespace SampleApi.Controllers
10 | {
11 | [ApiController]
12 | public class SampleController : ControllerBase
13 | {
14 | private readonly IOptions _messagesConfig;
15 | private readonly ILogger _logger;
16 |
17 | public SampleController(IOptions messagesConfig, ILogger logger)
18 | {
19 | _messagesConfig = messagesConfig;
20 | _logger = logger;
21 | }
22 |
23 | [Route("{name?}")]
24 | public ActionResult Hello(string name)
25 | {
26 | var model = new HelloOutputModel();
27 | model.WelcomeMessage = $"{_messagesConfig.Value.WelcomeMessage} {name ?? "whoever you are!"}";
28 | return Ok(model);}
29 |
30 | [HttpPost]
31 | [Route("calculate")]
32 | public ActionResult Calculate(CalculateInputModel input)
33 | {
34 | var result = new CalculateOutputModel();
35 |
36 | try
37 | {
38 | result.Result = input.Number1 + input.Number2;
39 | _logger.LogInformation("Successfully calculated a result");
40 | }
41 | catch (Exception ex)
42 | {
43 | _logger.LogError(ex, "Unable to calculate a result");
44 | }
45 | return Ok(result);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/InputModels/CalculateInputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.InputModels
7 | {
8 | public class CalculateInputModel
9 | {
10 | public int Number1 { get; set; }
11 | public int Number2 { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/OutputModels/CalculateOutputModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace SampleApi.OutputModels
7 | {
8 | public class CalculateOutputModel
9 | {
10 | public int Result { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/OutputModels/HelloOutputModel.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace SampleApi.OutputModels
3 | {
4 | public class HelloOutputModel
5 | {
6 | public string WelcomeMessage { get; set; } = "Hello";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.Logging;
10 |
11 | namespace SampleApi
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | CreateWebHostBuilder(args).Build().Run();
18 | }
19 |
20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21 | WebHost.CreateDefaultBuilder(args)
22 | .UseStartup();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65244",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/SampleApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using SampleApi.Configuration;
7 |
8 | namespace SampleApi
9 | {
10 | public class Startup
11 | {
12 | public IConfiguration Configuration { get; }
13 |
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | // This method gets called by the runtime. Use this method to add services to the container.
20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.Configure(Configuration.GetSection("Messages"));
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseMvc();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/appsettings.development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "Messages": {
10 | "WelcomeMessage": "Hey from dev"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/src/SampleApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "Messages": {
8 | "WelcomeMessage": "Hey"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/test/SampleApi.IntegrationTest/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:59827/",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi.IntegrationTest": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "environmentVariables": {
22 | "ASPNETCORE_ENVIRONMENT": "Development"
23 | },
24 | "applicationUrl": "http://localhost:59828/"
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/test/SampleApi.IntegrationTest/SampleApi.IntegrationTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/test/SampleApi.IntegrationTest/SampleControllerIntegrationTests.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using FluentAssertions;
3 | using Microsoft.AspNetCore.Mvc.Testing;
4 | using Xunit;
5 |
6 | namespace SampleApi.IntegrationTest
7 | {
8 | public class SampleControllerIntegrationTests : IClassFixture>
9 | {
10 | private const string JsonContentType = "application/json; charset=utf-8";
11 |
12 | private readonly WebApplicationFactory _factory;
13 |
14 | public SampleControllerIntegrationTests(WebApplicationFactory factory)
15 | {
16 | _factory = factory;
17 | }
18 |
19 | [Fact]
20 | public async Task Hello_ReturnsExpectedContentType()
21 | {
22 | var client = _factory.CreateClient();
23 |
24 | var response = await client.GetAsync("/Steve");
25 |
26 | response.EnsureSuccessStatusCode(); // Status Code 200-299
27 | response.Content.Headers.ContentType.ToString().Should().Be(JsonContentType);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/test/SampleApi.IntegrationTest/xunit.runner.json:
--------------------------------------------------------------------------------
1 | {
2 | "shadowCopy": false
3 | }
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/test/SampleApi.Test/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:55988/",
7 | "sslPort": 0
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SampleApi.Test": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "environmentVariables": {
22 | "ASPNETCORE_ENVIRONMENT": "Development"
23 | },
24 | "applicationUrl": "http://localhost:55989/"
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/test/SampleApi.Test/SampleApi.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/steps/15-Testing-In-Docker/test/SampleApi.Test/SampleControllerTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FluentAssertions;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Logging.Abstractions;
5 | using Microsoft.Extensions.Options;
6 | using Moq;
7 | using SampleApi.Configuration;
8 | using SampleApi.Controllers;
9 | using SampleApi.OutputModels;
10 | using Xunit;
11 |
12 | namespace SampleApi.Test
13 | {
14 | public class SampleControllerTests
15 | {
16 | [Fact]
17 | public void Hello_Should_ReturnExpectedWelcomeMessage()
18 | {
19 | const string welcomeMessage = "TEST";
20 | const string name = "Bob";
21 |
22 | var expectedWelcome = $"{welcomeMessage} {name}";
23 |
24 | var mockOptions = new Mock>();
25 | mockOptions.Setup(x => x.Value).Returns(new MessagesConfiguration { WelcomeMessage = welcomeMessage });
26 |
27 | var sut = new SampleController(mockOptions.Object, new NullLogger());
28 |
29 | var actionResult = sut.Hello(name);
30 |
31 | var okResult = actionResult.Result.Should().BeAssignableTo()
32 | .Which.Value.Should().BeAssignableTo()
33 | .Which.WelcomeMessage.Should().Be(expectedWelcome);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------