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/.gitignore b/MyFirstBlog/.gitignore
new file mode 100644
index 00000000..b99f1c65
--- /dev/null
+++ b/MyFirstBlog/.gitignore
@@ -0,0 +1,16 @@
+# Ignore Visual Studio files
+.vs/
+*.suo
+*.user
+*.vsidx
+
+# Ignore build folders
+bin/
+obj/
+
+# Ignore Rider, VS Code settings
+.idea/
+.vscode/
+
+# Ignore test results or local test data
+TestStore/
diff --git a/MyFirstBlog/Controllers/PostsController.cs b/MyFirstBlog/Controllers/PostsController.cs
index 8fa6bf2c..0344310f 100644
--- a/MyFirstBlog/Controllers/PostsController.cs
+++ b/MyFirstBlog/Controllers/PostsController.cs
@@ -31,4 +31,29 @@ public ActionResult GetPost(string slug) {
return post;
}
+
+ [HttpPost]
+ public IActionResult CreatePost([FromBody] CreatePostRequest request)
+ {
+ if (string.IsNullOrWhiteSpace(request.Title))
+ {
+ return BadRequest(new { errors = new[] { "Title cannot be blank" } });
+ }
+
+ var post = _postService.CreatePost(request.Title, request.Description);
+
+ return Created("", new { post });
+ }
+
}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyFirstBlog/Dtos/CreatePostRequest.cs b/MyFirstBlog/Dtos/CreatePostRequest.cs
new file mode 100644
index 00000000..9d42e551
--- /dev/null
+++ b/MyFirstBlog/Dtos/CreatePostRequest.cs
@@ -0,0 +1,8 @@
+namespace MyFirstBlog.Dtos;
+
+public class CreatePostRequest
+{
+ public string Title { get; set; } = string.Empty;
+ public string Description { get; set; } = string.Empty;
+}
+
diff --git a/MyFirstBlog/Dtos/DtoExtensions.cs b/MyFirstBlog/Dtos/DtoExtensions.cs
new file mode 100644
index 00000000..e447e01f
--- /dev/null
+++ b/MyFirstBlog/Dtos/DtoExtensions.cs
@@ -0,0 +1,19 @@
+using MyFirstBlog.Entities;
+
+namespace MyFirstBlog.Dtos;
+
+public static class DtoExtensions
+{
+ public static PostDto AsDto(this Post post)
+ {
+ return new PostDto
+ {
+ Id = post.Id,
+ Title = post.Title,
+ Slug = post.Slug,
+ Body = post.Body,
+ CreatedDate = post.CreatedDate
+ };
+ }
+}
+
diff --git a/MyFirstBlog/Entities/DataContext.cs b/MyFirstBlog/Entities/DataContext.cs
new file mode 100644
index 00000000..cac18822
--- /dev/null
+++ b/MyFirstBlog/Entities/DataContext.cs
@@ -0,0 +1,33 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using MyFirstBlog.Entities;
+
+namespace MyFirstBlog.Entities
+{
+ public class DataContext : DbContext
+ {
+ protected readonly IConfiguration _configuration;
+
+ public DataContext(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public DataContext(IConfiguration configuration, DbContextOptions options)
+ : base(options)
+ {
+ _configuration = configuration;
+ }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder options)
+ {
+ if (!options.IsConfigured)
+ {
+ options.UseNpgsql(_configuration.GetConnectionString("DefaultConnection"));
+ }
+ }
+
+ public DbSet Posts { get; set; }
+ }
+}
+
diff --git a/MyFirstBlog/Helpers/DataContext.cs b/MyFirstBlog/Helpers/DataContext.cs
deleted file mode 100644
index 60ad2bfc..00000000
--- a/MyFirstBlog/Helpers/DataContext.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace MyFirstBlog.Helpers;
-
-using Microsoft.EntityFrameworkCore;
-using MyFirstBlog.Entities;
-
-
-public class DataContext : DbContext
-{
- protected readonly IConfiguration Configuration;
-
- public DataContext(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- protected override void OnConfiguring(DbContextOptionsBuilder options)
- {
- options.UseNpgsql(ConnectionHelper.GetConnectionString(Configuration));
- }
-
- public DbSet Posts { get; set; }
-}
\ No newline at end of file
diff --git a/MyFirstBlog/Helpers/DatabaseHelper.cs b/MyFirstBlog/Helpers/DatabaseHelper.cs
index 56418c5d..10bf67cd 100644
--- a/MyFirstBlog/Helpers/DatabaseHelper.cs
+++ b/MyFirstBlog/Helpers/DatabaseHelper.cs
@@ -1,4 +1,5 @@
namespace MyFirstBlog.Helpers;
+using MyFirstBlog.Entities;
using Microsoft.EntityFrameworkCore;
diff --git a/MyFirstBlog/Migrations/20221128224120_InitialCreate.Designer.cs b/MyFirstBlog/Migrations/20221128224120_InitialCreate.Designer.cs
index a8d15762..42bca320 100644
--- a/MyFirstBlog/Migrations/20221128224120_InitialCreate.Designer.cs
+++ b/MyFirstBlog/Migrations/20221128224120_InitialCreate.Designer.cs
@@ -5,6 +5,7 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MyFirstBlog.Helpers;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using MyFirstBlog.Entities;
#nullable disable
diff --git a/MyFirstBlog/Migrations/DataContextModelSnapshot.cs b/MyFirstBlog/Migrations/DataContextModelSnapshot.cs
index 2965cd9a..8af92031 100644
--- a/MyFirstBlog/Migrations/DataContextModelSnapshot.cs
+++ b/MyFirstBlog/Migrations/DataContextModelSnapshot.cs
@@ -4,6 +4,7 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MyFirstBlog.Helpers;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using MyFirstBlog.Entities;
#nullable disable
diff --git a/MyFirstBlog/Program.cs b/MyFirstBlog/Program.cs
index 4042b610..f129982e 100644
--- a/MyFirstBlog/Program.cs
+++ b/MyFirstBlog/Program.cs
@@ -1,6 +1,9 @@
using MyFirstBlog.Helpers;
+using MyFirstBlog.Entities;
+
using MyFirstBlog.Services;
+
var MyAllowLocalhostOrigins = "_myAllowLocalhostOrigins";
var builder = WebApplication.CreateBuilder(args);
diff --git a/MyFirstBlog/Services/PostService.cs b/MyFirstBlog/Services/PostService.cs
index 6bac099f..3a54658e 100644
--- a/MyFirstBlog/Services/PostService.cs
+++ b/MyFirstBlog/Services/PostService.cs
@@ -9,6 +9,8 @@ public interface IPostService
{
IEnumerable GetPosts();
PostDto GetPost(String slug);
+
+ PostDto CreatePost(string title, string body);
}
public class PostService : IPostService
@@ -34,4 +36,29 @@ private Post getPost(string slug)
{
return _context.Posts.Where(a=>a.Slug==slug.ToString()).SingleOrDefault();
}
+
+ public PostDto CreatePost(string title, string body)
+ {
+ if (string.IsNullOrWhiteSpace(title))
+ {
+ throw new ArgumentException("Title cannot be blank");
+ }
+
+ var slug = Regex.Replace(title.ToLower(), @"\s+", "-");
+
+ var post = new Post
+ {
+ Id = Guid.NewGuid(),
+ Title = title,
+ Slug = slug,
+ Body = body,
+ CreatedDate = DateTime.UtcNow
+ };
+
+ _context.Posts.Add(post);
+ _context.SaveChanges();
+
+ return post.AsDto();
+ }
+
}
diff --git a/MyFirstBlogTests/MyFirstBlogTests.csproj b/MyFirstBlogTests/MyFirstBlogTests.csproj
index 79ed3371..6f48b629 100644
--- a/MyFirstBlogTests/MyFirstBlogTests.csproj
+++ b/MyFirstBlogTests/MyFirstBlogTests.csproj
@@ -1,16 +1,21 @@
-
+
- net5.0
+ net7.0
false
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/MyFirstBlogTests/UnitTest1.cs b/MyFirstBlogTests/UnitTest1.cs
index 921a6668..4a0a949a 100644
--- a/MyFirstBlogTests/UnitTest1.cs
+++ b/MyFirstBlogTests/UnitTest1.cs
@@ -1,18 +1,180 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using MyFirstBlog.Entities;
+using MyFirstBlog.Helpers;
+using MyFirstBlog.Services;
using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
-namespace MyFirstBlogTests
+public class PostServiceTests
{
- public class Tests
+ private DataContext _context;
+ private PostService _service;
+
+ [SetUp]
+ public void Setup()
{
- [SetUp]
- public void Setup()
- {
- }
-
- [Test]
- public void Test1()
- {
- Assert.Pass();
- }
+ var options = new DbContextOptionsBuilder()
+ .UseInMemoryDatabase(Guid.NewGuid().ToString())
+ .Options;
+
+ var config = new ConfigurationBuilder()
+ .AddInMemoryCollection(new Dictionary())
+ .Build();
+
+ _context = new DataContext(config, options);
+ _context.Database.EnsureCreated();
+
+ _service = new PostService(_context);
+ }
+
+ [Test]
+ public void CreatePost_Should_Add_Post_To_Database()
+ {
+ // Arrange
+ var title = "My First Post";
+ var body = "This is the body.";
+
+ // Act
+ var result = _service.CreatePost(title, body);
+
+ // Assert
+ Assert.IsNotNull(result);
+ Assert.AreEqual(title, result.Title);
+ Assert.AreEqual("my-first-post", result.Slug);
+ }
+
+ [Test]
+ public void GetPost_Should_Return_Correct_Post_By_Slug()
+ {
+ // Arrange
+ var post = _service.CreatePost("Test Post", "Test Body");
+
+ // Act
+ var result = _service.GetPost(post.Slug);
+
+ // Assert
+ Assert.IsNotNull(result);
+ Assert.AreEqual(post.Title, result.Title);
+ }
+
+ [Test]
+ public void GetPosts_Should_Return_All_Posts()
+ {
+ // Arrange
+ _service.CreatePost("Post 1", "Body 1");
+ _service.CreatePost("Post 2", "Body 2");
+
+ // Act
+ var posts = _service.GetPosts().ToList();
+
+ // Assert
+ Assert.AreEqual(2, posts.Count);
+ }
+
+ [Test]
+ public void CreatePost_Should_Throw_If_Title_Is_Blank()
+ {
+ // Arrange & Act & Assert
+ var ex = Assert.Throws(() =>
+ _service.CreatePost(" ", "Body"));
+
+ Assert.AreEqual("Title cannot be blank", ex.Message);
}
}
+
+
+
+
+
+
+
+
+
+
+
+//using NUnit.Framework;
+//using MyFirstBlog.Services;
+//using MyFirstBlog.Entities;
+//using MyFirstBlog.Helpers;
+//using Microsoft.EntityFrameworkCore;
+//using Microsoft.Extensions.Configuration;
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+
+
+//namespace MyFirstBlogTests;
+
+//public class PostServiceTests
+//{
+// private IPostService _service;
+// private DataContext _context;
+
+// [SetUp]
+// public void Setup()
+// {
+// var options = new DbContextOptionsBuilder()
+// .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
+// .Options;
+
+// var configuration = new ConfigurationBuilder().AddInMemoryCollection().Build();
+// _context = new DataContext(configuration);
+// _context.Database.EnsureCreated();
+
+// _service = new PostService(_context);
+// }
+
+// [Test]
+// public void CreatePost_WithTitleAndBody_ReturnsPost()
+// {
+// var result = _service.CreatePost("Hello World", "Test Body");
+
+// Assert.IsNotNull(result);
+// Assert.AreEqual("Hello World", result.Title);
+// Assert.AreEqual("hello-world", result.Slug);
+// }
+
+// [Test]
+// public void CreatePost_WithEmptyTitle_ThrowsError()
+// {
+// var ex = Assert.Throws(() =>
+// {
+// _service.CreatePost("", "Test Body");
+// });
+
+// Assert.That(ex.Message, Is.EqualTo("Title cannot be blank"));
+// }
+//}
+
+
+
+
+
+
+
+
+
+
+
+
+//using NUnit.Framework;
+
+//namespace MyFirstBlogTests
+//{
+// public class Tests
+// {
+// [SetUp]
+// public void Setup()
+// {
+// }
+
+// [Test]
+// public void Test1()
+// {
+// Assert.Pass();
+// }
+// }
+//}