diff --git a/.gitignore b/.gitignore
index 3a868930..bcc8aa16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,28 @@
+# Ignore build output directories
bin/
obj/
-/packages/
-riderModule.iml
-/_ReSharper.Caches/
-.fake
-.vscode
+
+# Ignore NuGet packages
+*.nupkg
+**/packages/*
+
+# Ignore temporary files
+*.tmp
+*.temp
+*.log
+*.suo
+*.cache
+*.csproj.user
+*.userosscache
+*.sln.docstates
+*.vs/
+
+# Ignore Visual Studio/Code workspace and configuration files
+.vscode/
+.idea/
+.vs/
+
+# Ignore configuration files generated by NuGet
+project.lock.json
+project.fragment.lock.json
+project.assets.json
\ 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/Controllers/PostsController.cs b/MyFirstBlog/Controllers/PostsController.cs
index 8fa6bf2c..218e5b44 100644
--- a/MyFirstBlog/Controllers/PostsController.cs
+++ b/MyFirstBlog/Controllers/PostsController.cs
@@ -7,28 +7,45 @@ namespace MyFirstBlog.Controllers;
[ApiController]
[Route("posts")]
-public class PostsController : ControllerBase {
+public class PostsController : ControllerBase
+{
private IPostService _postService;
- public PostsController(IPostService postService) {
+ public PostsController(IPostService postService)
+ {
_postService = postService;
}
- // Get /posts
[HttpGet]
- public IEnumerable GetPosts() {
+ public IEnumerable GetPosts()
+ {
return _postService.GetPosts();
}
- // Get /posts/:slug
[HttpGet("{slug}")]
- public ActionResult GetPost(string slug) {
+ public ActionResult GetPost(string slug)
+ {
var post = _postService.GetPost(slug);
- if (post is null) {
+ if (post is null)
+ {
return NotFound();
}
return post;
}
-}
+
+ [HttpPost]
+ public ActionResult CreatePost(CreatePostDto postDto)
+ {
+ try
+ {
+ var createdPost = _postService.CreatePost(postDto);
+ return CreatedAtAction(nameof(GetPost), new { slug = createdPost.Slug }, createdPost);
+ }
+ catch (ArgumentException ex)
+ {
+ return BadRequest(new { errors = new[] { ex.Message } });
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyFirstBlog/Dtos/CreatePostDto.cs b/MyFirstBlog/Dtos/CreatePostDto.cs
new file mode 100644
index 00000000..0edb3bb9
--- /dev/null
+++ b/MyFirstBlog/Dtos/CreatePostDto.cs
@@ -0,0 +1,8 @@
+namespace MyFirstBlog.Dtos
+{
+ public class CreatePostDto
+ {
+ public string Title { get; set; }
+ public string Description { get; set; }
+ }
+}
diff --git a/MyFirstBlog/Services/PostService.cs b/MyFirstBlog/Services/PostService.cs
index 6bac099f..c98f726f 100644
--- a/MyFirstBlog/Services/PostService.cs
+++ b/MyFirstBlog/Services/PostService.cs
@@ -1,37 +1,69 @@
-namespace MyFirstBlog.Services;
-
+using System;
+using System.Linq;
using MyFirstBlog.Helpers;
using MyFirstBlog.Entities;
-using System.Text.RegularExpressions;
using MyFirstBlog.Dtos;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
-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);
+ PostDto CreatePost(CreatePostDto postDto);
}
- 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 => post.AsDto());
+ }
+
+ public PostDto GetPost(string slug)
+ {
+ return getPost(slug)?.AsDto();
+ }
+
+ public PostDto CreatePost(CreatePostDto postDto)
+ {
+ if (string.IsNullOrWhiteSpace(postDto.Title))
+ {
+ throw new ArgumentException("Title cannot be blank.");
+ }
+
+ var newPost = new Post
+ {
+ Id = Guid.NewGuid(),
+ Title = postDto.Title,
+ Slug = GenerateSlug(postDto.Title),
+ Body = postDto.Description,
+ CreatedDate = DateTime.UtcNow
+ };
+
+ _context.Posts.Add(newPost);
+ _context.SaveChanges();
+
+ return newPost.AsDto();
+ }
+
+ private Post getPost(string slug)
+ {
+ return _context.Posts.SingleOrDefault(a => a.Slug == slug);
+ }
+
+ private string GenerateSlug(string title)
+ {
+ return Regex.Replace(title.ToLower(), @"\s+", "-");
+ }
}
}