19 | Swapping to the Development environment displays detailed information about the error that occurred.
20 |
21 |
22 | The Development environment shouldn't be enabled for deployed applications.
23 | It can result in displaying sensitive information from exceptions to end users.
24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
25 | and restarting the app.
26 |
14 | A starter kit for your next web application. Boilerplate for ASP.NET Core reference application with Entity Framework Core, demonstrating a layered application architecture with DDD best practices.
15 |
16 |
17 |
18 | You can check full documentation and step by step development of 100+ page eBook PDF from here -> http://www.aspnetrun.com/
19 |
20 |
21 |
22 | ASP.NET Run is a general purpose starter kit application specially designed for new modern web applications. It uses already familiar tools and implements best practices around them to provide you a SOLID development experience. This repository focused on traditional Web Application Development with a single deployment.
23 |
24 |
25 |
26 | The goal for this boilerplate is to demonstrate some of the principles and patterns described in the eBook. Also there are sample projects which is implemented this base repositories and build sample of eCommerce reference application, you can check implementation of repo in this location : run-aspnetcore-basic-realworld
27 |
54 |
55 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
72 |
78 |
79 |
80 |
81 | @RenderSection("Scripts", required: false)
82 |
83 |
84 |
--------------------------------------------------------------------------------
/AspNetRunBasic/Pages/Shared/_ValidationScriptsPartial.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
18 |
19 |
--------------------------------------------------------------------------------
/AspNetRunBasic/Pages/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @using AspNetRunBasic
2 | @namespace AspNetRunBasic.Pages
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 |
--------------------------------------------------------------------------------
/AspNetRunBasic/Pages/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "_Layout";
3 | }
4 |
--------------------------------------------------------------------------------
/AspNetRunBasic/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using AspNetRunBasic.Data;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 | using Microsoft.Extensions.Logging;
7 |
8 | namespace AspNetRunBasic
9 | {
10 | public class Program
11 | {
12 | public static void Main(string[] args)
13 | {
14 | var host = CreateHostBuilder(args).Build();
15 | SeedDatabase(host);
16 | host.Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 |
26 | private static void SeedDatabase(IHost host)
27 | {
28 | using (var scope = host.Services.CreateScope())
29 | {
30 | var services = scope.ServiceProvider;
31 | var loggerFactory = services.GetRequiredService();
32 |
33 | try
34 | {
35 | var aspnetRunContext = services.GetRequiredService();
36 | AspnetRunContextSeed.SeedAsync(aspnetRunContext, loggerFactory).Wait();
37 | }
38 | catch (Exception exception)
39 | {
40 | var logger = loggerFactory.CreateLogger();
41 | logger.LogError(exception, "An error occurred seeding the DB.");
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/AspNetRunBasic/Repositories/IProductRepository.cs:
--------------------------------------------------------------------------------
1 | using AspNetRunBasic.Entities;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace AspNetRunBasic.Repositories
6 | {
7 | public interface IProductRepository
8 | {
9 | Task> GetProductListAsync();
10 | Task GetProductByIdAsync(int id);
11 | Task> GetProductByNameAsync(string name);
12 | Task> GetProductByCategoryAsync(int categoryId);
13 | Task AddAsync(Product product);
14 | Task UpdateAsync(Product product);
15 | Task DeleteAsync(Product product);
16 | Task> GetCategories();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/AspNetRunBasic/Repositories/ProductRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using AspNetRunBasic.Data;
6 | using AspNetRunBasic.Entities;
7 | using Microsoft.EntityFrameworkCore;
8 |
9 | namespace AspNetRunBasic.Repositories
10 | {
11 | public class ProductRepository : IProductRepository
12 | {
13 | protected readonly AspnetRunContext _dbContext;
14 |
15 | public ProductRepository(AspnetRunContext dbContext)
16 | {
17 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
18 | }
19 |
20 | public async Task> GetProductListAsync()
21 | {
22 | return await _dbContext.Products.ToListAsync();
23 | }
24 |
25 | public async Task GetProductByIdAsync(int id)
26 | {
27 | return await _dbContext.Products
28 | .Include(p => p.Category)
29 | .FirstOrDefaultAsync(p => p.Id == id);
30 | }
31 |
32 | public async Task> GetProductByNameAsync(string name)
33 | {
34 | return await _dbContext.Products
35 | .Include(p => p.Category)
36 | .Where(p => string.IsNullOrEmpty(name) || p.Name.ToLower().Contains(name.ToLower()))
37 | .OrderBy(p => p.Name)
38 | .ToListAsync();
39 | }
40 |
41 | public async Task> GetProductByCategoryAsync(int categoryId)
42 | {
43 | return await _dbContext.Products
44 | .Where(x => x.CategoryId == categoryId)
45 | .ToListAsync();
46 | }
47 |
48 | public async Task AddAsync(Product product)
49 | {
50 | _dbContext.Products.Add(product);
51 | await _dbContext.SaveChangesAsync();
52 | return product;
53 | }
54 |
55 | public async Task UpdateAsync(Product product)
56 | {
57 | _dbContext.Entry(product).State = EntityState.Modified;
58 | await _dbContext.SaveChangesAsync();
59 | }
60 |
61 | public async Task DeleteAsync(Product product)
62 | {
63 | _dbContext.Products.Remove(product);
64 | await _dbContext.SaveChangesAsync();
65 | }
66 |
67 | public async Task> GetCategories()
68 | {
69 | return await _dbContext.Categories.ToListAsync();
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/AspNetRunBasic/Startup.cs:
--------------------------------------------------------------------------------
1 | using AspNetRunBasic.Data;
2 | using AspNetRunBasic.Repositories;
3 | using Microsoft.AspNetCore.Builder;
4 | using Microsoft.AspNetCore.Hosting;
5 | using Microsoft.EntityFrameworkCore;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.DependencyInjection;
8 | using Microsoft.Extensions.Hosting;
9 |
10 | namespace AspNetRunBasic
11 | {
12 | public class Startup
13 | {
14 | public Startup(IConfiguration configuration)
15 | {
16 | Configuration = configuration;
17 | }
18 |
19 | public IConfiguration Configuration { get; }
20 |
21 | // This method gets called by the runtime. Use this method to add services to the container.
22 | public void ConfigureServices(IServiceCollection services)
23 | {
24 | #region Database Connection
25 |
26 | // use in-memory database
27 | services.AddDbContext(c =>
28 | c.UseInMemoryDatabase("AspnetRunConnection"));
29 |
30 | //// add real database dependecy
31 | //services.AddDbContext(c =>
32 | // c.UseSqlServer(Configuration.GetConnectionString("AspnetRunConnection")));
33 |
34 | #endregion
35 |
36 | #region Dependencies
37 |
38 | // add repository dependecy
39 | services.AddScoped();
40 |
41 | #endregion
42 |
43 | services.Configure(options =>
44 | {
45 | // This lambda determines whether user consent for non-essential cookies is needed for a given request.
46 | options.CheckConsentNeeded = context => true;
47 | });
48 |
49 | services.AddRazorPages()
50 | .AddNewtonsoftJson();
51 | }
52 |
53 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
54 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
55 | {
56 | if (env.IsDevelopment())
57 | {
58 | app.UseDeveloperExceptionPage();
59 | }
60 | else
61 | {
62 | app.UseExceptionHandler("/Error");
63 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
64 | app.UseHsts();
65 | }
66 |
67 | app.UseHttpsRedirection();
68 | app.UseStaticFiles();
69 | app.UseCookiePolicy();
70 | app.UseRouting();
71 | app.UseAuthorization();
72 |
73 | app.UseEndpoints(endpoints =>
74 | {
75 | endpoints.MapRazorPages();
76 | });
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/AspNetRunBasic/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/AspNetRunBasic/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ConnectionStrings": {
3 | "AspnetRunConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=AspnetRunBasic;"
4 | },
5 | "Logging": {
6 | "LogLevel": {
7 | "Default": "Information",
8 | "Microsoft": "Warning",
9 | "Microsoft.Hosting.Lifetime": "Information"
10 | }
11 | },
12 | "AllowedHosts": "*"
13 | }
14 |
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/css/site.css:
--------------------------------------------------------------------------------
1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
2 | for details on configuring this project to bundle and minify static web assets. */
3 |
4 | a.navbar-brand {
5 | white-space: normal;
6 | text-align: center;
7 | word-break: break-all;
8 | }
9 |
10 | /* Sticky footer styles
11 | -------------------------------------------------- */
12 | html {
13 | font-size: 14px;
14 | }
15 | @media (min-width: 768px) {
16 | html {
17 | font-size: 16px;
18 | }
19 | }
20 |
21 | .border-top {
22 | border-top: 1px solid #e5e5e5;
23 | }
24 | .border-bottom {
25 | border-bottom: 1px solid #e5e5e5;
26 | }
27 |
28 | .box-shadow {
29 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
30 | }
31 |
32 | button.accept-policy {
33 | font-size: 1rem;
34 | line-height: inherit;
35 | }
36 |
37 | /* Sticky footer styles
38 | -------------------------------------------------- */
39 | html {
40 | position: relative;
41 | min-height: 100%;
42 | }
43 |
44 | body {
45 | /* Margin bottom by footer height */
46 | margin-bottom: 60px;
47 | }
48 | .footer {
49 | position: absolute;
50 | bottom: 0;
51 | width: 100%;
52 | white-space: nowrap;
53 | /* Set the fixed height of the footer here */
54 | height: 60px;
55 | line-height: 60px; /* Vertically center the text there */
56 | }
57 |
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aspnetrun/run-aspnetcore-basics_retired/5ecfd408fa96812b89d5ff558088e83717957fe0/AspNetRunBasic/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/js/site.js:
--------------------------------------------------------------------------------
1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
2 | // for details on configuring this project to bundle and minify static web assets.
3 |
4 | // Write your Javascript code.
5 |
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/lib/bootstrap/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2011-2018 Twitter, Inc.
4 | Copyright (c) 2011-2018 The Bootstrap Authors
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
3 | * Copyright 2011-2019 The Bootstrap Authors
4 | * Copyright 2011-2019 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */
8 | *,
9 | *::before,
10 | *::after {
11 | box-sizing: border-box;
12 | }
13 |
14 | html {
15 | font-family: sans-serif;
16 | line-height: 1.15;
17 | -webkit-text-size-adjust: 100%;
18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
19 | }
20 |
21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
22 | display: block;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
28 | font-size: 1rem;
29 | font-weight: 400;
30 | line-height: 1.5;
31 | color: #212529;
32 | text-align: left;
33 | background-color: #fff;
34 | }
35 |
36 | [tabindex="-1"]:focus {
37 | outline: 0 !important;
38 | }
39 |
40 | hr {
41 | box-sizing: content-box;
42 | height: 0;
43 | overflow: visible;
44 | }
45 |
46 | h1, h2, h3, h4, h5, h6 {
47 | margin-top: 0;
48 | margin-bottom: 0.5rem;
49 | }
50 |
51 | p {
52 | margin-top: 0;
53 | margin-bottom: 1rem;
54 | }
55 |
56 | abbr[title],
57 | abbr[data-original-title] {
58 | text-decoration: underline;
59 | -webkit-text-decoration: underline dotted;
60 | text-decoration: underline dotted;
61 | cursor: help;
62 | border-bottom: 0;
63 | -webkit-text-decoration-skip-ink: none;
64 | text-decoration-skip-ink: none;
65 | }
66 |
67 | address {
68 | margin-bottom: 1rem;
69 | font-style: normal;
70 | line-height: inherit;
71 | }
72 |
73 | ol,
74 | ul,
75 | dl {
76 | margin-top: 0;
77 | margin-bottom: 1rem;
78 | }
79 |
80 | ol ol,
81 | ul ul,
82 | ol ul,
83 | ul ol {
84 | margin-bottom: 0;
85 | }
86 |
87 | dt {
88 | font-weight: 700;
89 | }
90 |
91 | dd {
92 | margin-bottom: .5rem;
93 | margin-left: 0;
94 | }
95 |
96 | blockquote {
97 | margin: 0 0 1rem;
98 | }
99 |
100 | b,
101 | strong {
102 | font-weight: bolder;
103 | }
104 |
105 | small {
106 | font-size: 80%;
107 | }
108 |
109 | sub,
110 | sup {
111 | position: relative;
112 | font-size: 75%;
113 | line-height: 0;
114 | vertical-align: baseline;
115 | }
116 |
117 | sub {
118 | bottom: -.25em;
119 | }
120 |
121 | sup {
122 | top: -.5em;
123 | }
124 |
125 | a {
126 | color: #007bff;
127 | text-decoration: none;
128 | background-color: transparent;
129 | }
130 |
131 | a:hover {
132 | color: #0056b3;
133 | text-decoration: underline;
134 | }
135 |
136 | a:not([href]):not([tabindex]) {
137 | color: inherit;
138 | text-decoration: none;
139 | }
140 |
141 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
142 | color: inherit;
143 | text-decoration: none;
144 | }
145 |
146 | a:not([href]):not([tabindex]):focus {
147 | outline: 0;
148 | }
149 |
150 | pre,
151 | code,
152 | kbd,
153 | samp {
154 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
155 | font-size: 1em;
156 | }
157 |
158 | pre {
159 | margin-top: 0;
160 | margin-bottom: 1rem;
161 | overflow: auto;
162 | }
163 |
164 | figure {
165 | margin: 0 0 1rem;
166 | }
167 |
168 | img {
169 | vertical-align: middle;
170 | border-style: none;
171 | }
172 |
173 | svg {
174 | overflow: hidden;
175 | vertical-align: middle;
176 | }
177 |
178 | table {
179 | border-collapse: collapse;
180 | }
181 |
182 | caption {
183 | padding-top: 0.75rem;
184 | padding-bottom: 0.75rem;
185 | color: #6c757d;
186 | text-align: left;
187 | caption-side: bottom;
188 | }
189 |
190 | th {
191 | text-align: inherit;
192 | }
193 |
194 | label {
195 | display: inline-block;
196 | margin-bottom: 0.5rem;
197 | }
198 |
199 | button {
200 | border-radius: 0;
201 | }
202 |
203 | button:focus {
204 | outline: 1px dotted;
205 | outline: 5px auto -webkit-focus-ring-color;
206 | }
207 |
208 | input,
209 | button,
210 | select,
211 | optgroup,
212 | textarea {
213 | margin: 0;
214 | font-family: inherit;
215 | font-size: inherit;
216 | line-height: inherit;
217 | }
218 |
219 | button,
220 | input {
221 | overflow: visible;
222 | }
223 |
224 | button,
225 | select {
226 | text-transform: none;
227 | }
228 |
229 | select {
230 | word-wrap: normal;
231 | }
232 |
233 | button,
234 | [type="button"],
235 | [type="reset"],
236 | [type="submit"] {
237 | -webkit-appearance: button;
238 | }
239 |
240 | button:not(:disabled),
241 | [type="button"]:not(:disabled),
242 | [type="reset"]:not(:disabled),
243 | [type="submit"]:not(:disabled) {
244 | cursor: pointer;
245 | }
246 |
247 | button::-moz-focus-inner,
248 | [type="button"]::-moz-focus-inner,
249 | [type="reset"]::-moz-focus-inner,
250 | [type="submit"]::-moz-focus-inner {
251 | padding: 0;
252 | border-style: none;
253 | }
254 |
255 | input[type="radio"],
256 | input[type="checkbox"] {
257 | box-sizing: border-box;
258 | padding: 0;
259 | }
260 |
261 | input[type="date"],
262 | input[type="time"],
263 | input[type="datetime-local"],
264 | input[type="month"] {
265 | -webkit-appearance: listbox;
266 | }
267 |
268 | textarea {
269 | overflow: auto;
270 | resize: vertical;
271 | }
272 |
273 | fieldset {
274 | min-width: 0;
275 | padding: 0;
276 | margin: 0;
277 | border: 0;
278 | }
279 |
280 | legend {
281 | display: block;
282 | width: 100%;
283 | max-width: 100%;
284 | padding: 0;
285 | margin-bottom: .5rem;
286 | font-size: 1.5rem;
287 | line-height: inherit;
288 | color: inherit;
289 | white-space: normal;
290 | }
291 |
292 | progress {
293 | vertical-align: baseline;
294 | }
295 |
296 | [type="number"]::-webkit-inner-spin-button,
297 | [type="number"]::-webkit-outer-spin-button {
298 | height: auto;
299 | }
300 |
301 | [type="search"] {
302 | outline-offset: -2px;
303 | -webkit-appearance: none;
304 | }
305 |
306 | [type="search"]::-webkit-search-decoration {
307 | -webkit-appearance: none;
308 | }
309 |
310 | ::-webkit-file-upload-button {
311 | font: inherit;
312 | -webkit-appearance: button;
313 | }
314 |
315 | output {
316 | display: inline-block;
317 | }
318 |
319 | summary {
320 | display: list-item;
321 | cursor: pointer;
322 | }
323 |
324 | template {
325 | display: none;
326 | }
327 |
328 | [hidden] {
329 | display: none !important;
330 | }
331 | /*# sourceMappingURL=bootstrap-reboot.css.map */
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
3 | * Copyright 2011-2019 The Bootstrap Authors
4 | * Copyright 2011-2019 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) .NET Foundation. All rights reserved.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | these files except in compliance with the License. You may obtain a copy of the
5 | License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software distributed
10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | specific language governing permissions and limitations under the License.
13 |
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js:
--------------------------------------------------------------------------------
1 | // Unobtrusive validation support library for jQuery and jQuery Validate
2 | // Copyright (c) .NET Foundation. All rights reserved.
3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
4 | // @version v3.2.11
5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive});
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/lib/jquery-validation/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | =====================
3 |
4 | Copyright Jörn Zaefferer
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/AspNetRunBasic/wwwroot/lib/jquery/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright JS Foundation and other contributors, https://js.foundation/
2 |
3 | This software consists of voluntary contributions made by many
4 | individuals. For exact contribution history, see the revision history
5 | available at https://github.com/jquery/jquery
6 |
7 | The following license applies to all parts of this software except as
8 | documented below:
9 |
10 | ====
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining
13 | a copy of this software and associated documentation files (the
14 | "Software"), to deal in the Software without restriction, including
15 | without limitation the rights to use, copy, modify, merge, publish,
16 | distribute, sublicense, and/or sell copies of the Software, and to
17 | permit persons to whom the Software is furnished to do so, subject to
18 | the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be
21 | included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 |
31 | ====
32 |
33 | All files located in the node_modules and external directories are
34 | externally maintained libraries used by this software which have their
35 | own licenses; we recommend you read them, as their terms may differ from
36 | the terms above.
37 |
--------------------------------------------------------------------------------
/AspNetRunBasic_Retired.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28803.202
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetRunBasic_Retired", "AspNetRunBasic\AspNetRunBasic_Retired.csproj", "{05D36AAF-146B-46E1-9A17-663F862EDC06}"
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 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.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 = {7C73BF53-E283-440E-813F-A451DF2EF4CF}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 aspnetrun
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 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Core/Entities/Base/Entity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Order.Core.Entities.Base
6 | {
7 | public abstract class Entity : EntityBase
8 | {
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Core/Entities/Base/EntityBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Order.Core.Entities.Base
6 | {
7 | public abstract class EntityBase : IEntityBase
8 | {
9 | public virtual TId Id { get; protected set; }
10 |
11 | int? _requestedHashCode;
12 |
13 | public bool IsTransient()
14 | {
15 | return Id.Equals(default(TId));
16 | }
17 |
18 | public override bool Equals(object obj)
19 | {
20 | if (obj == null || !(obj is EntityBase))
21 | return false;
22 |
23 | if (ReferenceEquals(this, obj))
24 | return true;
25 |
26 | if (GetType() != obj.GetType())
27 | return false;
28 |
29 | var item = (EntityBase)obj;
30 |
31 | if (item.IsTransient() || IsTransient())
32 | return false;
33 | else
34 | return item == this;
35 | }
36 |
37 | public override int GetHashCode()
38 | {
39 | if (!IsTransient())
40 | {
41 | if (!_requestedHashCode.HasValue)
42 | _requestedHashCode = Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx)
43 |
44 | return _requestedHashCode.Value;
45 | }
46 | else
47 | return base.GetHashCode();
48 | }
49 |
50 | public static bool operator ==(EntityBase left, EntityBase right)
51 | {
52 | if (Equals(left, null))
53 | return Equals(right, null) ? true : false;
54 | else
55 | return left.Equals(right);
56 | }
57 |
58 | public static bool operator !=(EntityBase left, EntityBase right)
59 | {
60 | return !(left == right);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Core/Entities/Base/IEntityBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Order.Core.Entities.Base
6 | {
7 | public interface IEntityBase
8 | {
9 | TId Id { get; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Core/Entities/Order.cs:
--------------------------------------------------------------------------------
1 | using Order.Core.Entities.Base;
2 |
3 | namespace Order.Core.Entities
4 | {
5 | public class Order : Entity
6 | {
7 | public string UserName { get; set; }
8 | public decimal TotalPrice { get; set; }
9 |
10 | // BillingAddress
11 | public string FirstName { get; set; }
12 | public string LastName { get; set; }
13 | public string EmailAddress { get; set; }
14 | public string AddressLine { get; set; }
15 | public string Country { get; set; }
16 | public string State { get; set; }
17 | public string ZipCode { get; set; }
18 |
19 | // Payment
20 | public string CardName { get; set; }
21 | public string CardNumber { get; set; }
22 | public string Expiration { get; set; }
23 | public string CVV { get; set; }
24 | public PaymentMethod PaymentMethod { get; set; }
25 | }
26 |
27 | public enum PaymentMethod
28 | {
29 | CreditCard = 1,
30 | DebitCard = 2,
31 | Paypal = 3
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Core/Order.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Core/Repositories/Base/IRepository.cs:
--------------------------------------------------------------------------------
1 | using Order.Core.Entities.Base;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Linq.Expressions;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Order.Core.Repositories.Base
10 | {
11 | public interface IRepository where T : Entity
12 | {
13 | Task> GetAllAsync();
14 | Task> GetAsync(Expression> predicate);
15 | Task> GetAsync(Expression> predicate = null,
16 | Func, IOrderedQueryable> orderBy = null,
17 | string includeString = null,
18 | bool disableTracking = true);
19 | Task> GetAsync(Expression> predicate = null,
20 | Func, IOrderedQueryable> orderBy = null,
21 | List>> includes = null,
22 | bool disableTracking = true);
23 | Task GetByIdAsync(int id);
24 | Task AddAsync(T entity);
25 | Task UpdateAsync(T entity);
26 | Task DeleteAsync(T entity);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Core/Repositories/IOrderRepository.cs:
--------------------------------------------------------------------------------
1 | using Order.Core.Repositories.Base;
2 | using Order.Core.Entities;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Order.Core.Repositories
9 | {
10 | public interface IOrderRepository : IRepository
11 | {
12 | Task> GetOrderListAsync();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Infrastructure/Class1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Order.Infrastructure
4 | {
5 | public class Class1
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/basicmicroservice/Order.Infrastructure/Order.Infrastructure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/basicmicroservice/basicmicroservice.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29806.167
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{5AFB00CF-8E6E-4402-8870-05CF483F43BC}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{4F4FB78C-17C7-4726-A65D-C5CA1E40A806}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Basket", "Basket", "{D6F43D19-A527-4BDB-9CF7-2ABB731C1014}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Order", "Order", "{ED7226E2-4D3C-4164-A88C-436845332BC1}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Catalog.API", "src\Catalog\Catalog.API\Catalog.API.csproj", "{C81249E2-63E5-41EC-9A29-C66D622AF86D}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebUI", "WebUI", "{A620B284-D093-4BB9-92B2-8E0FE0B7B24C}"
19 | EndProject
20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGateway", "ApiGateway", "{652564FB-14BE-4016-BB38-57039BB73B2A}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShopApp", "src\webui\ShopApp\ShopApp.csproj", "{B445668C-7C71-469D-9A6A-27C87043EF60}"
23 | EndProject
24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Order.API", "src\Order\Order.API\Order.API.csproj", "{981A5534-0E42-4DC9-B99C-2A95EAF97ADF}"
25 | EndProject
26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Basket.API", "src\Basket\Basket.API\Basket.API.csproj", "{A80C8D6B-E128-4ABD-996B-DE9872845A91}"
27 | EndProject
28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Order.Core", "Order.Core\Order.Core.csproj", "{268069EA-D298-4F9A-9C9E-1A823815124B}"
29 | EndProject
30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Order.Infrastructure", "src\order\Order.Infrastructure\Order.Infrastructure.csproj", "{F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}"
31 | EndProject
32 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipment", "Shipment", "{97A43AA5-C1D3-4CB0-B0EB-501A71422A35}"
33 | EndProject
34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipment.API", "src\shipment\Shipment.API\Shipment.API.csproj", "{3F0400B9-666C-4E0F-9CAD-58C3ED760C76}"
35 | EndProject
36 | Global
37 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
38 | Debug|Any CPU = Debug|Any CPU
39 | Release|Any CPU = Release|Any CPU
40 | EndGlobalSection
41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
42 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Release|Any CPU.Build.0 = Release|Any CPU
54 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Debug|Any CPU.Build.0 = Debug|Any CPU
60 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Release|Any CPU.Build.0 = Release|Any CPU
62 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
64 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
65 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Release|Any CPU.Build.0 = Release|Any CPU
66 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Debug|Any CPU.Build.0 = Debug|Any CPU
68 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Release|Any CPU.ActiveCfg = Release|Any CPU
69 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Release|Any CPU.Build.0 = Release|Any CPU
70 | EndGlobalSection
71 | GlobalSection(SolutionProperties) = preSolution
72 | HideSolutionNode = FALSE
73 | EndGlobalSection
74 | GlobalSection(NestedProjects) = preSolution
75 | {4F4FB78C-17C7-4726-A65D-C5CA1E40A806} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}
76 | {D6F43D19-A527-4BDB-9CF7-2ABB731C1014} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}
77 | {ED7226E2-4D3C-4164-A88C-436845332BC1} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}
78 | {C81249E2-63E5-41EC-9A29-C66D622AF86D} = {4F4FB78C-17C7-4726-A65D-C5CA1E40A806}
79 | {A620B284-D093-4BB9-92B2-8E0FE0B7B24C} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}
80 | {652564FB-14BE-4016-BB38-57039BB73B2A} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}
81 | {B445668C-7C71-469D-9A6A-27C87043EF60} = {A620B284-D093-4BB9-92B2-8E0FE0B7B24C}
82 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF} = {ED7226E2-4D3C-4164-A88C-436845332BC1}
83 | {A80C8D6B-E128-4ABD-996B-DE9872845A91} = {D6F43D19-A527-4BDB-9CF7-2ABB731C1014}
84 | {268069EA-D298-4F9A-9C9E-1A823815124B} = {ED7226E2-4D3C-4164-A88C-436845332BC1}
85 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B} = {ED7226E2-4D3C-4164-A88C-436845332BC1}
86 | {97A43AA5-C1D3-4CB0-B0EB-501A71422A35} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}
87 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76} = {97A43AA5-C1D3-4CB0-B0EB-501A71422A35}
88 | EndGlobalSection
89 | GlobalSection(ExtensibilityGlobals) = postSolution
90 | SolutionGuid = {84204196-8211-4BEA-8688-10C3584CADB2}
91 | EndGlobalSection
92 | EndGlobal
93 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Basket.API.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Controllers/BasketController.cs:
--------------------------------------------------------------------------------
1 | using Basket.API.Entities;
2 | using Basket.API.RabbitMq;
3 | using Basket.API.Repositories.Interface;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.Logging;
6 | using System;
7 | using System.Net;
8 | using System.Security.Claims;
9 | using System.Threading.Tasks;
10 |
11 | namespace Basket.API.Controllers
12 | {
13 | [Route("api/v1/[controller]")]
14 | [ApiController]
15 | public class BasketController : ControllerBase
16 | {
17 | private readonly IBasketRepository _repository;
18 | private readonly EventBusRabbitMQPublisher _eventBus;
19 | private readonly ILogger _logger;
20 |
21 | public BasketController(IBasketRepository repository, EventBusRabbitMQPublisher eventBus, ILogger logger)
22 | {
23 | _repository = repository ?? throw new ArgumentNullException(nameof(repository));
24 | _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
25 | _logger = logger ?? throw new ArgumentNullException(nameof(logger));
26 | }
27 |
28 | [HttpGet("{id}")]
29 | [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
30 | public async Task> GetBasketByIdAsync(string id)
31 | {
32 | var basket = await _repository.GetBasketAsync(id);
33 | return Ok(basket ?? new CustomerBasket(id));
34 | }
35 |
36 | [HttpPost]
37 | [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
38 | public async Task> UpdateBasketAsync([FromBody]CustomerBasket value)
39 | {
40 | return Ok(await _repository.UpdateBasketAsync(value));
41 | }
42 |
43 | // DELETE api/values/5
44 | [HttpDelete("{id}")]
45 | [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)]
46 | public async Task DeleteBasketByIdAsync(string id)
47 | {
48 | await _repository.DeleteBasketAsync(id);
49 | }
50 |
51 | [Route("checkout")]
52 | [HttpPost]
53 | [ProducesResponseType((int)HttpStatusCode.Accepted)]
54 | [ProducesResponseType((int)HttpStatusCode.BadRequest)]
55 | public async Task CheckoutAsync([FromBody]BasketCheckout basketCheckout)
56 | {
57 | // remove the basket
58 | // send checkout event to rabbitMq
59 |
60 | var userId = "swn"; // _identityService.GetUserIdentity();
61 |
62 | var basketRemoved = await _repository.DeleteBasketAsync(userId);
63 | if (!basketRemoved)
64 | {
65 | return BadRequest();
66 | }
67 |
68 | basketCheckout.RequestId = Guid.NewGuid();
69 | basketCheckout.Buyer = userId;
70 | basketCheckout.City = "asd";
71 | basketCheckout.Country = "asd";
72 |
73 | _eventBus.PublishBasketCheckout("basketCheckoutQueue", basketCheckout);
74 |
75 | // TODO : burayı alttaki gibi yapılacak -- rabbitMQ kısmı ayrı bir class library yapılıp BasketCheckoutAcceptedIntegrationEvent class ı yapılıp 2 tarafta onu kullanacak
76 |
77 | //var userName = this.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value;
78 |
79 | //var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName, basketCheckout.City, basketCheckout.Street,
80 | // basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName,
81 | // basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket);
82 |
83 | //// Once basket is checkout, sends an integration event to
84 | //// ordering.api to convert basket to order and proceeds with
85 | //// order creation process
86 | //try
87 | //{
88 | // _eventBus.Publish(eventMessage);
89 | //}
90 | //catch (Exception ex)
91 | //{
92 | // _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, "asd");
93 | // throw;
94 | //}
95 |
96 | return Accepted();
97 | }
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Entities/BasketCheckout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Basket.API.Entities
4 | {
5 | public class BasketCheckout
6 | {
7 | public string City { get; set; }
8 | public string Street { get; set; }
9 | public string State { get; set; }
10 | public string Country { get; set; }
11 | public string ZipCode { get; set; }
12 | public string CardNumber { get; set; }
13 | public string CardHolderName { get; set; }
14 | public DateTime CardExpiration { get; set; }
15 | public string CardSecurityNumber { get; set; }
16 | public int CardTypeId { get; set; }
17 | public string Buyer { get; set; }
18 | public Guid RequestId { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Entities/BasketItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace Basket.API.Entities
8 | {
9 | public class BasketItem : IValidatableObject
10 | {
11 | public string Id { get; set; }
12 | public int ProductId { get; set; }
13 | public string ProductName { get; set; }
14 | public decimal UnitPrice { get; set; }
15 | public decimal OldUnitPrice { get; set; }
16 | public int Quantity { get; set; }
17 | public string PictureUrl { get; set; }
18 |
19 | public IEnumerable Validate(ValidationContext validationContext)
20 | {
21 | var results = new List();
22 |
23 | if (Quantity < 1)
24 | {
25 | results.Add(new ValidationResult("Invalid number of units", new[] { "Quantity" }));
26 | }
27 |
28 | return results;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Entities/CustomerBasket.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Basket.API.Entities
4 | {
5 | public class CustomerBasket
6 | {
7 | public string BuyerId { get; set; }
8 |
9 | public List Items { get; set; } = new List();
10 |
11 | public CustomerBasket()
12 | {
13 |
14 | }
15 |
16 | public CustomerBasket(string customerId)
17 | {
18 | BuyerId = customerId;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace Basket.API
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | CreateHostBuilder(args).Build().Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/RabbitMq/EventBusRabbitMQPublisher.cs:
--------------------------------------------------------------------------------
1 | using Basket.API.Entities;
2 | using Newtonsoft.Json;
3 | using RabbitMQ.Client;
4 | using RabbitMQ.Client.Events;
5 | using System;
6 | using System.Text;
7 |
8 | namespace Basket.API.RabbitMq
9 | {
10 | // https://github.com/isanka88/Send-and-Receive-Data-in-Asp.net-Core-With-RabbitMQ
11 | // https://stackoverflow.com/questions/43609345/setup-rabbitmq-consumer-in-asp-net-core-application/43610530#comment98659771_43610530
12 | public class EventBusRabbitMQPublisher
13 | {
14 | private readonly IRabbitMQConnection _connection;
15 |
16 | public EventBusRabbitMQPublisher(IRabbitMQConnection connection)
17 | {
18 | _connection = connection ?? throw new ArgumentNullException(nameof(connection));
19 | }
20 |
21 | public void PublishBasketCheckout(string queueName, BasketCheckout publishModel)
22 | {
23 | using (var channel = _connection.CreateModel())
24 | {
25 | channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
26 | var message = JsonConvert.SerializeObject(publishModel);
27 | var body = Encoding.UTF8.GetBytes(message);
28 |
29 | IBasicProperties properties = channel.CreateBasicProperties();
30 | properties.Persistent = true;
31 | properties.DeliveryMode = 2;
32 |
33 | channel.ConfirmSelect();
34 | channel.BasicPublish(exchange: "", routingKey: queueName, mandatory: true, basicProperties: properties, body: body);
35 | channel.WaitForConfirmsOrDie();
36 |
37 | channel.BasicAcks += (sender, eventArgs) =>
38 | {
39 | Console.WriteLine("Sent RabbitMQ");
40 | //implement ack handle
41 | };
42 | channel.ConfirmSelect();
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/RabbitMq/IRabbitMQConnection.cs:
--------------------------------------------------------------------------------
1 | using RabbitMQ.Client;
2 | using System;
3 |
4 | namespace Basket.API.RabbitMq
5 | {
6 | public interface IRabbitMQConnection : IDisposable
7 | {
8 | bool IsConnected { get; }
9 | bool TryConnect();
10 | IModel CreateModel();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/RabbitMq/RabbitMQConnection.cs:
--------------------------------------------------------------------------------
1 | using RabbitMQ.Client;
2 | using RabbitMQ.Client.Events;
3 | using RabbitMQ.Client.Exceptions;
4 | using System;
5 | using System.IO;
6 | using System.Threading;
7 |
8 | namespace Basket.API.RabbitMq
9 | {
10 | public class RabbitMQConnection : IRabbitMQConnection
11 | {
12 | private readonly IConnectionFactory _connectionFactory;
13 | private IConnection _connection;
14 | private bool _disposed;
15 |
16 | public RabbitMQConnection(IConnectionFactory connectionFactory)
17 | {
18 | _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
19 | if (!IsConnected)
20 | {
21 | TryConnect();
22 | }
23 | }
24 |
25 | public bool IsConnected
26 | {
27 | get
28 | {
29 | return _connection != null && _connection.IsOpen && !_disposed;
30 | }
31 | }
32 |
33 | public bool TryConnect()
34 | {
35 | try
36 | {
37 | _connection = _connectionFactory.CreateConnection();
38 | }
39 | catch (BrokerUnreachableException)
40 | {
41 | Thread.Sleep(2000);
42 | _connection = _connectionFactory.CreateConnection();
43 | }
44 |
45 | if (IsConnected)
46 | {
47 | Console.WriteLine($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events");
48 | return true;
49 | }
50 | else
51 | {
52 | Console.WriteLine("FATAL ERROR: RabbitMQ connections could not be created and opened");
53 | return false;
54 | }
55 | }
56 |
57 | public IModel CreateModel()
58 | {
59 | if (!IsConnected)
60 | {
61 | throw new InvalidOperationException("No RabbitMQ connections are available to perform this action");
62 | }
63 | return _connection.CreateModel();
64 | }
65 |
66 | public void Dispose()
67 | {
68 | if (_disposed) return;
69 |
70 | _disposed = true;
71 |
72 | try
73 | {
74 | _connection.Dispose();
75 | }
76 | catch (IOException ex)
77 | {
78 | Console.WriteLine(ex.ToString());
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Repositories/Interface/IBasketRepository.cs:
--------------------------------------------------------------------------------
1 | using Basket.API.Entities;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace Basket.API.Repositories.Interface
8 | {
9 | public interface IBasketRepository
10 | {
11 | Task GetBasketAsync(string customerId);
12 | IEnumerable GetUsers();
13 | Task UpdateBasketAsync(CustomerBasket basket);
14 | Task DeleteBasketAsync(string id);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Repositories/RedisBasketRepository.cs:
--------------------------------------------------------------------------------
1 | using Basket.API.Entities;
2 | using Basket.API.Repositories.Interface;
3 | using Microsoft.Extensions.Logging;
4 | using Newtonsoft.Json;
5 | using StackExchange.Redis;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 |
11 | namespace Basket.API.Repositories
12 | {
13 | // https://dotnetcorecentral.com/blog/redis-cache-in-net-core-docker-container/
14 | // https://stackexchange.github.io/StackExchange.Redis/Configuration.html
15 | public class RedisBasketRepository : IBasketRepository
16 | {
17 | private readonly ILogger _logger;
18 | private readonly ConnectionMultiplexer _redis;
19 | private readonly IDatabase _database;
20 |
21 | public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis)
22 | {
23 | _logger = loggerFactory.CreateLogger();
24 | _redis = redis;
25 | _database = redis.GetDatabase();
26 | }
27 |
28 | public async Task DeleteBasketAsync(string id)
29 | {
30 | return await _database.KeyDeleteAsync(id);
31 | }
32 |
33 | public IEnumerable GetUsers()
34 | {
35 | var server = GetServer();
36 | var data = server.Keys();
37 |
38 | return data?.Select(k => k.ToString());
39 | }
40 |
41 | public async Task GetBasketAsync(string customerId)
42 | {
43 | var data = await _database.StringGetAsync(customerId);
44 |
45 | if (data.IsNullOrEmpty)
46 | {
47 | return null;
48 | }
49 |
50 | return JsonConvert.DeserializeObject(data);
51 | }
52 |
53 | public async Task UpdateBasketAsync(CustomerBasket basket)
54 | {
55 | var created = await _database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket));
56 |
57 | if (!created)
58 | {
59 | _logger.LogInformation("Problem occur persisting the item.");
60 | return null;
61 | }
62 |
63 | _logger.LogInformation("Basket item persisted succesfully.");
64 |
65 | return await GetBasketAsync(basket.BuyerId);
66 | }
67 |
68 | private IServer GetServer()
69 | {
70 | var endpoint = _redis.GetEndPoints();
71 | return _redis.GetServer(endpoint.First());
72 |
73 |
74 | //var customerBasket = new CustomerBasket();
75 | //customerBasket.BuyerId = "swn";
76 | //customerBasket.Items.Add(
77 | // new BasketItem
78 | // {
79 | // Id = "1",
80 | // ProductId = 2,
81 | // OldUnitPrice = 3,
82 | // PictureUrl = "asd",
83 | // ProductName = "bas",
84 | // Quantity = 3,
85 | // UnitPrice = 4
86 | // }
87 | // );
88 |
89 | //var ser = JsonConvert.SerializeObject(customerBasket);
90 | //var created = _database.StringSet(customerBasket.BuyerId, ser);
91 | //var getResult = _database.StringGet(customerBasket.BuyerId);
92 | //var newObject = JsonConvert.DeserializeObject(getResult);
93 | }
94 |
95 |
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Service/BasketService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace Basket.API.Service
7 | {
8 | // https://medium.com/@matthew.bajorek/creating-a-redis-service-in-asp-net-core-2-2-web-api-17b8b5704454
9 | public class BasketService
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Basket.API.RabbitMq;
6 | using Basket.API.Repositories;
7 | using Basket.API.Repositories.Interface;
8 | using Microsoft.AspNetCore.Builder;
9 | using Microsoft.AspNetCore.Hosting;
10 | using Microsoft.AspNetCore.Mvc;
11 | using Microsoft.Extensions.Configuration;
12 | using Microsoft.Extensions.DependencyInjection;
13 | using Microsoft.Extensions.Hosting;
14 | using Microsoft.Extensions.Logging;
15 | using Microsoft.Extensions.Options;
16 | using RabbitMQ.Client;
17 | using StackExchange.Redis;
18 |
19 | namespace Basket.API
20 | {
21 | public class Startup
22 | {
23 | public Startup(IConfiguration configuration)
24 | {
25 | Configuration = configuration;
26 | }
27 |
28 | public IConfiguration Configuration { get; }
29 |
30 | // This method gets called by the runtime. Use this method to add services to the container.
31 | public void ConfigureServices(IServiceCollection services)
32 | {
33 | services.AddControllers();
34 |
35 | // add redis
36 | services.AddSingleton(sp =>
37 | {
38 | var configuration = ConfigurationOptions.Parse(Configuration.GetConnectionString("RedisCache"), true);
39 | return ConnectionMultiplexer.Connect(configuration);
40 | });
41 |
42 | #region project services
43 |
44 | // add repository dependecy
45 | services.AddScoped();
46 |
47 | services.AddSingleton(sp =>
48 | {
49 | var factory = new ConnectionFactory()
50 | {
51 | HostName = Configuration["EventBusHostName"]
52 | };
53 |
54 | if (!string.IsNullOrEmpty(Configuration["EventBusUserName"]))
55 | {
56 | factory.UserName = Configuration["EventBusUserName"];
57 | }
58 |
59 | if (!string.IsNullOrEmpty(Configuration["EventBusPassword"]))
60 | {
61 | factory.Password = Configuration["EventBusPassword"];
62 | }
63 |
64 | return new RabbitMQConnection(factory);
65 | });
66 |
67 | services.AddSingleton();
68 |
69 | #endregion
70 | }
71 |
72 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
73 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
74 | {
75 | if (env.IsDevelopment())
76 | {
77 | app.UseDeveloperExceptionPage();
78 | }
79 |
80 | app.UseRouting();
81 |
82 | app.UseAuthorization();
83 |
84 | app.UseEndpoints(endpoints =>
85 | {
86 | endpoints.MapControllers();
87 | });
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Basket/Basket.API/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ConnectionStrings": {
3 | "RedisCache": "localhost:6379"
4 | },
5 |
6 | "Logging": {
7 | "LogLevel": {
8 | "Default": "Information",
9 | "Microsoft": "Warning",
10 | "Microsoft.Hosting.Lifetime": "Information"
11 | }
12 | },
13 | "AllowedHosts": "*",
14 |
15 | "EventBusHostName": "localhost",
16 | "EventBusUserName": "guest",
17 | "EventBusPassword": "guest"
18 | }
19 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Catalog.API.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 | all
12 | runtime; build; native; contentfiles; analyzers; buildtransitive
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Controllers/CatalogController.cs:
--------------------------------------------------------------------------------
1 | using Catalog.API.Repositories.Interfaces;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 | using System;
5 | using System.Threading.Tasks;
6 |
7 | namespace Catalog.API.Controllers
8 | {
9 | [Route("api/v1/[controller]")]
10 | [ApiController]
11 | public class CatalogController : ControllerBase
12 | {
13 | private readonly IProductRepository _repository;
14 | private readonly ILogger _logger;
15 |
16 | public CatalogController(IProductRepository repository, ILogger logger)
17 | {
18 | _repository = repository ?? throw new ArgumentNullException(nameof(repository));
19 | _logger = logger ?? throw new ArgumentNullException(nameof(logger));
20 | }
21 |
22 | [HttpGet]
23 | public async Task GetProducts()
24 | {
25 | var products = await _repository.GetProducts();
26 | return Ok(products);
27 | }
28 |
29 | [HttpGet("{id}")]
30 | public async Task GetProductById(int id)
31 | {
32 | var productWithCategory = await _repository.GetProductById(id);
33 |
34 | if (productWithCategory == null)
35 | {
36 | return NotFound();
37 | }
38 |
39 | return Ok(productWithCategory);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Data/CatalogContext.cs:
--------------------------------------------------------------------------------
1 | using Catalog.API.Entities;
2 | using Microsoft.EntityFrameworkCore;
3 |
4 | namespace Catalog.API.Data
5 | {
6 | public class CatalogContext : DbContext
7 | {
8 | public CatalogContext(DbContextOptions options)
9 | : base(options)
10 | {
11 | }
12 |
13 | public DbSet Products { get; set; }
14 | public DbSet Categories { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Data/CatalogContextSeed.cs:
--------------------------------------------------------------------------------
1 | using Catalog.API.Entities;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 |
8 | namespace Catalog.API.Data
9 | {
10 | public class CatalogContextSeed
11 | {
12 | public static async Task SeedAsync(CatalogContext aspnetrunContext, ILoggerFactory loggerFactory, int? retry = 0)
13 | {
14 | int retryForAvailability = retry.Value;
15 |
16 | try
17 | {
18 | // TODO: Only run this if using a real database
19 | // aspnetrunContext.Database.Migrate();
20 | // aspnetrunContext.Database.EnsureCreated();
21 |
22 | if (!aspnetrunContext.Categories.Any())
23 | {
24 | aspnetrunContext.Categories.AddRange(GetPreconfiguredCategories());
25 | await aspnetrunContext.SaveChangesAsync();
26 | }
27 |
28 | if (!aspnetrunContext.Products.Any())
29 | {
30 | aspnetrunContext.Products.AddRange(GetPreconfiguredProducts());
31 | await aspnetrunContext.SaveChangesAsync();
32 | }
33 | }
34 | catch (Exception exception)
35 | {
36 | if (retryForAvailability < 10)
37 | {
38 | retryForAvailability++;
39 | var log = loggerFactory.CreateLogger();
40 | log.LogError(exception.Message);
41 | await SeedAsync(aspnetrunContext, loggerFactory, retryForAvailability);
42 | }
43 | throw;
44 | }
45 | }
46 |
47 | private static IEnumerable GetPreconfiguredCategories()
48 | {
49 | return new List()
50 | {
51 | new Category()
52 | {
53 | Name = "White Appliances",
54 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat.",
55 | ImageName = "one"
56 | },
57 | new Category()
58 | {
59 | Name = "Smart Watches",
60 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat.",
61 | ImageName = "two"
62 | },
63 | new Category()
64 | {
65 | Name = "Home & Kitchen",
66 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat.",
67 | ImageName = "tree"
68 | }
69 | };
70 | }
71 |
72 | private static IEnumerable GetPreconfiguredProducts()
73 | {
74 | return new List()
75 | {
76 | new Product()
77 | {
78 | Name = "IPhone X",
79 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
80 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
81 | ImageFile = "product-1.png",
82 | Price = 950.00M,
83 | CategoryId = 1
84 | },
85 | new Product()
86 | {
87 | Name = "Samsung 10",
88 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
89 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
90 | ImageFile = "product-2.png",
91 | Price = 840.00M,
92 | CategoryId = 1
93 | },
94 | new Product()
95 | {
96 | Name = "Huawei Plus",
97 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
98 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
99 | ImageFile = "product-3.png",
100 | Price = 650.00M,
101 | CategoryId = 2
102 | },
103 | new Product()
104 | {
105 | Name = "Xiaomi Mi 9",
106 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
107 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
108 | ImageFile = "product-4.png",
109 | Price = 470.00M,
110 | CategoryId = 1
111 | },
112 | new Product()
113 | {
114 | Name = "HTC U11+ Plus",
115 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
116 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
117 | ImageFile = "product-5.png",
118 | Price = 380.00M,
119 | CategoryId = 1
120 | },
121 | new Product()
122 | {
123 | Name = "LG G7 ThinQ",
124 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.",
125 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.",
126 | ImageFile = "product-6.png",
127 | Price = 240.00M,
128 | CategoryId = 1
129 | }
130 | };
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Entities/Category.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace Catalog.API.Entities
4 | {
5 | public class Category
6 | {
7 | public int Id { get; set; }
8 |
9 | [Required, StringLength(80)]
10 | public string Name { get; set; }
11 | public string Description { get; set; }
12 | public string ImageName { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Entities/Product.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace Catalog.API.Entities
4 | {
5 | public class Product
6 | {
7 | public int Id { get; set; }
8 |
9 | [Required, StringLength(80)]
10 | public string Name { get; set; }
11 |
12 | public string Summary { get; set; }
13 | public string Description { get; set; }
14 | public string ImageFile { get; set; }
15 | public decimal Price { get; set; }
16 | public int CategoryId { get; set; }
17 | public Category Category { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Migrations/20200401150236_initial.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using Catalog.API.Data;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.EntityFrameworkCore.Infrastructure;
5 | using Microsoft.EntityFrameworkCore.Metadata;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | namespace Catalog.API.Migrations
10 | {
11 | [DbContext(typeof(CatalogContext))]
12 | [Migration("20200401150236_initial")]
13 | partial class initial
14 | {
15 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
16 | {
17 | #pragma warning disable 612, 618
18 | modelBuilder
19 | .HasAnnotation("ProductVersion", "3.1.3")
20 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
21 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
22 |
23 | modelBuilder.Entity("Catalog.API.Entities.Category", b =>
24 | {
25 | b.Property("Id")
26 | .ValueGeneratedOnAdd()
27 | .HasColumnType("int")
28 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
29 |
30 | b.Property("Description")
31 | .HasColumnType("nvarchar(max)");
32 |
33 | b.Property("ImageName")
34 | .HasColumnType("nvarchar(max)");
35 |
36 | b.Property("Name")
37 | .IsRequired()
38 | .HasColumnType("nvarchar(80)")
39 | .HasMaxLength(80);
40 |
41 | b.HasKey("Id");
42 |
43 | b.ToTable("Categories");
44 | });
45 |
46 | modelBuilder.Entity("Catalog.API.Entities.Product", b =>
47 | {
48 | b.Property("Id")
49 | .ValueGeneratedOnAdd()
50 | .HasColumnType("int")
51 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
52 |
53 | b.Property("CategoryId")
54 | .HasColumnType("int");
55 |
56 | b.Property("Description")
57 | .HasColumnType("nvarchar(max)");
58 |
59 | b.Property("ImageFile")
60 | .HasColumnType("nvarchar(max)");
61 |
62 | b.Property("Name")
63 | .IsRequired()
64 | .HasColumnType("nvarchar(80)")
65 | .HasMaxLength(80);
66 |
67 | b.Property("Price")
68 | .HasColumnType("decimal(18,2)");
69 |
70 | b.Property("Summary")
71 | .HasColumnType("nvarchar(max)");
72 |
73 | b.HasKey("Id");
74 |
75 | b.HasIndex("CategoryId");
76 |
77 | b.ToTable("Products");
78 | });
79 |
80 | modelBuilder.Entity("Catalog.API.Entities.Product", b =>
81 | {
82 | b.HasOne("Catalog.API.Entities.Category", "Category")
83 | .WithMany()
84 | .HasForeignKey("CategoryId")
85 | .OnDelete(DeleteBehavior.Cascade)
86 | .IsRequired();
87 | });
88 | #pragma warning restore 612, 618
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Migrations/20200401150236_initial.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | namespace Catalog.API.Migrations
4 | {
5 | public partial class initial : Migration
6 | {
7 | protected override void Up(MigrationBuilder migrationBuilder)
8 | {
9 | migrationBuilder.CreateTable(
10 | name: "Categories",
11 | columns: table => new
12 | {
13 | Id = table.Column(nullable: false)
14 | .Annotation("SqlServer:Identity", "1, 1"),
15 | Name = table.Column(maxLength: 80, nullable: false),
16 | Description = table.Column(nullable: true),
17 | ImageName = table.Column(nullable: true)
18 | },
19 | constraints: table =>
20 | {
21 | table.PrimaryKey("PK_Categories", x => x.Id);
22 | });
23 |
24 | migrationBuilder.CreateTable(
25 | name: "Products",
26 | columns: table => new
27 | {
28 | Id = table.Column(nullable: false)
29 | .Annotation("SqlServer:Identity", "1, 1"),
30 | Name = table.Column(maxLength: 80, nullable: false),
31 | Summary = table.Column(nullable: true),
32 | Description = table.Column(nullable: true),
33 | ImageFile = table.Column(nullable: true),
34 | Price = table.Column(nullable: false),
35 | CategoryId = table.Column(nullable: false)
36 | },
37 | constraints: table =>
38 | {
39 | table.PrimaryKey("PK_Products", x => x.Id);
40 | table.ForeignKey(
41 | name: "FK_Products_Categories_CategoryId",
42 | column: x => x.CategoryId,
43 | principalTable: "Categories",
44 | principalColumn: "Id",
45 | onDelete: ReferentialAction.Cascade);
46 | });
47 |
48 | migrationBuilder.CreateIndex(
49 | name: "IX_Products_CategoryId",
50 | table: "Products",
51 | column: "CategoryId");
52 | }
53 |
54 | protected override void Down(MigrationBuilder migrationBuilder)
55 | {
56 | migrationBuilder.DropTable(
57 | name: "Products");
58 |
59 | migrationBuilder.DropTable(
60 | name: "Categories");
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Migrations/CatalogContextModelSnapshot.cs:
--------------------------------------------------------------------------------
1 | //
2 | using Catalog.API.Data;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.EntityFrameworkCore.Infrastructure;
5 | using Microsoft.EntityFrameworkCore.Metadata;
6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
7 |
8 | namespace Catalog.API.Migrations
9 | {
10 | [DbContext(typeof(CatalogContext))]
11 | partial class CatalogContextModelSnapshot : ModelSnapshot
12 | {
13 | protected override void BuildModel(ModelBuilder modelBuilder)
14 | {
15 | #pragma warning disable 612, 618
16 | modelBuilder
17 | .HasAnnotation("ProductVersion", "3.1.3")
18 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
19 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
20 |
21 | modelBuilder.Entity("Catalog.API.Entities.Category", b =>
22 | {
23 | b.Property("Id")
24 | .ValueGeneratedOnAdd()
25 | .HasColumnType("int")
26 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 |
28 | b.Property("Description")
29 | .HasColumnType("nvarchar(max)");
30 |
31 | b.Property("ImageName")
32 | .HasColumnType("nvarchar(max)");
33 |
34 | b.Property("Name")
35 | .IsRequired()
36 | .HasColumnType("nvarchar(80)")
37 | .HasMaxLength(80);
38 |
39 | b.HasKey("Id");
40 |
41 | b.ToTable("Categories");
42 | });
43 |
44 | modelBuilder.Entity("Catalog.API.Entities.Product", b =>
45 | {
46 | b.Property("Id")
47 | .ValueGeneratedOnAdd()
48 | .HasColumnType("int")
49 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
50 |
51 | b.Property("CategoryId")
52 | .HasColumnType("int");
53 |
54 | b.Property("Description")
55 | .HasColumnType("nvarchar(max)");
56 |
57 | b.Property("ImageFile")
58 | .HasColumnType("nvarchar(max)");
59 |
60 | b.Property("Name")
61 | .IsRequired()
62 | .HasColumnType("nvarchar(80)")
63 | .HasMaxLength(80);
64 |
65 | b.Property("Price")
66 | .HasColumnType("decimal(18,2)");
67 |
68 | b.Property("Summary")
69 | .HasColumnType("nvarchar(max)");
70 |
71 | b.HasKey("Id");
72 |
73 | b.HasIndex("CategoryId");
74 |
75 | b.ToTable("Products");
76 | });
77 |
78 | modelBuilder.Entity("Catalog.API.Entities.Product", b =>
79 | {
80 | b.HasOne("Catalog.API.Entities.Category", "Category")
81 | .WithMany()
82 | .HasForeignKey("CategoryId")
83 | .OnDelete(DeleteBehavior.Cascade)
84 | .IsRequired();
85 | });
86 | #pragma warning restore 612, 618
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Catalog.API.Data;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 | using Microsoft.Extensions.Logging;
7 |
8 | namespace Catalog.API
9 | {
10 | public class Program
11 | {
12 | public static void Main(string[] args)
13 | {
14 | var host = CreateHostBuilder(args).Build();
15 | SeedDatabase(host);
16 | host.Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 |
26 | private static void SeedDatabase(IHost host)
27 | {
28 | using (var scope = host.Services.CreateScope())
29 | {
30 | var services = scope.ServiceProvider;
31 | var loggerFactory = services.GetRequiredService();
32 |
33 | try
34 | {
35 | var aspnetRunContext = services.GetRequiredService();
36 | CatalogContextSeed.SeedAsync(aspnetRunContext, loggerFactory).Wait();
37 | }
38 | catch (Exception exception)
39 | {
40 | var logger = loggerFactory.CreateLogger();
41 | logger.LogError(exception, "An error occurred seeding the DB.");
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Repositories/Interfaces/IProductRepository.cs:
--------------------------------------------------------------------------------
1 | using Catalog.API.Entities;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace Catalog.API.Repositories.Interfaces
6 | {
7 | public interface IProductRepository
8 | {
9 | Task> GetProducts();
10 | Task GetProductById(int id);
11 | Task> GetProductByName(string name);
12 | Task> GetProductByCategory(int categoryId);
13 | Task> GetCategories();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Repositories/ProductRepository.cs:
--------------------------------------------------------------------------------
1 | using Catalog.API.Data;
2 | using Catalog.API.Entities;
3 | using Catalog.API.Repositories.Interfaces;
4 | using Microsoft.EntityFrameworkCore;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 |
10 | namespace Catalog.API.Repositories
11 | {
12 | public class ProductRepository : IProductRepository
13 | {
14 | protected readonly CatalogContext _dbContext;
15 |
16 | public ProductRepository(CatalogContext dbContext)
17 | {
18 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
19 | }
20 |
21 | public async Task> GetProducts()
22 | {
23 | return await _dbContext.Products.ToListAsync();
24 | }
25 |
26 | public async Task GetProductById(int id)
27 | {
28 | return await _dbContext.Products
29 | .Include(p => p.Category)
30 | .FirstOrDefaultAsync(p => p.Id == id);
31 | }
32 |
33 | public async Task> GetProductByName(string name)
34 | {
35 | return await _dbContext.Products
36 | .Include(p => p.Category)
37 | .Where(p => string.IsNullOrEmpty(name) || p.Name.ToLower().Contains(name.ToLower()))
38 | .OrderBy(p => p.Name)
39 | .ToListAsync();
40 | }
41 |
42 | public async Task> GetProductByCategory(int categoryId)
43 | {
44 | return await _dbContext.Products
45 | .Where(x => x.CategoryId == categoryId)
46 | .ToListAsync();
47 | }
48 |
49 | public async Task AddAsync(Product product)
50 | {
51 | _dbContext.Products.Add(product);
52 | await _dbContext.SaveChangesAsync();
53 | return product;
54 | }
55 |
56 | public async Task UpdateAsync(Product product)
57 | {
58 | _dbContext.Entry(product).State = EntityState.Modified;
59 | await _dbContext.SaveChangesAsync();
60 | }
61 |
62 | public async Task DeleteAsync(Product product)
63 | {
64 | _dbContext.Products.Remove(product);
65 | await _dbContext.SaveChangesAsync();
66 | }
67 |
68 | public async Task> GetCategories()
69 | {
70 | return await _dbContext.Categories.ToListAsync();
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/Startup.cs:
--------------------------------------------------------------------------------
1 | using Catalog.API.Data;
2 | using Catalog.API.Repositories;
3 | using Catalog.API.Repositories.Interfaces;
4 | using Microsoft.AspNetCore.Builder;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.EntityFrameworkCore;
7 | using Microsoft.Extensions.Configuration;
8 | using Microsoft.Extensions.DependencyInjection;
9 | using Microsoft.Extensions.Hosting;
10 |
11 | namespace Catalog.API
12 | {
13 | public class Startup
14 | {
15 | public Startup(IConfiguration configuration)
16 | {
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 | {
25 | #region database services
26 |
27 | //// use in-memory database
28 | //services.AddDbContext(c =>
29 | // c.UseInMemoryDatabase("AspnetRunConnection"));
30 |
31 | // add database dependecy
32 | services.AddDbContext(c =>
33 | c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection")));
34 |
35 | #endregion
36 |
37 | #region project services
38 |
39 | // add repository dependecy
40 | services.AddScoped();
41 |
42 | #endregion
43 |
44 | services.AddControllers();
45 | }
46 |
47 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
48 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
49 | {
50 | if (env.IsDevelopment())
51 | {
52 | app.UseDeveloperExceptionPage();
53 | }
54 |
55 | app.UseRouting();
56 |
57 | app.UseAuthorization();
58 |
59 | app.UseEndpoints(endpoints =>
60 | {
61 | endpoints.MapControllers();
62 | });
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Catalog/Catalog.API/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ConnectionStrings": {
3 | "CatalogConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=CatalogDB;"
4 | },
5 | "Logging": {
6 | "LogLevel": {
7 | "Default": "Information",
8 | "Microsoft": "Warning",
9 | "Microsoft.Hosting.Lifetime": "Information"
10 | }
11 | },
12 | "AllowedHosts": "*"
13 | }
14 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/Controllers/OrderController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.Extensions.Logging;
7 |
8 | namespace Order.API.Controllers
9 | {
10 | [ApiController]
11 | [Route("[controller]")]
12 | public class OrderController : ControllerBase
13 | {
14 | //private readonly IBasketRepository _repository;
15 | private readonly ILogger _logger;
16 |
17 | //public BasketController(IBasketRepository repository, EventBusRabbitMQPublisher eventBus, ILogger logger)
18 | //{
19 | // _repository = repository ?? throw new ArgumentNullException(nameof(repository));
20 | // _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
21 | // _logger = logger ?? throw new ArgumentNullException(nameof(logger));
22 | //}
23 |
24 | //[HttpGet("{id}")]
25 | //[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
26 | //public async Task> GetBasketByIdAsync(string id)
27 | //{
28 | // var basket = await _repository.GetBasketAsync(id);
29 | // return Ok(basket ?? new CustomerBasket(id));
30 | //}
31 |
32 |
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/Order.API.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace Order.API
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | CreateHostBuilder(args).Build().Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/RabbitMq/EventBusRabbitMQConsumer.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using RabbitMQ.Client;
3 | using RabbitMQ.Client.Events;
4 | using System;
5 | using System.Text;
6 |
7 | namespace Order.API.RabbitMq
8 | {
9 | public class EventBusRabbitMQConsumer
10 | {
11 | const string QUEUE_NAME = "basketCheckoutQueue";
12 |
13 | private readonly IRabbitMQConnection _connection;
14 |
15 | public EventBusRabbitMQConsumer(IRabbitMQConnection connection)
16 | {
17 | _connection = connection ?? throw new ArgumentNullException(nameof(connection));
18 | }
19 |
20 | public void Consume()
21 | {
22 | var channel = _connection.CreateModel();
23 | channel.QueueDeclare(queue: QUEUE_NAME, durable: false, exclusive: false, autoDelete: false, arguments: null);
24 |
25 | var consumer = new EventingBasicConsumer(channel);
26 |
27 | //Create event when something receive
28 | consumer.Received += ReceivedEvent;
29 |
30 | channel.BasicConsume(queue: QUEUE_NAME, autoAck: true, consumer: consumer);
31 | }
32 |
33 | private void ReceivedEvent(object sender, BasicDeliverEventArgs e)
34 | {
35 | if (e.RoutingKey == QUEUE_NAME)
36 | {
37 | var message = Encoding.UTF8.GetString(e.Body);
38 | BasketCheckout basketCheckout = JsonConvert.DeserializeObject(message);
39 |
40 | // TODO : stuff
41 | }
42 | }
43 |
44 | public void Disconnect()
45 | {
46 | _connection.Dispose();
47 | }
48 | }
49 |
50 | public class BasketCheckout
51 | {
52 | public string City { get; set; }
53 | public string Street { get; set; }
54 | public string State { get; set; }
55 | public string Country { get; set; }
56 | public string ZipCode { get; set; }
57 | public string CardNumber { get; set; }
58 | public string CardHolderName { get; set; }
59 | public DateTime CardExpiration { get; set; }
60 | public string CardSecurityNumber { get; set; }
61 | public int CardTypeId { get; set; }
62 | public string Buyer { get; set; }
63 | public Guid RequestId { get; set; }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/RabbitMq/IRabbitMQConnection.cs:
--------------------------------------------------------------------------------
1 | using RabbitMQ.Client;
2 | using System;
3 |
4 | namespace Order.API.RabbitMq
5 | {
6 | public interface IRabbitMQConnection : IDisposable
7 | {
8 | bool IsConnected { get; }
9 | bool TryConnect();
10 | IModel CreateModel();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/RabbitMq/RabbitMQConnection.cs:
--------------------------------------------------------------------------------
1 | using RabbitMQ.Client;
2 | using RabbitMQ.Client.Exceptions;
3 | using System;
4 | using System.IO;
5 | using System.Threading;
6 |
7 | namespace Order.API.RabbitMq
8 | {
9 | public class RabbitMQConnection : IRabbitMQConnection
10 | {
11 | private readonly IConnectionFactory _connectionFactory;
12 | private IConnection _connection;
13 | private bool _disposed;
14 |
15 | public RabbitMQConnection(IConnectionFactory connectionFactory)
16 | {
17 | _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
18 | if (!IsConnected)
19 | {
20 | TryConnect();
21 | }
22 | }
23 |
24 | public bool IsConnected
25 | {
26 | get
27 | {
28 | return _connection != null && _connection.IsOpen && !_disposed;
29 | }
30 | }
31 |
32 | public bool TryConnect()
33 | {
34 | try
35 | {
36 | _connection = _connectionFactory.CreateConnection();
37 | }
38 | catch (BrokerUnreachableException)
39 | {
40 | Thread.Sleep(2000);
41 | _connection = _connectionFactory.CreateConnection();
42 | }
43 |
44 | if (IsConnected)
45 | {
46 | Console.WriteLine($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events");
47 | return true;
48 | }
49 | else
50 | {
51 | Console.WriteLine("FATAL ERROR: RabbitMQ connections could not be created and opened");
52 | return false;
53 | }
54 | }
55 |
56 | public IModel CreateModel()
57 | {
58 | if (!IsConnected)
59 | {
60 | throw new InvalidOperationException("No RabbitMQ connections are available to perform this action");
61 | }
62 | return _connection.CreateModel();
63 | }
64 |
65 | public void Dispose()
66 | {
67 | if (_disposed) return;
68 |
69 | _disposed = true;
70 |
71 | try
72 | {
73 | _connection.Dispose();
74 | }
75 | catch (IOException ex)
76 | {
77 | Console.WriteLine(ex.ToString());
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.Extensions.Configuration;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 | using Order.API.RabbitMq;
7 | using RabbitMQ.Client;
8 |
9 | namespace Order.API
10 | {
11 | public class Startup
12 | {
13 | public Startup(IConfiguration configuration)
14 | {
15 | Configuration = configuration;
16 | }
17 |
18 | public IConfiguration Configuration { get; }
19 |
20 | // This method gets called by the runtime. Use this method to add services to the container.
21 | public void ConfigureServices(IServiceCollection services)
22 | {
23 | services.AddControllers();
24 |
25 | #region project services
26 |
27 | // add repository dependecy
28 |
29 | services.AddSingleton(sp =>
30 | {
31 | var factory = new ConnectionFactory()
32 | {
33 | HostName = Configuration["EventBusHostName"]
34 | };
35 |
36 | if (!string.IsNullOrEmpty(Configuration["EventBusUserName"]))
37 | {
38 | factory.UserName = Configuration["EventBusUserName"];
39 | }
40 |
41 | if (!string.IsNullOrEmpty(Configuration["EventBusPassword"]))
42 | {
43 | factory.Password = Configuration["EventBusPassword"];
44 | }
45 |
46 | return new RabbitMQConnection(factory);
47 | });
48 |
49 | services.AddSingleton();
50 |
51 | #endregion
52 | }
53 |
54 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
55 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
56 | {
57 | if (env.IsDevelopment())
58 | {
59 | app.UseDeveloperExceptionPage();
60 | }
61 |
62 | app.UseRouting();
63 |
64 | app.UseAuthorization();
65 |
66 | app.UseEndpoints(endpoints =>
67 | {
68 | endpoints.MapControllers();
69 | });
70 |
71 | //Initilize Rabbit Listener in ApplicationBuilderExtentions
72 | app.UseRabbitListener();
73 | }
74 | }
75 |
76 | public static class ApplicationBuilderExtentions
77 | {
78 | public static EventBusRabbitMQConsumer Listener { get; set; }
79 |
80 | public static IApplicationBuilder UseRabbitListener(this IApplicationBuilder app)
81 | {
82 | Listener = app.ApplicationServices.GetService();
83 | var life = app.ApplicationServices.GetService();
84 |
85 | life.ApplicationStarted.Register(OnStarted);
86 | life.ApplicationStopping.Register(OnStopping);
87 |
88 | return app;
89 | }
90 |
91 | private static void OnStarted()
92 | {
93 | Listener.Consume();
94 | }
95 |
96 | private static void OnStopping()
97 | {
98 | Listener.Disconnect();
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.API/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*",
10 |
11 | "EventBusHostName": "localhost",
12 | "EventBusUserName": "guest",
13 | "EventBusPassword": "guest"
14 | }
15 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.Infrastructure/Data/OrderContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace Order.Infrastructure.Data
7 | {
8 | // https://www.npgsql.org/efcore/index.html
9 | // https://medium.com/faun/asp-net-core-entity-framework-core-with-postgresql-code-first-d99b909796d7
10 | public class OrderContext : DbContext
11 | {
12 | public OrderContext(DbContextOptions options) : base(options)
13 | {
14 | // TODO : Burdasın -- postresql ayrı class lib olmadı -- o zaman bunu catalog da yap burda sql server olsun
15 | // olmuyor degistir
16 | }
17 |
18 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
19 | => optionsBuilder.UseNpgsql("Host=my_host;Database=my_db;Username=my_user;Password=my_pw");
20 |
21 | public DbSet Orders { get; set; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.Infrastructure/Data/OrderContextSeed.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Order.Infrastructure.Data
9 | {
10 | public class OrderContextSeed
11 | {
12 | public static async Task SeedAsync(OrderContext aspnetrunContext, ILoggerFactory loggerFactory, int? retry = 0)
13 | {
14 | int retryForAvailability = retry.Value;
15 |
16 | try
17 | {
18 | // TODO: Only run this if using a real database
19 | // aspnetrunContext.Database.Migrate();
20 | // aspnetrunContext.Database.EnsureCreated();
21 |
22 | if (!aspnetrunContext.Orders.Any())
23 | {
24 | aspnetrunContext.Orders.AddRange(GetPreconfiguredOrders());
25 | await aspnetrunContext.SaveChangesAsync();
26 | }
27 |
28 | }
29 | catch (Exception exception)
30 | {
31 | if (retryForAvailability < 10)
32 | {
33 | retryForAvailability++;
34 | var log = loggerFactory.CreateLogger();
35 | log.LogError(exception.Message);
36 | await SeedAsync(aspnetrunContext, loggerFactory, retryForAvailability);
37 | }
38 | throw;
39 | }
40 | }
41 |
42 | private static IEnumerable GetPreconfiguredOrders()
43 | {
44 | return new List()
45 | {
46 | new Order.Core.Entities.Order() { FirstName = "swn", LastName = "asd", AddressLine = "bahcelievler" },
47 | new Order.Core.Entities.Order() { FirstName = "swn2", LastName = "asd2", AddressLine = "bahcelievler2" }
48 | };
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.Infrastructure/Order.Infrastructure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 | all
10 | runtime; build; native; contentfiles; analyzers; buildtransitive
11 |
12 |
13 | all
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.Infrastructure/Repository/Base/Repository.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 | using Order.Core.Entities.Base;
3 | using Order.Core.Repositories.Base;
4 | using Order.Infrastructure.Data;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Linq.Expressions;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace Order.Infrastructure.Repository.Base
13 | {
14 | public class Repository : IRepository where T : Entity
15 | {
16 | protected readonly OrderContext _dbContext;
17 |
18 | public Repository(OrderContext dbContext)
19 | {
20 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
21 | }
22 |
23 | public async Task> GetAllAsync()
24 | {
25 | return await _dbContext.Set().ToListAsync();
26 | }
27 |
28 | public async Task> GetAsync(Expression> predicate)
29 | {
30 | return await _dbContext.Set().Where(predicate).ToListAsync();
31 | }
32 |
33 | public async Task> GetAsync(Expression> predicate = null, Func, IOrderedQueryable> orderBy = null, string includeString = null, bool disableTracking = true)
34 | {
35 | IQueryable query = _dbContext.Set();
36 | if (disableTracking) query = query.AsNoTracking();
37 |
38 | if (!string.IsNullOrWhiteSpace(includeString)) query = query.Include(includeString);
39 |
40 | if (predicate != null) query = query.Where(predicate);
41 |
42 | if (orderBy != null)
43 | return await orderBy(query).ToListAsync();
44 | return await query.ToListAsync();
45 | }
46 |
47 | public async Task> GetAsync(Expression> predicate = null, Func, IOrderedQueryable> orderBy = null, List>> includes = null, bool disableTracking = true)
48 | {
49 | IQueryable query = _dbContext.Set();
50 | if (disableTracking) query = query.AsNoTracking();
51 |
52 | if (includes != null) query = includes.Aggregate(query, (current, include) => current.Include(include));
53 |
54 | if (predicate != null) query = query.Where(predicate);
55 |
56 | if (orderBy != null)
57 | return await orderBy(query).ToListAsync();
58 | return await query.ToListAsync();
59 | }
60 |
61 | public virtual async Task GetByIdAsync(int id)
62 | {
63 | return await _dbContext.Set().FindAsync(id);
64 | }
65 |
66 | public async Task AddAsync(T entity)
67 | {
68 | _dbContext.Set().Add(entity);
69 | await _dbContext.SaveChangesAsync();
70 | return entity;
71 | }
72 |
73 | public async Task UpdateAsync(T entity)
74 | {
75 | _dbContext.Entry(entity).State = EntityState.Modified;
76 | await _dbContext.SaveChangesAsync();
77 | }
78 |
79 | public async Task DeleteAsync(T entity)
80 | {
81 | _dbContext.Set().Remove(entity);
82 | await _dbContext.SaveChangesAsync();
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/basicmicroservice/src/Order/Order.Infrastructure/Repository/OrderRepository.cs:
--------------------------------------------------------------------------------
1 | using Order.Core.Repositories;
2 | using Order.Infrastructure.Data;
3 | using Order.Infrastructure.Repository.Base;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Order.Infrastructure.Repository
10 | {
11 | public class OrderRepository : Repository, IOrderRepository
12 | {
13 | public OrderRepository(OrderContext dbContext) : base(dbContext)
14 | {
15 | }
16 |
17 | public async Task> GetOrderListAsync()
18 | {
19 | // second way
20 | return await GetAllAsync();
21 | }
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/Controllers/BooksController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using Shipment.API.Entities;
3 | using Shipment.API.Services;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 |
9 | namespace Shipment.API.Controllers
10 | {
11 | [Route("api/[controller]")]
12 | [ApiController]
13 | public class BooksController : ControllerBase
14 | {
15 | private readonly BookService _bookService;
16 |
17 | public BooksController(BookService bookService)
18 | {
19 | _bookService = bookService;
20 | }
21 |
22 | [HttpGet]
23 | public ActionResult> Get() =>
24 | _bookService.Get();
25 |
26 | [HttpGet("{id:length(24)}", Name = "GetBook")]
27 | public ActionResult Get(string id)
28 | {
29 | var book = _bookService.Get(id);
30 |
31 | if (book == null)
32 | {
33 | return NotFound();
34 | }
35 |
36 | return book;
37 | }
38 |
39 | [HttpPost]
40 | public ActionResult Create(Book book)
41 | {
42 | _bookService.Create(book);
43 |
44 | return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);
45 | }
46 |
47 | [HttpPut("{id:length(24)}")]
48 | public IActionResult Update(string id, Book bookIn)
49 | {
50 | var book = _bookService.Get(id);
51 |
52 | if (book == null)
53 | {
54 | return NotFound();
55 | }
56 |
57 | _bookService.Update(id, bookIn);
58 |
59 | return NoContent();
60 | }
61 |
62 | [HttpDelete("{id:length(24)}")]
63 | public IActionResult Delete(string id)
64 | {
65 | var book = _bookService.Get(id);
66 |
67 | if (book == null)
68 | {
69 | return NotFound();
70 | }
71 |
72 | _bookService.Remove(book.Id);
73 |
74 | return NoContent();
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/Controllers/ShipmentController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace Shipment.API.Controllers
8 | {
9 | public class ShipmentController : ControllerBase
10 | {
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/Entities/Book.cs:
--------------------------------------------------------------------------------
1 | using MongoDB.Bson;
2 | using MongoDB.Bson.Serialization.Attributes;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 |
8 | namespace Shipment.API.Entities
9 | {
10 | public class Book
11 | {
12 | [BsonId]
13 | [BsonRepresentation(BsonType.ObjectId)]
14 | public string Id { get; set; }
15 |
16 | [BsonElement("Name")]
17 | public string BookName { get; set; }
18 |
19 | public decimal Price { get; set; }
20 |
21 | public string Category { get; set; }
22 |
23 | public string Author { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace Shipment.API
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | CreateHostBuilder(args).Build().Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/Services/BookService.cs:
--------------------------------------------------------------------------------
1 | using MongoDB.Driver;
2 | using Shipment.API.Entities;
3 | using Shipment.API.Settings;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 |
9 | namespace Shipment.API.Services
10 | {
11 | public class BookService
12 | {
13 | private readonly IMongoCollection _books;
14 |
15 | public BookService(IBookstoreDatabaseSettings settings)
16 | {
17 | var client = new MongoClient(settings.ConnectionString);
18 | var database = client.GetDatabase(settings.DatabaseName);
19 |
20 | _books = database.GetCollection(settings.BooksCollectionName);
21 | }
22 |
23 | public List Get() =>
24 | _books.Find(book => true).ToList();
25 |
26 | public Book Get(string id) =>
27 | _books.Find(book => book.Id == id).FirstOrDefault();
28 |
29 | public Book Create(Book book)
30 | {
31 | _books.InsertOne(book);
32 | return book;
33 | }
34 |
35 | public void Update(string id, Book bookIn) =>
36 | _books.ReplaceOne(book => book.Id == id, bookIn);
37 |
38 | public void Remove(Book bookIn) =>
39 | _books.DeleteOne(book => book.Id == bookIn.Id);
40 |
41 | public void Remove(string id) =>
42 | _books.DeleteOne(book => book.Id == id);
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/Settings/BookstoreDatabaseSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace Shipment.API.Settings
7 | {
8 | public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
9 | {
10 | public string BooksCollectionName { get; set; }
11 | public string ConnectionString { get; set; }
12 | public string DatabaseName { get; set; }
13 | }
14 |
15 | public interface IBookstoreDatabaseSettings
16 | {
17 | string BooksCollectionName { get; set; }
18 | string ConnectionString { get; set; }
19 | string DatabaseName { get; set; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/Shipment.API.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/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.Mvc;
8 | using Microsoft.Extensions.Configuration;
9 | using Microsoft.Extensions.DependencyInjection;
10 | using Microsoft.Extensions.Hosting;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 | using Shipment.API.Services;
14 | using Shipment.API.Settings;
15 |
16 | namespace Shipment.API
17 | {
18 | public class Startup
19 | {
20 | public Startup(IConfiguration configuration)
21 | {
22 | Configuration = configuration;
23 | }
24 |
25 | public IConfiguration Configuration { get; }
26 |
27 | // This method gets called by the runtime. Use this method to add services to the container.
28 | public void ConfigureServices(IServiceCollection services)
29 | {
30 | // requires using Microsoft.Extensions.Options
31 | services.Configure(
32 | Configuration.GetSection(nameof(BookstoreDatabaseSettings)));
33 |
34 | services.AddSingleton(sp =>
35 | sp.GetRequiredService>().Value);
36 |
37 | services.AddSingleton();
38 |
39 | services.AddControllers();
40 | }
41 |
42 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
43 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
44 | {
45 | if (env.IsDevelopment())
46 | {
47 | app.UseDeveloperExceptionPage();
48 | }
49 |
50 | app.UseRouting();
51 |
52 | app.UseAuthorization();
53 |
54 | app.UseEndpoints(endpoints =>
55 | {
56 | endpoints.MapControllers();
57 | });
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/basicmicroservice/src/shipment/Shipment.API/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "BookstoreDatabaseSettings": {
3 | "BooksCollectionName": "Books",
4 | "ConnectionString": "mongodb://localhost:27017",
5 | "DatabaseName": "BookstoreDb"
6 | },
7 | "Logging": {
8 | "LogLevel": {
9 | "Default": "Information",
10 | "Microsoft": "Warning",
11 | "Microsoft.Hosting.Lifetime": "Information"
12 | }
13 | },
14 | "AllowedHosts": "*"
15 | }
16 |
--------------------------------------------------------------------------------
/basicmicroservice/src/webui/ShopApp/Pages/Error.cshtml:
--------------------------------------------------------------------------------
1 | @page
2 | @model ErrorModel
3 | @{
4 | ViewData["Title"] = "Error";
5 | }
6 |
7 |
Error.
8 |
An error occurred while processing your request.
9 |
10 | @if (Model.ShowRequestId)
11 | {
12 |
13 | Request ID:@Model.RequestId
14 |
15 | }
16 |
17 |
Development Mode
18 |
19 | Swapping to the Development environment displays detailed information about the error that occurred.
20 |
21 |
22 | The Development environment shouldn't be enabled for deployed applications.
23 | It can result in displaying sensitive information from exceptions to end users.
24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
25 | and restarting the app.
26 |