├── .gitignore
├── Chapter 10
└── FtpSampleApp
│ ├── FtpSampleApp.csproj
│ ├── FtpSampleApp.sln
│ └── Program.cs
├── Chapter 11
├── SampleTcpClient
│ ├── Program.cs
│ ├── SampleTcpClient.csproj
│ └── SampleTcpClient.sln
├── SampleTcpServer
│ ├── Program.cs
│ ├── SampleTcpServer.csproj
│ └── SampleTcpServer.sln
├── SampleUdpClient
│ ├── Program.cs
│ ├── SampleUdpClient.csproj
│ └── SampleUdpClient.sln
└── SampleUdpServer
│ ├── Program.cs
│ ├── SampleUdpServer.csproj
│ └── SampleUdpServer.sln
├── Chapter 12
└── DNSSimulation
│ ├── Controllers
│ └── HostsController.cs
│ ├── DNSSimulation.csproj
│ ├── DNSSimulation.sln
│ ├── Data
│ └── Hosts.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ └── hosts.json
├── Chapter 13
└── DemoTLS
│ ├── Controllers
│ └── TlsController.cs
│ ├── DemoTLS.csproj
│ ├── DemoTLS.sln
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── Services
│ └── SessionService.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── Chapter 14
└── AuthSample
│ ├── AuthSample.csproj
│ ├── AuthSample.sln
│ ├── Controllers
│ └── AuthController.cs
│ ├── Data
│ └── UserVault.cs
│ ├── Models
│ └── Credentials.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── Security
│ └── SecurityService.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ └── user_vault.json
├── Chapter 15
├── CacheSample
│ ├── CacheSample.csproj
│ ├── CacheSample.sln
│ ├── Constants.cs
│ ├── Controllers
│ │ └── ValuesController.cs
│ ├── Models
│ │ └── DataRecord.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Services
│ │ ├── CacheService.cs
│ │ └── DataService.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
└── DataSimulation
│ ├── Controllers
│ └── DataController.cs
│ ├── DataSimulation.csproj
│ ├── DataSimulation.sln
│ ├── Models
│ └── OutputRecord.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── Chapter 16
├── AggregatorDemo
│ ├── AggregatorDemo.csproj
│ ├── AggregatorDemo.sln
│ ├── Controllers
│ │ └── AggregatorController.cs
│ ├── Middleware
│ │ └── DependencyHealthCheck.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Services
│ │ └── DependentDataService.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── DataAccessDemo
│ ├── Controllers
│ │ └── DependencyController.cs
│ ├── DataAccessDemo.csproj
│ ├── DataAccessDemo.sln
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Services
│ │ └── Latency.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
└── WatchdogDemo
│ ├── Program.cs
│ ├── WatchdogDemo.csproj
│ └── WatchdogDemo.sln
├── Chapter 17
└── CustomProtocolDemo
│ ├── CustomProtocolDemo.csproj
│ ├── CustomProtocolDemo.sln
│ ├── Program.cs
│ ├── RockStatus.cs
│ ├── RockVerb.cs
│ └── WebServices
│ ├── RockWebRequest.cs
│ ├── RockWebRequestCreator.cs
│ └── RockWebResponse.cs
├── Chapter 18
└── NetworkAnalysisDemo
│ ├── NetworkAnalysisDemo.csproj
│ ├── NetworkAnalysisDemo.sln
│ └── Program.cs
├── Chapter 19
└── SshDemo
│ ├── Program.cs
│ ├── SshDemo.csproj
│ └── SshDemo.sln
├── Chapter 2
└── Dns_Samples
│ ├── DnsTest
│ ├── DnsTest.csproj
│ └── DnsTestProgram.cs
│ ├── Dns_Samples.sln
│ └── UriTest
│ ├── UriTest.csproj
│ ├── UriTest.sln
│ └── UriTestProgram.cs
├── Chapter 5
└── WebRequest_Samples
│ ├── WebRequest_Samples.sln
│ └── WebRequest_Samples
│ ├── RequestService.cs
│ └── WebRequest_Samples.csproj
├── Chapter 6
└── StreamsAndAsync
│ ├── StreamsAndAsync.sln
│ └── StreamsAndAsync
│ ├── ComplexModels.cs
│ ├── Program.cs
│ ├── ResultObject.cs
│ └── StreamsAndAsync.csproj
├── Chapter 7
└── ErrorHandling
│ ├── AsyncDemo.cs
│ ├── ErrorHandling.csproj
│ ├── ErrorHandling.sln
│ ├── PollyDemo.cs
│ ├── Program.cs
│ └── ResultObject.cs
├── Chapter 8
├── SampleApp
│ ├── Controllers
│ │ └── ValuesController.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── SampleApp.csproj
│ ├── SampleApp.sln
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
└── SocketsAndPorts
│ ├── Program.cs
│ ├── SocketsAndPorts.csproj
│ └── SocketsAndPorts.sln
├── Chapter 9
├── FitnessApp
│ ├── Controllers
│ │ └── FitnessController.cs
│ ├── FitnessApp.csproj
│ ├── FitnessApp.sln
│ ├── Models
│ │ └── FitnessRecord.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Services
│ │ └── FitnessDataStoreClient.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── FitnessDataStore
│ ├── Controllers
│ │ └── FitnessController.cs
│ ├── FitnessDataStore.csproj
│ ├── FitnessDataStore.sln
│ ├── Models
│ │ └── FitnessRecord.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Services
│ │ └── DataAccess.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── Program.cs
└── fitness_data.txt
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]og/
27 |
28 | # Visual Studio 2015/2017 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # Visual Studio 2017 auto generated files
34 | Generated\ Files/
35 |
36 | # MSTest test Results
37 | [Tt]est[Rr]esult*/
38 | [Bb]uild[Ll]og.*
39 |
40 | # NUNIT
41 | *.VisualState.xml
42 | TestResult.xml
43 |
44 | # Build Results of an ATL Project
45 | [Dd]ebugPS/
46 | [Rr]eleasePS/
47 | dlldata.c
48 |
49 | # Benchmark Results
50 | BenchmarkDotNet.Artifacts/
51 |
52 | # .NET Core
53 | project.lock.json
54 | project.fragment.lock.json
55 | artifacts/
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_h.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.iobj
68 | *.pch
69 | *.pdb
70 | *.ipdb
71 | *.pgc
72 | *.pgd
73 | *.rsp
74 | *.sbr
75 | *.tlb
76 | *.tli
77 | *.tlh
78 | *.tmp
79 | *.tmp_proj
80 | *_wpftmp.csproj
81 | *.log
82 | *.vspscc
83 | *.vssscc
84 | .builds
85 | *.pidb
86 | *.svclog
87 | *.scc
88 |
89 | # Chutzpah Test files
90 | _Chutzpah*
91 |
92 | # Visual C++ cache files
93 | ipch/
94 | *.aps
95 | *.ncb
96 | *.opendb
97 | *.opensdf
98 | *.sdf
99 | *.cachefile
100 | *.VC.db
101 | *.VC.VC.opendb
102 |
103 | # Visual Studio profiler
104 | *.psess
105 | *.vsp
106 | *.vspx
107 | *.sap
108 |
109 | # Visual Studio Trace Files
110 | *.e2e
111 |
112 | # TFS 2012 Local Workspace
113 | $tf/
114 |
115 | # Guidance Automation Toolkit
116 | *.gpState
117 |
118 | # ReSharper is a .NET coding add-in
119 | _ReSharper*/
120 | *.[Rr]e[Ss]harper
121 | *.DotSettings.user
122 |
123 | # JustCode is a .NET coding add-in
124 | .JustCode
125 |
126 | # TeamCity is a build add-in
127 | _TeamCity*
128 |
129 | # DotCover is a Code Coverage Tool
130 | *.dotCover
131 |
132 | # AxoCover is a Code Coverage Tool
133 | .axoCover/*
134 | !.axoCover/settings.json
135 |
136 | # Visual Studio code coverage results
137 | *.coverage
138 | *.coveragexml
139 |
140 | # NCrunch
141 | _NCrunch_*
142 | .*crunch*.local.xml
143 | nCrunchTemp_*
144 |
145 | # MightyMoose
146 | *.mm.*
147 | AutoTest.Net/
148 |
149 | # Web workbench (sass)
150 | .sass-cache/
151 |
152 | # Installshield output folder
153 | [Ee]xpress/
154 |
155 | # DocProject is a documentation generator add-in
156 | DocProject/buildhelp/
157 | DocProject/Help/*.HxT
158 | DocProject/Help/*.HxC
159 | DocProject/Help/*.hhc
160 | DocProject/Help/*.hhk
161 | DocProject/Help/*.hhp
162 | DocProject/Help/Html2
163 | DocProject/Help/html
164 |
165 | # Click-Once directory
166 | publish/
167 |
168 | # Publish Web Output
169 | *.[Pp]ublish.xml
170 | *.azurePubxml
171 | # Note: Comment the next line if you want to checkin your web deploy settings,
172 | # but database connection strings (with potential passwords) will be unencrypted
173 | *.pubxml
174 | *.publishproj
175 |
176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
177 | # checkin your Azure Web App publish settings, but sensitive information contained
178 | # in these scripts will be unencrypted
179 | PublishScripts/
180 |
181 | # NuGet Packages
182 | *.nupkg
183 | # The packages folder can be ignored because of Package Restore
184 | **/[Pp]ackages/*
185 | # except build/, which is used as an MSBuild target.
186 | !**/[Pp]ackages/build/
187 | # Uncomment if necessary however generally it will be regenerated when needed
188 | #!**/[Pp]ackages/repositories.config
189 | # NuGet v3's project.json files produces more ignorable files
190 | *.nuget.props
191 | *.nuget.targets
192 |
193 | # Microsoft Azure Build Output
194 | csx/
195 | *.build.csdef
196 |
197 | # Microsoft Azure Emulator
198 | ecf/
199 | rcf/
200 |
201 | # Windows Store app package directories and files
202 | AppPackages/
203 | BundleArtifacts/
204 | Package.StoreAssociation.xml
205 | _pkginfo.txt
206 | *.appx
207 |
208 | # Visual Studio cache files
209 | # files ending in .cache can be ignored
210 | *.[Cc]ache
211 | # but keep track of directories ending in .cache
212 | !*.[Cc]ache/
213 |
214 | # Others
215 | ClientBin/
216 | ~$*
217 | *~
218 | *.dbmdl
219 | *.dbproj.schemaview
220 | *.jfm
221 | *.pfx
222 | *.publishsettings
223 | orleans.codegen.cs
224 |
225 | # Including strong name files can present a security risk
226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
227 | #*.snk
228 |
229 | # Since there are multiple workflows, uncomment next line to ignore bower_components
230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
231 | #bower_components/
232 |
233 | # RIA/Silverlight projects
234 | Generated_Code/
235 |
236 | # Backup & report files from converting an old project file
237 | # to a newer Visual Studio version. Backup files are not needed,
238 | # because we have git ;-)
239 | _UpgradeReport_Files/
240 | Backup*/
241 | UpgradeLog*.XML
242 | UpgradeLog*.htm
243 | ServiceFabricBackup/
244 | *.rptproj.bak
245 |
246 | # SQL Server files
247 | *.mdf
248 | *.ldf
249 | *.ndf
250 |
251 | # Business Intelligence projects
252 | *.rdl.data
253 | *.bim.layout
254 | *.bim_*.settings
255 | *.rptproj.rsuser
256 |
257 | # Microsoft Fakes
258 | FakesAssemblies/
259 |
260 | # GhostDoc plugin setting file
261 | *.GhostDoc.xml
262 |
263 | # Node.js Tools for Visual Studio
264 | .ntvs_analysis.dat
265 | node_modules/
266 |
267 | # Visual Studio 6 build log
268 | *.plg
269 |
270 | # Visual Studio 6 workspace options file
271 | *.opt
272 |
273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
274 | *.vbw
275 |
276 | # Visual Studio LightSwitch build output
277 | **/*.HTMLClient/GeneratedArtifacts
278 | **/*.DesktopClient/GeneratedArtifacts
279 | **/*.DesktopClient/ModelManifest.xml
280 | **/*.Server/GeneratedArtifacts
281 | **/*.Server/ModelManifest.xml
282 | _Pvt_Extensions
283 |
284 | # Paket dependency manager
285 | .paket/paket.exe
286 | paket-files/
287 |
288 | # FAKE - F# Make
289 | .fake/
290 |
291 | # JetBrains Rider
292 | .idea/
293 | *.sln.iml
294 |
295 | # CodeRush personal settings
296 | .cr/personal
297 |
298 | # Python Tools for Visual Studio (PTVS)
299 | __pycache__/
300 | *.pyc
301 |
302 | # Cake - Uncomment if you are using it
303 | # tools/**
304 | # !tools/packages.config
305 |
306 | # Tabs Studio
307 | *.tss
308 |
309 | # Telerik's JustMock configuration file
310 | *.jmconfig
311 |
312 | # BizTalk build output
313 | *.btp.cs
314 | *.btm.cs
315 | *.odx.cs
316 | *.xsd.cs
317 |
318 | # OpenCover UI analysis results
319 | OpenCover/
320 |
321 | # Azure Stream Analytics local run output
322 | ASALocalRun/
323 |
324 | # MSBuild Binary and Structured Log
325 | *.binlog
326 |
327 | # NVidia Nsight GPU debugger configuration file
328 | *.nvuser
329 |
330 | # MFractors (Xamarin productivity tool) working folder
331 | .mfractor/
332 |
333 | # Local History for Visual Studio
334 | .localhistory/
--------------------------------------------------------------------------------
/Chapter 10/FtpSampleApp/FtpSampleApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | FtpSampleApp.Program
7 | latest
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Chapter 10/FtpSampleApp/FtpSampleApp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FtpSampleApp", "FtpSampleApp.csproj", "{67562967-19B6-40D9-BBC1-495B57BB105E}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {67562967-19B6-40D9-BBC1-495B57BB105E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {67562967-19B6-40D9-BBC1-495B57BB105E}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {67562967-19B6-40D9-BBC1-495B57BB105E}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {67562967-19B6-40D9-BBC1-495B57BB105E}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {8A95643F-AB45-4F95-98DB-A4916B46F1DE}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 10/FtpSampleApp/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace FtpSampleApp {
9 | class Program {
10 | static async Task Main(string[] args) {
11 | Console.WriteLine(await GetDirectoryListing());
12 | Console.WriteLine(await RequestFile());
13 | Console.WriteLine(await PushFile());
14 |
15 | Thread.Sleep(5000);
16 | }
17 |
18 | public static async Task GetDirectoryListing() {
19 | StringBuilder strBuilder = new StringBuilder();
20 | FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://localhost");
21 | req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
22 |
23 | req.Credentials = new NetworkCredential("s_burns", "test_password");
24 | req.EnableSsl = false;
25 |
26 | FtpWebResponse resp = (FtpWebResponse)await req.GetResponseAsync();
27 |
28 | using (var respStream = resp.GetResponseStream()) {
29 | using (var reader = new StreamReader(respStream)) {
30 | strBuilder.Append(reader.ReadToEnd());
31 | strBuilder.Append(resp.WelcomeMessage);
32 | strBuilder.Append($"Request returned status: {resp.StatusDescription}");
33 | }
34 | }
35 | return strBuilder.ToString();
36 | }
37 |
38 | public static async Task RequestFile() {
39 | StringBuilder strBuilder = new StringBuilder();
40 | FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://localhost/FitnessApp/Startup.cs");
41 | req.Method = WebRequestMethods.Ftp.DownloadFile;
42 |
43 | req.Credentials = new NetworkCredential("s_burns", "test_password");
44 | req.UsePassive = true;
45 |
46 | using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
47 |
48 | using (var respStream = resp.GetResponseStream()) {
49 | strBuilder.Append(resp.StatusDescription);
50 | if (!File.Exists(@"../Copy_Startup.cs")) {
51 | using (var file = File.Create(@"../Copy_Startup.cs")) {
52 | //We only use this to create the file in the path if it doesn't exist.
53 | }
54 | }
55 | using (var respReader = new StreamReader(respStream)) {
56 | using (var fileWriter = File.OpenWrite(@"../Copy_Startup.cs")) {
57 | using (var strWriter = new StreamWriter(fileWriter)) {
58 | await strWriter.WriteAsync(respReader.ReadToEnd());
59 | }
60 | }
61 | }
62 | }
63 | }
64 |
65 | return strBuilder.ToString();
66 | }
67 |
68 | public static async Task PushFile() {
69 | StringBuilder strBuilder = new StringBuilder();
70 | FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://localhost/Program.cs");
71 | req.Method = WebRequestMethods.Ftp.UploadFile;
72 |
73 | req.Credentials = new NetworkCredential("s_burns", "test_password");
74 | req.UsePassive = true;
75 |
76 | byte[] fileBytes;
77 |
78 | using (var reader = new StreamReader(@"Program.cs")) {
79 | fileBytes = Encoding.ASCII.GetBytes(reader.ReadToEnd());
80 | }
81 |
82 | req.ContentLength = fileBytes.Length;
83 |
84 | using (var reqStream = await req.GetRequestStreamAsync()) {
85 | await reqStream.WriteAsync(fileBytes, 0, fileBytes.Length);
86 | }
87 |
88 | using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
89 | strBuilder.Append(resp.StatusDescription);
90 | }
91 |
92 | return strBuilder.ToString();
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Chapter 11/SampleTcpClient/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace SampleTcpClient {
9 | class Program {
10 | public static async Task Main(string[] args) {
11 | int port = 54321;
12 | IPAddress address = IPAddress.Parse("127.0.0.1");
13 | var messages = new string[] {
14 | "Hello server | Return this payload to sender!",
15 | "To the server | Send this payload back to me!",
16 | "Server Header | Another returned message.",
17 | "Header Value | Payload to be returned",
18 | "TERMINATE"
19 | };
20 | var i = 0;
21 | while (i < messages.Length) {
22 | using (TcpClient client = new TcpClient()) {
23 | client.Connect(address, port);
24 | if (client.Connected) {
25 | Console.WriteLine("We've connected from the client");
26 | }
27 |
28 | var bytes = Encoding.UTF8.GetBytes(messages[i++]);
29 | using (var requestStream = client.GetStream()) {
30 | await requestStream.WriteAsync(bytes, 0, bytes.Length);
31 | var responseBytes = new byte[256];
32 | await requestStream.ReadAsync(responseBytes, 0, responseBytes.Length);
33 | var responseMessage = Encoding.UTF8.GetString(responseBytes);
34 | Console.WriteLine();
35 | Console.WriteLine("Response Received From Server:");
36 | Console.WriteLine(responseMessage);
37 | }
38 | }
39 | var sleepDuration = new Random().Next(2000, 10000);
40 | Console.WriteLine($"Generating a new request in {sleepDuration / 1000} seconds");
41 | Thread.Sleep(sleepDuration);
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Chapter 11/SampleTcpClient/SampleTcpClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Chapter 11/SampleTcpClient/SampleTcpClient.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleTcpClient", "SampleTcpClient.csproj", "{85F046B8-17AF-473C-8FEB-857F03102FB8}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {85F046B8-17AF-473C-8FEB-857F03102FB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {85F046B8-17AF-473C-8FEB-857F03102FB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {85F046B8-17AF-473C-8FEB-857F03102FB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {85F046B8-17AF-473C-8FEB-857F03102FB8}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {7E912ACD-A34E-4516-8707-0B1BB418F764}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 11/SampleTcpServer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text;
4 | using System.Net;
5 | using System.Net.Sockets;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace SampleTcpServer {
10 | class Program {
11 | public static async Task Main(string[] args) {
12 | bool done = false;
13 | string DELIMITER = "|";
14 | string TERMINATE = "TERMINATE";
15 | int port = 54321;
16 | IPAddress address = IPAddress.Any;
17 | TcpListener server = new TcpListener(address, port);
18 | server.Start();
19 | var loggedNoRequest = false;
20 |
21 | while (!done) {
22 | if (!server.Pending()) {
23 | if (!loggedNoRequest) {
24 | Console.WriteLine();
25 | Console.WriteLine("No pending requests as of yet");
26 | Console.WriteLine("Server listening...");
27 | loggedNoRequest = true;
28 | }
29 | } else {
30 | loggedNoRequest = false;
31 | byte[] bytes = new byte[256];
32 |
33 | using (var client = await server.AcceptTcpClientAsync()) {
34 | using (var tcpStream = client.GetStream()) {
35 | await tcpStream.ReadAsync(bytes, 0, bytes.Length);
36 | var requestMessage = Encoding.UTF8.GetString(bytes).Replace("\0", string.Empty);
37 |
38 | if (requestMessage.Equals(TERMINATE)) {
39 | done = true;
40 | } else {
41 | Console.WriteLine();
42 | Console.WriteLine("Message Received From Client:");
43 | Console.WriteLine(requestMessage);
44 | var payload = requestMessage.Split(DELIMITER).Last();
45 | var responseMessage = $"Greetings from the server! | {payload}";
46 | var responseBytes = Encoding.UTF8.GetBytes(responseMessage);
47 | await tcpStream.WriteAsync(responseBytes, 0, responseBytes.Length);
48 | }
49 | }
50 | }
51 | }
52 | }
53 | server.Stop();
54 | Thread.Sleep(10000);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chapter 11/SampleTcpServer/SampleTcpServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Chapter 11/SampleTcpServer/SampleTcpServer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleTcpServer", "SampleTcpServer.csproj", "{45093907-B206-4A32-BF10-5AB89A01CEF1}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {45093907-B206-4A32-BF10-5AB89A01CEF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {45093907-B206-4A32-BF10-5AB89A01CEF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {45093907-B206-4A32-BF10-5AB89A01CEF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {45093907-B206-4A32-BF10-5AB89A01CEF1}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {59113063-A374-4522-8BC3-B692C1CA9B25}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 11/SampleUdpClient/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace SampleUdpClient {
9 | class Program {
10 | public static async Task Main(string[] args) {
11 | using (var client = new UdpClient(34567)) {
12 | var remoteEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 45678);
13 |
14 | client.Connect(remoteEndpoint);
15 |
16 | var message = "Testing UDP";
17 | byte[] messageBytes = Encoding.UTF8.GetBytes(message);
18 | await client.SendAsync(messageBytes, messageBytes.Length);
19 |
20 | var response = await client.ReceiveAsync();
21 | var responseMessage = Encoding.UTF8.GetString(response.Buffer);
22 | Console.WriteLine(responseMessage);
23 |
24 | Thread.Sleep(10000);
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Chapter 11/SampleUdpClient/SampleUdpClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Chapter 11/SampleUdpClient/SampleUdpClient.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleUdpClient", "SampleUdpClient.csproj", "{00C0F20C-C673-4DB5-BEBE-4AF0D750C783}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {00C0F20C-C673-4DB5-BEBE-4AF0D750C783}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {00C0F20C-C673-4DB5-BEBE-4AF0D750C783}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {00C0F20C-C673-4DB5-BEBE-4AF0D750C783}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {00C0F20C-C673-4DB5-BEBE-4AF0D750C783}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {E0077B4A-8398-46F2-8893-5BD8979A993A}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 11/SampleUdpServer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace SampleUdpServer {
9 | class Program {
10 | public static async Task Main(string[] args) {
11 | using (var client = new UdpClient(45678)) {
12 | IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 34567);
13 |
14 | var incomingMessage = await client.ReceiveAsync();
15 | var message = Encoding.UTF8.GetString(incomingMessage.Buffer);
16 | Console.WriteLine(message);
17 |
18 |
19 | var responseString = $"Packet received from client: {message}";
20 | byte[] response = Encoding.UTF8.GetBytes(responseString);
21 | await client.SendAsync(response, response.Length, remoteEndpoint);
22 | }
23 | Thread.Sleep(10000);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Chapter 11/SampleUdpServer/SampleUdpServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Chapter 11/SampleUdpServer/SampleUdpServer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleUdpServer", "SampleUdpServer.csproj", "{07EE65AB-DD21-41E7-8AA2-3F819FCAD445}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {07EE65AB-DD21-41E7-8AA2-3F819FCAD445}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {07EE65AB-DD21-41E7-8AA2-3F819FCAD445}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {07EE65AB-DD21-41E7-8AA2-3F819FCAD445}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {07EE65AB-DD21-41E7-8AA2-3F819FCAD445}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {C86B51AF-A073-430B-997F-C0B9F907D61E}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/Controllers/HostsController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Microsoft.AspNetCore.Mvc;
8 |
9 | using Newtonsoft.Json;
10 |
11 | namespace DNSSimulation {
12 | [Route("dns/[controller]")]
13 | [ApiController]
14 | public class HostsController : ControllerBase {
15 | [HttpPost]
16 | public string Post([FromBody] string domainName) {
17 | var uri = new UriBuilder(domainName).Uri;
18 | IEnumerable ipAddressStrings;
19 | if (!Hosts.Map.TryGetValue(uri.Host, out ipAddressStrings)) {
20 | return GetSerializedIPAddresses(Dns.GetHostAddresses(uri.Host));
21 | }
22 |
23 | var addresses = new List();
24 | foreach (var addressString in ipAddressStrings) {
25 | if (!IPAddress.TryParse(addressString, out var newAddress)) {
26 | continue;
27 | }
28 | addresses.Add(newAddress);
29 | }
30 | return GetSerializedIPAddresses(addresses);
31 | }
32 |
33 | private string GetSerializedIPAddresses(IEnumerable addresses) {
34 | var str = new StringBuilder("[");
35 | var firstInstance = true;
36 | foreach (var address in addresses) {
37 | if (!firstInstance) {
38 | str.Append(",");
39 | } else {
40 | firstInstance = false;
41 | }
42 | str.Append("{");
43 | str.Append($"\"Address\": {address.ToString()},");
44 | str.Append($"\"AddressFamily\": {address.AddressFamily},");
45 | str.Append($"\"IsIPv4MappedToIPv6\": {address.IsIPv4MappedToIPv6},");
46 | str.Append($"\"IsIPv6LinkLocal\": {address.IsIPv6LinkLocal},");
47 | str.Append($"\"IsIPv6Multicast\": {address.IsIPv6Multicast},");
48 | str.Append($"\"IsIPv6SiteLocal\": {address.IsIPv6SiteLocal},");
49 | str.Append($"\"IsIPv6Teredo\": {address.IsIPv6Teredo}");
50 | str.Append("}");
51 | }
52 |
53 | str.Append("]");
54 | return str.ToString();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/DNSSimulation.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/DNSSimulation.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DNSSimulation", "DNSSimulation.csproj", "{47F82F87-8C2A-4212-BE45-42A222791E36}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {47F82F87-8C2A-4212-BE45-42A222791E36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {47F82F87-8C2A-4212-BE45-42A222791E36}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {47F82F87-8C2A-4212-BE45-42A222791E36}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {47F82F87-8C2A-4212-BE45-42A222791E36}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {DEBB7FB1-FB17-4D1F-A928-B712B60B6EB4}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/Data/Hosts.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Newtonsoft.Json;
7 |
8 | namespace DNSSimulation {
9 | public static class Hosts {
10 | public static IDictionary> Map;
11 | static Hosts() {
12 | try {
13 | using (var sr = new StreamReader("hosts.json")) {
14 | var json = sr.ReadToEnd();
15 | Map = JsonConvert.DeserializeObject>>(json);
16 | }
17 | } catch (Exception e) {
18 | throw e;
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/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 DNSSimulation
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 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:7693",
8 | "sslPort": 44307
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "DNSSimulation": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/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.HttpsPolicy;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace DNSSimulation
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | // This method gets called by the runtime. Use this method to add services to the container.
26 | public void ConfigureServices(IServiceCollection services)
27 | {
28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
29 | }
30 |
31 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
32 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
33 | {
34 | if (env.IsDevelopment())
35 | {
36 | app.UseDeveloperExceptionPage();
37 | }
38 | else
39 | {
40 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
41 | app.UseHsts();
42 | }
43 |
44 | app.UseHttpsRedirection();
45 | app.UseMvc();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 12/DNSSimulation/hosts.json:
--------------------------------------------------------------------------------
1 | {
2 | "test.com": [ "172.112.98.123" ],
3 | "fake.net": [
4 | "133.54.121.89",
5 | "fe80:0000:0000:0000:5584:7902:d228:6f0e"
6 | ],
7 | "not-real.org": [
8 | "123.12.13.134",
9 | "dc39::7354:23f3:c34e"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/Controllers/TlsController.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Microsoft.AspNetCore.Mvc;
3 |
4 | namespace DemoTLS {
5 | [Route("demo/[controller]")]
6 | [ApiController]
7 | public class TlsController : ControllerBase {
8 | [HttpGet("initiate-connection")]
9 | public ActionResult GetCertificate() {
10 | return "CERTIFICATE_DELIVERED";
11 | }
12 |
13 | [HttpGet("certificate-verified")]
14 | public ActionResult GetVerification() {
15 | return "PUBLIC_KEY_FOR_ENCRYPTING_HANDSHAKE";
16 | }
17 |
18 | [HttpGet("hash-algorithms-requested")]
19 | public ActionResult> GetAlgorithms() {
20 | return new string[] {
21 | "SHA-256",
22 | "AES",
23 | "RSA"
24 | };
25 | }
26 |
27 | [HttpPost("hash-algorithm-selected")]
28 | public ActionResult Post([FromBody] string sharedAlgorithm) {
29 | SessionService.CurrentAlgorithm = sharedAlgorithm;
30 | return SessionService.GenerateSharedKeyWithPrivateKeyAndRandomSessionKey();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/DemoTLS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/DemoTLS.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DemoTLS", "DemoTLS.csproj", "{792F3983-4ECA-49B2-A3D6-5226C8A90684}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {792F3983-4ECA-49B2-A3D6-5226C8A90684}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {792F3983-4ECA-49B2-A3D6-5226C8A90684}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {792F3983-4ECA-49B2-A3D6-5226C8A90684}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {792F3983-4ECA-49B2-A3D6-5226C8A90684}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {FE5C410B-8450-457B-BE60-169ACECA388E}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/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 DemoTLS
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 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:52649",
8 | "sslPort": 44383
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "DemoTLS": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/Services/SessionService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace DemoTLS {
7 | public static class SessionService {
8 | public static string CurrentAlgorithm { get; set; }
9 |
10 | public static string GenerateSharedKeyWithPrivateKeyAndRandomSessionKey() {
11 | return "SHARED_SECRET";
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/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.AspNetCore.HttpsPolicy;
9 | using Microsoft.AspNetCore.Mvc;
10 | using Microsoft.Extensions.Configuration;
11 | using Microsoft.Extensions.DependencyInjection;
12 | using Microsoft.Extensions.Logging;
13 | using Microsoft.Extensions.Options;
14 |
15 | namespace DemoTLS {
16 | public class Startup {
17 | public Startup(IConfiguration configuration) {
18 | Configuration = configuration;
19 | }
20 |
21 | public IConfiguration Configuration { get; }
22 |
23 | // This method gets called by the runtime. Use this method to add services to the container.
24 | public void ConfigureServices(IServiceCollection services) {
25 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
26 |
27 | services.AddHttpsRedirection(options => {
28 | options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
29 | options.HttpsPort = 5001;
30 | });
31 | }
32 |
33 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
34 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
35 | if (env.IsDevelopment()) {
36 | app.UseDeveloperExceptionPage();
37 | } else {
38 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
39 | app.UseHsts();
40 | }
41 |
42 | app.UseHttpsRedirection();
43 | app.UseMvc();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 13/DemoTLS/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/AuthSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/AuthSample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AuthSample", "AuthSample.csproj", "{E3475C7A-C631-4C76-B8A9-C68CE4186F81}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {E3475C7A-C631-4C76-B8A9-C68CE4186F81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {E3475C7A-C631-4C76-B8A9-C68CE4186F81}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {E3475C7A-C631-4C76-B8A9-C68CE4186F81}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {E3475C7A-C631-4C76-B8A9-C68CE4186F81}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {A4D64CED-7D03-45F0-9CB2-B6648A175D6C}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/Controllers/AuthController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.Claims;
5 | using System.IdentityModel.Tokens.Jwt;
6 | using Microsoft.AspNetCore.Authorization;
7 | using Microsoft.AspNetCore.Mvc;
8 | using Microsoft.IdentityModel.Tokens;
9 | using System.Security.Principal;
10 |
11 | namespace AuthSample {
12 |
13 | [Route("api/[controller]")]
14 | [ApiController]
15 | [Authorize]
16 | public class AuthController : ControllerBase {
17 |
18 | [HttpGet("secret")]
19 | public ActionResult GetRestrictedResource() {
20 | var validClaims = GetClaims().Select(x => x.Type);
21 | var userClaims = HttpContext.User.Claims.Select(x => x.Type);
22 | if (validClaims.Intersect(userClaims).Count() < 1) {
23 | return StatusCode(403);
24 | }
25 | return "This message is top secret!";
26 | }
27 |
28 | [HttpPost]
29 | [AllowAnonymous]
30 | public ActionResult AuthenticateUser([FromBody] Credentials creds) {
31 | if (UserVault.ContainsCredentials(creds.UserName, creds.Password)) {
32 | var key = SecurityService.GetSecurityKey();
33 | var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
34 | var identity = new ClaimsIdentity(new GenericIdentity(creds.UserName, "username"));
35 | identity.AddClaims(GetClaims());
36 |
37 | var handler = new JwtSecurityTokenHandler();
38 | var token = handler.CreateToken(new SecurityTokenDescriptor() {
39 | Issuer = SecurityService.GetIssuer(),
40 | Audience = SecurityService.GetAudience(),
41 | SigningCredentials = signingCredentials,
42 | Subject = identity,
43 | Expires = DateTime.Now.AddMinutes(10),
44 | NotBefore = DateTime.Now
45 | });
46 | return handler.WriteToken(token);
47 | } else {
48 | return StatusCode(401);
49 | }
50 | }
51 |
52 | private IEnumerable GetClaims() {
53 | return new List() {
54 | new Claim("secret_access", "true"),
55 | new Claim("excellent_code", "true")
56 | };
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/Data/UserVault.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 |
5 | using Newtonsoft.Json;
6 |
7 | namespace AuthSample {
8 |
9 | public static class UserVault {
10 | private static Dictionary _users { get; set; }
11 |
12 | static UserVault() {
13 | try {
14 | using (var sr = new StreamReader("user_vault.json")) {
15 | var json = sr.ReadToEnd();
16 | _users = JsonConvert.DeserializeObject>(json);
17 | }
18 | } catch (Exception e) {
19 | throw e;
20 | }
21 | }
22 |
23 | public static bool ContainsCredentials(string userName, string password) {
24 | if (_users.ContainsKey(userName)) {
25 | string storedPassword;
26 | if (_users.TryGetValue(userName, out storedPassword)) {
27 | return storedPassword.Equals(password);
28 | }
29 | }
30 | return false;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/Models/Credentials.cs:
--------------------------------------------------------------------------------
1 | namespace AuthSample {
2 | public class Credentials {
3 | public string UserName { get; set; }
4 | public string Password { get; set; }
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore;
2 | using Microsoft.AspNetCore.Hosting;
3 |
4 | namespace AuthSample
5 | {
6 | public class Program
7 | {
8 | public static void Main(string[] args)
9 | {
10 | CreateWebHostBuilder(args).Build().Run();
11 | }
12 |
13 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
14 | WebHost.CreateDefaultBuilder(args)
15 | .UseUrls("https://[::]:44444")
16 | .UseStartup();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:31281",
8 | "sslPort": 44390
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "AuthSample": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/Security/SecurityService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.IdentityModel.Tokens;
2 | using System.Text;
3 |
4 | namespace AuthSample {
5 | public static class SecurityService {
6 | public static SymmetricSecurityKey GetSecurityKey() {
7 | string key = "0125eb1b-0251-4a86-8d43-8ebeeeb39d9a";
8 | return new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key));
9 | }
10 |
11 | public static string GetIssuer() {
12 | return "https://our-issuer.com/oauth";
13 | }
14 |
15 | public static string GetAudience() {
16 | return "we_the_audience";
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Authentication.JwtBearer;
2 | using Microsoft.AspNetCore.Builder;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.IdentityModel.Tokens;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.DependencyInjection;
8 |
9 | namespace AuthSample {
10 | public class Startup {
11 | public Startup(IConfiguration configuration) {
12 | Configuration = configuration;
13 | }
14 |
15 | public IConfiguration Configuration { get; }
16 |
17 | // This method gets called by the runtime. Use this method to add services to the container.
18 | public void ConfigureServices(IServiceCollection services) {
19 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
20 | services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
21 | .AddJwtBearer(options => {
22 | options.TokenValidationParameters = new TokenValidationParameters {
23 | IssuerSigningKey = SecurityService.GetSecurityKey(),
24 | RequireSignedTokens = true,
25 | ValidateActor = false,
26 | ValidateAudience = true,
27 | ValidAudience = SecurityService.GetAudience(),
28 | ValidateIssuer = true,
29 | ValidIssuer = SecurityService.GetIssuer()
30 | };
31 | });
32 | }
33 |
34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
35 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
36 | if (env.IsDevelopment()) {
37 | app.UseDeveloperExceptionPage();
38 | } else {
39 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
40 | app.UseHsts();
41 | }
42 | app.UseAuthentication();
43 | app.UseHttpsRedirection();
44 | app.UseMvc();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 14/AuthSample/user_vault.json:
--------------------------------------------------------------------------------
1 | {
2 | "aladdin": "open_sesame",
3 | "dr_suess": "green_eggs_and_ham",
4 | "jack_skellington": "halloween"
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/CacheSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/CacheSample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheSample", "CacheSample.csproj", "{08BF35EC-A46C-4792-A2E8-6B2C9DDC48E2}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {08BF35EC-A46C-4792-A2E8-6B2C9DDC48E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {08BF35EC-A46C-4792-A2E8-6B2C9DDC48E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {08BF35EC-A46C-4792-A2E8-6B2C9DDC48E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {08BF35EC-A46C-4792-A2E8-6B2C9DDC48E2}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {BE871197-D002-491A-8F03-4807782CB69A}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace CacheSample {
2 | public class Constants {
3 | public static readonly string DATA_CLIENT = "DATA_CLIENT";
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/Controllers/ValuesController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace CacheSample {
8 | [Route("api/cache-client")]
9 | [ApiController]
10 | public class ValuesController : ControllerBase {
11 |
12 | private IDataService _dataService;
13 | private ICacheService _cache;
14 |
15 | public ValuesController(IDataService data, ICacheService cache) {
16 | _dataService = data;
17 | _cache = cache;
18 | }
19 |
20 | [HttpGet("value/{id}")]
21 | public async Task> GetValue(string id) {
22 | var key = $"{id}value";
23 | if (await _cache.HasCacheRecord(key)) {
24 | return await _cache.FetchString(key);
25 | }
26 | var value = await _dataService.GetStringValueById(id);
27 | await _cache.WriteString(key, value);
28 | return value;
29 | }
30 |
31 | [HttpGet("values/{id}")]
32 | public async Task> GetValues(string id) {
33 | var key = $"{id}values";
34 | if (await _cache.HasCacheRecord(key)) {
35 | return await _cache.FetchRecord>(key);
36 | }
37 | var value = await _dataService.GetStringListById(id);
38 | await _cache.WriteRecord(key, value);
39 | return value;
40 | }
41 |
42 | [HttpGet("record/{id}")]
43 | public async Task> GetRecord(string id) {
44 | var key = $"{id}record";
45 | if (await _cache.HasCacheRecord(key)) {
46 | return await _cache.FetchRecord(key);
47 | }
48 | var value = await _dataService.GetRecordById(id);
49 | await _cache.WriteRecord(key, value);
50 | return value;
51 | }
52 |
53 | [HttpGet("records/{id}")]
54 | public async Task> Get(string id) {
55 | var key = $"{id}records";
56 | if (await _cache.HasCacheRecord(key)) {
57 | return await _cache.FetchRecord>(key);
58 | }
59 | var value = await _dataService.GetRecordListById(id);
60 | await _cache.WriteRecord(key, value);
61 | return value;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/Models/DataRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace CacheSample {
7 | public class DataRecord {
8 | public int Id { get; set; }
9 | public string SimpleString { get; set; }
10 | public List StringList { get; set; } = new List();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/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 CacheSample
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 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:42914",
8 | "sslPort": 44331
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "CacheSample": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/Services/CacheService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Caching.Distributed;
2 | using System;
3 | using System.Threading.Tasks;
4 |
5 | using Newtonsoft.Json;
6 |
7 | namespace CacheSample {
8 |
9 | public interface ICacheService {
10 | Task HasCacheRecord(string id);
11 | Task FetchString(string id);
12 | Task FetchRecord(string id);
13 | Task WriteString(string id, string value);
14 | Task WriteRecord(string id, T record);
15 | }
16 |
17 | public class CacheService : ICacheService {
18 | IDistributedCache _cache;
19 |
20 | public CacheService(IDistributedCache cache) {
21 | _cache = cache;
22 | }
23 |
24 | public async Task HasCacheRecord(string id) {
25 | var record = await _cache.GetStringAsync(id);
26 | return record != null;
27 | }
28 |
29 | public async Task FetchString(string id) {
30 | return await _cache.GetStringAsync(id);
31 | }
32 |
33 | public async Task FetchRecord(string id) {
34 | var record = await _cache.GetStringAsync(id);
35 | T result = JsonConvert.DeserializeObject(record);
36 | return result;
37 | }
38 |
39 | public async Task WriteString(string id, string value) {
40 | DistributedCacheEntryOptions opts = new DistributedCacheEntryOptions() {
41 | SlidingExpiration = TimeSpan.FromMinutes(60)
42 | };
43 | await _cache.SetStringAsync(id, value, opts);
44 | }
45 |
46 | public async Task WriteRecord(string id, T record) {
47 | var value = JsonConvert.SerializeObject(record);
48 | DistributedCacheEntryOptions opts = new DistributedCacheEntryOptions() {
49 | SlidingExpiration = TimeSpan.FromMinutes(60)
50 | };
51 |
52 | await _cache.SetStringAsync(id, value, opts);
53 | }
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/Services/DataService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Net.Http;
3 | using System.Threading.Tasks;
4 |
5 | using Newtonsoft.Json;
6 |
7 | namespace CacheSample {
8 | public interface IDataService {
9 | Task GetStringValueById(string id);
10 | Task> GetStringListById(string id);
11 | Task GetRecordById(string id);
12 | Task> GetRecordListById(string id);
13 | }
14 |
15 | public class DataService : IDataService {
16 | private IHttpClientFactory _httpFactory;
17 |
18 | public DataService(IHttpClientFactory httpFactory) {
19 | _httpFactory = httpFactory;
20 | }
21 |
22 | public async Task GetStringValueById(string id) {
23 | return await GetResponseString($"api/data/value/{id}");
24 | }
25 |
26 | public async Task> GetStringListById(string id) {
27 | var respStr = await GetResponseString($"api/data/values/{id}");
28 | return JsonConvert.DeserializeObject>(respStr);
29 | }
30 |
31 | public async Task GetRecordById(string id) {
32 | var respStr = await GetResponseString($"api/data/record/{id}");
33 | return JsonConvert.DeserializeObject(respStr);
34 | }
35 |
36 | public async Task> GetRecordListById(string id) {
37 | var respStr = await GetResponseString($"api/data/records/{id}");
38 | return JsonConvert.DeserializeObject>(respStr);
39 | }
40 |
41 | private async Task GetResponseString(string path) {
42 | var client = _httpFactory.CreateClient(Constants.DATA_CLIENT);
43 | var request = new HttpRequestMessage(HttpMethod.Get, path);
44 | var response = await client.SendAsync(request);
45 | return await response.Content.ReadAsStringAsync();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Builder;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.Configuration;
6 | using Microsoft.Extensions.DependencyInjection;
7 |
8 | namespace CacheSample {
9 | public class Startup {
10 | public Startup(IConfiguration configuration) {
11 | Configuration = configuration;
12 | }
13 |
14 | public IConfiguration Configuration { get; }
15 |
16 | public void ConfigureServices(IServiceCollection services) {
17 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
18 |
19 | services.AddDistributedRedisCache(options => {
20 | options.Configuration = "localhost";
21 | options.InstanceName = "local";
22 | });
23 |
24 | services.AddHttpClient(Constants.DATA_CLIENT, options => {
25 | options.BaseAddress = new Uri("https://localhost:33333");
26 | options.DefaultRequestHeaders.Add("Accept", "application/json");
27 | });
28 |
29 | services.AddSingleton();
30 | services.AddSingleton();
31 | }
32 |
33 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
34 | if (env.IsDevelopment()) {
35 | app.UseDeveloperExceptionPage();
36 | } else {
37 | app.UseHsts();
38 | }
39 |
40 | app.UseHttpsRedirection();
41 | app.UseMvc();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 15/CacheSample/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/Controllers/DataController.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading;
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | namespace DataSimulation {
6 | [Route("api/[controller]")]
7 | [ApiController]
8 | public class DataController : ControllerBase {
9 |
10 | [HttpGet("value/{id}")]
11 | public ActionResult GetString(int id) {
12 | Thread.Sleep(5000);
13 | return $"{id}: some data";
14 | }
15 |
16 | [HttpGet("values/{id}")]
17 | public ActionResult> GetStrings(int id) {
18 | Thread.Sleep(5000);
19 | return new string[] { $"{id}: value1", $"{id + 1}: value2" };
20 | }
21 |
22 | [HttpGet("record/{id}")]
23 | public ActionResult GetRecord(int id) {
24 | Thread.Sleep(5000);
25 | return new OutputRecord() {
26 | Id = id,
27 | SimpleString = $"{id}: value 1",
28 | StringList = new List {
29 | $"{id}:value 2",
30 | $"{id}:value 3"
31 | }
32 | };
33 | }
34 |
35 | [HttpGet("records/{id}")]
36 | public ActionResult> GetRecords(int id) {
37 | Thread.Sleep(5000);
38 | return new List(){
39 | new OutputRecord() {
40 | Id = id,
41 | SimpleString = $"{id}: value 1",
42 | StringList = new List {
43 | $"{id}:value 2",
44 | $"{id}:value 3"
45 | }
46 | }, new OutputRecord() {
47 | Id = id + 1,
48 | SimpleString = $"{id + 1}: value 4",
49 | StringList = new List {
50 | $"{id + 1}:value 5",
51 | $"{id + 1}:value 6"
52 | }
53 | }
54 | };
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/DataSimulation.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/DataSimulation.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataSimulation", "DataSimulation.csproj", "{0B336309-076D-47BF-A4A7-06EDE8191266}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {0B336309-076D-47BF-A4A7-06EDE8191266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {0B336309-076D-47BF-A4A7-06EDE8191266}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {0B336309-076D-47BF-A4A7-06EDE8191266}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {0B336309-076D-47BF-A4A7-06EDE8191266}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {35F694E8-126B-4A22-AA74-13BFCD8E6A51}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/Models/OutputRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace DataSimulation {
7 | public class OutputRecord {
8 | public int Id { get; set; }
9 | public string SimpleString { get; set; }
10 | public List StringList { get; set; } = new List();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore;
2 | using Microsoft.AspNetCore.Hosting;
3 |
4 | namespace DataSimulation {
5 | public class Program {
6 | public static void Main(string[] args) {
7 | CreateWebHostBuilder(args).Build().Run();
8 | }
9 |
10 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
11 | WebHost.CreateDefaultBuilder(args)
12 | .UseUrls("https://[::]:33333")
13 | .UseStartup();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:10175",
8 | "sslPort": 44305
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "DataSimulation": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/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.HttpsPolicy;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace DataSimulation
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | // This method gets called by the runtime. Use this method to add services to the container.
26 | public void ConfigureServices(IServiceCollection services)
27 | {
28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
29 | }
30 |
31 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
32 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
33 | {
34 | if (env.IsDevelopment())
35 | {
36 | app.UseDeveloperExceptionPage();
37 | }
38 | else
39 | {
40 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
41 | app.UseHsts();
42 | }
43 |
44 | app.UseHttpsRedirection();
45 | app.UseMvc();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 15/DataSimulation/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/AggregatorDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/AggregatorDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregatorDemo", "AggregatorDemo.csproj", "{439847D7-B9EB-4554-9328-33AB83B6AE7D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {439847D7-B9EB-4554-9328-33AB83B6AE7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {439847D7-B9EB-4554-9328-33AB83B6AE7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {439847D7-B9EB-4554-9328-33AB83B6AE7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {439847D7-B9EB-4554-9328-33AB83B6AE7D}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {8B48890F-C730-4FF3-856C-7219860B8D33}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/Controllers/AggregatorController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace AggregatorDemo {
8 | [Route("api/[controller]")]
9 | [ApiController]
10 | public class AggregatorController : ControllerBase {
11 |
12 | private IDependentDataService _dependentService;
13 |
14 | public AggregatorController(IDependentDataService depSvc) {
15 | _dependentService = depSvc;
16 | }
17 |
18 | [HttpGet("data")]
19 | public async Task> Get() {
20 | return await _dependentService.GetDataResponse();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/Middleware/DependencyHealthCheck.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Diagnostics.HealthChecks;
2 | using System;
3 | using System.Diagnostics;
4 | using System.Net.Http;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace AggregatorDemo {
9 | public class DependencyHealthCheck : IHealthCheck {
10 | private readonly int DEGRADING_THRESHOLD = 2000;
11 | private readonly int UNHEALTHY_THRESHOLD = 5000;
12 |
13 | public async Task CheckHealthAsync(
14 | HealthCheckContext context,
15 | CancellationToken token = default(CancellationToken)
16 | ) {
17 | var httpClient = HttpClientFactory.Create();
18 | httpClient.BaseAddress = new Uri("https://localhost:33333");
19 | var request = new HttpRequestMessage(HttpMethod.Get, "/api/dependency/new-data");
20 | Stopwatch sw = Stopwatch.StartNew();
21 | var response = await httpClient.SendAsync(request);
22 | sw.Stop();
23 | var responseTime = sw.ElapsedMilliseconds;
24 | if (responseTime < DEGRADING_THRESHOLD) {
25 | return HealthCheckResult.Healthy("The dependent system is performing within acceptable parameters");
26 | } else if (responseTime < UNHEALTHY_THRESHOLD) {
27 | return HealthCheckResult.Degraded("The dependent system is degrading and likely to fail soon");
28 | } else {
29 | return HealthCheckResult.Unhealthy("The dependent system is unacceptably degraded. Restart.");
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/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 AggregatorDemo
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 | .UseUrls("https://[::]:44444")
23 | .UseStartup();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:61789",
8 | "sslPort": 44316
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "AggregatorDemo": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/Services/DependentDataService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Threading.Tasks;
6 |
7 | namespace AggregatorDemo {
8 |
9 | public interface IDependentDataService {
10 | Task GetDataResponse();
11 | }
12 |
13 | public class DependentDataService : IDependentDataService {
14 | private IHttpClientFactory _httpFactory;
15 |
16 | public DependentDataService(IHttpClientFactory factory) {
17 | _httpFactory = factory;
18 | }
19 |
20 | public async Task GetDataResponse() {
21 | var client = _httpFactory.CreateClient();
22 | client.BaseAddress = new Uri("https://localhost:33333");
23 |
24 | var request = new HttpRequestMessage(HttpMethod.Get, "/api/dependency/new-data");
25 |
26 | var response = await client.SendAsync(request);
27 |
28 | return await response.Content.ReadAsStringAsync();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/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.HttpsPolicy;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace AggregatorDemo
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | public void ConfigureServices(IServiceCollection services)
26 | {
27 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
28 | services.AddSingleton();
29 | services.AddHttpClient();
30 |
31 | services.AddHealthChecks()
32 | .AddCheck("DataDependencyCheck", new DependencyHealthCheck());
33 | }
34 |
35 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
36 | {
37 | if (env.IsDevelopment())
38 | {
39 | app.UseDeveloperExceptionPage();
40 | }
41 | else
42 | {
43 | app.UseHsts();
44 | }
45 | app.UseHealthChecks("/health");
46 | app.UseHttpsRedirection();
47 | app.UseMvc();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 16/AggregatorDemo/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/Controllers/DependencyController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | namespace DataAccessDemo {
6 | [Route("api/[controller]")]
7 | [ApiController]
8 | public class DependencyController : ControllerBase {
9 | [HttpGet("new-data")]
10 | public ActionResult GetDependentValue() {
11 | Thread.Sleep(Latency.GetLatency());
12 | return $"requested data: {new Random().Next() }";
13 | }
14 |
15 | [HttpGet("reset")]
16 | public ActionResult Reset() {
17 | Latency.ResetLatency();
18 | return "success";
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/DataAccessDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | InProcess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/DataAccessDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataAccessDemo", "DataAccessDemo.csproj", "{21C6C03C-78A4-44C5-AD37-B6C37BC1EEE5}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {21C6C03C-78A4-44C5-AD37-B6C37BC1EEE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {21C6C03C-78A4-44C5-AD37-B6C37BC1EEE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {21C6C03C-78A4-44C5-AD37-B6C37BC1EEE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {21C6C03C-78A4-44C5-AD37-B6C37BC1EEE5}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {27DF7008-3160-4E1B-B07D-0578BD271341}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/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 DataAccessDemo
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 | .UseUrls("https://[::]:33333")
23 | .UseStartup();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:35502",
8 | "sslPort": 44331
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "DataAccessDemo": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/Services/Latency.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace DataAccessDemo {
7 | public static class Latency {
8 | private static int initialLatency = 1;
9 | private static int counter = 1;
10 |
11 | public static int GetLatency() {
12 | //milliseconds of latency. increase by .5 second per request
13 | return counter++ * 500;
14 | }
15 |
16 | public static void ResetLatency() {
17 | counter = initialLatency;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/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.HttpsPolicy;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace DataAccessDemo
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | // This method gets called by the runtime. Use this method to add services to the container.
26 | public void ConfigureServices(IServiceCollection services)
27 | {
28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
29 | }
30 |
31 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
32 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
33 | {
34 | if (env.IsDevelopment())
35 | {
36 | app.UseDeveloperExceptionPage();
37 | }
38 | else
39 | {
40 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
41 | app.UseHsts();
42 | }
43 |
44 | app.UseHttpsRedirection();
45 | app.UseMvc();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 16/DataAccessDemo/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 16/WatchdogDemo/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Http;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace WatchdogDemo {
7 | public class Program {
8 | private static readonly HttpClient client = new HttpClient();
9 | private static readonly string HEALTHY_STATUS = "Healthy";
10 |
11 | static async Task Main(string[] args) {
12 | while (true) {
13 | var healthRequest = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44444/health");
14 | var healthResponse = await client.SendAsync(healthRequest);
15 | var healthStatus = await healthResponse.Content.ReadAsStringAsync();
16 |
17 | if (healthStatus != HEALTHY_STATUS) {
18 | Console.WriteLine($"{ DateTime.Now.ToLocalTime().ToLongTimeString()} : Unhealthy API. Restarting Dependency");
19 | var resetRequest = new HttpRequestMessage(HttpMethod.Get, "https://localhost:33333/api/dependency/reset");
20 | var resetResponse = await client.SendAsync(resetRequest);
21 | } else {
22 | Console.WriteLine($"{DateTime.Now.ToLocalTime().ToLongTimeString()} : Healthy API");
23 | }
24 | Thread.Sleep(15000);
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Chapter 16/WatchdogDemo/WatchdogDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Chapter 16/WatchdogDemo/WatchdogDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchdogDemo", "WatchdogDemo.csproj", "{E8E80AFC-251D-491F-A949-137EC341F7F7}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {E8E80AFC-251D-491F-A949-137EC341F7F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {E8E80AFC-251D-491F-A949-137EC341F7F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {E8E80AFC-251D-491F-A949-137EC341F7F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {E8E80AFC-251D-491F-A949-137EC341F7F7}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {8B9948C3-3AC2-449E-A479-4A66FBB1E9D4}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/CustomProtocolDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/CustomProtocolDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomProtocolDemo", "CustomProtocolDemo.csproj", "{C5818222-E205-4714-8477-0C405C7B5C4C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {C5818222-E205-4714-8477-0C405C7B5C4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {C5818222-E205-4714-8477-0C405C7B5C4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {C5818222-E205-4714-8477-0C405C7B5C4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {C5818222-E205-4714-8477-0C405C7B5C4C}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {549AD4CE-7B19-48A9-9904-ABD3E204337B}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Threading.Tasks;
4 |
5 | namespace CustomProtocolDemo
6 | {
7 | public class Program
8 | {
9 | static async Task Main(string[] args)
10 | {
11 | WebRequest.RegisterPrefix("dtrj", new RockWebRequestCreator());
12 |
13 | Console.WriteLine("Hello World!");
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/RockStatus.cs:
--------------------------------------------------------------------------------
1 | namespace CustomProtocolDemo {
2 | public enum RockStatus {
3 | SUCCESS,
4 | PARTIAL,
5 | FAILURE
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/RockVerb.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace CustomProtocolDemo {
6 | public enum RockVerb {
7 | Delete = 0b000000000000000000000000,
8 | Insert = 0b010000000000000000000000,
9 | Update = 0b100000000000000000000000
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/WebServices/RockWebRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.IO;
7 | using System.Security.Cryptography;
8 | using System.Net.Sockets;
9 |
10 | namespace CustomProtocolDemo {
11 | public class RockWebRequest : WebRequest {
12 | public override Uri RequestUri { get; }
13 | public RockVerb Verb { get; set; } = RockVerb.Update;
14 | public IEnumerable Records { get; set; }
15 | public long Fields { get; set; }
16 |
17 |
18 | public RockWebRequest(Uri uri) {
19 | RequestUri = uri;
20 | }
21 |
22 | public override WebResponse GetResponse() {
23 | var messageString = ConcatenateRecords();
24 | var message = Encoding.ASCII.GetBytes(messageString);
25 | var checksum = SHA256.Create().ComputeHash(message);
26 |
27 | var byteList = new List();
28 | byteList.AddRange(GetHeaderBytes(message.Length));
29 | byteList.AddRange(checksum);
30 | byteList.AddRange(message);
31 | TcpClient client = new TcpClient(RequestUri.Host, RequestUri.Port);
32 | var stream = client.GetStream();
33 | stream.Write(byteList.ToArray(), 0, byteList.Count);
34 | return new RockWebResponse(stream);
35 | }
36 |
37 | private string ConcatenateRecords() {
38 | StringBuilder messageBuilder = new StringBuilder();
39 | foreach (var record in Records) {
40 | if (messageBuilder.ToString().Length > 0) {
41 | messageBuilder.Append(Environment.NewLine);
42 | }
43 | messageBuilder.Append(record);
44 | }
45 | return messageBuilder.ToString();
46 | }
47 |
48 | private IEnumerable GetHeaderBytes(int messageSize) {
49 | var headerBytes = new List();
50 | int verbAndSize = (int)Verb | (messageSize >> 2);
51 | headerBytes.AddRange(BitConverter.GetBytes(verbAndSize));
52 |
53 | //Add empty byte padding in the FIELDS header
54 | for (var i = 0; i < 20; i++) {
55 | headerBytes.Add(0b00000000);
56 | }
57 |
58 | headerBytes.AddRange(BitConverter.GetBytes(Fields));
59 | return headerBytes;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/WebServices/RockWebRequestCreator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 |
4 |
5 | namespace CustomProtocolDemo {
6 | public class RockWebRequestCreator : IWebRequestCreate {
7 | public WebRequest Create(Uri uri) {
8 | return new RockWebRequest(uri);
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/Chapter 17/CustomProtocolDemo/WebServices/RockWebResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.IO;
4 |
5 | namespace CustomProtocolDemo {
6 | public class RockWebResponse : WebResponse {
7 | private Stream _responseStream { get; set; }
8 | public DateTime TimeStamp { get; set; }
9 | public RockStatus Status { get; set; }
10 | public int Size { get; set; }
11 |
12 | public RockWebResponse(Stream responseStream) {
13 | _responseStream = responseStream;
14 |
15 | byte[] header = new byte[4];
16 | _responseStream.Read(header, 0, 4);
17 | var isValid = ValidateHeaders(header);
18 | }
19 |
20 | public Stream GetResponseStream() {
21 | return _responseStream;
22 | }
23 |
24 | private bool ValidateHeaders(byte[] header) {
25 | return true;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Chapter 18/NetworkAnalysisDemo/NetworkAnalysisDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Chapter 18/NetworkAnalysisDemo/NetworkAnalysisDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetworkAnalysisDemo", "NetworkAnalysisDemo.csproj", "{D9553DC4-F27A-4350-AF72-E3E594A19B23}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {D9553DC4-F27A-4350-AF72-E3E594A19B23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {D9553DC4-F27A-4350-AF72-E3E594A19B23}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {D9553DC4-F27A-4350-AF72-E3E594A19B23}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {D9553DC4-F27A-4350-AF72-E3E594A19B23}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {B2C219FF-396E-403C-A8E5-69AB2DBD4D8E}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 18/NetworkAnalysisDemo/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Collections.Generic;
4 | using System.Net.NetworkInformation;
5 |
6 | namespace NetworkAnalysisDemo {
7 | class Program {
8 | static void Main(string[] args) {
9 | DisplayDeviceInformation();
10 | Console.ReadLine();
11 | DisplayActiveTcpConnections();
12 | Console.ReadLine();
13 | DisplayIPv4TrafficStatistics();
14 | Console.ReadLine();
15 | Thread.Sleep(20000);
16 | }
17 |
18 | private static void DisplayDeviceInformation() {
19 | var adapters = NetworkInterface.GetAllNetworkInterfaces();
20 | Console.WriteLine($"There were {adapters.Length} devices detected on your machine");
21 | Console.WriteLine();
22 | Console.WriteLine("Device Details");
23 | foreach (NetworkInterface adapter in adapters) {
24 | Console.WriteLine("=========================================================================");
25 | Console.WriteLine();
26 | Console.WriteLine($"Device ID: ----------------- {adapter.Id}");
27 | Console.WriteLine($"Device Name: --------------- {adapter.Name}");
28 | Console.WriteLine($"Description: --------------- {adapter.Description}");
29 | Console.WriteLine($"Interface type: ------------ {adapter.NetworkInterfaceType}");
30 | Console.WriteLine($"Physical Address: ---------- {adapter.GetPhysicalAddress().ToString()}");
31 | Console.WriteLine($"Operational status: -------- {adapter.OperationalStatus}");
32 | Console.WriteLine($"Adapter Speed: ------------- {adapter.Speed}");
33 | Console.WriteLine($"Multicast Support: --------- {adapter.SupportsMulticast}");
34 | }
35 |
36 | }
37 |
38 | private static void DisplayActiveTcpConnections() {
39 | var ipStats = IPGlobalProperties.GetIPGlobalProperties();
40 | var tcpConnections = ipStats.GetActiveTcpConnections();
41 |
42 | Console.WriteLine($"There are currently {tcpConnections.Length} active TCP connections on this machine");
43 | Console.WriteLine();
44 |
45 | foreach (var connection in tcpConnections) {
46 | Console.WriteLine("=============================================");
47 | Console.WriteLine($"Local host:");
48 | Console.WriteLine($" Connected On Address: {connection.LocalEndPoint.Address.ToString()}");
49 | Console.WriteLine($" Over Port Number: {connection.LocalEndPoint.Port}");
50 | Console.WriteLine($"Remote host: {connection.RemoteEndPoint.Address}");
51 | Console.WriteLine($" Connected On Address: {connection.RemoteEndPoint.Address.ToString()}");
52 | Console.WriteLine($" Over Port Number: {connection.RemoteEndPoint.Port}");
53 | Console.WriteLine($"Connection State: {connection.State.ToString()}");
54 | }
55 | }
56 |
57 | private static void DisplayIPv4TrafficStatistics() {
58 | var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
59 | var ipStats = ipProperties.GetIPv4GlobalStatistics();
60 | Console.WriteLine($"Incoming Packets: {ipStats.ReceivedPackets}");
61 | Console.WriteLine($"Outgoing Packets: {ipStats.OutputPacketRequests}");
62 | Console.WriteLine($"Discareded Incoming Packets: {ipStats.ReceivedPacketsDiscarded}");
63 | Console.WriteLine($"Discarded Outgoing Packets: {ipStats.OutputPacketsDiscarded}");
64 | Console.WriteLine($"Fragmentation Failures: {ipStats.PacketFragmentFailures}");
65 | Console.WriteLine($"Reassembly Failures: {ipStats.PacketReassemblyFailures}");
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Chapter 19/SshDemo/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Renci.SshNet;
5 |
6 | namespace SshDemo {
7 | class Program {
8 | public static async Task Main(string[] args) {
9 | AuthenticationMethod method = new PasswordAuthenticationMethod("tuxbox", "fiddlesticks");
10 | ConnectionInfo connection = new ConnectionInfo("127.0.0.1", "tuxbox", method);
11 | var client = new SshClient(connection);
12 | if (!client.IsConnected) {
13 | Console.WriteLine("We're connected!");
14 | client.Connect();
15 | }
16 | var readCommand = client.RunCommand("uname -mrs");
17 | Console.WriteLine(readCommand.Result);
18 | var writeCommand = client.RunCommand("mkdir \"/home/tuxbox/Desktop/ssh_output\"");
19 | Thread.Sleep(10000);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Chapter 19/SshDemo/SshDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter 19/SshDemo/SshDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SshDemo", "SshDemo.csproj", "{158EA10A-6480-4938-B218-AAB4347AF812}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {158EA10A-6480-4938-B218-AAB4347AF812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {158EA10A-6480-4938-B218-AAB4347AF812}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {158EA10A-6480-4938-B218-AAB4347AF812}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {158EA10A-6480-4938-B218-AAB4347AF812}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {A63D7C14-77D7-4B17-B8EF-2105AD7B2419}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 2/Dns_Samples/DnsTest/DnsTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Chapter 2/Dns_Samples/DnsTest/DnsTestProgram.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Threading;
4 |
5 | namespace DnsTest
6 | {
7 | class DnsTestProgram {
8 | static void Main(string[] args) {
9 | var domainEntry = Dns.GetHostEntry("fun.with.dns.com");
10 | Console.WriteLine(domainEntry.HostName);
11 | foreach (var ip in domainEntry.AddressList) {
12 | Console.WriteLine(ip);
13 | }
14 |
15 | var domainEntryByAddress = Dns.GetHostEntry("127.0.0.1");
16 | Console.WriteLine(domainEntryByAddress.HostName);
17 | foreach (var ip in domainEntryByAddress.AddressList) {
18 | Console.WriteLine(ip);
19 | }
20 | Thread.Sleep(10000);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Chapter 2/Dns_Samples/Dns_Samples.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UriTest", "Dns_Samples\UriTest.csproj", "{832015B9-30C4-4DB4-8320-54D15289CFFF}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DnsTest", "DnsTest\DnsTest.csproj", "{65628F40-5A4C-4E5A-9571-C95F81101C1F}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {832015B9-30C4-4DB4-8320-54D15289CFFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {832015B9-30C4-4DB4-8320-54D15289CFFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {832015B9-30C4-4DB4-8320-54D15289CFFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {832015B9-30C4-4DB4-8320-54D15289CFFF}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {65628F40-5A4C-4E5A-9571-C95F81101C1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {65628F40-5A4C-4E5A-9571-C95F81101C1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {65628F40-5A4C-4E5A-9571-C95F81101C1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {65628F40-5A4C-4E5A-9571-C95F81101C1F}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {85A0A341-32CE-4A50-B761-5F48CC45D181}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/Chapter 2/Dns_Samples/UriTest/UriTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Chapter 2/Dns_Samples/UriTest/UriTest.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UriTest", "UriTest.csproj", "{0ADE0AD2-3B53-4A56-9AB3-E6FB081209DC}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {0ADE0AD2-3B53-4A56-9AB3-E6FB081209DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {0ADE0AD2-3B53-4A56-9AB3-E6FB081209DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {0ADE0AD2-3B53-4A56-9AB3-E6FB081209DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {0ADE0AD2-3B53-4A56-9AB3-E6FB081209DC}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {1F2315EF-F77C-4E7F-BF6A-8D5A75DF18CA}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 2/Dns_Samples/UriTest/UriTestProgram.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace UriTest
5 | {
6 | public class UriTestProgram
7 | {
8 | public static Uri GetSimpleUri() {
9 | var builder = new UriBuilder();
10 | builder.Scheme = "http";
11 | builder.Host = "packt.com";
12 | return builder.Uri;
13 | }
14 |
15 | public static Uri GetSimpleUri_Constructor() {
16 | var builder = new UriBuilder("http", "packt.com");
17 | return builder.Uri;
18 | }
19 |
20 | public static void Main(string[] args)
21 | {
22 | var simpleUri = GetSimpleUri();
23 | Console.WriteLine(simpleUri.ToString());
24 | // Expected output: http://packt.com
25 |
26 | var constructorUri = GetSimpleUri_Constructor();
27 | Console.WriteLine(constructorUri.ToString());
28 | // Expected output: http://packt.com
29 |
30 | Thread.Sleep(10000);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Chapter 5/WebRequest_Samples/WebRequest_Samples.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebRequest_Samples", "WebRequest_Samples\WebRequest_Samples.csproj", "{55CEEFE9-6F56-4733-9A20-3688B48FDBF7}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {55CEEFE9-6F56-4733-9A20-3688B48FDBF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {55CEEFE9-6F56-4733-9A20-3688B48FDBF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {55CEEFE9-6F56-4733-9A20-3688B48FDBF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {55CEEFE9-6F56-4733-9A20-3688B48FDBF7}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {9B857E4A-0011-4BDF-8D8C-6E362E241974}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 5/WebRequest_Samples/WebRequest_Samples/RequestService.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using System.IO;
3 | using System.Net;
4 | using System.Net.Cache;
5 | using System.Net.Security;
6 |
7 | namespace WebRequest_Samples
8 | {
9 | public class RequestService
10 | {
11 | private static readonly string FINANCE_CONN_GROUP = "financial_connection";
12 | private static readonly string REAL_ESTATE_CONN_GROUP = "real_estate_connection";
13 |
14 | public static void Main(string[] argsa) {
15 | SubmitRealEstateRequest();
16 | }
17 |
18 | public static void SubmitRealEstateRequest()
19 | {
20 | WebRequest req = WebRequest.Create("https://real-estate-detail.com/market/api");
21 | req.ConnectionGroupName = REAL_ESTATE_CONN_GROUP;
22 | var noCachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
23 | req.CachePolicy = noCachePolicy;
24 | req.AuthenticationLevel = AuthenticationLevel.MutualAuthRequired;
25 | req.Credentials = new NetworkCredential("test_user", "secure_and_safe_password");
26 | Stream reqStream = req.GetRequestStream();
27 | var messageString = "test";
28 | var messageBytes = Encoding.UTF8.GetBytes(messageString);
29 | reqStream.Write(messageBytes, 0, messageBytes.Length);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Chapter 5/WebRequest_Samples/WebRequest_Samples/WebRequest_Samples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.0
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Chapter 6/StreamsAndAsync/StreamsAndAsync.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StreamsAndAsync", "StreamsAndAsync\StreamsAndAsync.csproj", "{58F56003-4201-41B6-9BC7-7CDFFCBCBD79}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {58F56003-4201-41B6-9BC7-7CDFFCBCBD79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {58F56003-4201-41B6-9BC7-7CDFFCBCBD79}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {58F56003-4201-41B6-9BC7-7CDFFCBCBD79}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {58F56003-4201-41B6-9BC7-7CDFFCBCBD79}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {585AA4E8-799B-4B7B-A61D-7638362C6785}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 6/StreamsAndAsync/StreamsAndAsync/ComplexModels.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace StreamsAndAsync {
5 | public class ComplexModel {
6 | public string ComplexModelId { get; set; } = Guid.NewGuid().ToString();
7 | public int NumberDemonstration { get; set; } = 12354;
8 | public InnerModel smallInnerModel { get; set; }
9 | public List listOfInnerModels { get; set; } = new List() {
10 | new InnerModel(),
11 | new InnerModel()
12 | };
13 | }
14 |
15 | public class InnerModel {
16 | public string randomId { get; set; } = Guid.NewGuid().ToString();
17 | public string nonRandomString { get; set; } = "I wrote this here.";
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Chapter 6/StreamsAndAsync/StreamsAndAsync/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Threading;
4 | using Newtonsoft.Json;
5 | using System.Threading.Tasks;
6 | using System.Net;
7 |
8 | namespace StreamsAndAsync {
9 |
10 |
11 | public class Program {
12 |
13 | public static void Main(string[] args) {
14 | var res = AsyncMethodDemo().Result;
15 | ComplexModel testModel = new ComplexModel();
16 | string testMessage = JsonConvert.SerializeObject(testModel);
17 |
18 | using (Stream ioStream = new FileStream(@"../stream_demo_file.txt", FileMode.OpenOrCreate)) {
19 | using (StreamWriter sw = new StreamWriter(ioStream)) {
20 | sw.Write(testMessage);
21 | sw.BaseStream.Seek(10, SeekOrigin.Begin);
22 | sw.Write(testMessage);
23 | }
24 | }
25 |
26 | Console.WriteLine("Done!");
27 | Thread.Sleep(10000);
28 | }
29 |
30 | public static async Task AsyncMethodDemo() {
31 | ResultObject result = new ResultObject();
32 | WebRequest request = WebRequest.Create("http://you.com");
33 | request.Method = "POST";
34 | Stream reqStream = request.GetRequestStream();
35 |
36 | using (StreamWriter sw = new StreamWriter(reqStream)) {
37 | sw.Write("Our test data query");
38 | }
39 | var responseTask = request.GetResponseAsync();
40 |
41 | result.LocalResult = 27;
42 | var webResponse = await responseTask;
43 |
44 | using (StreamReader sr = new StreamReader(webResponse.GetResponseStream())) {
45 | result.RequestResult = await sr.ReadToEndAsync();
46 | }
47 |
48 | return result;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Chapter 6/StreamsAndAsync/StreamsAndAsync/ResultObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace StreamsAndAsync {
6 | public class ResultObject {
7 | public object LocalResult { get; set; }
8 | public object RequestResult { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Chapter 6/StreamsAndAsync/StreamsAndAsync/StreamsAndAsync.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 7/ErrorHandling/AsyncDemo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using System.IO;
4 | using System.Net;
5 |
6 | namespace ErrorHandling {
7 | public static class AsyncDemo {
8 | public static async Task AsyncMethodDemo() {
9 | ResultObject result = new ResultObject();
10 | WebRequest request = WebRequest.Create("http://test-domain.com");
11 | request.Method = "POST";
12 | Stream reqStream = request.GetRequestStream();
13 |
14 | using (StreamWriter sw = new StreamWriter(reqStream)) {
15 | sw.Write("Our test data query");
16 | }
17 | var responseTask = request.GetResponseAsync();
18 |
19 | result.LocalResult = 27;
20 | try {
21 | var webResponse = await responseTask;
22 |
23 | using (StreamReader sr = new StreamReader(webResponse.GetResponseStream())) {
24 | result.RequestResult = await sr.ReadToEndAsync();
25 | }
26 | } catch (WebException ex) {
27 | ProcessException(ex);
28 | }
29 |
30 | return result;
31 | }
32 |
33 | private static void ProcessException(WebException ex) {
34 | switch (ex.Status) {
35 | case WebExceptionStatus.ConnectFailure:
36 | case WebExceptionStatus.ConnectionClosed:
37 | case WebExceptionStatus.RequestCanceled:
38 | case WebExceptionStatus.PipelineFailure:
39 | case WebExceptionStatus.SendFailure:
40 | case WebExceptionStatus.KeepAliveFailure:
41 | case WebExceptionStatus.Timeout:
42 | Console.WriteLine("We should retry connection attempts");
43 | break;
44 | case WebExceptionStatus.NameResolutionFailure:
45 | case WebExceptionStatus.ProxyNameResolutionFailure:
46 | case WebExceptionStatus.ServerProtocolViolation:
47 | Console.WriteLine("Prevent further attempts and notify consumers to check URL configurations");
48 | break;
49 | case WebExceptionStatus.SecureChannelFailure:
50 | case WebExceptionStatus.TrustFailure:
51 | Console.WriteLine("Authentication or security issue. Prompt for credentials and perhaps try again");
52 | break;
53 |
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chapter 7/ErrorHandling/ErrorHandling.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 | latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Chapter 7/ErrorHandling/ErrorHandling.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ErrorHandling", "ErrorHandling.csproj", "{EF3FDDCA-E39C-4B5E-A48D-31D06E798FA3}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {EF3FDDCA-E39C-4B5E-A48D-31D06E798FA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {EF3FDDCA-E39C-4B5E-A48D-31D06E798FA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {EF3FDDCA-E39C-4B5E-A48D-31D06E798FA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {EF3FDDCA-E39C-4B5E-A48D-31D06E798FA3}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {7FEA167E-ADA5-4894-A4CE-BAE9D92F49DC}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 7/ErrorHandling/PollyDemo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Http;
4 | using System.Collections.Generic;
5 | using Polly;
6 |
7 | namespace ErrorHandling {
8 | public static class PollyDemo {
9 | private static List connectionFailure = new List() {
10 | WebExceptionStatus.ConnectFailure,
11 | WebExceptionStatus.ConnectionClosed,
12 | WebExceptionStatus.RequestCanceled,
13 | WebExceptionStatus.PipelineFailure,
14 | WebExceptionStatus.SendFailure,
15 | WebExceptionStatus.KeepAliveFailure,
16 | WebExceptionStatus.Timeout
17 | };
18 |
19 | private static List resourceAccessFailure = new List() {
20 | WebExceptionStatus.NameResolutionFailure,
21 | WebExceptionStatus.ProxyNameResolutionFailure,
22 | WebExceptionStatus.ServerProtocolViolation
23 | };
24 |
25 | private static List securityFailure = new List() {
26 | WebExceptionStatus.SecureChannelFailure,
27 | WebExceptionStatus.TrustFailure
28 | };
29 |
30 | public static HttpResponseMessage ExecuteRemoteLookup() {
31 | var num = new Random().Next();
32 | if (num % 3 == 0) {
33 | Console.WriteLine("Breaking the circuit");
34 | throw new WebException("Name Resolution Failure", WebExceptionStatus.NameResolutionFailure);
35 | } else if (num % 4 == 0) {
36 | Console.WriteLine("Falling Back");
37 | throw new WebException("Security Failure", WebExceptionStatus.TrustFailure);
38 | } else if (num % 2 == 0) {
39 | Console.WriteLine("Retrying connections...");
40 | throw new WebException("Connection Failure", WebExceptionStatus.ConnectFailure);
41 | }
42 | return new HttpResponseMessage();
43 | }
44 |
45 | private static HttpResponseMessage GetAuthorizationErrorResponse() {
46 | return new HttpResponseMessage(HttpStatusCode.Unauthorized);
47 | }
48 |
49 | public static void ExecuteRemoteLookupWithPolly() {
50 | Policy connFailurePolicy = Policy
51 | .Handle(x => connectionFailure.Contains(x.Status))
52 | .RetryForever();
53 |
54 | Policy authFailurePolicy = Policy
55 | .Handle(x => securityFailure.Contains(x.Status))
56 | .Fallback(() => GetAuthorizationErrorResponse());
57 |
58 | Policy nameResolutionPolicy = Policy
59 | .Handle(x => resourceAccessFailure.Contains(x.Status))
60 | .CircuitBreaker(1, TimeSpan.FromMinutes(2));
61 |
62 | Policy intermediatePolicy = Policy
63 | .Wrap(connFailurePolicy, nameResolutionPolicy);
64 |
65 | Policy combinedPolicies = intermediatePolicy
66 | .Wrap(authFailurePolicy);
67 |
68 | try {
69 | HttpResponseMessage resp = combinedPolicies.Execute(() => ExecuteRemoteLookup());
70 | if (resp.IsSuccessStatusCode) {
71 | Console.WriteLine("Success!");
72 | } else if (resp.StatusCode.Equals(HttpStatusCode.Unauthorized)) {
73 | Console.WriteLine("We have fallen back!");
74 | }
75 | } catch (WebException ex) {
76 | if (resourceAccessFailure.Contains(ex.Status)) {
77 | Console.WriteLine("We should expect to see a broken circuit.");
78 | }
79 | }
80 | }
81 |
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Chapter 7/ErrorHandling/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 |
5 | namespace ErrorHandling {
6 | public class Program {
7 | public static async Task Main(string[] args) {
8 | var test = await AsyncDemo.AsyncMethodDemo();
9 | for (var i = 0; i < 24; i++) {
10 | Console.WriteLine($"Polly Demo Attempt {i}");
11 | Console.WriteLine("-------------");
12 | PollyDemo.ExecuteRemoteLookupWithPolly();
13 | Console.WriteLine("-------------");
14 | Thread.Sleep(5000);
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Chapter 7/ErrorHandling/ResultObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace ErrorHandling {
6 | public class ResultObject {
7 | public object LocalResult { get; set; }
8 | public object RequestResult { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/Controllers/ValuesController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace SampleApp.Controllers
8 | {
9 | [Route("api/[controller]")]
10 | [ApiController]
11 | public class ValuesController : ControllerBase
12 | {
13 | // GET api/values
14 | [HttpGet]
15 | public ActionResult> Get()
16 | {
17 | return new string[] { "value1", "value2" };
18 | }
19 |
20 | // GET api/values/5
21 | [HttpGet("{id}")]
22 | public ActionResult Get(int id)
23 | {
24 | return "value";
25 | }
26 |
27 | // POST api/values
28 | [HttpPost]
29 | public void Post([FromBody] string value)
30 | {
31 | }
32 |
33 | // PUT api/values/5
34 | [HttpPut("{id}")]
35 | public void Put(int id, [FromBody] string value)
36 | {
37 | }
38 |
39 | // DELETE api/values/5
40 | [HttpDelete("{id}")]
41 | public void Delete(int id)
42 | {
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/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 SampleApp
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 |
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:25670",
8 | "sslPort": 44381
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "SampleApp": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/SampleApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | inprocess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/SampleApp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "SampleApp.csproj", "{6085FAB0-D050-46F1-B811-FF55FCD532FD}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {6085FAB0-D050-46F1-B811-FF55FCD532FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {6085FAB0-D050-46F1-B811-FF55FCD532FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {6085FAB0-D050-46F1-B811-FF55FCD532FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {6085FAB0-D050-46F1-B811-FF55FCD532FD}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {54490EC7-4D51-4E3D-A3A2-AD5969FC726C}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/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.HttpsPolicy;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace SampleApp
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | // This method gets called by the runtime. Use this method to add services to the container.
26 | public void ConfigureServices(IServiceCollection services)
27 | {
28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
29 | }
30 |
31 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
32 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
33 | {
34 | if (env.IsDevelopment())
35 | {
36 | app.UseDeveloperExceptionPage();
37 | }
38 | else
39 | {
40 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
41 | app.UseHsts();
42 | }
43 | app.UseMvc();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 8/SampleApp/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 8/SocketsAndPorts/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Net;
4 | using System.Net.Sockets;
5 | using System.Threading;
6 |
7 | namespace SocketsAndPorts {
8 | class Program {
9 | static void Main(string[] args) {
10 | string server = "localhost";
11 | int port = 5000;
12 | string path = "/api/values";
13 |
14 | Socket socket = null;
15 | IPEndPoint endpoint = null;
16 | var host = Dns.GetHostEntry(server);
17 |
18 | foreach (var address in host.AddressList) {
19 | socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
20 | endpoint = new IPEndPoint(address, port);
21 | socket.ConnectAsync(endpoint).Wait();
22 | if (socket.Connected) {
23 | break;
24 | }
25 | }
26 |
27 | var message = GetRequestMessage(server, port, path);
28 | var messageBytes = Encoding.ASCII.GetBytes(message);
29 | var segment = new ArraySegment(messageBytes);
30 |
31 | socket.SendAsync(segment, SocketFlags.None).Wait();
32 |
33 | var receiveSeg = new ArraySegment(new byte[512], 0, 512);
34 |
35 | socket.ReceiveAsync(receiveSeg, SocketFlags.None).Wait();
36 |
37 | string receivedMessage = Encoding.ASCII.GetString(receiveSeg);
38 |
39 | foreach (var line in receivedMessage.Split("\r\n")) {
40 | Console.WriteLine(line);
41 | }
42 |
43 | socket.Disconnect(false);
44 | socket.Dispose();
45 | Thread.Sleep(10000);
46 | }
47 |
48 | private static string GetRequestMessage(string server, int port, string path) {
49 | var message = $"GET {path} HTTP/1.1\r\n";
50 | message += $"Host: {server}:{port}\r\n";
51 | message += "cache-control: no-cache\r\n";
52 | message += "\r\n";
53 | return message;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Chapter 8/SocketsAndPorts/SocketsAndPorts.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.2
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Chapter 8/SocketsAndPorts/SocketsAndPorts.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocketsAndPorts", "SocketsAndPorts.csproj", "{4674BE54-6B22-4265-AD21-14E5FA177199}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {4674BE54-6B22-4265-AD21-14E5FA177199}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {4674BE54-6B22-4265-AD21-14E5FA177199}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {4674BE54-6B22-4265-AD21-14E5FA177199}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {4674BE54-6B22-4265-AD21-14E5FA177199}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {A4037AFC-F770-4B04-B3A1-E5D89012A86B}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/Controllers/FitnessController.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 | using System;
7 |
8 | namespace FitnessApp {
9 | [Route("api/fitness-app")]
10 | [ApiController]
11 | public class FitnessController : ControllerBase {
12 | private readonly IDataStoreClient _dataStore;
13 |
14 | public FitnessController(IDataStoreClient data) {
15 | _dataStore = data;
16 | }
17 |
18 | [HttpGet]
19 | public async Task>> Get() {
20 | return await _dataStore.GetAllRecords();
21 | }
22 |
23 | [HttpGet("{title}")]
24 | public async Task> GetRecord(string title) {
25 | return await _dataStore.GetRecordByTitle(title);
26 | }
27 |
28 | [HttpGet("type/{type}")]
29 | public async Task>> GetRecordsByType(string type) {
30 | return await _dataStore.GetRecordsByWorkoutType(type);
31 | }
32 |
33 | [HttpPost]
34 | public async Task NewRecord([FromBody] FitnessRecord newRecord) {
35 | if (await _dataStore.WriteRecord(newRecord)) {
36 | return Ok("new record successfully written");
37 | }
38 | return StatusCode(400);
39 | }
40 |
41 | [HttpPatch("{title}/comments")]
42 | public async Task UpdateComment(string title, [FromBody] string newComments) {
43 | if (await _dataStore.UpdateRecord(title, newComments)) {
44 | return Ok("record successfully updated");
45 | }
46 | return StatusCode(400);
47 | }
48 |
49 | [HttpDelete("{title}")]
50 | public async Task Delete(string title) {
51 | if (await _dataStore.DeleteRecord(title)) {
52 | return Ok("record successfully deleted");
53 | }
54 | return StatusCode(400);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/FitnessApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | inprocess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/FitnessApp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FitnessApp", "FitnessApp.csproj", "{10AC53F8-4A2A-4A1B-A42A-661866112344}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {10AC53F8-4A2A-4A1B-A42A-661866112344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {10AC53F8-4A2A-4A1B-A42A-661866112344}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {10AC53F8-4A2A-4A1B-A42A-661866112344}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {10AC53F8-4A2A-4A1B-A42A-661866112344}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {927045FB-D2EB-4ABB-A4D8-83093424C20F}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/Models/FitnessRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace FitnessApp {
7 | public class FitnessRecord {
8 | public string title { get; set; }
9 | public string workoutType { get; set; }
10 | public string comments { get; set; }
11 | public DateTime workoutDate { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Microsoft.AspNetCore;
8 | using Microsoft.AspNetCore.Hosting;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.Logging;
11 |
12 | namespace FitnessApp
13 | {
14 | public class Program
15 | {
16 | public static void Main(string[] args)
17 | {
18 | CreateWebHostBuilder(args).Build().Run();
19 | }
20 |
21 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
22 | WebHost.CreateDefaultBuilder(args)
23 | .UseUrls(new string[] { "http://[::]:80", "https://[::]:443", "http://[::]:65432", "https://[::]:65431" })
24 | .UseStartup();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:14489",
8 | "sslPort": 44335
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "FitnessApp": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/Services/FitnessDataStoreClient.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Net.Http;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using Newtonsoft.Json;
6 |
7 | namespace FitnessApp {
8 | public interface IDataStoreClient {
9 | Task WriteRecord(FitnessRecord newRecord);
10 | Task> GetAllRecords();
11 | Task> GetRecordsByWorkoutType(string workoutType);
12 | Task GetRecordByTitle(string title);
13 | Task UpdateRecord(string title, string newComment);
14 | Task DeleteRecord(string title);
15 | }
16 |
17 | public class FitnessDataStoreClient : IDataStoreClient {
18 | private readonly IHttpClientFactory _httpFactory;
19 |
20 | public FitnessDataStoreClient(IHttpClientFactory httpFactoryInstance) {
21 | _httpFactory = httpFactoryInstance;
22 | }
23 |
24 | public async Task WriteRecord(FitnessRecord newRecord) {
25 | var client = _httpFactory.CreateClient("WRITER");
26 |
27 | HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, "/api/fitness-data");
28 | var requestJson = JsonConvert.SerializeObject(newRecord);
29 | message.Content = new StringContent(requestJson, Encoding.UTF8, "application/json");
30 |
31 | var response = await client.SendAsync(message);
32 | return response.IsSuccessStatusCode;
33 | }
34 |
35 | public async Task> GetAllRecords() {
36 | var client = _httpFactory.CreateClient("READER");
37 |
38 | HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, "/api/fitness-data");
39 |
40 | var response = await client.SendAsync(message);
41 |
42 | if (!response.IsSuccessStatusCode) {
43 | return new List();
44 | }
45 |
46 | var json = await response.Content.ReadAsStringAsync();
47 | var result = JsonConvert.DeserializeObject>(json);
48 | return result;
49 | }
50 |
51 | public async Task> GetRecordsByWorkoutType(string workoutType) {
52 | var client = _httpFactory.CreateClient("READER");
53 |
54 | HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, $"/api/fitness-data/type/{workoutType}");
55 |
56 | var response = await client.SendAsync(message);
57 |
58 | if (!response.IsSuccessStatusCode) {
59 | return new List();
60 | }
61 |
62 | var json = await response.Content.ReadAsStringAsync();
63 | var result = JsonConvert.DeserializeObject>(json);
64 | return result;
65 | }
66 |
67 | public async Task GetRecordByTitle(string title) {
68 | var client = _httpFactory.CreateClient("READER");
69 |
70 | HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, $"/api/fitness-data/{title}");
71 |
72 | var response = await client.SendAsync(message);
73 |
74 | if (!response.IsSuccessStatusCode) {
75 | return new FitnessRecord();
76 | }
77 |
78 | var json = await response.Content.ReadAsStringAsync();
79 | var result = JsonConvert.DeserializeObject(json);
80 | return result;
81 | }
82 |
83 | public async Task UpdateRecord(string title, string newComment) {
84 | var client = _httpFactory.CreateClient("WRITER");
85 |
86 | HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Patch, $"/api/fitness-data/{title}/comments");
87 | message.Content = new StringContent($"\"{newComment}\"", Encoding.UTF8, "application/json");
88 |
89 | var response = await client.SendAsync(message);
90 | return response.IsSuccessStatusCode;
91 | }
92 |
93 | public async Task DeleteRecord(string title) {
94 | var client = _httpFactory.CreateClient("WRITER");
95 |
96 | HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Delete, $"/api/fitness-data/{title}");
97 |
98 | var response = await client.SendAsync(message);
99 | return response.IsSuccessStatusCode;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/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.HttpsPolicy;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace FitnessApp {
15 | public class Startup {
16 | public Startup(IConfiguration configuration) {
17 | Configuration = configuration;
18 | }
19 |
20 | public IConfiguration Configuration { get; }
21 |
22 | // This method gets called by the runtime. Use this method to add services to the container.
23 | public void ConfigureServices(IServiceCollection services) {
24 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
25 | services.AddSingleton();
26 |
27 | services.AddHttpClient("WRITER", c => {
28 | c.BaseAddress = new Uri("http://fitness.write.data.com:56789");
29 | c.DefaultRequestHeaders.Add("Accept", "application/json");
30 | });
31 |
32 | services.AddHttpClient("READER", c => {
33 | c.BaseAddress = new Uri("http://fitness.read.data.com:56789");
34 | c.DefaultRequestHeaders.Add("Accept", "application/json");
35 | });
36 | }
37 |
38 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
39 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
40 | if (env.IsDevelopment()) {
41 | app.UseDeveloperExceptionPage();
42 | } else {
43 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
44 | app.UseHttpsRedirection();
45 | app.UseHsts();
46 | }
47 | app.UseMvc();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessApp/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/Controllers/FitnessController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace FitnessDataStore {
8 | [Route("api/fitness-data")]
9 | [ApiController]
10 | public class FitnessDataController : ControllerBase {
11 | private readonly IDataAccess _dataStore;
12 |
13 | public FitnessDataController(IDataAccess data) {
14 | _dataStore = data;
15 | }
16 |
17 | [HttpGet]
18 | public async Task>> Get() {
19 | return await _dataStore.GetAllRecords();
20 | }
21 |
22 | [HttpGet("{title}")]
23 | public async Task> GetRecord(string title) {
24 | return await _dataStore.GetRecordByTitle(title);
25 | }
26 |
27 | [HttpGet("type/{type}")]
28 | public async Task>> GetRecordsByType(string type) {
29 | return await _dataStore.GetRecordsByWorkoutType(type);
30 | }
31 |
32 | [HttpPost]
33 | public async Task NewRecord([FromBody] FitnessRecord newRecord) {
34 | if (await _dataStore.WriteRecord(newRecord)) {
35 | return Ok("new record successfully written");
36 | }
37 | return StatusCode(400);
38 | }
39 |
40 | [HttpPatch("{title}/comments")]
41 | public async Task Put(string title, [FromBody] string newComment) {
42 | if (await _dataStore.UpdateRecord(title, newComment)) {
43 | return Ok("record successfully updated");
44 | }
45 | return StatusCode(400);
46 | }
47 |
48 | [HttpDelete("{title}")]
49 | public async Task Delete(string title) {
50 | if (await _dataStore.DeleteRecord(title)) {
51 | return Ok("record successfully deleted");
52 | }
53 | return StatusCode(400);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/FitnessDataStore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 | inprocess
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/FitnessDataStore.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2048
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FitnessDataStore", "FitnessDataStore.csproj", "{02B1911B-7547-4EA8-968F-289DAAB3458F}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {02B1911B-7547-4EA8-968F-289DAAB3458F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {02B1911B-7547-4EA8-968F-289DAAB3458F}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {02B1911B-7547-4EA8-968F-289DAAB3458F}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {02B1911B-7547-4EA8-968F-289DAAB3458F}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {B8DEED56-DA73-4C3D-96BE-D3058C4C0EE0}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/Models/FitnessRecord.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace FitnessDataStore {
7 | public class FitnessRecord {
8 | public string title { get; set; }
9 | public string workoutType { get; set; }
10 | public string comments { get; set; }
11 | public DateTime workoutDate { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/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 FitnessDataStore
12 | {
13 | public class Program {
14 | public static void Main(string[] args) {
15 | CreateWebHostBuilder(args).Build().Run();
16 | }
17 |
18 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
19 | WebHost.CreateDefaultBuilder(args)
20 | .UseUrls(new string[] { "http://[::]:56789", "http://127.0.0.1:56789", "https://127.0.0.1:56780", "https://[::]:56780"})
21 | .UseStartup();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:36703",
8 | "sslPort": 44372
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "api/values",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "FitnessDataStore": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "api/values",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/Services/DataAccess.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Newtonsoft.Json;
8 |
9 | namespace FitnessDataStore {
10 | public interface IDataAccess {
11 | Task WriteRecord(FitnessRecord newRecord);
12 | Task> GetAllRecords();
13 | Task> GetRecordsByWorkoutType(string workoutType);
14 | Task GetRecordByTitle(string title);
15 | Task UpdateRecord(string title, string newComment);
16 | Task DeleteRecord(string title);
17 | }
18 |
19 | public class DataAccess : IDataAccess {
20 | private readonly string FILE_PATH = @"../fitness_data.txt";
21 |
22 | public async Task WriteRecord(FitnessRecord newRecord) {
23 | var records = await GetAllRecords();
24 | if (records.Where(x => x.title.ToUpper().Equals(newRecord.title.ToUpper())).Count() > 0) {
25 | return false;
26 | }
27 | using (StreamWriter sw = File.AppendText(FILE_PATH)) {
28 | var recordStr = JsonConvert.SerializeObject(newRecord);
29 | await sw.WriteLineAsync(recordStr);
30 | }
31 | return true;
32 | }
33 |
34 | public async Task> GetAllRecords() {
35 | List currentRecords = new List();
36 | if (!File.Exists(FILE_PATH)) {
37 | using (var file = File.Create(FILE_PATH)){
38 | //We only use this to create the file in the path if it doesn't exist.
39 | }
40 | }
41 | using (StreamReader sr = File.OpenText(FILE_PATH)) {
42 | while (!sr.EndOfStream) {
43 | var recordStr = await sr.ReadLineAsync();
44 | currentRecords.Add(JsonConvert.DeserializeObject(recordStr));
45 | }
46 | }
47 | return currentRecords;
48 | }
49 |
50 | public async Task> GetRecordsByWorkoutType(string workoutType) {
51 | var records = await GetAllRecords();
52 | return records.Where(x => x.workoutType.ToUpper().Contains(workoutType.ToUpper())).ToList();
53 | }
54 |
55 | public async Task GetRecordByTitle(string title) {
56 | var records = await GetAllRecords();
57 | return records.Where(x => x.title.ToUpper().Equals(title.ToUpper())).FirstOrDefault();
58 | }
59 |
60 | public async Task UpdateRecord(string title, string newComment) {
61 | bool didUpdate = false;
62 |
63 | var records = await GetAllRecords();
64 | StringBuilder sb = new StringBuilder();
65 |
66 | foreach (var record in records) {
67 | if (record.title.ToUpper().Equals(title.ToUpper())) {
68 | record.comments = newComment;
69 | didUpdate = true;
70 | }
71 | var recordJson = JsonConvert.SerializeObject(record);
72 | sb.Append(recordJson);
73 | sb.Append(Environment.NewLine);
74 | }
75 |
76 | File.WriteAllText(FILE_PATH, sb.ToString());
77 | return didUpdate;
78 | }
79 |
80 | public async Task DeleteRecord(string title) {
81 | bool didDelete = false;
82 |
83 | var records = await GetAllRecords();
84 | StringBuilder sb = new StringBuilder();
85 |
86 | foreach (var record in records) {
87 | if (record.title.ToUpper().Equals(title.ToUpper())) {
88 | didDelete = true;
89 | continue;
90 | }
91 | var recordJson = JsonConvert.SerializeObject(record);
92 | sb.Append(recordJson);
93 | }
94 |
95 | File.WriteAllText(FILE_PATH, sb.ToString());
96 | return didDelete;
97 | }
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/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.HttpsPolicy;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace FitnessDataStore
15 | {
16 | public class Startup
17 | {
18 | public Startup(IConfiguration configuration)
19 | {
20 | Configuration = configuration;
21 | }
22 |
23 | public IConfiguration Configuration { get; }
24 |
25 | // This method gets called by the runtime. Use this method to add services to the container.
26 | public void ConfigureServices(IServiceCollection services)
27 | {
28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
29 | services.AddSingleton();
30 | }
31 |
32 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
33 | public void Configure(IApplicationBuilder app, IHostingEnvironment env)
34 | {
35 | if (env.IsDevelopment())
36 | {
37 | app.UseDeveloperExceptionPage();
38 | }
39 | else
40 | {
41 | app.UseHsts();
42 | }
43 | app.UseMvc();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Chapter 9/FitnessDataStore/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Warning"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Chapter 9/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace FtpSampleApp {
9 | class Program {
10 | static async Task Main(string[] args) {
11 | Console.WriteLine(await GetDirectoryListing());
12 | Console.WriteLine(await RequestFile());
13 | Console.WriteLine(await PushFile());
14 | }
15 |
16 | public static async Task GetDirectoryListing() {
17 | StringBuilder strBuilder = new StringBuilder();
18 | FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://localhost");
19 | req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
20 |
21 | req.Credentials = new NetworkCredential("s_burns", "test_password");
22 |
23 | FtpWebResponse resp = (FtpWebResponse)await req.GetResponseAsync();
24 |
25 | using (var respStream = resp.GetResponseStream()) {
26 | using (var reader = new StreamReader(respStream)) {
27 | strBuilder.Append(reader.ReadToEnd());
28 | strBuilder.Append(resp.WelcomeMessage);
29 | strBuilder.Append($"Request returned status: {resp.StatusDescription}");
30 | }
31 | }
32 | return strBuilder.ToString();
33 | }
34 |
35 | public static async Task RequestFile() {
36 | StringBuilder strBuilder = new StringBuilder();
37 | FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://localhost/FitnessApp/Startup.cs");
38 | req.Method = WebRequestMethods.Ftp.DownloadFile;
39 |
40 | req.Credentials = new NetworkCredential("s_burns", "test_password");
41 | req.UsePassive = true;
42 |
43 | using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
44 |
45 | using (var respStream = resp.GetResponseStream()) {
46 | strBuilder.Append(resp.StatusDescription);
47 | if (!File.Exists(@"../Copy_Startup.cs")) {
48 | using (var file = File.Create(@"../Copy_Startup.cs")) {
49 | //We only use this to create the file in the path if it doesn't exist.
50 | }
51 | }
52 | using (var respReader = new StreamReader(respStream)) {
53 | using (var fileWriter = File.OpenWrite(@"../Copy_Startup.cs")) {
54 | using (var strWriter = new StreamWriter(fileWriter)) {
55 | await strWriter.WriteAsync(respReader.ReadToEnd());
56 | }
57 | }
58 | }
59 | }
60 | }
61 |
62 | return strBuilder.ToString();
63 | }
64 |
65 | public static async Task PushFile() {
66 | StringBuilder strBuilder = new StringBuilder();
67 | FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://localhost/Program.cs");
68 | req.Method = WebRequestMethods.Ftp.UploadFile;
69 |
70 | req.Credentials = new NetworkCredential("s_burns", "test_password");
71 | req.UsePassive = true;
72 |
73 | byte[] fileBytes;
74 |
75 | using (var reader = new StreamReader(@"Program.cs")) {
76 | fileBytes = Encoding.ASCII.GetBytes(reader.ReadToEnd());
77 | }
78 |
79 | req.ContentLength = fileBytes.Length;
80 |
81 | using (var reqStream = await req.GetRequestStreamAsync()) {
82 | await reqStream.WriteAsync(fileBytes, 0, fileBytes.Length);
83 | }
84 |
85 | using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
86 | strBuilder.Append(resp.StatusDescription);
87 | }
88 |
89 | return strBuilder.ToString();
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Chapter 9/fitness_data.txt:
--------------------------------------------------------------------------------
1 | {"title":"Test Workout 1","workoutType":"Run","comments":"Fast run!","workoutDate":"2019-01-29T00:00:00"}
2 | {"title":"Test Workout 2","workoutType":"Run","comments":"Faster run!","workoutDate":"2019-01-29T00:00:00"}
3 | {"title":"Test Workout 3","workoutType":"Jog","comments":"The slowest possible run!","workoutDate":"2019-01-29T00:00:00"}
4 | {"title":"Test Workout 4","workoutType":"Bike","comments":"Faster biking!","workoutDate":"2019-01-29T00:00:00"}
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Packt
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hands-On-Network-Programming-with-C-and-.NET-Core
2 | Hands-On Network Programming with C# and .NET Core, published by Packt
3 |
--------------------------------------------------------------------------------