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(); +// } +// } +//}