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
Binary file modified .vs/MyFirstBlog/DesignTimeBuild/.dtbcache.v2
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified .vs/MyFirstBlog/v17/.suo
Binary file not shown.
Binary file added .vs/MyFirstBlogBackendd/v17/.wsuo
Binary file not shown.
66 changes: 42 additions & 24 deletions MyFirstBlog/Controllers/PostsController.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,52 @@
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")]
// GET: api/posts
[HttpGet]
public ActionResult<IEnumerable<PostDto>> GetPosts()
{
var posts = _postService.GetPosts();
return Ok(posts);
}

public class PostsController : ControllerBase {
private IPostService _postService;
// GET: api/posts/{slug}
[HttpGet("{slug}")]
public ActionResult<PostDto> 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<PostDto> GetPosts() {
return _postService.GetPosts();
}
// POST: api/posts/new
[HttpPost("new")]
public ActionResult<PostDto> 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<PostDto> 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;
}
}
}
33 changes: 25 additions & 8 deletions MyFirstBlog/Dtos/PostDto.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
17 changes: 10 additions & 7 deletions MyFirstBlog/Entities/Post.cs
Original file line number Diff line number Diff line change
@@ -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
}
}
25 changes: 11 additions & 14 deletions MyFirstBlog/Extensions.cs
Original file line number Diff line number Diff line change
@@ -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
}
}
};
}
51 changes: 26 additions & 25 deletions MyFirstBlog/Helpers/ConnectionHelper.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
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();
}
}
}
35 changes: 18 additions & 17 deletions MyFirstBlog/Helpers/DataContext.cs
Original file line number Diff line number Diff line change
@@ -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<Post> Posts { get; set; }
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseNpgsql(ConnectionHelper.GetConnectionString(Configuration));
}

public DbSet<Post> Posts { get; set; }
}
}
16 changes: 16 additions & 0 deletions MyFirstBlog/Helpers/DatabaseHelperBasecs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace MyFirstBlog.Helpers
{
public static class DatabaseHelperBase
{

public static async Task ManageMigrationsAsync(IServiceProvider svcProvider)
{
//Service: An instance of db context
var dbContextSvc = svcProvider.GetRequiredService<DataContext>();

//Migration: This is the programmatic equivalent to Update-Database


}
}
}
1 change: 1 addition & 0 deletions MyFirstBlog/MyFirstBlog.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
12 changes: 7 additions & 5 deletions MyFirstBlog/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using MyFirstBlog.Helpers;
using MyFirstBlog.Services;
using Microsoft.EntityFrameworkCore;

var MyAllowLocalhostOrigins = "_myAllowLocalhostOrigins";
var MyAllowLocalhostOrigins = "_myAllowLocalhostOrigins";

var builder = WebApplication.CreateBuilder(args);

Expand All @@ -10,10 +11,11 @@

// Add services to the container.

services.AddDbContext<DataContext>();
services.AddDbContext<DataContext>(options =>
options.UseNpgsql(ConnectionHelper.GetConnectionString(builder.Configuration)));

services.AddCors(policyBuilder => {
policyBuilder.AddPolicy( MyAllowLocalhostOrigins,
policyBuilder.AddPolicy(MyAllowLocalhostOrigins,
policy => {
policy.WithOrigins("http://localhost:3000").AllowAnyHeader().AllowAnyMethod();
});
Expand All @@ -24,7 +26,7 @@
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();

services.AddScoped<IPostService, PostService>();
services.AddScoped<PostService>(); // Register PostService directly

var app = builder.Build();

Expand All @@ -49,4 +51,4 @@

app.MapControllers();

app.Run();
app.Run();
Loading