├── .gitattributes
├── .gitignore
├── 1_Tpfkss_hdHNyaaJ_3bBgWQ.png
├── CleanArchitecture.sln
├── CleanArchitecture
├── CleanArchitecture.csproj
├── Common
│ └── ResultModel.cs
├── Controllers
│ ├── BaseController.cs
│ ├── RoleController.cs
│ └── UserController.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── Startup.cs
├── Versioning
│ └── ApplyMethod.cs
├── appsettings.Development.json
└── appsettings.json
├── DataAccessLayer
├── ApplicationDbContext
│ └── CFCDbContext.cs
├── DataAccessLayer.csproj
├── EntityMappers
│ ├── BranchMap.cs
│ ├── UserMap.cs
│ └── UserRoleMap.cs
├── Migrations
│ ├── 20201205074151_Initial.Designer.cs
│ ├── 20201205074151_Initial.cs
│ └── CFCDbContextModelSnapshot.cs
├── Models
│ ├── BaseModel.cs
│ ├── Branches.cs
│ ├── User.cs
│ └── UserRoles.cs
└── SeedData
│ └── ModelBuilderExtension.cs
├── License
├── README.md
└── Services
├── Mapper
└── Mapper.cs
├── RepositoryPattern
└── UserLogin
│ ├── IUserService.cs
│ └── UserService.cs
├── Services.csproj
└── ViewModels
└── CommonModel.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/1_Tpfkss_hdHNyaaJ_3bBgWQ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JayKrishnareddy/CleanArchitecture/ae13e8faf209317b0bf851072a6320eef0f82aef/1_Tpfkss_hdHNyaaJ_3bBgWQ.png
--------------------------------------------------------------------------------
/CleanArchitecture.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30717.126
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanArchitecture", "CleanArchitecture\CleanArchitecture.csproj", "{65F5EDA1-BB1F-4A54-8C18-2163CCCB22F9}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataAccessLayer", "DataAccessLayer\DataAccessLayer.csproj", "{7B2216D5-26D2-4FB5-9217-133CF8D5A99D}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Services", "Services\Services.csproj", "{25C13766-31CB-40D7-B2CC-7F4AABF9A922}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {65F5EDA1-BB1F-4A54-8C18-2163CCCB22F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {65F5EDA1-BB1F-4A54-8C18-2163CCCB22F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {65F5EDA1-BB1F-4A54-8C18-2163CCCB22F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {65F5EDA1-BB1F-4A54-8C18-2163CCCB22F9}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {7B2216D5-26D2-4FB5-9217-133CF8D5A99D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {7B2216D5-26D2-4FB5-9217-133CF8D5A99D}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {7B2216D5-26D2-4FB5-9217-133CF8D5A99D}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {7B2216D5-26D2-4FB5-9217-133CF8D5A99D}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {25C13766-31CB-40D7-B2CC-7F4AABF9A922}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {25C13766-31CB-40D7-B2CC-7F4AABF9A922}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {25C13766-31CB-40D7-B2CC-7F4AABF9A922}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {25C13766-31CB-40D7-B2CC-7F4AABF9A922}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {E3472163-6A0B-4EE2-BA26-9D584EE7ACF0}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/CleanArchitecture/CleanArchitecture.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | all
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 |
16 |
17 | all
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/CleanArchitecture/Common/ResultModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace CleanArchitecture.ViewModels.Common
7 | {
8 | public class ResultModel
9 | {
10 | public int Code { get; set; }
11 | public string Message { get; set; }
12 | public object Data { get; set; }
13 | public ResultModel(int code = 0, string message = "", object data = null)
14 | {
15 | Code = code;
16 | Message = message;
17 | Data = data;
18 | }
19 | public Result result { get; set; }
20 | public Result GetFormatObject()
21 | {
22 | return new Result
23 | {
24 | status = new Status
25 | {
26 | code = Code,
27 | message = Message
28 | },
29 | data = Data ?? ""
30 | };
31 | }
32 | public class Result
33 | {
34 | public Status status { get; set; }
35 | public object data { get; set; }
36 | }
37 | public class Status
38 | {
39 | public int code { get; set; }
40 | public string message { get; set; }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/CleanArchitecture/Controllers/BaseController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Authorization;
2 | using Microsoft.AspNetCore.Http;
3 | using Microsoft.AspNetCore.Mvc;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Threading.Tasks;
9 | using static CleanArchitecture.ViewModels.Common.ResultModel;
10 |
11 | namespace CleanArchitecture.Controllers
12 | {
13 | [Route("api/v{version:apiversion}/[controller]")]
14 | [Authorize(AuthenticationSchemes = Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme)]
15 | public class BaseController : ControllerBase
16 | {
17 | #region Protected Members
18 | ///
19 | /// Detailed Exception
20 | ///
21 | ///
22 | ///
23 | protected object DetailedException(Exception ex)
24 | {
25 | var errormessage = ex.Message;
26 | if (ex.InnerException != null)
27 | {
28 | errormessage = "\n\nException: " + GetInnerException(ex);
29 | }
30 | var result = new Result
31 | {
32 | status = new Status
33 | {
34 | code = (int)HttpStatusCode.InternalServerError,
35 | message = errormessage
36 | }
37 | };
38 | return result;
39 | }
40 |
41 | ///
42 | /// Get Inner Exception
43 | ///
44 | ///
45 | ///
46 | private string GetInnerException(Exception ex)
47 | {
48 | if (ex.InnerException != null)
49 | {
50 | return
51 | $"{ex.InnerException.Message + "( \n " + ex.Message + " \n )"} > {GetInnerException(ex.InnerException)} ";
52 | }
53 | return string.Empty;
54 | }
55 | #endregion
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/CleanArchitecture/Controllers/RoleController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Services.RepositoryPattern.UserLogin;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 |
9 | namespace CleanArchitecture.Controllers
10 | {
11 | [ApiVersion("2.0")]
12 | [ApiExplorerSettings(GroupName = "v2")]
13 | public class RoleController : BaseController
14 | {
15 | #region Property
16 | private readonly IUserService _userService;
17 | #endregion
18 |
19 | #region Constructor
20 | public RoleController(IUserService userService)
21 | {
22 | _userService = userService;
23 | }
24 | #endregion
25 |
26 | #region GetRoles
27 | ///
28 | /// Get the User Roles
29 | ///
30 | ///
31 | [HttpGet(nameof(GetUserRoles))]
32 | public async Task GetUserRoles()
33 | {
34 | try
35 | {
36 | var result = await _userService.GetUserRolesAsync();
37 | if (result is not null) return Ok(result); else return BadRequest("No Data Found");
38 | }
39 | catch (Exception ex)
40 | {
41 | return BadRequest(ex);
42 | throw;
43 | }
44 | }
45 | #endregion
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/CleanArchitecture/Controllers/UserController.cs:
--------------------------------------------------------------------------------
1 | using Services.RepositoryPattern.UserLogin;
2 | using Microsoft.AspNetCore.Authorization;
3 | using Microsoft.AspNetCore.Http;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.Configuration;
6 | using Microsoft.IdentityModel.Tokens;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.IdentityModel.Tokens.Jwt;
10 | using System.Linq;
11 | using System.Security.Claims;
12 | using System.Text;
13 | using System.Threading.Tasks;
14 | using static Services.ViewModels.CommonModel;
15 |
16 | namespace CleanArchitecture.Controllers
17 | {
18 | [ApiVersion("1.0")]
19 | [ApiExplorerSettings(GroupName = "v1")]
20 | public class UserController : BaseController
21 | {
22 | #region Property
23 | private readonly IUserService _userService;
24 | private readonly IConfiguration _configuration;
25 | #endregion
26 |
27 | #region Constructor
28 | public UserController(IUserService userService, IConfiguration configuration)
29 | {
30 | _userService = userService;
31 | _configuration = configuration;
32 | }
33 | #endregion
34 |
35 | #region Create User
36 | ///
37 | /// To Create a User
38 | ///
39 | ///
40 | ///
41 | [HttpPost(nameof(CreateUser))]
42 | public async Task CreateUser([FromBody]UserModel userModel)
43 | {
44 | try
45 | {
46 | if (ModelState.IsValid)
47 | {
48 | var result = await _userService.CreateUserAsync(userModel);
49 | return Ok(result);
50 | }
51 | else
52 | {
53 | return BadRequest("Please fill all the required parameters");
54 | }
55 |
56 | }
57 | catch (Exception ex)
58 | {
59 | return BadRequest(ex);
60 | throw;
61 | }
62 | }
63 | #endregion
64 |
65 | #region User Login
66 | ///
67 | /// Login Authentication
68 | ///
69 | ///
70 | ///
71 | [HttpPost(nameof(Login)), AllowAnonymous]
72 | public async Task Login([FromBody]LoginModel loginModel)
73 | {
74 | try
75 | {
76 | var response = await _userService.UserLoginAsync(loginModel);
77 | if (response is true)
78 | {
79 | var userRoles = await _userService.GetUserRolesAsync();
80 | var authClaims = new List
81 | {
82 | new Claim(ClaimTypes.Name, loginModel.UserName),
83 | new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
84 | };
85 |
86 | foreach (var userRole in userRoles)
87 | {
88 | authClaims.Add(new Claim(ClaimTypes.Role, userRole.RoleName));
89 | }
90 |
91 | var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
92 |
93 | var token = new JwtSecurityToken(
94 | issuer: _configuration["Jwt:Issuer"],
95 | audience: _configuration["Jwt:Issuer"],
96 | expires: DateTime.Now.AddHours(3),
97 | claims: authClaims,
98 | signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
99 | );
100 | return Ok(new
101 | {
102 | token = new JwtSecurityTokenHandler().WriteToken(token),
103 | expiration = token.ValidTo
104 | });
105 | }
106 | return Unauthorized();
107 |
108 | }
109 |
110 | catch (Exception ex)
111 | {
112 | return BadRequest(ex);
113 | throw;
114 | }
115 | }
116 | #endregion
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/CleanArchitecture/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Hosting;
2 | using Microsoft.Extensions.Configuration;
3 | using Microsoft.Extensions.Hosting;
4 | using Microsoft.Extensions.Logging;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 |
10 | namespace CleanArchitecture
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 |
--------------------------------------------------------------------------------
/CleanArchitecture/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:64925",
8 | "sslPort": 44380
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "swagger",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "CleanArchitecture": {
21 | "commandName": "Project",
22 | "dotnetRunMessages": "true",
23 | "launchBrowser": true,
24 | "launchUrl": "swagger",
25 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
26 | "environmentVariables": {
27 | "ASPNETCORE_ENVIRONMENT": "Development"
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CleanArchitecture/Startup.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JayKrishnareddy/CleanArchitecture/ae13e8faf209317b0bf851072a6320eef0f82aef/CleanArchitecture/Startup.cs
--------------------------------------------------------------------------------
/CleanArchitecture/Versioning/ApplyMethod.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.OpenApi.Models;
2 | using Swashbuckle.AspNetCore.SwaggerGen;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 |
8 | namespace CFC_API.Versioning
9 | {
10 | public class RemoveVersionFromParameterv : IOperationFilter
11 | {
12 | public void Apply(OpenApiOperation operation, OperationFilterContext context)
13 | {
14 | if (operation.Parameters.Count > 0)
15 | {
16 | var versionparameter = operation.Parameters.Single(a => a.Name == "version");
17 | operation.Parameters.Remove(versionparameter);
18 | }
19 | }
20 | }
21 | public class ReplaceVersionWithExactValueInPath : IDocumentFilter
22 | {
23 | public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
24 | {
25 | var paths = swaggerDoc.Paths;
26 | swaggerDoc.Paths = new OpenApiPaths();
27 | foreach (var path in paths)
28 | {
29 | var key = path.Key.Replace("v{version}", swaggerDoc.Info.Version);
30 | var value = path.Value;
31 | swaggerDoc.Paths.Add(key, value);
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/CleanArchitecture/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/CleanArchitecture/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*",
10 | "Jwt": {
11 | "Key": "BB698DAF-6E3F-45FF-8493-06ECCF2F60D0",
12 | "Issuer": "https://localhost:44393",
13 | },
14 | "ConnectionStrings": {
15 | "myconn": "server=N-20RJPF2CFK06\\SQLEXPRESS; database=CFCDb;Trusted_Connection=True;"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/DataAccessLayer/ApplicationDbContext/CFCDbContext.cs:
--------------------------------------------------------------------------------
1 | using DataAccessLayer.EntityMappers;
2 | using DataAccessLayer.Models;
3 | using DataAccessLayer.SeedData;
4 | using Microsoft.EntityFrameworkCore;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Text;
8 |
9 | namespace DataAccessLayer.ApplicationDbContext
10 | {
11 | public partial class CFCDbContext : DbContext
12 | {
13 | public CFCDbContext(DbContextOptions options) : base(options)
14 | {
15 |
16 | }
17 | public DbSet users { get; set; }
18 | public DbSet userRoles { get; set; }
19 |
20 | protected override void OnModelCreating(ModelBuilder modelBuilder)
21 | {
22 | modelBuilder.ApplyConfiguration(new UserMap());
23 | modelBuilder.ApplyConfiguration(new UserRoleMap());
24 | modelBuilder.ApplyConfiguration(new BranchMap());
25 | base.OnModelCreating(modelBuilder);
26 | modelBuilder.Seed();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/DataAccessLayer/DataAccessLayer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 | all
11 | runtime; build; native; contentfiles; analyzers; buildtransitive
12 |
13 |
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers; buildtransitive
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/DataAccessLayer/EntityMappers/BranchMap.cs:
--------------------------------------------------------------------------------
1 | using DataAccessLayer.Models;
2 | using Microsoft.EntityFrameworkCore;
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace DataAccessLayer.EntityMappers
6 | {
7 | public class BranchMap : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder builder)
10 | {
11 | builder.ToTable("branches");
12 | builder.HasKey(x => x.BranchId)
13 | .HasName("pk_branch_id");
14 | builder.Property(x => x.BranchId)
15 | .ValueGeneratedOnAdd()
16 | .HasColumnName("branch_id")
17 | .HasColumnType("INT");
18 | builder.Property(x => x.BranchName)
19 | .HasColumnName("branch_name")
20 | .HasColumnType("NVARCHAR(100)")
21 | .IsRequired();
22 | builder.Property(x => x.BranchManager)
23 | .HasColumnName("branch_manager")
24 | .HasColumnType("NVARCHAR(100)")
25 | .IsRequired();
26 | builder.Property(x => x.BranchLocation)
27 | .HasColumnName("branch_location")
28 | .HasColumnType("NVARCHAR(100)")
29 | .IsRequired();
30 | builder.Property(x => x.BranchNumber)
31 | .HasColumnName("branch_number")
32 | .HasColumnType("BIGINT")
33 | .IsRequired();
34 | builder.Property(x => x.CreatedDate)
35 | .HasColumnName("created_date")
36 | .HasColumnType("DATETIME");
37 | builder.Property(x => x.ModifiedDate)
38 | .HasColumnName("modified_date")
39 | .HasColumnType("DATETIME");
40 | builder.Property(x => x.IsActive)
41 | .HasColumnName("is_active")
42 | .HasColumnType("BIT");
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/DataAccessLayer/EntityMappers/UserMap.cs:
--------------------------------------------------------------------------------
1 | using DataAccessLayer.Models;
2 | using Microsoft.EntityFrameworkCore;
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace DataAccessLayer.EntityMappers
6 | {
7 | public class UserMap : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder builder)
10 | {
11 | builder.ToTable("users");
12 | builder.HasKey(x => x.UserId)
13 | .HasName("pk_user");
14 | builder.Property(x => x.UserId)
15 | .ValueGeneratedOnAdd()
16 | .HasColumnName("user_id")
17 | .HasColumnType("INT");
18 | builder.Property(x => x.FirstName)
19 | .HasColumnName("first_name")
20 | .HasColumnType("NVARCHAR(100)")
21 | .IsRequired();
22 | builder.Property(x => x.LastName)
23 | .HasColumnName("last_name")
24 | .HasColumnType("NVARCHAR(100)")
25 | .IsRequired();
26 | builder.Property(x => x.PhoneNumber)
27 | .HasColumnName("phone_number")
28 | .HasColumnType("BIGINT")
29 | .IsRequired();
30 | builder.Property(x => x.Password)
31 | .HasColumnName("password")
32 | .HasColumnType("NVARCHAR(100)")
33 | .IsRequired();
34 | builder.Property(x => x.Email)
35 | .HasColumnName("email")
36 | .HasColumnType("NVARCHAR(100)")
37 | .IsRequired();
38 | builder.HasOne(x => x.UserRoles)
39 | .WithOne(x => x.User)
40 | .HasForeignKey(x => x.RoleId)
41 | .OnDelete(DeleteBehavior.ClientSetNull)
42 | .HasConstraintName("fk_user_user_roles");
43 | builder.Property(x => x.CreatedDate)
44 | .HasColumnName("created_date")
45 | .HasColumnType("DATETIME");
46 | builder.Property(x => x.ModifiedDate)
47 | .HasColumnName("modified_date")
48 | .HasColumnType("DATETIME");
49 | builder.Property(x => x.IsActive)
50 | .HasColumnName("is_active")
51 | .HasColumnType("BIT");
52 |
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/DataAccessLayer/EntityMappers/UserRoleMap.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 | using DataAccessLayer.Models;
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace DataAccessLayer.EntityMappers
6 | {
7 | public class UserRoleMap : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder builder)
10 | {
11 | builder.ToTable("user_role");
12 | builder.HasKey(x => x.RoleId)
13 | .HasName("pk_user_role");
14 | builder.Property(x => x.RoleId)
15 | .ValueGeneratedOnAdd()
16 | .HasColumnName("role_id")
17 | .HasColumnType("INT");
18 | builder.Property(x => x.RoleName)
19 | .HasColumnName("role_name")
20 | .HasColumnType("NVARCHAR(100)")
21 | .IsRequired();
22 | builder.Property(x => x.IsActive)
23 | .HasColumnName("is_active")
24 | .HasColumnType("BIT")
25 | .IsRequired();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/DataAccessLayer/Migrations/20201205074151_Initial.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using DataAccessLayer.ApplicationDbContext;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Metadata;
7 | using Microsoft.EntityFrameworkCore.Migrations;
8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 |
10 | namespace DataAccessLayer.Migrations
11 | {
12 | [DbContext(typeof(CFCDbContext))]
13 | [Migration("20201205074151_Initial")]
14 | partial class Initial
15 | {
16 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
17 | {
18 | #pragma warning disable 612, 618
19 | modelBuilder
20 | .UseIdentityColumns()
21 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
22 | .HasAnnotation("ProductVersion", "5.0.0");
23 |
24 | modelBuilder.Entity("DataAccessLayer.Models.Branches", b =>
25 | {
26 | b.Property("BranchId")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("INT")
29 | .HasColumnName("branch_id")
30 | .UseIdentityColumn();
31 |
32 | b.Property("BranchLocation")
33 | .IsRequired()
34 | .HasColumnType("NVARCHAR(100)")
35 | .HasColumnName("branch_location");
36 |
37 | b.Property("BranchManager")
38 | .IsRequired()
39 | .HasColumnType("NVARCHAR(100)")
40 | .HasColumnName("branch_manager");
41 |
42 | b.Property("BranchName")
43 | .IsRequired()
44 | .HasColumnType("NVARCHAR(100)")
45 | .HasColumnName("branch_name");
46 |
47 | b.Property("BranchNumber")
48 | .HasColumnType("BIGINT")
49 | .HasColumnName("branch_number");
50 |
51 | b.Property("CreatedDate")
52 | .HasColumnType("DATETIME")
53 | .HasColumnName("created_date");
54 |
55 | b.Property("IsActive")
56 | .HasColumnType("BIT")
57 | .HasColumnName("is_active");
58 |
59 | b.Property("ModifiedDate")
60 | .HasColumnType("DATETIME")
61 | .HasColumnName("modified_date");
62 |
63 | b.HasKey("BranchId")
64 | .HasName("pk_branch_id");
65 |
66 | b.ToTable("branches");
67 | });
68 |
69 | modelBuilder.Entity("DataAccessLayer.Models.User", b =>
70 | {
71 | b.Property("UserId")
72 | .ValueGeneratedOnAdd()
73 | .HasColumnType("INT")
74 | .HasColumnName("user_id")
75 | .UseIdentityColumn();
76 |
77 | b.Property("CreatedDate")
78 | .HasColumnType("DATETIME")
79 | .HasColumnName("created_date");
80 |
81 | b.Property("Email")
82 | .IsRequired()
83 | .HasColumnType("NVARCHAR(100)")
84 | .HasColumnName("email");
85 |
86 | b.Property("FirstName")
87 | .IsRequired()
88 | .HasColumnType("NVARCHAR(100)")
89 | .HasColumnName("last_name");
90 |
91 | b.Property("IsActive")
92 | .HasColumnType("BIT")
93 | .HasColumnName("is_active");
94 |
95 | b.Property("LastName")
96 | .HasColumnType("nvarchar(max)");
97 |
98 | b.Property("ModifiedDate")
99 | .HasColumnType("DATETIME")
100 | .HasColumnName("modified_date");
101 |
102 | b.Property("Password")
103 | .IsRequired()
104 | .HasColumnType("NVARCHAR(100)")
105 | .HasColumnName("password");
106 |
107 | b.Property("PhoneNumber")
108 | .HasColumnType("BIGINT")
109 | .HasColumnName("phone_number");
110 |
111 | b.Property("RoleId")
112 | .HasColumnType("INT");
113 |
114 | b.HasKey("UserId")
115 | .HasName("pk_user");
116 |
117 | b.HasIndex("RoleId")
118 | .IsUnique();
119 |
120 | b.ToTable("users");
121 | });
122 |
123 | modelBuilder.Entity("DataAccessLayer.Models.UserRoles", b =>
124 | {
125 | b.Property("RoleId")
126 | .ValueGeneratedOnAdd()
127 | .HasColumnType("INT")
128 | .HasColumnName("role_id")
129 | .UseIdentityColumn();
130 |
131 | b.Property("IsActive")
132 | .HasColumnType("BIT")
133 | .HasColumnName("is_active");
134 |
135 | b.Property("RoleName")
136 | .IsRequired()
137 | .HasColumnType("NVARCHAR(100)")
138 | .HasColumnName("role_name");
139 |
140 | b.HasKey("RoleId")
141 | .HasName("pk_user_role");
142 |
143 | b.ToTable("user_role");
144 |
145 | b.HasData(
146 | new
147 | {
148 | RoleId = 1,
149 | IsActive = true,
150 | RoleName = "SuperAdmin"
151 | },
152 | new
153 | {
154 | RoleId = 2,
155 | IsActive = true,
156 | RoleName = "Admin"
157 | });
158 | });
159 |
160 | modelBuilder.Entity("DataAccessLayer.Models.User", b =>
161 | {
162 | b.HasOne("DataAccessLayer.Models.UserRoles", "UserRoles")
163 | .WithOne("User")
164 | .HasForeignKey("DataAccessLayer.Models.User", "RoleId")
165 | .HasConstraintName("fk_user_user_roles")
166 | .IsRequired();
167 |
168 | b.Navigation("UserRoles");
169 | });
170 |
171 | modelBuilder.Entity("DataAccessLayer.Models.UserRoles", b =>
172 | {
173 | b.Navigation("User");
174 | });
175 | #pragma warning restore 612, 618
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/DataAccessLayer/Migrations/20201205074151_Initial.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.EntityFrameworkCore.Migrations;
3 |
4 | namespace DataAccessLayer.Migrations
5 | {
6 | public partial class Initial : Migration
7 | {
8 | protected override void Up(MigrationBuilder migrationBuilder)
9 | {
10 | migrationBuilder.CreateTable(
11 | name: "branches",
12 | columns: table => new
13 | {
14 | branch_id = table.Column(type: "INT", nullable: false)
15 | .Annotation("SqlServer:Identity", "1, 1"),
16 | branch_name = table.Column(type: "NVARCHAR(100)", nullable: false),
17 | branch_manager = table.Column(type: "NVARCHAR(100)", nullable: false),
18 | branch_number = table.Column(type: "BIGINT", nullable: false),
19 | branch_location = table.Column(type: "NVARCHAR(100)", nullable: false),
20 | is_active = table.Column(type: "BIT", nullable: false),
21 | created_date = table.Column(type: "DATETIME", nullable: false),
22 | modified_date = table.Column(type: "DATETIME", nullable: false)
23 | },
24 | constraints: table =>
25 | {
26 | table.PrimaryKey("pk_branch_id", x => x.branch_id);
27 | });
28 |
29 | migrationBuilder.CreateTable(
30 | name: "user_role",
31 | columns: table => new
32 | {
33 | role_id = table.Column(type: "INT", nullable: false)
34 | .Annotation("SqlServer:Identity", "1, 1"),
35 | role_name = table.Column(type: "NVARCHAR(100)", nullable: false),
36 | is_active = table.Column(type: "BIT", nullable: false)
37 | },
38 | constraints: table =>
39 | {
40 | table.PrimaryKey("pk_user_role", x => x.role_id);
41 | });
42 |
43 | migrationBuilder.CreateTable(
44 | name: "users",
45 | columns: table => new
46 | {
47 | user_id = table.Column(type: "INT", nullable: false)
48 | .Annotation("SqlServer:Identity", "1, 1"),
49 | last_name = table.Column(type: "NVARCHAR(100)", nullable: false),
50 | LastName = table.Column(type: "nvarchar(max)", nullable: true),
51 | phone_number = table.Column(type: "BIGINT", nullable: false),
52 | password = table.Column(type: "NVARCHAR(100)", nullable: false),
53 | email = table.Column(type: "NVARCHAR(100)", nullable: false),
54 | RoleId = table.Column(type: "INT", nullable: false),
55 | is_active = table.Column(type: "BIT", nullable: false),
56 | created_date = table.Column(type: "DATETIME", nullable: false),
57 | modified_date = table.Column(type: "DATETIME", nullable: false)
58 | },
59 | constraints: table =>
60 | {
61 | table.PrimaryKey("pk_user", x => x.user_id);
62 | table.ForeignKey(
63 | name: "fk_user_user_roles",
64 | column: x => x.RoleId,
65 | principalTable: "user_role",
66 | principalColumn: "role_id",
67 | onDelete: ReferentialAction.Restrict);
68 | });
69 |
70 | migrationBuilder.InsertData(
71 | table: "user_role",
72 | columns: new[] { "role_id", "is_active", "role_name" },
73 | values: new object[] { 1, true, "SuperAdmin" });
74 |
75 | migrationBuilder.InsertData(
76 | table: "user_role",
77 | columns: new[] { "role_id", "is_active", "role_name" },
78 | values: new object[] { 2, true, "Admin" });
79 |
80 | migrationBuilder.CreateIndex(
81 | name: "IX_users_RoleId",
82 | table: "users",
83 | column: "RoleId",
84 | unique: true);
85 | }
86 |
87 | protected override void Down(MigrationBuilder migrationBuilder)
88 | {
89 | migrationBuilder.DropTable(
90 | name: "branches");
91 |
92 | migrationBuilder.DropTable(
93 | name: "users");
94 |
95 | migrationBuilder.DropTable(
96 | name: "user_role");
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/DataAccessLayer/Migrations/CFCDbContextModelSnapshot.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using DataAccessLayer.ApplicationDbContext;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Metadata;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | namespace DataAccessLayer.Migrations
10 | {
11 | [DbContext(typeof(CFCDbContext))]
12 | partial class CFCDbContextModelSnapshot : ModelSnapshot
13 | {
14 | protected override void BuildModel(ModelBuilder modelBuilder)
15 | {
16 | #pragma warning disable 612, 618
17 | modelBuilder
18 | .UseIdentityColumns()
19 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
20 | .HasAnnotation("ProductVersion", "5.0.0");
21 |
22 | modelBuilder.Entity("DataAccessLayer.Models.Branches", b =>
23 | {
24 | b.Property("BranchId")
25 | .ValueGeneratedOnAdd()
26 | .HasColumnType("INT")
27 | .HasColumnName("branch_id")
28 | .UseIdentityColumn();
29 |
30 | b.Property("BranchLocation")
31 | .IsRequired()
32 | .HasColumnType("NVARCHAR(100)")
33 | .HasColumnName("branch_location");
34 |
35 | b.Property("BranchManager")
36 | .IsRequired()
37 | .HasColumnType("NVARCHAR(100)")
38 | .HasColumnName("branch_manager");
39 |
40 | b.Property("BranchName")
41 | .IsRequired()
42 | .HasColumnType("NVARCHAR(100)")
43 | .HasColumnName("branch_name");
44 |
45 | b.Property("BranchNumber")
46 | .HasColumnType("BIGINT")
47 | .HasColumnName("branch_number");
48 |
49 | b.Property("CreatedDate")
50 | .HasColumnType("DATETIME")
51 | .HasColumnName("created_date");
52 |
53 | b.Property("IsActive")
54 | .HasColumnType("BIT")
55 | .HasColumnName("is_active");
56 |
57 | b.Property("ModifiedDate")
58 | .HasColumnType("DATETIME")
59 | .HasColumnName("modified_date");
60 |
61 | b.HasKey("BranchId")
62 | .HasName("pk_branch_id");
63 |
64 | b.ToTable("branches");
65 | });
66 |
67 | modelBuilder.Entity("DataAccessLayer.Models.User", b =>
68 | {
69 | b.Property("UserId")
70 | .ValueGeneratedOnAdd()
71 | .HasColumnType("INT")
72 | .HasColumnName("user_id")
73 | .UseIdentityColumn();
74 |
75 | b.Property("CreatedDate")
76 | .HasColumnType("DATETIME")
77 | .HasColumnName("created_date");
78 |
79 | b.Property("Email")
80 | .IsRequired()
81 | .HasColumnType("NVARCHAR(100)")
82 | .HasColumnName("email");
83 |
84 | b.Property("FirstName")
85 | .IsRequired()
86 | .HasColumnType("NVARCHAR(100)")
87 | .HasColumnName("last_name");
88 |
89 | b.Property("IsActive")
90 | .HasColumnType("BIT")
91 | .HasColumnName("is_active");
92 |
93 | b.Property("LastName")
94 | .HasColumnType("nvarchar(max)");
95 |
96 | b.Property("ModifiedDate")
97 | .HasColumnType("DATETIME")
98 | .HasColumnName("modified_date");
99 |
100 | b.Property("Password")
101 | .IsRequired()
102 | .HasColumnType("NVARCHAR(100)")
103 | .HasColumnName("password");
104 |
105 | b.Property("PhoneNumber")
106 | .HasColumnType("BIGINT")
107 | .HasColumnName("phone_number");
108 |
109 | b.Property("RoleId")
110 | .HasColumnType("INT");
111 |
112 | b.HasKey("UserId")
113 | .HasName("pk_user");
114 |
115 | b.HasIndex("RoleId")
116 | .IsUnique();
117 |
118 | b.ToTable("users");
119 | });
120 |
121 | modelBuilder.Entity("DataAccessLayer.Models.UserRoles", b =>
122 | {
123 | b.Property("RoleId")
124 | .ValueGeneratedOnAdd()
125 | .HasColumnType("INT")
126 | .HasColumnName("role_id")
127 | .UseIdentityColumn();
128 |
129 | b.Property("IsActive")
130 | .HasColumnType("BIT")
131 | .HasColumnName("is_active");
132 |
133 | b.Property("RoleName")
134 | .IsRequired()
135 | .HasColumnType("NVARCHAR(100)")
136 | .HasColumnName("role_name");
137 |
138 | b.HasKey("RoleId")
139 | .HasName("pk_user_role");
140 |
141 | b.ToTable("user_role");
142 |
143 | b.HasData(
144 | new
145 | {
146 | RoleId = 1,
147 | IsActive = true,
148 | RoleName = "SuperAdmin"
149 | },
150 | new
151 | {
152 | RoleId = 2,
153 | IsActive = true,
154 | RoleName = "Admin"
155 | });
156 | });
157 |
158 | modelBuilder.Entity("DataAccessLayer.Models.User", b =>
159 | {
160 | b.HasOne("DataAccessLayer.Models.UserRoles", "UserRoles")
161 | .WithOne("User")
162 | .HasForeignKey("DataAccessLayer.Models.User", "RoleId")
163 | .HasConstraintName("fk_user_user_roles")
164 | .IsRequired();
165 |
166 | b.Navigation("UserRoles");
167 | });
168 |
169 | modelBuilder.Entity("DataAccessLayer.Models.UserRoles", b =>
170 | {
171 | b.Navigation("User");
172 | });
173 | #pragma warning restore 612, 618
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/DataAccessLayer/Models/BaseModel.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace DataAccessLayer.Models
7 | {
8 | public class BaseModel
9 | {
10 | [JsonProperty(PropertyName = "is_active")]
11 | public bool IsActive { get; set; }
12 | [JsonProperty(PropertyName = "created_date")]
13 | public DateTime CreatedDate { get; set; }
14 | [JsonProperty(PropertyName = "modified_date")]
15 | public DateTime ModifiedDate { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/DataAccessLayer/Models/Branches.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace DataAccessLayer.Models
7 | {
8 | public class Branches : BaseModel
9 | {
10 | [JsonProperty(PropertyName = "branch_id")]
11 | public int BranchId { get; set; }
12 | [JsonProperty(PropertyName = "branch_name")]
13 | public string BranchName { get; set; }
14 | [JsonProperty(PropertyName = "branch_manager")]
15 | public string BranchManager { get; set; }
16 | [JsonProperty(PropertyName = "branch_number")]
17 | public long BranchNumber { get; set; }
18 | [JsonProperty(PropertyName = "branch_location")]
19 | public string BranchLocation { get; set; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DataAccessLayer/Models/User.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace DataAccessLayer.Models
7 | {
8 | public class User : BaseModel
9 | {
10 | [JsonProperty(PropertyName = "user_id")]
11 | public int UserId { get; set; }
12 | [JsonProperty(PropertyName = "first_name")]
13 | public string FirstName { get; set; }
14 | [JsonProperty(PropertyName = "last_name")]
15 | public string LastName { get; set; }
16 | [JsonProperty(PropertyName = "phone_number")]
17 | public long PhoneNumber { get; set; }
18 | [JsonProperty(PropertyName = "password")]
19 | public string Password { get; set; }
20 | [JsonProperty(PropertyName = "email")]
21 | public string Email { get; set; }
22 | [JsonProperty(PropertyName = "role_id")]
23 | public int RoleId { get; set; }
24 | public virtual UserRoles UserRoles { get; set; }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/DataAccessLayer/Models/UserRoles.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace DataAccessLayer.Models
7 | {
8 | public class UserRoles
9 | {
10 | [JsonProperty(PropertyName = "role_id")]
11 | public int RoleId { get; set; }
12 | [JsonProperty(PropertyName = "role_name")]
13 | public string RoleName { get; set; }
14 | [JsonProperty(PropertyName = "is_active")]
15 | public bool IsActive { get; set; }
16 | public virtual User User { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/DataAccessLayer/SeedData/ModelBuilderExtension.cs:
--------------------------------------------------------------------------------
1 | using DataAccessLayer.Models;
2 | using Microsoft.EntityFrameworkCore;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 |
7 | namespace DataAccessLayer.SeedData
8 | {
9 | public static class ModelBuilderExtension
10 | {
11 | public static void Seed(this ModelBuilder modelBuilder)
12 | {
13 | // Seed Data for Admin Roles
14 | modelBuilder.Entity().HasData(
15 | new UserRoles { RoleId = 1,RoleName = "SuperAdmin",IsActive = true },
16 | new UserRoles { RoleId = 2,RoleName = "Admin",IsActive = true }
17 | );
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/License:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Jay Krishna Reddy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## Clean Architecture in ASP.NET Core 5.0
3 |
4 | 
5 |
6 | ### What we are going to cover in this .NET 5 Clean Architecture?
7 | - Entity Framework Code First Approach
8 | - Dependency Injection
9 | - Automapper
10 | - JWT Authentication
11 | - Versioning of API's
12 | - Swagger (Versioning)
13 |
14 |
15 | If you want to learn more about this Article 👇🏻
16 |
17 | [**C# Corner**](https://www.c-sharpcorner.com/article/clean-architecture-end-to-end-in-net-5/ "C# Corner")
18 |
19 | [**Medium**](https://medium.com/nerd-for-tech/clean-architecture-end-to-end-in-net-5-c9eb2c39ca7b "Medium")
20 |
21 | [**Hashnode**](https://jaykrishnareddy.hashnode.dev/clean-architecture-end-to-end-in-net-5 "Hashnode")
22 |
23 | If you liked the repo then kindly support it by giving it a star ⭐
24 |
--------------------------------------------------------------------------------
/Services/Mapper/Mapper.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using DataAccessLayer.Models;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using static Services.ViewModels.CommonModel;
7 |
8 | namespace Services.Mapper
9 | {
10 | public class Mapper : Profile
11 | {
12 | public Mapper()
13 | {
14 | AllowNullDestinationValues = true;
15 | //Source -> Destination
16 | CreateMap()
17 | .ForMember(dto => dto.RoleId, opt => opt.MapFrom(src => src.RoleId))
18 | .ForMember(dto => dto.RoleName, opt => opt.MapFrom(src => src.RoleName));
19 | CreateMap()
20 | .ForMember(dto => dto.UserName, opt => opt.MapFrom(src => src.Email));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Services/RepositoryPattern/UserLogin/IUserService.cs:
--------------------------------------------------------------------------------
1 | using DataAccessLayer.Models;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using static Services.ViewModels.CommonModel;
7 |
8 | namespace Services.RepositoryPattern.UserLogin
9 | {
10 | public interface IUserService
11 | {
12 | Task> GetUserRolesAsync();
13 | Task CreateUserAsync(UserModel userModel);
14 | Task UserLoginAsync(LoginModel loginModel);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Services/RepositoryPattern/UserLogin/UserService.cs:
--------------------------------------------------------------------------------
1 | using DataAccessLayer.ApplicationDbContext;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using DataAccessLayer.Models;
7 | using System.Linq;
8 | using static Services.ViewModels.CommonModel;
9 | using AutoMapper;
10 | using Microsoft.EntityFrameworkCore;
11 | using System.Security.Claims;
12 | using System.IdentityModel.Tokens.Jwt;
13 | using Microsoft.IdentityModel.Tokens;
14 | using Microsoft.Extensions.Configuration;
15 |
16 | namespace Services.RepositoryPattern.UserLogin
17 | {
18 | public class UserService : IUserService
19 | {
20 | #region Property
21 | private readonly CFCDbContext _cFCDbContext;
22 | private readonly IMapper _mapper;
23 |
24 | #endregion
25 |
26 | #region Constructor
27 | public UserService(CFCDbContext cFCDbContext, IMapper mapper)
28 | {
29 | _cFCDbContext = cFCDbContext;
30 | _mapper = mapper;
31 |
32 | }
33 | #endregion
34 |
35 | #region Get User Roles
36 | ///
37 | /// Get User Roles from Db
38 | ///
39 | ///
40 | public async Task> GetUserRolesAsync()
41 | {
42 | try
43 | {
44 | var userRoles = await _cFCDbContext.userRoles.Where(c => c.IsActive.Equals(true)).ToListAsync();
45 | return _mapper.Map>(userRoles);
46 | }
47 | catch (Exception ex)
48 | {
49 | throw ex;
50 | }
51 | }
52 | #endregion
53 |
54 | #region Create User
55 | ///
56 | /// Create user to Db
57 | ///
58 | ///
59 | ///
60 | public async Task CreateUserAsync(UserModel userModel)
61 | {
62 | try
63 | {
64 | var userExists = await _cFCDbContext.users.Where(c => c.Email.Equals(userModel.Email)).AnyAsync();
65 | if (userExists is false)
66 | {
67 | User res = new User
68 | {
69 | FirstName = userModel.FirstName,
70 | LastName = userModel.LastName,
71 | PhoneNumber = userModel.PhoneNumber,
72 | Password = userModel.Password,
73 | Email = userModel.Email,
74 | RoleId = await _cFCDbContext.userRoles.Where(c => c.IsActive.Equals(true) && c.RoleName.Equals(userModel.RoleName)).Select(x => x.RoleId).FirstOrDefaultAsync(),
75 | IsActive = true,
76 | CreatedDate = DateTime.UtcNow,
77 | ModifiedDate = DateTime.UtcNow
78 | };
79 | await _cFCDbContext.users.AddAsync(res);
80 | await _cFCDbContext.SaveChangesAsync();
81 | return "User Created Success";
82 | }
83 | else return "Email already exists";
84 |
85 | }
86 | catch (Exception ex)
87 | {
88 | throw ex;
89 | }
90 | }
91 | #endregion
92 |
93 | #region User Login
94 | public async Task UserLoginAsync(LoginModel loginModel)
95 | {
96 | try
97 | {
98 | var response = await _cFCDbContext.users.Where(c => c.Email.Equals(loginModel.UserName) && c.Password.Equals(loginModel.Password) && c.IsActive.Equals(true)).AnyAsync();
99 | if (response is true) return true; else return false;
100 | }
101 | catch (Exception ex)
102 | {
103 | throw ex;
104 | }
105 | }
106 | #endregion
107 |
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/Services/Services.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Services/ViewModels/CommonModel.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel.DataAnnotations;
5 | using System.Text;
6 |
7 | namespace Services.ViewModels
8 | {
9 | public class CommonModel
10 | {
11 | public class UserModel
12 | {
13 | [JsonProperty(PropertyName = "firstname")]
14 | [Required]
15 | public string FirstName { get; set; }
16 | [JsonProperty(PropertyName = "lastname")]
17 | [Required]
18 | public string LastName { get; set; }
19 | [JsonProperty(PropertyName = "phonenumber")]
20 | [Required]
21 | public long PhoneNumber { get; set; }
22 | [JsonProperty(PropertyName = "password")]
23 | [Required]
24 | public string Password { get; set; }
25 | [JsonProperty(PropertyName = "email")]
26 | [Required]
27 | public string Email { get; set; }
28 | [JsonProperty(PropertyName = "rolename")]
29 | [Required]
30 | public string RoleName { get; set; }
31 | }
32 |
33 | public class RolesModel
34 | {
35 | [JsonProperty(PropertyName = "role_id")]
36 | public int RoleId { get; set; }
37 | [JsonProperty(PropertyName = "role_name")]
38 | public string RoleName { get; set; }
39 | }
40 | public class LoginModel
41 | {
42 | [JsonProperty(PropertyName = "username")]
43 | [Required]
44 | public string UserName { get; set; }
45 | [JsonProperty(PropertyName = "password")]
46 | [Required]
47 | public string Password { get; set; }
48 | }
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------