diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..111933fd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,242 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_collection_expression = when_types_loosely_match +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_prefer_top_level_statements = true:silent + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:silent + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_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_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +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.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.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 + +[*.{cs,vb}] +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3a868930..b42fe34c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ riderModule.iml /_ReSharper.Caches/ .fake .vscode +/MyFirstBlog.sln +.vs/ \ No newline at end of file diff --git a/.vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2 b/.vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2 deleted file mode 100644 index e3a42a61..00000000 Binary files a/.vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2 and /dev/null differ diff --git a/.vs/MyFirstBlog/FileContentIndex/1451f00c-8a3c-4b67-9988-24ae06d88ff9.vsidx b/.vs/MyFirstBlog/FileContentIndex/1451f00c-8a3c-4b67-9988-24ae06d88ff9.vsidx deleted file mode 100644 index ae1b509b..00000000 Binary files a/.vs/MyFirstBlog/FileContentIndex/1451f00c-8a3c-4b67-9988-24ae06d88ff9.vsidx and /dev/null differ diff --git a/.vs/MyFirstBlog/FileContentIndex/3671b2ea-91c1-4fa3-8590-3e73598d97ea.vsidx b/.vs/MyFirstBlog/FileContentIndex/3671b2ea-91c1-4fa3-8590-3e73598d97ea.vsidx deleted file mode 100644 index 78b55c80..00000000 Binary files a/.vs/MyFirstBlog/FileContentIndex/3671b2ea-91c1-4fa3-8590-3e73598d97ea.vsidx and /dev/null differ diff --git a/.vs/MyFirstBlog/config/applicationhost.config b/.vs/MyFirstBlog/config/applicationhost.config deleted file mode 100644 index 0d88f0db..00000000 --- a/.vs/MyFirstBlog/config/applicationhost.config +++ /dev/null @@ -1,1016 +0,0 @@ - - - - - - - -
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.vs/MyFirstBlog/v17/.futdcache.v2 b/.vs/MyFirstBlog/v17/.futdcache.v2 deleted file mode 100644 index 128982d8..00000000 Binary files a/.vs/MyFirstBlog/v17/.futdcache.v2 and /dev/null differ diff --git a/.vs/MyFirstBlog/v17/.suo b/.vs/MyFirstBlog/v17/.suo deleted file mode 100644 index 74e1a08b..00000000 Binary files a/.vs/MyFirstBlog/v17/.suo and /dev/null differ diff --git a/.vs/MyFirstBlog/v17/DocumentLayout.json b/.vs/MyFirstBlog/v17/DocumentLayout.json deleted file mode 100644 index 653eb6b4..00000000 --- a/.vs/MyFirstBlog/v17/DocumentLayout.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "Version": 1, - "WorkspaceRootPath": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\", - "Documents": [ - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\properties\\launchsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\properties\\launchsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}" - }, - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\entities\\post.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\entities\\post.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\services\\postservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\services\\postservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}" - }, - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\extensions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\extensions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\dtos\\postdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\dtos\\postdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\00code\\fullstack\\myfirstblogbackend\\myfirstblog\\controllers\\postscontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\controllers\\postscontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - } - ], - "DocumentGroupContainers": [ - { - "Orientation": 0, - "VerticalTabListWidth": 256, - "DocumentGroups": [ - { - "DockedWidth": 200, - "SelectedChildIndex": 6, - "Children": [ - { - "$type": "Document", - "DocumentIndex": 1, - "Title": "Program.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Program.cs", - "RelativeDocumentMoniker": "MyFirstBlog\\Program.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Program.cs", - "RelativeToolTip": "MyFirstBlog\\Program.cs", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAA4AAAAjAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:44:39.864Z" - }, - { - "$type": "Document", - "DocumentIndex": 2, - "Title": "Post.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Entities\\Post.cs", - "RelativeDocumentMoniker": "MyFirstBlog\\Entities\\Post.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Entities\\Post.cs", - "RelativeToolTip": "MyFirstBlog\\Entities\\Post.cs", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAAEAAAAAAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:43:03.248Z" - }, - { - "$type": "Document", - "DocumentIndex": 6, - "Title": "PostDto.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Dtos\\PostDto.cs", - "RelativeDocumentMoniker": "MyFirstBlog\\Dtos\\PostDto.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Dtos\\PostDto.cs", - "RelativeToolTip": "MyFirstBlog\\Dtos\\PostDto.cs", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAAgAAAABAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:42:47.081Z" - }, - { - "$type": "Document", - "DocumentIndex": 4, - "Title": "appsettings.json", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\appsettings.json", - "RelativeDocumentMoniker": "MyFirstBlog\\appsettings.json", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\appsettings.json", - "RelativeToolTip": "MyFirstBlog\\appsettings.json", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|", - "WhenOpened": "2024-05-15T14:49:58.169Z" - }, - { - "$type": "Document", - "DocumentIndex": 3, - "Title": "PostService.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Services\\PostService.cs", - "RelativeDocumentMoniker": "MyFirstBlog\\Services\\PostService.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Services\\PostService.cs", - "RelativeToolTip": "MyFirstBlog\\Services\\PostService.cs", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAAkAAAAkAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:45:00.15Z" - }, - { - "$type": "Document", - "DocumentIndex": 5, - "Title": "Extensions.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Extensions.cs", - "RelativeDocumentMoniker": "MyFirstBlog\\Extensions.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Extensions.cs", - "RelativeToolTip": "MyFirstBlog\\Extensions.cs", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAAwAAAAuAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:44:53.417Z" - }, - { - "$type": "Document", - "DocumentIndex": 0, - "Title": "launchSettings.json", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Properties\\launchSettings.json", - "RelativeDocumentMoniker": "MyFirstBlog\\Properties\\launchSettings.json", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Properties\\launchSettings.json", - "RelativeToolTip": "MyFirstBlog\\Properties\\launchSettings.json", - "ViewState": "AQIAAA8AAAAAAAAAAAAAABkAAAAfAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|", - "WhenOpened": "2024-05-15T14:50:05.724Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 7, - "Title": "PostsController.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Controllers\\PostsController.cs", - "RelativeDocumentMoniker": "MyFirstBlog\\Controllers\\PostsController.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Controllers\\PostsController.cs", - "RelativeToolTip": "MyFirstBlog\\Controllers\\PostsController.cs", - "ViewState": "AQIAAAYAAAAAAAAAAAAAAAsAAAAAAAAA", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:42:54.111Z" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/.vs/ProjectEvaluation/myfirstblog.metadata.v7.bin b/.vs/ProjectEvaluation/myfirstblog.metadata.v7.bin deleted file mode 100644 index a3a97897..00000000 Binary files a/.vs/ProjectEvaluation/myfirstblog.metadata.v7.bin and /dev/null differ diff --git a/.vs/ProjectEvaluation/myfirstblog.projects.v7.bin b/.vs/ProjectEvaluation/myfirstblog.projects.v7.bin deleted file mode 100644 index cfc3e6a4..00000000 Binary files a/.vs/ProjectEvaluation/myfirstblog.projects.v7.bin and /dev/null differ diff --git a/MyFirstBlog.sln b/MyFirstBlog.sln deleted file mode 100644 index e2ffab4c..00000000 --- a/MyFirstBlog.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFirstBlog", "MyFirstBlog\MyFirstBlog.csproj", "{BB64A02C-C5D9-4D64-A357-7322C54B1419}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFirstBlogTests", "MyFirstBlogTests\MyFirstBlogTests.csproj", "{84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {BB64A02C-C5D9-4D64-A357-7322C54B1419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BB64A02C-C5D9-4D64-A357-7322C54B1419}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB64A02C-C5D9-4D64-A357-7322C54B1419}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BB64A02C-C5D9-4D64-A357-7322C54B1419}.Release|Any CPU.Build.0 = Release|Any CPU - {84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/MyFirstBlog/Controllers/PostsController.cs b/MyFirstBlog/Controllers/PostsController.cs index 8fa6bf2c..89447bc5 100644 --- a/MyFirstBlog/Controllers/PostsController.cs +++ b/MyFirstBlog/Controllers/PostsController.cs @@ -1,34 +1,55 @@ -namespace MyFirstBlog.Controllers; - using Microsoft.AspNetCore.Mvc; using MyFirstBlog.Dtos; +using MyFirstBlog.Entities; using MyFirstBlog.Services; +using System.Collections.Generic; + +namespace MyFirstBlog.Controllers +{ + [ApiController] + [Route("posts")] + public class PostsController : ControllerBase + { + private readonly IPostService _postService; + + public PostsController(IPostService postService) + { + _postService = postService; + } -[ApiController] -[Route("posts")] - -public class PostsController : ControllerBase { - private IPostService _postService; + // Get /posts + [HttpGet] + public IEnumerable GetPosts() + { + return _postService.GetPosts(); + } - public PostsController(IPostService postService) { - _postService = postService; - } + // Get /posts/:slug + [HttpGet("{slug}")] + public ActionResult GetPost(string slug) + { + var post = _postService.GetPost(slug); + + if (post is null) + { + return NotFound(); + } + return post; + } - // Get /posts - [HttpGet] - public IEnumerable GetPosts() { - return _postService.GetPosts(); - } + // Post /posts + [HttpPost("createnewpost")] + public IActionResult CreatePost([FromBody] CreatePostDto createPostDto) + { + if (string.IsNullOrWhiteSpace(createPostDto.Title)) + { + return BadRequest(new { errors = new[] { "Title cannot be blank" } }); + } - // Get /posts/:slug - [HttpGet("{slug}")] - public ActionResult GetPost(string slug) { - var post = _postService.GetPost(slug); + var post = _postService.CreatePost(createPostDto.Title, createPostDto.Description, createPostDto.Body); - if (post is null) { - return NotFound(); + return CreatedAtAction(nameof(GetPost), new { slug = post.Slug }, post); } - return post; } } diff --git a/MyFirstBlog/Dtos/CreatePostDto.cs b/MyFirstBlog/Dtos/CreatePostDto.cs new file mode 100644 index 00000000..410b0235 --- /dev/null +++ b/MyFirstBlog/Dtos/CreatePostDto.cs @@ -0,0 +1,10 @@ +namespace MyFirstBlog.Dtos +{ + public class CreatePostDto + { + public string Title { get; set; } + public string Description { get; set; } + + public string Body { get; set; } + } +} diff --git a/MyFirstBlog/Dtos/PostDto.cs b/MyFirstBlog/Dtos/PostDto.cs index 12ca4818..ea3a835d 100644 --- a/MyFirstBlog/Dtos/PostDto.cs +++ b/MyFirstBlog/Dtos/PostDto.cs @@ -4,6 +4,8 @@ public record PostDto { public Guid Id { get; init; } public string Title { get; init; } = default!; public string Slug { get; init; } = default!; + + public string Description { get; init; } = default!; public string Body { get; init; } = default!; public DateTime CreatedDate { get; init; } } diff --git a/MyFirstBlog/Entities/Post.cs b/MyFirstBlog/Entities/Post.cs index 9347e859..bc0b8c8e 100644 --- a/MyFirstBlog/Entities/Post.cs +++ b/MyFirstBlog/Entities/Post.cs @@ -5,4 +5,5 @@ public record Post { public string Slug { get; init; } = default!; public string Body { get; init; } = default!; public DateTime CreatedDate { get; init; } + public string Description { get; init; } = default!; } diff --git a/MyFirstBlog/Helpers/DataContext.cs b/MyFirstBlog/Helpers/DataContext.cs index 60ad2bfc..0b3ef1a0 100644 --- a/MyFirstBlog/Helpers/DataContext.cs +++ b/MyFirstBlog/Helpers/DataContext.cs @@ -1,22 +1,23 @@ -namespace MyFirstBlog.Helpers; - using Microsoft.EntityFrameworkCore; using MyFirstBlog.Entities; +using Microsoft.Extensions.Configuration; - -public class DataContext : DbContext +namespace MyFirstBlog.Helpers { - protected readonly IConfiguration Configuration; - - public DataContext(IConfiguration configuration) + public class DataContext : DbContext { - Configuration = configuration; - } + protected readonly IConfiguration Configuration; - protected override void OnConfiguring(DbContextOptionsBuilder options) - { - options.UseNpgsql(ConnectionHelper.GetConnectionString(Configuration)); - } + public DataContext(IConfiguration configuration) + { + Configuration = configuration; + } - public DbSet Posts { get; set; } -} \ No newline at end of file + protected override void OnConfiguring(DbContextOptionsBuilder options) + { + options.UseNpgsql(ConnectionHelper.GetConnectionString(Configuration)); + } + + public DbSet Posts { get; set; } + } +} diff --git a/MyFirstBlog/Program.cs b/MyFirstBlog/Program.cs index 4042b610..266729f1 100644 --- a/MyFirstBlog/Program.cs +++ b/MyFirstBlog/Program.cs @@ -35,7 +35,7 @@ if (env.IsDevelopment()) { app.UseSwagger(); - app.UseSwaggerUI(); + app.UseSwaggerUI(); app.UseCors(MyAllowLocalhostOrigins); } diff --git a/MyFirstBlog/Services/PostService.cs b/MyFirstBlog/Services/PostService.cs index 6bac099f..ef4e8845 100644 --- a/MyFirstBlog/Services/PostService.cs +++ b/MyFirstBlog/Services/PostService.cs @@ -1,37 +1,81 @@ -namespace MyFirstBlog.Services; - using MyFirstBlog.Helpers; using MyFirstBlog.Entities; using System.Text.RegularExpressions; using MyFirstBlog.Dtos; +using System.Collections.Generic; +using System.Linq; -public interface IPostService -{ - IEnumerable GetPosts(); - PostDto GetPost(String slug); -} - -public class PostService : IPostService +namespace MyFirstBlog.Services { - private DataContext _context; - - public PostService(DataContext context) + public interface IPostService { - _context = context; + IEnumerable GetPosts(); + PostDto GetPost(string slug); + Post CreatePost(string title, string description, string body); } - public IEnumerable GetPosts() + public class PostService : IPostService { - return _context.Posts.Select(post => post.AsDto()); - } + private readonly DataContext _context; - public PostDto GetPost(string slug) - { - return getPost(slug).AsDto(); - } + public PostService(DataContext context) + { + _context = context; + } - private Post getPost(string slug) - { - return _context.Posts.Where(a=>a.Slug==slug.ToString()).SingleOrDefault(); + public IEnumerable GetPosts() + { + return _context.Posts.Select(post => new PostDto + { + Title = post.Title, + Description = post.Description, + Slug = post.Slug, + CreatedDate = post.CreatedDate + }); + } + + public PostDto GetPost(string slug) + { + var post = getPost(slug); + if (post == null) return null; + + return new PostDto + { + Title = post.Title, + Description = post.Description, + Slug = post.Slug, + CreatedDate = post.CreatedDate + }; + } + + private Post getPost(string slug) + { + return _context.Posts.FirstOrDefault(a => a.Slug == slug); + } + + public Post CreatePost(string title, string description, string body) + { + var post = new Post + { + Title = title, + Description = description, + Body = body, + Slug = GenerateSlug(title), + CreatedDate = DateTime.UtcNow + }; + + _context.Posts.Add(post); + _context.SaveChanges(); + + return post; + } + + private string GenerateSlug(string title) + { + var slug = Regex.Replace(title.ToLower(), @"[^a-z0-9\s-]", ""); + slug = Regex.Replace(slug, @"\s+", " ").Trim(); + slug = Regex.Replace(slug, @"\s", "-"); + return slug; + } } }