diff --git a/.gitignore b/.gitignore index 8a30d25..cca254b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,7 +33,7 @@ bld/ [Ll]ogs/ # Visual Studio 2015/2017 cache/options directory -.vs/ +DotnetFoundation/.vs # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ @@ -396,3 +396,10 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml + +# Build Results +**/bin +**/obj + +# Log Files +**/logs \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..d48b106 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "kreativ-software.csharpextensions", + "jmrog.vscode-nuget-package-manager", + "fudge.auto-using", + "formulahendry.dotnet", + "pkief.material-icon-theme", + "patcx.vscode-nuget-gallery" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5426b0a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/DotnetBoilerPlate/DotnetBoilerPlate.API/bin/Debug/net6.0/DotnetBoilerPlate.API.dll", + "args": [], + "cwd": "${workspaceFolder}/DotnetBoilerPlate/DotnetBoilerPlate.API", + "stopAtEntry": false, + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..5b41ab9 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/DotnetBoilerPlate/DotnetBoilerPlate.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/DotnetBoilerPlate/DotnetBoilerPlate.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/DotnetBoilerPlate/DotnetBoilerPlate.sln" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/DotnetFoundation/.editorconfig b/DotnetFoundation/.editorconfig new file mode 100644 index 0000000..ef258be --- /dev/null +++ b/DotnetFoundation/.editorconfig @@ -0,0 +1,398 @@ +root = true + +# All Files +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:warning +csharp_style_namespace_declarations = block_scoped:warning +csharp_style_prefer_method_group_conversion = true:suggestion +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_methods = true:none +csharp_style_expression_bodied_constructors = true:warning +csharp_style_expression_bodied_operators = true:warning +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = true:warning +csharp_style_throw_expression = true:warning +csharp_style_prefer_null_check_over_type_check = true:warning +csharp_prefer_simple_default_expression = true:warning +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:warning +csharp_style_prefer_range_operator = true:warning +csharp_style_implicit_object_creation_when_type_is_apparent = false:warning +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_inlined_variable_declaration = true:warning +csharp_style_deconstructed_variable_declaration = true:warning +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion +csharp_prefer_static_local_function = true:warning +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_conditional_delegate_call = true:warning +csharp_style_prefer_switch_expression = true:warning +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_var_for_built_in_types = false:error +csharp_style_var_when_type_is_apparent = false:error +csharp_style_var_elsewhere = false:error +csharp_space_between_parentheses = expressions +csharp_preserve_single_line_statements = true +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_space_around_binary_operators = before_and_after + +########################################## +# File Extension Settings +########################################## + +# Visual Studio Solution Files +[*.sln] +indent_style = tab + +# Visual Studio XML Project Files +[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# XML Configuration Files +[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] +indent_size = 2 + +# JSON Files +[*.{json,json5,webmanifest}] +indent_size = 2 + +# YAML Files +[*.{yml,yaml}] +indent_size = 2 + +# Markdown Files +[*.{md,mdx}] +trim_trailing_whitespace = false + +# Web Files +[*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}] +indent_size = 2 + +# Batch Files +[*.{cmd,bat}] +end_of_line = crlf + +# Bash Files +[*.sh] +end_of_line = lf + +# Makefiles +[Makefile] +indent_style = tab + +########################################## +# Default .NET Code Style Severities +########################################## + +[*.{cs,csx,cake,vb,vbx}] +# Default Severity for all .NET Code Style rules below +dotnet_analyzer_diagnostic.severity = warning + +########################################## +# Language Rules +########################################## + +# .NET Style Rules +[*.{cs,csx,cake,vb,vbx}] +# "this." and "Me." qualifiers +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning +# Language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +# Modifier preferences +dotnet_style_require_accessibility_modifiers = always:warning +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning +visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:warning +dotnet_style_readonly_field = true:suggestion +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +# Expression-level preferences +dotnet_style_object_initializer = true:silent +dotnet_style_collection_initializer = true:silent +dotnet_style_explicit_tuple_names = true:warning +dotnet_style_prefer_inferred_tuple_names = false:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = false:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_diagnostic.IDE0045.severity = suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_diagnostic.IDE0046.severity = suggestion +dotnet_style_prefer_compound_assignment = true:silent +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +# Null-checking preferences +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning + +dotnet_style_operator_placement_when_wrapping = end_of_line +csharp_style_prefer_null_check_over_type_check = true:warning + +# C# Style Rules +[*.{cs,csx,cake}] +# Expression-bodied members +csharp_style_expression_bodied_methods = true:none +csharp_style_expression_bodied_constructors = true:warning +csharp_style_expression_bodied_operators = true:warning +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning +csharp_style_expression_bodied_lambdas = false:disabled +csharp_style_expression_bodied_local_functions = true:warning +# Pattern matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:disabled +csharp_style_pattern_matching_over_as_with_null_check = true:disabled +csharp_style_prefer_switch_expression = true:warning +csharp_style_prefer_pattern_matching = true:disabled +csharp_style_prefer_not_pattern = true:disabled +# Expression-level preferences +csharp_style_inlined_variable_declaration = true:warning +csharp_prefer_simple_default_expression = true:warning +csharp_style_pattern_local_over_anonymous_function = true:warning +csharp_style_deconstructed_variable_declaration = true:warning +csharp_style_prefer_index_operator = true:warning +csharp_style_prefer_range_operator = true:warning +csharp_style_implicit_object_creation_when_type_is_apparent = false:warning +# "Null" checking preferences +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning +# Code block preferences +csharp_prefer_braces = true:warning +csharp_prefer_simple_using_statement = true:suggestion +dotnet_diagnostic.IDE0063.severity = suggestion +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:silent +# Modifier preferences +csharp_prefer_static_local_function = true:warning + +########################################## +# Unnecessary Code Rules +########################################## + +# .NET Unnecessary code rules +[*.{cs,csx,cake,vb,vbx}] +dotnet_code_quality_unused_parameters = non_public:error +dotnet_remove_unnecessary_suppression_exclusions = none:warning + +# C# Unnecessary code rules +[*.{cs,csx,cake}] +csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion +dotnet_diagnostic.IDE0058.severity = none +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +dotnet_diagnostic.IDE0059.severity = suggestion + +########################################## +# Formatting Rules +########################################## + +# .NET formatting rules +[*.{cs,csx,cake,vb,vbx}] +# Organize using directives +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false +# Dotnet namespace options +dotnet_style_namespace_match_folder = true:suggestion +dotnet_diagnostic.IDE0130.severity = suggestion + +# C# formatting rules +[*.{cs,csx,cake}] +# Newline options +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true +# Indentation options +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents_when_block = false +# Spacing options +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_after_comma = true +csharp_space_before_comma = false +csharp_space_after_dot = false +csharp_space_before_dot = false +csharp_space_after_semicolon_in_for_statement = true +csharp_space_before_semicolon_in_for_statement = false +csharp_space_around_declaration_statements = false +csharp_space_before_open_square_brackets = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_square_brackets = false +# Wrap options +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true +# Namespace options +csharp_style_namespace_declarations = block_scoped:warning + +########################################## +# .NET Naming Rules +########################################## + +[*.{cs,vb}] + +########################################## +# Styles +########################################## + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf + +# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +dotnet_diagnostic.CS8618.severity = none +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent + +# CA2254: Template should be a static expression +dotnet_diagnostic.CA2254.severity = none + +dotnet_diagnostic.CA1848.severity = none + +# CA1305: Specify IFormatProvider +dotnet_diagnostic.CA1305.severity = none + +# CA2201: Do not raise reserved exception types +dotnet_diagnostic.CA2201.severity = none + +# CS8602: Dereference of a possibly null reference. +dotnet_diagnostic.CS8602.severity = none + +# CS8604: Possible null reference argument. +dotnet_diagnostic.CS8604.severity = none + +# CS8625: Cannot convert null literal to non-nullable reference type. +dotnet_diagnostic.CS8625.severity = none + +# CS8629: Nullable value type may be null. +dotnet_diagnostic.CS8629.severity = none + +# CS8600: Converting null literal or possible null value to non-nullable type. +dotnet_diagnostic.CS8600.severity = none + +# CA1716: Identifiers should not match keywords +dotnet_diagnostic.CA1716.severity = none + +# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +dotnet_diagnostic.CS8618.severity = none + +dotnet_diagnostic.CS8603.severity = none + +# CA1707: Identifiers should not contain underscores +dotnet_diagnostic.CA1707.severity = none + +# IDE1006: Naming Styles +dotnet_diagnostic.IDE1006.severity = none + +# CA2211: Non-constant fields should not be visible +dotnet_diagnostic.CA2211.severity = none + +# CA1805: Do not initialize unnecessarily +dotnet_diagnostic.CA1805.severity = none + +# IDE0022: Use expression body for methods +dotnet_diagnostic.IDE0022.severity = none + +dotnet_analyzer_diagnostic.category-Performance.severity = none + +dotnet_diagnostic.CA1816.severity = none + +# CS8601: Possible null reference assignment +dotnet_diagnostic.CS8601.severity = silent + +# CS8622: Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes) +dotnet_diagnostic.CS8622.severity = silent + +dotnet_diagnostic.CA2251.severity = error + +# CA2249: Consider using 'string.Contains' instead of 'string.IndexOf' +dotnet_diagnostic.CA2249.severity = error + +# JSON002: Probable JSON string detected +dotnet_diagnostic.JSON002.severity = none diff --git a/DotnetFoundation/DotnetFoundation.API/BLL/Interfaces/IUsersBLL.cs b/DotnetFoundation/DotnetFoundation.API/BLL/Interfaces/IUsersBLL.cs new file mode 100644 index 0000000..79aca7e --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/BLL/Interfaces/IUsersBLL.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using DotnetFoundation.API.Models; +using DotnetFoundation.DAL.Models; + +namespace DotnetFoundation.API.BLL.Interfaces +{ + public interface IUsersBLL + { + ActionResult>> GetAllUsers(); + ActionResult> GetUserById(string userId); + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/BLL/UsersBLL.cs b/DotnetFoundation/DotnetFoundation.API/BLL/UsersBLL.cs new file mode 100644 index 0000000..4e9b53f --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/BLL/UsersBLL.cs @@ -0,0 +1,99 @@ +using AutoMapper; +using Microsoft.AspNetCore.Mvc; +using DotnetFoundation.API.BLL.Interfaces; +using DotnetFoundation.API.Helpers; +using DotnetFoundation.API.Models; +using DotnetFoundation.DAL.DatabaseContext; +using DotnetFoundation.DAL.Models; +using DotnetFoundation.DAL.Repositories.Interfaces; + +namespace DotnetFoundation.API.BLL +{ + public class UsersBLL : Controller, IUsersBLL + { + private readonly IUsersRepo _usersRepo; + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + private readonly SqlDatabaseContext _databaseContext; + private readonly IMapper _mapper; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IWebHostEnvironment _hostingEnvironment; + + public UsersBLL(IUsersRepo userRepo, ILogger logger, IConfiguration configuration, SqlDatabaseContext databaseContext, IMapper mapper, IHttpContextAccessor httpContextAccessor, IWebHostEnvironment hostingEnvironment) + { + _usersRepo = userRepo; + _logger = logger; + _configuration = configuration; + _databaseContext = databaseContext; + _mapper = mapper; + _httpContextAccessor = httpContextAccessor; + _hostingEnvironment = hostingEnvironment; + } + + public ActionResult>> GetAllUsers() + { + BaseResponse> response = new BaseResponse>(ResponseStatus.Fail); + + try + { + // Get all users + response.Data = _usersRepo.GetAllUsers(); + response.Status = ResponseStatus.Success; + } + catch (BadHttpRequestException ex) + { + _logger.LogError(ex.Message); + response.Status = ResponseStatus.Error; + response.ErrorCode = EnumHelper.ConvertToEnum(ex.Message); + return BadRequest(response); + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + response.ErrorCode = ErrorCode.INTERNAL_SERVER_ERROR; + response.Status = ResponseStatus.Error; + return StatusCode(StatusCodes.Status500InternalServerError, response); + } + + return Ok(response); + } + + public ActionResult> GetUserById(string userId) + { + BaseResponse response = new BaseResponse(ResponseStatus.Fail); + + try + { + // If user id not found then return bad request + if (string.IsNullOrWhiteSpace(userId)) + { + throw new BadHttpRequestException(EnumHelper.ConvertToString(ErrorCode.USER_ID_REQUIRED)); + } + + // Get user by user id + UsersDBO user = _usersRepo.GetUserById(userId); + + // Assign user to data if found else throw bad request + response.Data = user ?? throw new BadHttpRequestException(EnumHelper.ConvertToString(ErrorCode.USER_NOT_FOUND)); + + response.Status = ResponseStatus.Success; + } + catch (BadHttpRequestException ex) + { + _logger.LogError(ex.Message); + response.Status = ResponseStatus.Error; + response.ErrorCode = EnumHelper.ConvertToEnum(ex.Message); + return BadRequest(response); + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + response.ErrorCode = ErrorCode.INTERNAL_SERVER_ERROR; + response.Status = ResponseStatus.Error; + return StatusCode(StatusCodes.Status500InternalServerError, response); + } + + return Ok(response); + } + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/Controllers/UsersController.cs b/DotnetFoundation/DotnetFoundation.API/Controllers/UsersController.cs new file mode 100644 index 0000000..5db9fb9 --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/Controllers/UsersController.cs @@ -0,0 +1,49 @@ +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using DotnetFoundation.API.BLL.Interfaces; +using DotnetFoundation.API.Models; +using DotnetFoundation.DAL.Models; + +namespace DotnetFoundation.API.Controllers +{ + [EnableCors] + [ApiController] + public class UsersController : Controller + { + private readonly IUsersBLL _usersBll; + public UsersController(IUsersBLL usersBll) => _usersBll = usersBll; + + /// + /// Get All users. + /// + /// ERROR CODES: + /// INTERNAL_SERVER_ERROR + /// + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Route("users")] + public ActionResult>> GetAllUsers() + { + return _usersBll.GetAllUsers(); + } + + /// + /// Get user by id. + /// + /// user id to fetch + /// ERROR CODES: + /// USER_ID_REQUIRED, USER_NOT_FOUND, INTERNAL_SERVER_ERROR + /// + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [Route("users/{userId}")] + public ActionResult> GetUserById(string userId) + { + return _usersBll.GetUserById(userId); + } + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/DotnetFoundation.API.csproj b/DotnetFoundation/DotnetFoundation.API/DotnetFoundation.API.csproj new file mode 100644 index 0000000..94c447c --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/DotnetFoundation.API.csproj @@ -0,0 +1,35 @@ + + + + net6.0 + enable + enable + true + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + diff --git a/DotnetFoundation/DotnetFoundation.API/Helpers/AutoMappingProfile.cs b/DotnetFoundation/DotnetFoundation.API/Helpers/AutoMappingProfile.cs new file mode 100644 index 0000000..b8fcbf0 --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/Helpers/AutoMappingProfile.cs @@ -0,0 +1,8 @@ +using AutoMapper; + +namespace DotnetFoundation.API.Helpers +{ + public class AutoMappingProfile : Profile + { + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/Helpers/EnumHelper.cs b/DotnetFoundation/DotnetFoundation.API/Helpers/EnumHelper.cs new file mode 100644 index 0000000..5006bcb --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/Helpers/EnumHelper.cs @@ -0,0 +1,15 @@ +namespace DotnetFoundation.API.Helpers +{ + public static class EnumHelper + { + public static string ConvertToString(Enum enumElement) + { + return Enum.GetName(enumElement.GetType(), enumElement); + } + + public static TEnumType ConvertToEnum(string enumValue) + { + return (TEnumType)Enum.Parse(typeof(TEnumType), enumValue); + } + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/Models/BaseResponse.cs b/DotnetFoundation/DotnetFoundation.API/Models/BaseResponse.cs new file mode 100644 index 0000000..60ca5bb --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/Models/BaseResponse.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Mvc; + +namespace DotnetFoundation.API.Models +{ + public enum ResponseStatus + { + Success, + Fail, + Error + } + + public enum ErrorCode + { + INTERNAL_SERVER_ERROR, + USER_ID_REQUIRED, + USER_NOT_FOUND + } + + public class BaseResponse + { + public BaseResponse(ResponseStatus status) => Status = status; + public ResponseStatus? Status { get; set; } + public T? Data { get; set; } + public ErrorCode? ErrorCode { get; set; } + public string? Message { get; set; } + public string? StackTrace { get; set; } + } + + public class ModelValidationBadRequest + { + public static BadRequestObjectResult ModelValidationErrorResponse(ActionContext actionContext) + { + return new BadRequestObjectResult(actionContext.ModelState + .Where(modelError => modelError.Value.Errors.Count > 0) + .Select(modelError => new BaseResponse(ResponseStatus.Error) + { + ErrorCode = Enum.TryParse(modelError.Value.Errors.FirstOrDefault().ErrorMessage, out ErrorCode enumErrorCode) ? enumErrorCode : null, + Message = modelError.Value.Errors.FirstOrDefault().ErrorMessage + }).FirstOrDefault()); + } + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/Program.cs b/DotnetFoundation/DotnetFoundation.API/Program.cs new file mode 100644 index 0000000..1b3d077 --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/Program.cs @@ -0,0 +1,155 @@ +using System.Reflection; +using System.Text; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; +using Serilog; +using Serilog.Events; +using Swashbuckle.AspNetCore.Filters; +using DotnetFoundation.API.BLL; +using DotnetFoundation.API.BLL.Interfaces; +using DotnetFoundation.API.Models; +using DotnetFoundation.DAL.DatabaseContext; +using DotnetFoundation.DAL.Repositories; +using DotnetFoundation.DAL.Repositories.Interfaces; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +// Controller Services +builder.Services.AddControllers(options => +{ + options.Filters.Add(new ProducesAttribute("application/json")); +}) + .AddJsonOptions(options => + { + options.JsonSerializerOptions.PropertyNamingPolicy = null; + options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + +// AutoMapper Services +builder.Services.AddAutoMapper(typeof(Program)); + +// Swagger UI Services +builder.Services.AddSwaggerGen(options => +{ + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + { + Description = "Standard Authorization header using the Bearer Scheme (\"bearer {token}\")", + In = ParameterLocation.Header, + Name = "Authorization", + Type = SecuritySchemeType.ApiKey + }); + + options.OperationFilter(); + + string xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + string filePath = Path.Combine(AppContext.BaseDirectory, xmlFile); + options.IncludeXmlComments(filePath); +}); + +// CORS Services +string[] allowedCorsOrigin = builder.Configuration.GetSection("CorsPolicies:CorsOrigin").Value + .Split(new char[] { ',', ';' }) + .Select(origin => origin.Trim()) + .ToArray(); + +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(builder => + { + builder.WithOrigins(allowedCorsOrigin) + .AllowAnyHeader() + .AllowAnyMethod(); + }); +}); + +// Authentication +builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8 + .GetBytes(builder.Configuration.GetSection("AppSettings:JWT_Token").Value)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero, + ValidateLifetime = true, + LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => + { + TokenValidationParameters clonedParameters = validationParameters.Clone(); + clonedParameters.LifetimeValidator = null; + + // If token expiry time is not null, then validate lifetime + if (expires != null) + { + Validators.ValidateLifetime(notBefore, expires, securityToken, clonedParameters); + } + + return true; + } + }; + }); + +// Configure Error Response from Model Validations +builder.Services.AddMvc().ConfigureApiBehaviorOptions(options => +{ + options.InvalidModelStateResponseFactory = actionContext => + { + return ModelValidationBadRequest.ModelValidationErrorResponse(actionContext); + }; +}); + +// Logging service Serilogs +builder.Logging.AddSerilog(); +Log.Logger = new LoggerConfiguration() + .WriteTo.File( + path: "logs/log-.txt", + outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}{NewLine}{NewLine}", + rollingInterval: RollingInterval.Day, + restrictedToMinimumLevel: LogEventLevel.Information + ).CreateLogger(); + +// DB connection Setup +builder.Services.AddDbContext(options => +{ + string connectionString = builder.Configuration.GetConnectionString("DBConnection"); + options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); +}); + +// Adding HTTP Context +builder.Services.AddHttpContextAccessor(); + +// Adding Services Scope For BLLs - Dependency Injection +builder.Services.AddScoped(); + +// Adding Services Scope For Repositories - Dependency Injection +builder.Services.AddScoped(); + +WebApplication app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseStaticFiles(); + +app.UseHttpsRedirection(); + +app.UseCors(); + +app.UseAuthentication(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/DotnetFoundation/DotnetFoundation.API/Properties/launchSettings.json b/DotnetFoundation/DotnetFoundation.API/Properties/launchSettings.json new file mode 100644 index 0000000..ca4da32 --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:34886", + "sslPort": 44388 + } + }, + "profiles": { + "DotnetBoilerPlate.API": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7030;http://localhost:5064", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/appsettings.Development.json b/DotnetFoundation/DotnetFoundation.API/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/DotnetFoundation/DotnetFoundation.API/appsettings.json b/DotnetFoundation/DotnetFoundation.API/appsettings.json new file mode 100644 index 0000000..a6123fd --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.API/appsettings.json @@ -0,0 +1,19 @@ +{ + "AppSettings": { + "JWT_Token": "SAMPLE_JWT_TOKEN", + "Password_Salt": "SAMPLE_PASSWORD_SALT" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "DBConnection": "server=localhost;database=DotnetBoilerPlate;user=root;password=root" + }, + "CorsPolicies": { + "CorsOrigin": "http://localhost:4200" + } +} diff --git a/DotnetFoundation/DotnetFoundation.DAL/DatabaseContext/SqlDatabaseContext.cs b/DotnetFoundation/DotnetFoundation.DAL/DatabaseContext/SqlDatabaseContext.cs new file mode 100644 index 0000000..2d1e428 --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.DAL/DatabaseContext/SqlDatabaseContext.cs @@ -0,0 +1,182 @@ +using Microsoft.EntityFrameworkCore; +using DotnetFoundation.DAL.Models; + +namespace DotnetFoundation.DAL.DatabaseContext +{ + public partial class SqlDatabaseContext : DbContext + { + public SqlDatabaseContext() + { + } + + public SqlDatabaseContext(DbContextOptions options) + : base(options) + { + } + + + public DbSet Users { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .UseCollation("latin1_swedish_ci") + .HasCharSet("latin1"); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.UserId).HasName("PRIMARY"); + + entity + .ToTable("users") + .HasCharSet("utf8") + .UseCollation("utf8_general_ci"); + + entity.Property(e => e.UserId) + .HasMaxLength(36) + .HasColumnName("userid"); + entity.Property(e => e.Address1City) + .HasMaxLength(50) + .HasColumnName("address1_city"); + entity.Property(e => e.Address1Country) + .HasMaxLength(50) + .HasColumnName("address1_country"); + entity.Property(e => e.Address1Pincode) + .HasMaxLength(20) + .HasColumnName("address1_pincode"); + entity.Property(e => e.Address1State) + .HasMaxLength(50) + .HasColumnName("address1_state"); + entity.Property(e => e.Address1Street1) + .HasMaxLength(50) + .HasColumnName("address1_street1"); + entity.Property(e => e.Address1Street2) + .HasMaxLength(50) + .HasColumnName("address1_street2"); + entity.Property(e => e.Address2City) + .HasMaxLength(50) + .HasColumnName("address2_city"); + entity.Property(e => e.Address2Country) + .HasMaxLength(50) + .HasColumnName("address2_country"); + entity.Property(e => e.Address2Pincode) + .HasMaxLength(20) + .HasColumnName("address2_pincode"); + entity.Property(e => e.Address2State) + .HasMaxLength(50) + .HasColumnName("address2_state"); + entity.Property(e => e.Address2Street1) + .HasMaxLength(50) + .HasColumnName("address2_street1"); + entity.Property(e => e.Address2Street2) + .HasMaxLength(100) + .HasColumnName("address2_street2"); + entity.Property(e => e.CandidateComments) + .HasMaxLength(500) + .HasColumnName("candidatecomments"); + entity.Property(e => e.Comments) + .HasMaxLength(500) + .HasColumnName("comments"); + entity.Property(e => e.CreatedBy) + .HasMaxLength(36) + .HasColumnName("createdby"); + entity.Property(e => e.CreatedOn) + .HasColumnType("datetime") + .HasColumnName("createdon"); + entity.Property(e => e.DateOfBirth) + .HasColumnType("datetime") + .HasColumnName("dateofbirth"); + entity.Property(e => e.EmailAddress) + .HasMaxLength(50) + .HasColumnName("emailaddress"); + entity.Property(e => e.EmergencyContactNumber) + .HasMaxLength(20) + .HasColumnName("emergencycontactnumber"); + entity.Property(e => e.FacebookId) + .HasMaxLength(50) + .HasColumnName("facebookid"); + entity.Property(e => e.Features) + .HasColumnType("text") + .HasColumnName("features"); + entity.Property(e => e.FingerPrintValue) + .HasMaxLength(100) + .HasComment("Path of finger print") + .HasColumnName("fingerprintvalue"); + entity.Property(e => e.FirstName) + .HasMaxLength(50) + .HasColumnName("firstname"); + entity.Property(e => e.Gender).HasColumnName("gender"); + entity.Property(e => e.HallTicket) + .HasMaxLength(20) + .HasColumnName("hallticket"); + entity.Property(e => e.IsAcceptedTermsAndConditions).HasColumnName("isacceptedtermsandconditions"); + entity.Property(e => e.LastName) + .HasMaxLength(50) + .HasColumnName("lastname"); + entity.Property(e => e.LinkedinId) + .HasMaxLength(50) + .HasColumnName("linkedinid"); + entity.Property(e => e.MobileNumber) + .HasMaxLength(20) + .HasColumnName("mobilenumber"); + entity.Property(e => e.ModifiedBy) + .HasMaxLength(36) + .HasColumnName("modifiedby"); + entity.Property(e => e.ModifiedOn) + .HasColumnType("datetime") + .HasColumnName("modifiedon"); + entity.Property(e => e.Password) + .HasMaxLength(20) + .HasColumnName("password"); + entity.Property(e => e.ProfilePicPath) + .HasMaxLength(100) + .HasComment("Path of profile picture") + .HasColumnName("profilepicpath"); + entity.Property(e => e.QuestionPaperSetNumber).HasColumnName("questionpapersetnumber"); + entity.Property(e => e.RegistrationNumber) + .HasMaxLength(20) + .HasColumnName("registrationumber"); + entity.Property(e => e.ResFloat1).HasColumnName("res_float1"); + entity.Property(e => e.ResFloat2).HasColumnName("res_float2"); + entity.Property(e => e.ResInt1).HasColumnName("res_int1"); + entity.Property(e => e.ResInt2).HasColumnName("res_int2"); + entity.Property(e => e.ResString1) + .HasMaxLength(100) + .HasColumnName("res_string1"); + entity.Property(e => e.ResString2) + .HasMaxLength(100) + .HasColumnName("res_string2"); + entity.Property(e => e.Salutation) + .HasMaxLength(5) + .IsFixedLength() + .HasColumnName("salutation"); + entity.Property(e => e.Status) + .HasDefaultValueSql("'1'") + .HasComment("1 - active, 2 - deactive, 3 - deleted, 0 - dummy user, Shouldnot use 9") + .HasColumnName("status"); + entity.Property(e => e.ThumbImpression) + .HasMaxLength(100) + .HasComment("Path of thumb impression") + .HasColumnName("thumbimpression"); + entity.Property(e => e.TraineePhoto) + .HasMaxLength(100) + .HasComment("Path of trainee photo") + .HasColumnName("traineephoto"); + entity.Property(e => e.TrainingProviderId) + .HasMaxLength(36) + .HasColumnName("trainingproviderid"); + entity.Property(e => e.UnSubscribe).HasColumnName("unsubscribe"); + entity.Property(e => e.UserDisplayId) + .HasMaxLength(20) + .HasColumnName("userdisplayid"); + entity.Property(e => e.UserType) + .HasComment("0-Admin, 1-employee, 2-trainee, 3-super user, 4-trainingprovider") + .HasColumnName("usertype"); + }); + + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); + } +} diff --git a/DotnetFoundation/DotnetFoundation.DAL/DotnetFoundation.DAL.csproj b/DotnetFoundation/DotnetFoundation.DAL/DotnetFoundation.DAL.csproj new file mode 100644 index 0000000..f70804f --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.DAL/DotnetFoundation.DAL.csproj @@ -0,0 +1,28 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/DotnetFoundation/DotnetFoundation.DAL/Models/UsersDBO.cs b/DotnetFoundation/DotnetFoundation.DAL/Models/UsersDBO.cs new file mode 100644 index 0000000..31fe61c --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.DAL/Models/UsersDBO.cs @@ -0,0 +1,122 @@ +namespace DotnetFoundation.DAL.Models; + +public partial class UsersDBO +{ + public string UserId { get; set; } = null!; + + public string? UserDisplayId { get; set; } + + /// + /// 0-Admin, 1-employee, 2-trainee, 3-super user, 4-trainingprovider + /// + public int? UserType { get; set; } + + public string? FirstName { get; set; } + + public string? LastName { get; set; } + + public string? Salutation { get; set; } + + public string? MobileNumber { get; set; } + + public string? EmergencyContactNumber { get; set; } + + public string? EmailAddress { get; set; } + + public string? RegistrationNumber { get; set; } + + public string? Password { get; set; } + + public string? HallTicket { get; set; } + + public sbyte? QuestionPaperSetNumber { get; set; } + + public string? LinkedinId { get; set; } + + public string? FacebookId { get; set; } + + public bool? IsAcceptedTermsAndConditions { get; set; } + + public sbyte UnSubscribe { get; set; } + + /// + /// Path of profile picture + /// + public string? ProfilePicPath { get; set; } + + /// + /// Path of trainee photo + /// + public string? TraineePhoto { get; set; } + + /// + /// Path of finger print + /// + public string? FingerPrintValue { get; set; } + + /// + /// Path of thumb impression + /// + public string? ThumbImpression { get; set; } + + public bool? Gender { get; set; } + + public DateTime? DateOfBirth { get; set; } + + public string? Comments { get; set; } + + public string? CandidateComments { get; set; } + + public string? TrainingProviderId { get; set; } + + /// + /// 1 - active, 2 - deactive, 3 - deleted, 0 - dummy user, Shouldnot use 9 + /// + public bool? Status { get; set; } + + public string? CreatedBy { get; set; } + + public DateTime? CreatedOn { get; set; } + + public string? ModifiedBy { get; set; } + + public DateTime? ModifiedOn { get; set; } + + public string? Address1Street1 { get; set; } + + public string? Address1Street2 { get; set; } + + public string? Address1City { get; set; } + + public string? Address1State { get; set; } + + public string? Address1Country { get; set; } + + public string? Address1Pincode { get; set; } + + public string? Address2Street1 { get; set; } + + public string? Address2Street2 { get; set; } + + public string? Address2City { get; set; } + + public string? Address2State { get; set; } + + public string? Address2Country { get; set; } + + public string? Address2Pincode { get; set; } + + public string? ResString1 { get; set; } + + public string? ResString2 { get; set; } + + public float? ResFloat1 { get; set; } + + public float? ResFloat2 { get; set; } + + public int? ResInt1 { get; set; } + + public int? ResInt2 { get; set; } + + public string? Features { get; set; } +} diff --git a/DotnetFoundation/DotnetFoundation.DAL/Repositories/Interfaces/IUsersRepo.cs b/DotnetFoundation/DotnetFoundation.DAL/Repositories/Interfaces/IUsersRepo.cs new file mode 100644 index 0000000..6f05f87 --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.DAL/Repositories/Interfaces/IUsersRepo.cs @@ -0,0 +1,10 @@ +using DotnetFoundation.DAL.Models; + +namespace DotnetFoundation.DAL.Repositories.Interfaces +{ + public interface IUsersRepo + { + List GetAllUsers(); + UsersDBO GetUserById(string userId); + } +} diff --git a/DotnetFoundation/DotnetFoundation.DAL/Repositories/UsersRepo.cs b/DotnetFoundation/DotnetFoundation.DAL/Repositories/UsersRepo.cs new file mode 100644 index 0000000..2ad7e5f --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.DAL/Repositories/UsersRepo.cs @@ -0,0 +1,25 @@ +using DotnetFoundation.DAL.DatabaseContext; +using DotnetFoundation.DAL.Models; +using DotnetFoundation.DAL.Repositories.Interfaces; + +namespace DotnetFoundation.DAL.Repositories +{ + public class UsersRepo : IUsersRepo + { + private readonly SqlDatabaseContext _databaseContext; + + public UsersRepo(SqlDatabaseContext databaseContext) => _databaseContext = databaseContext; + + public List GetAllUsers() + { + return _databaseContext.Users.ToList(); + } + + public UsersDBO GetUserById(string userId) + { + return _databaseContext.Users + .Where(user => user.UserId == userId) + .FirstOrDefault(); + } + } +} diff --git a/DotnetFoundation/DotnetFoundation.sln b/DotnetFoundation/DotnetFoundation.sln new file mode 100644 index 0000000..ab7547e --- /dev/null +++ b/DotnetFoundation/DotnetFoundation.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34003.232 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotnetFoundation.API", "DotnetFoundation.API\DotnetFoundation.API.csproj", "{1C10A534-DB66-494B-B797-55143C40C9D1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotnetFoundation.DAL", "DotnetFoundation.DAL\DotnetFoundation.DAL.csproj", "{9E92CC0E-F0F8-4511-A5D9-D7B192CC9DA1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{37C6C65D-EB24-40A7-A954-0446B3D1511D}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1C10A534-DB66-494B-B797-55143C40C9D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C10A534-DB66-494B-B797-55143C40C9D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C10A534-DB66-494B-B797-55143C40C9D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C10A534-DB66-494B-B797-55143C40C9D1}.Release|Any CPU.Build.0 = Release|Any CPU + {9E92CC0E-F0F8-4511-A5D9-D7B192CC9DA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E92CC0E-F0F8-4511-A5D9-D7B192CC9DA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E92CC0E-F0F8-4511-A5D9-D7B192CC9DA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E92CC0E-F0F8-4511-A5D9-D7B192CC9DA1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {52544ABA-43AE-4042-B5BF-D7287DD51EDD} + EndGlobalSection +EndGlobal diff --git a/docs/img/dotnet-run.png b/docs/img/dotnet-run.png new file mode 100644 index 0000000..8e66c88 Binary files /dev/null and b/docs/img/dotnet-run.png differ diff --git a/docs/img/extensions.png b/docs/img/extensions.png new file mode 100644 index 0000000..fbda72d Binary files /dev/null and b/docs/img/extensions.png differ