diff --git a/.gitignore b/.gitignore index 3a868930..ee9c4006 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ riderModule.iml /_ReSharper.Caches/ .fake .vscode +.vs \ No newline at end of file diff --git a/.vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2 b/.vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2 index e3a42a61..29ecc6e9 100644 Binary files a/.vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2 and b/.vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2 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/v17/.futdcache.v2 b/.vs/MyFirstBlog/v17/.futdcache.v2 index 128982d8..5b468bc8 100644 Binary files a/.vs/MyFirstBlog/v17/.futdcache.v2 and b/.vs/MyFirstBlog/v17/.futdcache.v2 differ diff --git a/.vs/MyFirstBlog/v17/.suo b/.vs/MyFirstBlog/v17/.suo index 74e1a08b..23020ea2 100644 Binary files a/.vs/MyFirstBlog/v17/.suo and b/.vs/MyFirstBlog/v17/.suo differ diff --git a/.vs/MyFirstBlog/v17/DocumentLayout.json b/.vs/MyFirstBlog/v17/DocumentLayout.json index 653eb6b4..cffeabf7 100644 --- a/.vs/MyFirstBlog/v17/DocumentLayout.json +++ b/.vs/MyFirstBlog/v17/DocumentLayout.json @@ -1,38 +1,66 @@ { "Version": 1, - "WorkspaceRootPath": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\", + "WorkspaceRootPath": "C:\\Users\\levyz\\source\\repos\\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}", + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|c:\\users\\levyz\\source\\repos\\myfirstblogbackend\\myfirstblog\\migrations\\datacontextmodelsnapshot.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\migrations\\datacontextmodelsnapshot.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\myfirstblog\\myfirstblog.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|", + "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\myfirstblog.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|" + }, + { + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\myfirstblog\\migrations\\20240812194537_postgresql_migration_597.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\migrations\\20240812194537_postgresql_migration_597.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\myfirstblog\\migrations\\20221128224120_initialcreate.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\migrations\\20221128224120_initialcreate.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\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}", + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\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:{84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}|MyFirstBlogTests\\MyFirstBlogTests.csproj|C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\myfirstblogtests\\myfirstblogtests.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|", + "RelativeMoniker": "D:0:0:{84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}|MyFirstBlogTests\\MyFirstBlogTests.csproj|solutionrelative:myfirstblogtests\\myfirstblogtests.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|" }, { - "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:\\Users\\levyz\\source\\repos\\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\\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:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\myfirstblog\\helpers\\datacontext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\helpers\\datacontext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "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:\\Users\\levyz\\source\\repos\\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}" + }, + { + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\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\\dtos\\postdto.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\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}" + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\myfirstblog\\helpers\\connectionhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|solutionrelative:myfirstblog\\helpers\\connectionhelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{BB64A02C-C5D9-4D64-A357-7322C54B1419}|MyFirstBlog\\MyFirstBlog.csproj|C:\\Users\\levyz\\source\\repos\\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:\\Users\\levyz\\source\\repos\\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}" } ], "DocumentGroupContainers": [ @@ -44,102 +72,214 @@ "DockedWidth": 200, "SelectedChildIndex": 6, "Children": [ + { + "$type": "Bookmark", + "Name": "ST:0:0:{e78e0cf7-2e4e-48a7-bf7f-a94d9330a3be}" + }, + { + "$type": "Bookmark", + "Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:130:0:{1fc202d4-d401-403c-9834-5b218574bb67}" + }, + { + "$type": "Bookmark", + "Name": "ST:129:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" + }, + { + "$type": "Bookmark", + "Name": "ST:131:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}" + }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "DataContextModelSnapshot.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Migrations\\DataContextModelSnapshot.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Migrations\\DataContextModelSnapshot.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Migrations\\DataContextModelSnapshot.cs", + "RelativeToolTip": "MyFirstBlog\\Migrations\\DataContextModelSnapshot.cs", + "ViewState": "AQIAAAAAAAAAAAAAAAAAAAwAAAAkAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-01T19:41:51.328Z", + "EditorCaption": "" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{1c64b9c2-e352-428e-a56d-0ace190b99a6}" + }, + { + "$type": "Document", + "DocumentIndex": 7, + "Title": "Extensions.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Extensions.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Extensions.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Extensions.cs", + "RelativeToolTip": "MyFirstBlog\\Extensions.cs", + "ViewState": "AQIAAAAAAAAAAAAAAAAAAA8AAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-05-15T14:44:53.417Z" + }, + { + "$type": "Document", + "DocumentIndex": 4, + "Title": "launchSettings.json", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Properties\\launchSettings.json", + "RelativeDocumentMoniker": "MyFirstBlog\\Properties\\launchSettings.json", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Properties\\launchSettings.json", + "RelativeToolTip": "MyFirstBlog\\Properties\\launchSettings.json", + "ViewState": "AQIAABgAAAAAAAAAAAAAAB8AAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|", + "WhenOpened": "2024-05-15T14:50:05.724Z" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "20240812194537_postgresql_migration_597.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Migrations\\20240812194537_postgresql_migration_597.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Migrations\\20240812194537_postgresql_migration_597.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Migrations\\20240812194537_postgresql_migration_597.cs", + "RelativeToolTip": "MyFirstBlog\\Migrations\\20240812194537_postgresql_migration_597.cs", + "ViewState": "AQIAAAAAAAAAAAAAAAAAABYAAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-12T19:47:35.372Z" + }, { "$type": "Document", "DocumentIndex": 1, + "Title": "MyFirstBlog.csproj", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\MyFirstBlog.csproj", + "RelativeDocumentMoniker": "MyFirstBlog\\MyFirstBlog.csproj", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\MyFirstBlog.csproj", + "RelativeToolTip": "MyFirstBlog\\MyFirstBlog.csproj", + "ViewState": "AQIAAAAAAAAAAAAAAAAAAA4AAAA8AAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|", + "WhenOpened": "2024-08-12T19:45:03.875Z" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "20221128224120_InitialCreate.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Migrations\\20221128224120_InitialCreate.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Migrations\\20221128224120_InitialCreate.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Migrations\\20221128224120_InitialCreate.cs", + "RelativeToolTip": "MyFirstBlog\\Migrations\\20221128224120_InitialCreate.cs", + "ViewState": "AQIAABwAAAAAAAAAAAAQwAAAAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-01T19:41:52.773Z" + }, + { + "$type": "Document", + "DocumentIndex": 5, "Title": "Program.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Program.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Program.cs", "RelativeDocumentMoniker": "MyFirstBlog\\Program.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Program.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Program.cs", "RelativeToolTip": "MyFirstBlog\\Program.cs", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAA4AAAAjAAAA", + "ViewState": "AQIAAB4AAAAAAAAAAAAIwDUAAAAKAAAA", "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", + "DocumentIndex": 8, + "Title": "DataContext.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Helpers\\DataContext.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Helpers\\DataContext.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Helpers\\DataContext.cs", + "RelativeToolTip": "MyFirstBlog\\Helpers\\DataContext.cs", + "ViewState": "AQIAAAMAAAAAAAAAAAAQwBcAAAAAAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:43:03.248Z" + "WhenOpened": "2024-08-01T19:42:07.072Z" }, { "$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" + "Title": "MyFirstBlogTests.csproj", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlogTests\\MyFirstBlogTests.csproj", + "RelativeDocumentMoniker": "MyFirstBlogTests\\MyFirstBlogTests.csproj", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlogTests\\MyFirstBlogTests.csproj", + "RelativeToolTip": "MyFirstBlogTests\\MyFirstBlogTests.csproj", + "ViewState": "AQIAAAAAAAAAAAAAAAAAABAAAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|", + "WhenOpened": "2024-08-12T20:32:44.862Z" }, { "$type": "Document", - "DocumentIndex": 3, + "DocumentIndex": 10, "Title": "PostService.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Services\\PostService.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Services\\PostService.cs", "RelativeDocumentMoniker": "MyFirstBlog\\Services\\PostService.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Services\\PostService.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Services\\PostService.cs", "RelativeToolTip": "MyFirstBlog\\Services\\PostService.cs", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAAkAAAAkAAAA", + "ViewState": "AQIAADoAAAAAAAAAAAAowFIAAAAAAAAA", "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", + "DocumentIndex": 11, + "Title": "PostDto.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Dtos\\PostDto.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Dtos\\PostDto.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Dtos\\PostDto.cs", + "RelativeToolTip": "MyFirstBlog\\Dtos\\PostDto.cs", + "ViewState": "AQIAAAYAAAAAAAAAAAAAwBkAAAABAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2024-05-15T14:44:53.417Z" + "WhenOpened": "2024-05-15T14:42:47.081Z" }, { "$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": "" + "DocumentIndex": 13, + "Title": "Post.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Entities\\Post.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Entities\\Post.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Entities\\Post.cs", + "RelativeToolTip": "MyFirstBlog\\Entities\\Post.cs", + "ViewState": "AQIAAAAAAAAAAAAAAAAAAAsAAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-05-15T14:43:03.248Z" }, { "$type": "Document", - "DocumentIndex": 7, + "DocumentIndex": 9, "Title": "PostsController.cs", - "DocumentMoniker": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Controllers\\PostsController.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Controllers\\PostsController.cs", "RelativeDocumentMoniker": "MyFirstBlog\\Controllers\\PostsController.cs", - "ToolTip": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\MyFirstBlog\\Controllers\\PostsController.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Controllers\\PostsController.cs", "RelativeToolTip": "MyFirstBlog\\Controllers\\PostsController.cs", - "ViewState": "AQIAAAYAAAAAAAAAAAAAAAsAAAAAAAAA", + "ViewState": "AQIAABMAAAAAAAAAAAAQwCEAAAAJAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2024-05-15T14:42:54.111Z" + }, + { + "$type": "Document", + "DocumentIndex": 12, + "Title": "ConnectionHelper.cs", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Helpers\\ConnectionHelper.cs", + "RelativeDocumentMoniker": "MyFirstBlog\\Helpers\\ConnectionHelper.cs", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\Helpers\\ConnectionHelper.cs", + "RelativeToolTip": "MyFirstBlog\\Helpers\\ConnectionHelper.cs", + "ViewState": "AQIAAAAAAAAAAAAAAAAAABcAAAAnAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-08T18:55:00.103Z" + }, + { + "$type": "Document", + "DocumentIndex": 14, + "Title": "appsettings.json", + "DocumentMoniker": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\appsettings.json", + "RelativeDocumentMoniker": "MyFirstBlog\\appsettings.json", + "ToolTip": "C:\\Users\\levyz\\source\\repos\\MyFirstBlogBackEnd\\MyFirstBlog\\appsettings.json", + "RelativeToolTip": "MyFirstBlog\\appsettings.json", + "ViewState": "AQIAAAAAAAAAAAAAAAAAAAYAAAAEAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|", + "WhenOpened": "2024-08-08T20:01:13.742Z" } ] } diff --git a/.vs/ProjectEvaluation/myfirstblog.metadata.v7.bin b/.vs/ProjectEvaluation/myfirstblog.metadata.v7.bin index a3a97897..7a04eae8 100644 Binary files a/.vs/ProjectEvaluation/myfirstblog.metadata.v7.bin and b/.vs/ProjectEvaluation/myfirstblog.metadata.v7.bin differ diff --git a/.vs/ProjectEvaluation/myfirstblog.projects.v7.bin b/.vs/ProjectEvaluation/myfirstblog.projects.v7.bin index cfc3e6a4..0b5e5f44 100644 Binary files a/.vs/ProjectEvaluation/myfirstblog.projects.v7.bin and b/.vs/ProjectEvaluation/myfirstblog.projects.v7.bin differ diff --git a/MyFirstBlog/.config/dotnet-tools.json b/MyFirstBlog/.config/dotnet-tools.json new file mode 100644 index 00000000..608e342b --- /dev/null +++ b/MyFirstBlog/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "8.0.7", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/MyFirstBlog/Controllers/PostsController.cs b/MyFirstBlog/Controllers/PostsController.cs index 8fa6bf2c..2c168fcc 100644 --- a/MyFirstBlog/Controllers/PostsController.cs +++ b/MyFirstBlog/Controllers/PostsController.cs @@ -1,34 +1,49 @@ -namespace MyFirstBlog.Controllers; - using Microsoft.AspNetCore.Mvc; -using MyFirstBlog.Dtos; using MyFirstBlog.Services; +using MyFirstBlog.Dtos; +using System.Collections.Generic; + +namespace MyFirstBlog.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class PostsController : ControllerBase + { + private readonly PostService _postService; + + public PostsController(PostService postService) + { + _postService = postService; + } -[ApiController] -[Route("posts")] + [HttpGet] + public ActionResult> GetPosts() + { + var posts = _postService.GetPosts(); + return Ok(posts); + } -public class PostsController : ControllerBase { - private IPostService _postService; + [HttpGet("{slug}")] + public ActionResult GetPost(string slug) + { + var post = _postService.GetPost(slug); + if (post == null) + return NotFound(); - public PostsController(IPostService postService) { - _postService = postService; - } + return Ok(post); + } - // Get /posts - [HttpGet] - public IEnumerable GetPosts() { - return _postService.GetPosts(); - } + [HttpPost("new")] + public ActionResult AddPost([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); - if (post is null) { - return NotFound(); + return CreatedAtAction(nameof(GetPost), new { slug = post.Slug }, post); } - - return post; } } diff --git a/MyFirstBlog/Dtos/PostDto.cs b/MyFirstBlog/Dtos/PostDto.cs index 12ca4818..535404d5 100644 --- a/MyFirstBlog/Dtos/PostDto.cs +++ b/MyFirstBlog/Dtos/PostDto.cs @@ -1,9 +1,26 @@ -namespace MyFirstBlog.Dtos; - -public record PostDto { - public Guid Id { get; init; } - public string Title { get; init; } = default!; - public string Slug { get; init; } = default!; - public string Body { get; init; } = default!; - public DateTime CreatedDate { get; init; } +using System; +using System.ComponentModel.DataAnnotations; + +namespace MyFirstBlog.Dtos +{ + public class PostDto + { + public Guid Id { get; set; } + public string Title { get; set; } + public string Slug { get; set; } + public string Body { get; set; } + + [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")] + public DateTime CreatedDate { get; set; } + } + + public class CreatePostDto + { + public string Title { get; set; } + public string Slug { get; set; } + public string Body { get; set; } + + [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")] + public DateTime CreatedDate { get; set; } + } } diff --git a/MyFirstBlog/Entities/Post.cs b/MyFirstBlog/Entities/Post.cs index 9347e859..17410442 100644 --- a/MyFirstBlog/Entities/Post.cs +++ b/MyFirstBlog/Entities/Post.cs @@ -1,8 +1,11 @@ -namespace MyFirstBlog.Entities; -public record Post { - public Guid Id { get; init; } - public string Title { get; init; } = default!; - public string Slug { get; init; } = default!; - public string Body { get; init; } = default!; - public DateTime CreatedDate { get; init; } +namespace MyFirstBlog.Entities +{ + public class Post + { + public Guid Id { get; set; } + public string Title { get; set; } + public string Slug { get; set; } + public string Body { get; set; } + public DateTime CreatedDate { get; set; } // Updated to CreatedDate + } } diff --git a/MyFirstBlog/Extensions.cs b/MyFirstBlog/Extensions.cs index a5326018..f3865f08 100644 --- a/MyFirstBlog/Extensions.cs +++ b/MyFirstBlog/Extensions.cs @@ -1,18 +1,15 @@ using MyFirstBlog.Dtos; -using MyFirstBlog.Entities; +using System; -namespace MyFirstBlog { - public static class Extensions { - 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 - }; - +namespace MyFirstBlog.Extensions +{ + public static class PostExtensions + { + public static void UpdatePost(this PostDto postDto, string title, string body, DateTime createDate) + { + postDto.Title = title; + postDto.Body = body; + postDto.CreatedDate = createDate; // Correct usage of CreateDate } } -}; +} diff --git a/MyFirstBlog/Helpers/ConnectionHelper.cs b/MyFirstBlog/Helpers/ConnectionHelper.cs index 5e6671a6..f985785f 100644 --- a/MyFirstBlog/Helpers/ConnectionHelper.cs +++ b/MyFirstBlog/Helpers/ConnectionHelper.cs @@ -1,31 +1,32 @@ -namespace MyFirstBlog.Helpers; - using Npgsql; +using Microsoft.Extensions.Configuration; -public static class ConnectionHelper +namespace MyFirstBlog.Helpers { - public static string GetConnectionString(IConfiguration configuration) + public static class ConnectionHelper { - var connectionString = configuration.GetConnectionString("DefaultConnection"); - var databaseUrl = Environment.GetEnvironmentVariable("DATABASE_URL"); - return string.IsNullOrEmpty(databaseUrl) ? connectionString : BuildConnectionString(databaseUrl); - } + public static string GetConnectionString(IConfiguration configuration) + { + var connectionString = configuration.GetConnectionString("DefaultConnection"); + var databaseUrl = Environment.GetEnvironmentVariable("DATABASE_URL"); + return string.IsNullOrEmpty(databaseUrl) ? connectionString : BuildConnectionString(databaseUrl); + } - //build the connection string from the environment. i.e. Heroku or Railway - private static string BuildConnectionString(string databaseUrl) - { - var databaseUri = new Uri(databaseUrl); - var userInfo = databaseUri.UserInfo.Split(':'); - var builder = new NpgsqlConnectionStringBuilder + private static string BuildConnectionString(string databaseUrl) { - Host = databaseUri.Host, - Port = databaseUri.Port, - Username = userInfo[0], - Password = userInfo[1], - Database = databaseUri.LocalPath.TrimStart('/'), - SslMode = SslMode.Require, - TrustServerCertificate = true - }; - return builder.ToString(); - } -} \ No newline at end of file + var databaseUri = new Uri(databaseUrl); + var userInfo = databaseUri.UserInfo.Split(':'); + var builder = new NpgsqlConnectionStringBuilder + { + Host = databaseUri.Host, + Port = databaseUri.Port, + Username = userInfo[0], + Password = userInfo[1], + Database = databaseUri.LocalPath.TrimStart('/'), + SslMode = SslMode.Require, + TrustServerCertificate = true + }; + return builder.ToString(); + } + } +} diff --git a/MyFirstBlog/Helpers/DataContext.cs b/MyFirstBlog/Helpers/DataContext.cs index 60ad2bfc..4ef28ad5 100644 --- a/MyFirstBlog/Helpers/DataContext.cs +++ b/MyFirstBlog/Helpers/DataContext.cs @@ -1,22 +1,23 @@ -namespace MyFirstBlog.Helpers; - -using Microsoft.EntityFrameworkCore; -using MyFirstBlog.Entities; - - -public class DataContext : DbContext +namespace MyFirstBlog.Helpers { - protected readonly IConfiguration Configuration; + using Microsoft.EntityFrameworkCore; + using MyFirstBlog.Entities; + using Microsoft.Extensions.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/Migrations/20240812182313_AddCreatedDateToPosts.Designer.cs b/MyFirstBlog/Migrations/20240812182313_AddCreatedDateToPosts.Designer.cs new file mode 100644 index 00000000..da085d1f --- /dev/null +++ b/MyFirstBlog/Migrations/20240812182313_AddCreatedDateToPosts.Designer.cs @@ -0,0 +1,53 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyFirstBlog.Helpers; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MyFirstBlog.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20240812182313_AddCreatedDateToPosts")] + partial class AddCreatedDateToPosts + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MyFirstBlog.Entities.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Body") + .HasColumnType("text"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Posts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyFirstBlog/Migrations/20240812182313_AddCreatedDateToPosts.cs b/MyFirstBlog/Migrations/20240812182313_AddCreatedDateToPosts.cs new file mode 100644 index 00000000..6a89ed2f --- /dev/null +++ b/MyFirstBlog/Migrations/20240812182313_AddCreatedDateToPosts.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyFirstBlog.Migrations +{ + public partial class AddCreatedDateToPosts : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatedDate", + table: "Posts", + nullable: false, + defaultValue: DateTime.UtcNow); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CreatedDate", + table: "Posts"); + } + } +} diff --git a/MyFirstBlog/Migrations/20240812194537_postgresql_migration_597.Designer.cs b/MyFirstBlog/Migrations/20240812194537_postgresql_migration_597.Designer.cs new file mode 100644 index 00000000..ba7d2260 --- /dev/null +++ b/MyFirstBlog/Migrations/20240812194537_postgresql_migration_597.Designer.cs @@ -0,0 +1,53 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyFirstBlog.Helpers; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MyFirstBlog.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20240812194537_postgresql_migration_597")] + partial class postgresqlmigration597 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MyFirstBlog.Entities.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Body") + .HasColumnType("text"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Posts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyFirstBlog/Migrations/20240812194537_postgresql_migration_597.cs b/MyFirstBlog/Migrations/20240812194537_postgresql_migration_597.cs new file mode 100644 index 00000000..be058249 --- /dev/null +++ b/MyFirstBlog/Migrations/20240812194537_postgresql_migration_597.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyFirstBlog.Migrations +{ + /// + public partial class postgresqlmigration597 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/MyFirstBlog/Migrations/20240812213111_AddCreatedDateToPostsAgain.Designer.cs b/MyFirstBlog/Migrations/20240812213111_AddCreatedDateToPostsAgain.Designer.cs new file mode 100644 index 00000000..65c423c6 --- /dev/null +++ b/MyFirstBlog/Migrations/20240812213111_AddCreatedDateToPostsAgain.Designer.cs @@ -0,0 +1,53 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyFirstBlog.Helpers; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MyFirstBlog.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20240812213111_AddCreatedDateToPostsAgain")] + partial class AddCreatedDateToPostsAgain + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MyFirstBlog.Entities.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Body") + .HasColumnType("text"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Posts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyFirstBlog/Migrations/20240812213111_AddCreatedDateToPostsAgain.cs b/MyFirstBlog/Migrations/20240812213111_AddCreatedDateToPostsAgain.cs new file mode 100644 index 00000000..a9aec9cf --- /dev/null +++ b/MyFirstBlog/Migrations/20240812213111_AddCreatedDateToPostsAgain.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyFirstBlog.Migrations +{ + /// + public partial class AddCreatedDateToPostsAgain : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/MyFirstBlog/Migrations/DataContextModelSnapshot.cs b/MyFirstBlog/Migrations/DataContextModelSnapshot.cs index 2965cd9a..d84ee45e 100644 --- a/MyFirstBlog/Migrations/DataContextModelSnapshot.cs +++ b/MyFirstBlog/Migrations/DataContextModelSnapshot.cs @@ -1,4 +1,5 @@ // +using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -16,12 +17,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "7.0.0") + .HasAnnotation("ProductVersion", "7.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("MyFirstBlog.Models.Post", b => + modelBuilder.Entity("MyFirstBlog.Entities.Post", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -30,7 +31,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Body") .HasColumnType("text"); - b.Property("CreatedDate") + b.Property("CreatedDate") .HasColumnType("timestamp with time zone"); b.Property("Slug") diff --git a/MyFirstBlog/MyFirstBlog.csproj b/MyFirstBlog/MyFirstBlog.csproj index 04ccc9c1..83fe6e01 100644 --- a/MyFirstBlog/MyFirstBlog.csproj +++ b/MyFirstBlog/MyFirstBlog.csproj @@ -4,17 +4,23 @@ net7.0 Linux enable + 085be403-57ee-4045-a699-037cd1dd325b + runtime; build; native; contentfiles; analyzers; buildtransitive all - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/MyFirstBlog/MyFirstBlog.csproj.user b/MyFirstBlog/MyFirstBlog.csproj.user index 3d669754..cb570dab 100644 --- a/MyFirstBlog/MyFirstBlog.csproj.user +++ b/MyFirstBlog/MyFirstBlog.csproj.user @@ -5,5 +5,7 @@ MyFirstBlog + MvcControllerEmptyScaffolder + root/Common/MVC/Controller \ No newline at end of file diff --git a/MyFirstBlog/Program.cs b/MyFirstBlog/Program.cs index 4042b610..a550bff7 100644 --- a/MyFirstBlog/Program.cs +++ b/MyFirstBlog/Program.cs @@ -1,7 +1,8 @@ using MyFirstBlog.Helpers; using MyFirstBlog.Services; +using Microsoft.EntityFrameworkCore; -var MyAllowLocalhostOrigins = "_myAllowLocalhostOrigins"; +var MyAllowLocalhostOrigins = "_myAllowLocalhostOrigins"; var builder = WebApplication.CreateBuilder(args); @@ -10,10 +11,11 @@ // Add services to the container. -services.AddDbContext(); +services.AddDbContext(options => + options.UseNpgsql(ConnectionHelper.GetConnectionString(builder.Configuration))); services.AddCors(policyBuilder => { - policyBuilder.AddPolicy( MyAllowLocalhostOrigins, + policyBuilder.AddPolicy(MyAllowLocalhostOrigins, policy => { policy.WithOrigins("http://localhost:3000").AllowAnyHeader().AllowAnyMethod(); }); @@ -24,7 +26,7 @@ services.AddEndpointsApiExplorer(); services.AddSwaggerGen(); -services.AddScoped(); +services.AddScoped(); // Register PostService directly var app = builder.Build(); @@ -49,4 +51,4 @@ app.MapControllers(); -app.Run(); +app.Run(); \ No newline at end of file diff --git a/MyFirstBlog/Properties/serviceDependencies.json b/MyFirstBlog/Properties/serviceDependencies.json new file mode 100644 index 00000000..201474af --- /dev/null +++ b/MyFirstBlog/Properties/serviceDependencies.json @@ -0,0 +1,12 @@ +{ + "dependencies": { + "secrets1": { + "type": "secrets" + }, + "postgresql1": { + "type": "postgresql", + "connectionId": "PostgreSQLConnection", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/MyFirstBlog/Properties/serviceDependencies.local.json b/MyFirstBlog/Properties/serviceDependencies.local.json new file mode 100644 index 00000000..cd6a5457 --- /dev/null +++ b/MyFirstBlog/Properties/serviceDependencies.local.json @@ -0,0 +1,16 @@ +{ + "dependencies": { + "secrets1": { + "type": "secrets.user" + }, + "postgresql1": { + "containerPorts": "5432:5432", + "secretStore": "LocalSecretsFile", + "containerName": "postgresql", + "containerImage": "postgres", + "type": "postgresql.container", + "connectionId": "PostgreSQLConnection", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/MyFirstBlog/Properties/serviceDependencies.local.json.user b/MyFirstBlog/Properties/serviceDependencies.local.json.user new file mode 100644 index 00000000..32428742 --- /dev/null +++ b/MyFirstBlog/Properties/serviceDependencies.local.json.user @@ -0,0 +1,13 @@ +{ + "dependencies": { + "postgresql1": { + "restored": true, + "restoreTime": "2024-08-12T21:39:33.9525812Z" + }, + "secrets1": { + "restored": true, + "restoreTime": "2024-08-12T21:39:33.6821788Z" + } + }, + "parameters": {} +} \ No newline at end of file diff --git a/MyFirstBlog/Services/PostService.cs b/MyFirstBlog/Services/PostService.cs index 6bac099f..77e1cfe1 100644 --- a/MyFirstBlog/Services/PostService.cs +++ b/MyFirstBlog/Services/PostService.cs @@ -1,37 +1,82 @@ -namespace MyFirstBlog.Services; - -using MyFirstBlog.Helpers; +using System; +using System.Collections.Generic; +using System.Linq; +using Dapper; +using Npgsql; using MyFirstBlog.Entities; -using System.Text.RegularExpressions; using MyFirstBlog.Dtos; +using Microsoft.Extensions.Configuration; +using MyFirstBlog.Helpers; -public interface IPostService +namespace MyFirstBlog.Services { - IEnumerable GetPosts(); - PostDto GetPost(String slug); -} + public class PostService + { + private readonly string _connectionString; -public class PostService : IPostService -{ - private DataContext _context; + public PostService(IConfiguration configuration) + { + _connectionString = ConnectionHelper.GetConnectionString(configuration); + } - public PostService(DataContext context) - { - _context = context; - } + public IEnumerable GetPosts() + { + using var connection = new NpgsqlConnection(_connectionString); + var posts = connection.Query("SELECT * FROM Posts"); + return posts.Select(post => new PostDto + { + Id = post.Id, + Title = post.Title, + Slug = post.Slug, + Body = post.Body, + CreatedDate = post.CreatedDate + }).ToList(); + } - public IEnumerable GetPosts() - { - return _context.Posts.Select(post => post.AsDto()); - } + public PostDto GetPost(string slug) + { + using var connection = new NpgsqlConnection(_connectionString); + var post = connection.QuerySingleOrDefault("SELECT * FROM Posts WHERE Slug = @Slug", new { Slug = slug }); + if (post == null) + return null; - public PostDto GetPost(string slug) - { - return getPost(slug).AsDto(); - } + return new PostDto + { + Id = post.Id, + Title = post.Title, + Slug = post.Slug, + Body = post.Body, + CreatedDate = post.CreatedDate + }; + } - private Post getPost(string slug) - { - return _context.Posts.Where(a=>a.Slug==slug.ToString()).SingleOrDefault(); + public PostDto CreatePost(CreatePostDto createPostDto) + { + var newPost = new Post + { + Id = Guid.NewGuid(), + Title = createPostDto.Title, + Slug = string.IsNullOrEmpty(createPostDto.Slug) ? GenerateSlug(createPostDto.Title) : createPostDto.Slug, + Body = createPostDto.Body, + CreatedDate = createPostDto.CreatedDate == default ? DateTime.UtcNow : createPostDto.CreatedDate + }; + + using var connection = new NpgsqlConnection(_connectionString); + connection.Execute("INSERT INTO Posts (Id, Title, Slug, Body, CreatedDate) VALUES (@Id, @Title, @Slug, @Body, @CreatedDate)", newPost); + + return new PostDto + { + Id = newPost.Id, + Title = newPost.Title, + Slug = newPost.Slug, + Body = newPost.Body, + CreatedDate = newPost.CreatedDate + }; + } + + private string GenerateSlug(string title) + { + return title.ToLower().Replace(" ", "-"); + } } } diff --git a/MyFirstBlog/appsettings.json b/MyFirstBlog/appsettings.json index 10f68b8c..b3e74c65 100644 --- a/MyFirstBlog/appsettings.json +++ b/MyFirstBlog/appsettings.json @@ -5,5 +5,8 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "DefaultConnection": "Host=localhost;Database=bvc-blog;Username=postgres;Password=postgres" + } } diff --git a/MyFirstBlogBackEnd b/MyFirstBlogBackEnd new file mode 160000 index 00000000..89053233 --- /dev/null +++ b/MyFirstBlogBackEnd @@ -0,0 +1 @@ +Subproject commit 890532330f3bf78d204309e3fd7feada4883bc5a