Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ riderModule.iml
/_ReSharper.Caches/
.fake
.vscode
.vs/
Binary file modified .vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified .vs/MyFirstBlog/v17/.futdcache.v2
Binary file not shown.
Binary file modified .vs/MyFirstBlog/v17/.suo
Binary file not shown.
150 changes: 30 additions & 120 deletions .vs/MyFirstBlog/v17/DocumentLayout.json
Original file line number Diff line number Diff line change
@@ -1,38 +1,10 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\00code\\FullStack\\MyFirstBlogBackEnd\\",
"WorkspaceRootPath": "C:\\Users\\Diana Paola\\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}",
"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}"
"AbsoluteMoniker": "D:0:0:{9B011752-04F1-43B9-91DC-AD6788400F60}|Solution Items{9B011752-04F1-43B9-91DC-AD6788400F60}|C:\\Users\\Diana Paola\\source\\repos\\MyFirstBlogBackEnd\\.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{9B011752-04F1-43B9-91DC-AD6788400F60}|Solution Items{9B011752-04F1-43B9-91DC-AD6788400F60}|solutionrelative:.gitignore||{3B902123-F8A7-4915-9F01-361F908088D0}"
}
],
"DocumentGroupContainers": [
Expand All @@ -41,105 +13,43 @@
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 6,
"DockedWidth": 48,
"SelectedChildIndex": 1,
"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": "Bookmark",
"Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
},
{
"$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"
},
"DocumentIndex": 0,
"Title": ".gitignore",
"DocumentMoniker": "C:\\Users\\Diana Paola\\source\\repos\\MyFirstBlogBackEnd\\.gitignore",
"RelativeDocumentMoniker": ".gitignore",
"ToolTip": "C:\\Users\\Diana Paola\\source\\repos\\MyFirstBlogBackEnd\\.gitignore",
"RelativeToolTip": ".gitignore",
"ViewState": "AQIAAAAAAAAAAAAAAAAAAAcAAAAEAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
"WhenOpened": "2024-08-11T07:34:07.004Z",
"EditorCaption": ""
}
]
},
{
"DockedWidth": 148,
"SelectedChildIndex": -1,
"Children": [
{
"$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": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
},
{
"$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": "Bookmark",
"Name": "ST:2:0:{e8034f19-ab72-4f06-83fd-f6832b41aa63}"
},
{
"$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"
"$type": "Bookmark",
"Name": "ST:0:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}"
}
]
}
Expand Down
Binary file modified .vs/ProjectEvaluation/myfirstblog.metadata.v7.bin
Binary file not shown.
Binary file modified .vs/ProjectEvaluation/myfirstblog.projects.v7.bin
Binary file not shown.
15 changes: 13 additions & 2 deletions MyFirstBlog.sln
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFirstBlog", "MyFirstBlog\MyFirstBlog.csproj", "{BB64A02C-C5D9-4D64-A357-7322C54B1419}"
# Visual Studio Version 17
VisualStudioVersion = 17.9.34723.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyFirstBlog", "MyFirstBlog\MyFirstBlog.csproj", "{BB64A02C-C5D9-4D64-A357-7322C54B1419}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyFirstBlogTests", "MyFirstBlogTests\MyFirstBlogTests.csproj", "{84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyFirstBlogTests", "MyFirstBlogTests\MyFirstBlogTests.csproj", "{84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9B011752-04F1-43B9-91DC-AD6788400F60}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -19,4 +27,7 @@ Global
{84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84D99732-A7E9-4E69-B5C7-7DFAFE9815B7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
104 changes: 81 additions & 23 deletions MyFirstBlog/Controllers/PostsController.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,92 @@
namespace MyFirstBlog.Controllers;
namespace MyFirstBlog.Controllers
{
using Microsoft.AspNetCore.Mvc;
using MyFirstBlog.Dtos;
using MyFirstBlog.Services;
using MyFirstBlog.Entities;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

using Microsoft.AspNetCore.Mvc;
using MyFirstBlog.Dtos;
using MyFirstBlog.Services;
[ApiController]
[Route("posts")]
public class PostsController : ControllerBase
{
private readonly IPostService _postService;

[ApiController]
[Route("posts")]
public PostsController(IPostService postService)
{
_postService = postService;
}

public class PostsController : ControllerBase {
private IPostService _postService;
// GET /posts
[HttpGet]
public IEnumerable<PostDto> GetPosts()
{
return _postService.GetPosts();
}

public PostsController(IPostService postService) {
_postService = postService;
}
// GET /posts/{slug}
[HttpGet("{slug}")]
public ActionResult<PostDto> GetPost(string slug)
{
var post = _postService.GetPost(slug);

// Get /posts
[HttpGet]
public IEnumerable<PostDto> GetPosts() {
return _postService.GetPosts();
}
if (post is null)
{
return NotFound();
}

return post;
}

// POST /posts
[HttpPost]
public async Task<IActionResult> CreatePost([FromBody] PostDto newPost)
{
// Validate the incoming data
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

// Generate a unique slug based on the title (assuming slug should be unique and URL-friendly)
var slug = GenerateSlug(newPost.Title);

// Get /posts/:slug
[HttpGet("{slug}")]
public ActionResult<PostDto> GetPost(string slug) {
var post = _postService.GetPost(slug);
// Create a new Post entity from the DTO
var post = new Post
{
Id = Guid.NewGuid(), // Generate a new Guid for the post
Title = newPost.Title,
Slug = slug, // Generate a slug for the post
Body = newPost.Body, // Assuming 'Description' in PostDto corresponds to 'Body' in Post entity
CreatedDate = DateTime.UtcNow // Set the current date and time as the creation date
};

if (post is null) {
return NotFound();
// Use the service to save the new post
var createdPost = await _postService.CreatePostAsync(post);

// Return the result with a 201 Created status code
return CreatedAtAction(nameof(GetPost), new { slug = createdPost.Slug }, createdPost);
}

private string GenerateSlug(string title)
{
// Convert to lower case
string slug = title.ToLower();

// Replace spaces with hyphens
slug = slug.Replace(" ", "-");

// Remove invalid characters
slug = Regex.Replace(slug, @"[^a-z0-9\-]", "");

// Trim hyphens from the ends
slug = slug.Trim('-');

return slug;
}

return post;

}
}
35 changes: 8 additions & 27 deletions MyFirstBlog/Helpers/ConnectionHelper.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
namespace MyFirstBlog.Helpers;
using System.Data.SqlClient;

using Npgsql;

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);
}

//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
public static string GetConnectionString(IConfiguration configuration)
{
Host = databaseUri.Host,
Port = databaseUri.Port,
Username = userInfo[0],
Password = userInfo[1],
Database = databaseUri.LocalPath.TrimStart('/'),
SslMode = SslMode.Require,
TrustServerCertificate = true
};
return builder.ToString();
}
}
return configuration.GetConnectionString("DefaultConnection");
}
}
}
Loading