diff --git a/BlogWebApp/BlogMinimalApi/ApiEndpoints/AccountsApiEndpoints.cs b/BlogWebApp/BlogMinimalApi/ApiEndpoints/AccountsApiEndpoints.cs index 63f278f8..f7bc7c76 100644 --- a/BlogWebApp/BlogMinimalApi/ApiEndpoints/AccountsApiEndpoints.cs +++ b/BlogWebApp/BlogMinimalApi/ApiEndpoints/AccountsApiEndpoints.cs @@ -51,8 +51,13 @@ public void InstallApiRoutes(WebApplication app) return Results.Ok(response); }) + .WithName("Initialize") .Produces>() - .Produces(400); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Initialize") + .WithDescription("Initialize") + .HasApiVersion(1.0); // Get All Users @@ -65,7 +70,13 @@ public void InstallApiRoutes(WebApplication app) return Results.Ok(response); }) - .Produces>(); + .WithName("GetAllUsers") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All Users") + .WithDescription("Get All Users") + .HasApiVersion(1.0); // Login @@ -151,7 +162,11 @@ public void InstallApiRoutes(WebApplication app) return Results.NoContent(); }) - .Produces(204); + .WithName("SendConfirmationEmail") + .Produces(StatusCodes.Status204NoContent) + .WithSummary("Send Confirmation Email") + .WithDescription("Send Confirmation Email") + .HasApiVersion(1.0); // Users activity privateGroup.MapGet(ApiRoutes.AccountsController.UsersActivity, @@ -163,8 +178,13 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(activity); }) - .Produces() - .Produces(404); + .WithName("UsersActivity") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Users Activity") + .WithDescription("Users Activity") + .HasApiVersion(1.0); // Change password privateGroup.MapPut(ApiRoutes.AccountsController.ChangePassword, diff --git a/BlogWebApp/BlogMinimalApi/ApiEndpoints/CommentsApiEndpoints.cs b/BlogWebApp/BlogMinimalApi/ApiEndpoints/CommentsApiEndpoints.cs index f7f69e78..442a323a 100644 --- a/BlogWebApp/BlogMinimalApi/ApiEndpoints/CommentsApiEndpoints.cs +++ b/BlogWebApp/BlogMinimalApi/ApiEndpoints/CommentsApiEndpoints.cs @@ -44,7 +44,13 @@ public void InstallApiRoutes(WebApplication app) return Results.Ok(response); }) - .Produces>(); + .WithName("GetAll") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All") + .WithDescription("Get All") + .HasApiVersion(1.0); // Comments Activity @@ -57,8 +63,13 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(activity); }) - .Produces() - .Produces(404); + .WithName("CommentsActivity") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Comments Activity") + .WithDescription("Comments Activity") + .HasApiVersion(1.0); // Get Paged Comments @@ -78,8 +89,13 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(mapper.Map(result)); }) + //.RequireAuthorization() + .WithName("GetCommentsByFilter") .Produces() - .Produces(404); + .Produces(400) + .WithSummary("Get Comments By Filter") + .WithDescription("Get CommentsBy Filter") + .HasApiVersion(1.0); // Get Comments By Post @@ -101,8 +117,13 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(mapper.Map(result)); }) + //.RequireAuthorization() + .WithName("Get Comments By Post") .Produces() - .Produces(404); + .Produces(400) + .WithSummary("Get Comments By Post") + .WithDescription("Get Comments By Post") + .HasApiVersion(1.0); // Get Comment By ID @@ -117,9 +138,13 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(mapper.Map(comment)); }) - .WithName(ApiRoutes.CommentsController.GetComment) + .WithName("GetCommentById") .Produces() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Comment By Id") + .WithDescription("Get Comment By Id") + .HasApiVersion(1.0); // ------------------------- // PRIVATE (Authorized) diff --git a/BlogWebApp/BlogMinimalApi/ApiEndpoints/MessagesApiEndpoints.cs b/BlogWebApp/BlogMinimalApi/ApiEndpoints/MessagesApiEndpoints.cs index 1760b36e..5d88cbda 100644 --- a/BlogWebApp/BlogMinimalApi/ApiEndpoints/MessagesApiEndpoints.cs +++ b/BlogWebApp/BlogMinimalApi/ApiEndpoints/MessagesApiEndpoints.cs @@ -46,8 +46,13 @@ public void InstallApiRoutes(WebApplication app) return Results.Ok(response); }) + .WithName("GetAll") .Produces>() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All") + .WithDescription("Get All") + .HasApiVersion(1.0); // GET BY RECIPIENT @@ -65,8 +70,13 @@ public void InstallApiRoutes(WebApplication app) return Results.Ok(mapper.Map>(messages)); }) + .WithName("GetRecipientMessages") .Produces>() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Recipient Messages") + .WithDescription("Get Recipient Messages") + .HasApiVersion(1.0); // GET BY SENDER @@ -84,8 +94,13 @@ public void InstallApiRoutes(WebApplication app) return Results.Ok(mapper.Map>(messages)); }) + .WithName("GetSenderMessages") .Produces>() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Sender Messages") + .WithDescription("Get Sender Messages") + .HasApiVersion(1.0); // GET BY ID @@ -100,8 +115,13 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(mapper.Map(message)); }) + .WithName("GetById") .Produces() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get By Id") + .WithDescription("Get By Id") + .HasApiVersion(1.0); // ------------------------- diff --git a/BlogWebApp/BlogMinimalApi/ApiEndpoints/PostsApiEndpoints.cs b/BlogWebApp/BlogMinimalApi/ApiEndpoints/PostsApiEndpoints.cs index b89bb887..6ddf73e0 100644 --- a/BlogWebApp/BlogMinimalApi/ApiEndpoints/PostsApiEndpoints.cs +++ b/BlogWebApp/BlogMinimalApi/ApiEndpoints/PostsApiEndpoints.cs @@ -49,8 +49,13 @@ public void InstallApiRoutes(WebApplication app) return Results.Ok( mapper.Map>(posts)); }) + .WithName("GetAllPosts") .Produces>() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All Posts") + .WithDescription("Get All Posts") + .HasApiVersion(1.0); // POSTS ACTIVITY @@ -63,8 +68,13 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(activity); }) - .Produces() - .Produces(404); + .WithName("PostsActivity") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Posts Activity") + .WithDescription("Posts Activity") + .HasApiVersion(1.0); // FILTERED POSTS @@ -86,8 +96,12 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(mapper.Map(posts)); }) + .WithName("GetPosts") .Produces() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .WithSummary("Get Posts") + .WithDescription("Get Posts") + .HasApiVersion(1.0); // USER POSTS @@ -111,8 +125,12 @@ public void InstallApiRoutes(WebApplication app) ? Results.NotFound() : Results.Ok(mapper.Map(posts)); }) + .WithName("UserPosts") .Produces() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .WithSummary("User Posts") + .WithDescription("User Posts") + .HasApiVersion(1.0); // GET POST BY ID @@ -134,8 +152,13 @@ public void InstallApiRoutes(WebApplication app) : Results.Ok( mapper.Map(post)); }) + .WithName("GetPostById") .Produces() - .Produces(404); + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Post By Id") + .WithDescription("Get Post By Id") + .HasApiVersion(1.0); // ------------------------- diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/CQRSExtensions/CarterExtensions.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/CQRSExtensions/CarterExtensions.cs new file mode 100644 index 00000000..d1311f5f --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/CQRSExtensions/CarterExtensions.cs @@ -0,0 +1,19 @@ +using Asp.Versioning.Builder; +using Carter; + +namespace BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +public static class CarterExtensions +{ + public static IEndpointRouteBuilder MapVersionedCarter( + this IEndpointRouteBuilder app, + ApiVersionSet versionSet) + { + var group = app.MapGroup("/api/v{version:apiVersion}") + .WithApiVersionSet(versionSet); + + group.MapCarter(); // 👈 ключ + + return app; + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/GetAllUsers/GetAllUsersEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/GetAllUsers/GetAllUsersEndpoint.cs new file mode 100644 index 00000000..50f847c7 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/GetAllUsers/GetAllUsersEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.UsersResponses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Accounts.GetAllUsers; + +public class GetAllUsersEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Accounts") + .MapToApiVersion(1.0) + .WithTags("Accounts"); + + group.MapGet(ApiRoutes.AccountsController.GetAllUsers, async ([FromServices] ISender sender) => + { + var result = await sender.Send(new GetAllUsersQuery()); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetAllUsers") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All Users") + .WithDescription("Get All Users"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Initialize/InitializeEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Initialize/InitializeEndpoint.cs new file mode 100644 index 00000000..c54562a0 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Initialize/InitializeEndpoint.cs @@ -0,0 +1,36 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.UsersResponses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Accounts.Initialize; +/* +public class GetAllEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Accounts") + .MapToApiVersion(1.0) + .WithTags("Accounts"); + + group.MapGet(ApiRoutes.AccountsController.Initialize, async ([FromRoute] string userId, [FromServices] ISender sender) => + { + if (string.IsNullOrEmpty(userId)) + return Results.BadRequest("Something went wrong"); + + var result = await sender.Send(new InitializeQuery(UserId: userId)); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("Initialize") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Initialize") + .WithDescription("Initialize"); + } +}*/ \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Login/LoginEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Login/LoginEndpoint.cs index 8ed6406d..c3315912 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Login/LoginEndpoint.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Login/LoginEndpoint.cs @@ -3,6 +3,7 @@ using Carter; using Mapster; using MediatR; +using Microsoft.AspNetCore.Mvc; namespace BlogVerticalSliceCQRSMinimalApi.Features.Accounts.Login; @@ -10,18 +11,12 @@ public class LoginEndpoint : ICarterModule { public void AddRoutes(IEndpointRouteBuilder app) { - var versionSet = app.NewApiVersionSet() - .HasApiVersion(new ApiVersion(1, 0)) - .ReportApiVersions() - .Build(); - - var group = app.MapGroup(ApiRoutes.AccountsController.Accounts) - .WithApiVersionSet(versionSet) + var group = app.MapGroup("Accounts") .MapToApiVersion(1.0) .WithTags("Accounts"); group.MapPost(ApiRoutes.AccountsController.Login, - async (LoginRequest request, ISender sender) => + async ([FromBody] LoginRequest request, [FromServices] ISender sender) => { if (request is null) return Results.BadRequest(); @@ -39,7 +34,6 @@ public void AddRoutes(IEndpointRouteBuilder app) .Produces(200) .Produces(400) .WithSummary("Login") - .WithDescription("Login") - .HasApiVersion(1.0); + .WithDescription("Login"); } } \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Register/RegisterEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Register/RegisterEndpoint.cs index 8c16a3bd..81f96233 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Register/RegisterEndpoint.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/Register/RegisterEndpoint.cs @@ -4,6 +4,7 @@ using Mapster; using MediatR; using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; namespace BlogVerticalSliceCQRSMinimalApi.Features.Accounts.Register; @@ -11,18 +12,12 @@ public class RegisterEndpoint : ICarterModule { public void AddRoutes(IEndpointRouteBuilder app) { - var versionSet = app.NewApiVersionSet() - .HasApiVersion(new ApiVersion(1, 0)) - .ReportApiVersions() - .Build(); - - var group = app.MapGroup(ApiRoutes.AccountsController.Accounts) - .WithApiVersionSet(versionSet) + var group = app.MapGroup("Accounts") .MapToApiVersion(1.0) .WithTags("Accounts"); group.MapPost(ApiRoutes.AccountsController.Register, - async (RegisterRequest request, ISender sender) => + async ([FromBody] RegisterRequest request, [FromServices] ISender sender) => { var command = request.Adapt(); @@ -47,7 +42,6 @@ public void AddRoutes(IEndpointRouteBuilder app) .Produces(204) .Produces(400) .WithSummary("Register") - .WithDescription("Register") - .HasApiVersion(1.0); + .WithDescription("Register"); } } \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/SendConfirmationEmail/SendConfirmationEmailEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/SendConfirmationEmail/SendConfirmationEmailEndpoint.cs new file mode 100644 index 00000000..48e18281 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/SendConfirmationEmail/SendConfirmationEmailEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Accounts.SendConfirmationEmail; + +public class SendConfirmationEmailEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Accounts") + .MapToApiVersion(1.0) + .WithTags("Accounts"); + + group.MapGet(ApiRoutes.AccountsController.SendConfirmationEmail, async ([FromServices] HttpContext context, ISender sender) => + { + var email = context.User.Identity?.Name; + + if (string.IsNullOrEmpty(email)) + return Results.BadRequest(); + + var result = await sender.Send(new SendConfirmationEmailQuery(Email: email)); + + return Results.NoContent(); + }) + .WithName("SendConfirmationEmail") + .Produces(StatusCodes.Status204NoContent) + .WithSummary("Send Confirmation Email") + .WithDescription("Send Confirmation Email"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/UsersActivity/UsersActivityEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/UsersActivity/UsersActivityEndpoint.cs new file mode 100644 index 00000000..cb736233 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Accounts/UsersActivity/UsersActivityEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.Chart; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Accounts.UsersActivity; + +public class UsersActivityEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Accounts") + .MapToApiVersion(1.0) + .WithTags("Accounts"); + + group.MapGet(ApiRoutes.AccountsController.UsersActivity, async ([FromServices] ISender sender) => + { + var result = await sender.Send(new UsersActivityQuery()); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("UsersActivity") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Users Activity") + .WithDescription("Users Activity"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/CommentsActivity/CommentsActivityEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/CommentsActivity/CommentsActivityEndpoint.cs new file mode 100644 index 00000000..76a482ee --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/CommentsActivity/CommentsActivityEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.Chart; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.CommentsActivity; + +public class CommentsActivityEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Comments") + .MapToApiVersion(1.0) + .WithTags("Comments"); + + group.MapGet("/comments-activity/{userId}", async ([FromRoute] string userId, [FromServices] ISender sender) => + { + var result = await sender.Send(new CommentsActivityQuery()); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("CommentsActivity") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Comments Activity") + .WithDescription("Comments Activity"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/CreateComment/CreateCommentEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/CreateComment/CreateCommentEndpoint.cs index d064d9f6..d6126476 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/CreateComment/CreateCommentEndpoint.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/CreateComment/CreateCommentEndpoint.cs @@ -4,6 +4,7 @@ using Carter; using Mapster; using MediatR; +using Microsoft.AspNetCore.Mvc; namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.CreateComment; @@ -11,20 +12,14 @@ public class CreateCommentEndpoint : ICarterModule { public void AddRoutes(IEndpointRouteBuilder app) { - var versionSet = app.NewApiVersionSet() - .HasApiVersion(new ApiVersion(1, 0)) - .ReportApiVersions() - .Build(); - - var group = app.MapGroup(ApiRoutes.CommentsController.Comments) - .WithApiVersionSet(versionSet) + var group = app.MapGroup("Comments") .MapToApiVersion(1.0) .WithTags("Comments"); group.MapPost(ApiRoutes.CommentsController.CreateComment, - async (CreateCommentRequest request, - ISender sender, - HttpContext context) => + async ([FromBody] CreateCommentRequest request, + [FromServices] ISender sender, + [FromServices] HttpContext context) => { var command = request.Adapt(); @@ -44,7 +39,6 @@ public void AddRoutes(IEndpointRouteBuilder app) .Produces>(201) .Produces(400) .WithSummary("Create comment") - .WithDescription("Create comment") - .HasApiVersion(1.0); + .WithDescription("Create comment"); } } diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetAll/GetAllEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetAll/GetAllEndpoint.cs new file mode 100644 index 00000000..d8372cd1 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetAll/GetAllEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.CommentsResponses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetAll; + +/*public class GetAllEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("/сomments") + .MapToApiVersion(1.0) + .WithTags("Comments"); + + group.MapGet("", async ([FromRoute] string userId, [FromServices] ISender sender) => + { + var result = await sender.Send(new GetAllQuery()); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetAll") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All") + .WithDescription("Get All"); + } +}*/ \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetAll/GetAllQueryHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetAll/GetAllQueryHandler.cs index 1779e86f..d7277bb4 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetAll/GetAllQueryHandler.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetAll/GetAllQueryHandler.cs @@ -1,7 +1,7 @@ -using Blog.Contracts.V1.Responses.CommentsResponses; +using AutoMapper; +using Blog.Contracts.V1.Responses.CommentsResponses; using Blog.EntityServices.Interfaces; using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; -using MapsterMapper; namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetAll; diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentById/GetCommentByIdEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentById/GetCommentByIdEndpoint.cs new file mode 100644 index 00000000..f7b47ffe --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentById/GetCommentByIdEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.CommentsResponses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentById; + +public class GetCommentByIdEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Comments") + .MapToApiVersion(1.0) + .WithTags("Comments"); + + group.MapGet("{id:int}", async ([FromRoute] int id, [FromServices] ISender sender) => + { + var result = await sender.Send(new GetCommentByIdQuery(Id: id)); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetCommentById") + .Produces() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Comment By Id") + .WithDescription("Get Comment By Id"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterCommand.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterCommand.cs new file mode 100644 index 00000000..d6c881ec --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterCommand.cs @@ -0,0 +1,7 @@ +using Blog.Contracts.V1.Responses.CommentsResponses; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByFilter; + +public record GetCommentsByFilterCommand(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType) + : ICommand; diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterQueryHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterCommandHandler.cs similarity index 53% rename from BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterQueryHandler.cs rename to BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterCommandHandler.cs index 6bdf48d3..493bab77 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterQueryHandler.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterCommandHandler.cs @@ -6,19 +6,17 @@ namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByFilter; -public class GetCommentsByFilterQueryHandler( - ICommentsService service, - IMapper mapper) - : IQueryHandler +public class GetCommentsByFilterCommandHandler(ICommentsService service, IMapper mapper) + : ICommandHandler { - public async Task Handle(GetCommentsByFilterQuery query, CancellationToken cancellationToken) + public async Task Handle(GetCommentsByFilterCommand command, CancellationToken cancellationToken) { - query = query with { CurrentPage = query.CurrentPage ?? 1 }; - query = query with { PageSize = 10 }; + command = command with { CurrentPage = command.CurrentPage ?? 1 }; + command = command with { PageSize = 10 }; var result = await service.GetPagedComments( - mapper.Map(query)); + mapper.Map(command)); return mapper.Map(result); } -} \ No newline at end of file +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterEndpoint.cs new file mode 100644 index 00000000..ea735630 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterEndpoint.cs @@ -0,0 +1,38 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.CommentsResponses; +using Carter; +using Mapster; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByFilter; + +public class GetCommentsByFilterEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Comments") + .MapToApiVersion(1.0) + .WithTags("Comments"); + + group.MapPost(ApiRoutes.CommentsController.GetCommentsByFilter, + async ([FromServices] GetCommentsByFilterRequest request, + ISender sender) => + { + var command = request.Adapt(); + + var result = await sender.Send(command); + + return result is null + ? Results.NotFound() + : Results.Ok(result); + }) + //.RequireAuthorization() + .WithName("GetCommentsByFilter") + .Produces() + .Produces(400) + .WithSummary("Get Comments By Filter") + .WithDescription("Get CommentsBy Filter"); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterQuery.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterQuery.cs deleted file mode 100644 index 9728be0c..00000000 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterQuery.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Blog.Contracts.V1.Responses.CommentsResponses; -using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; - -namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByFilter; - -public record GetCommentsByFilterQuery(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType) - : SortParametersQuery(OrderBy, SortBy, CurrentPage, PageSize, DisplayType), IQuery; \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterRequest.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterRequest.cs new file mode 100644 index 00000000..5d291f5d --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByFilter/GetCommentsByFilterRequest.cs @@ -0,0 +1,3 @@ +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByFilter; + +public record GetCommentsByFilterRequest(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayTypel); diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostCommand.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostCommand.cs new file mode 100644 index 00000000..0a0a3d7b --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostCommand.cs @@ -0,0 +1,3 @@ +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByPost; + +public record GetCommentsByPostRequest(int PostId, string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType); \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostCommandHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostCommandHandler.cs new file mode 100644 index 00000000..90715857 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostCommandHandler.cs @@ -0,0 +1,22 @@ +using AutoMapper; +using Blog.Contracts.V1.Responses.CommentsResponses; +using Blog.EntityServices.Interfaces; +using Blog.Services.Core.Dtos; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByPost; + +public class GetCommentsByPostCommandHandler(ICommentsService service, IMapper mapper) + : ICommandHandler +{ + public async Task Handle(GetCommentsByPostCommand command, CancellationToken cancellationToken) + { + command = command with { CurrentPage = command.CurrentPage ?? 1 }; + command = command with { PageSize = 10 }; + + var result = await service.GetPagedCommentsByPostId(command.PostId, + mapper.Map(command)); + + return mapper.Map(result); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostEndpoint.cs new file mode 100644 index 00000000..bbf53d0e --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostEndpoint.cs @@ -0,0 +1,39 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.CommentsResponses; +using Carter; +using Mapster; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByPost; + +public class GetCommentsByPostEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Comments") + .MapToApiVersion(1.0) + .WithTags("Comments"); + + group.MapPost(ApiRoutes.CommentsController.GetCommentsByPost, + async ([FromRoute] int id, [FromBody] GetCommentsByPostRequest request, + [FromServices] ISender sender) => + { + var command = request.Adapt(); + command = command with { PostId = id }; + + var result = await sender.Send(command); + + return result is null + ? Results.NotFound() + : Results.Ok(result); + }) + //.RequireAuthorization() + .WithName("Get Comments By Post") + .Produces() + .Produces(400) + .WithSummary("Get Comments By Post") + .WithDescription("Get Comments By Post"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostQuery.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostQuery.cs deleted file mode 100644 index 4a29247d..00000000 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostQuery.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Blog.Contracts.V1.Responses.CommentsResponses; -using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; - -namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByPost; - -public record GetCommentsByPostQuery(int PostId, string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType) - : SortParametersQuery(OrderBy, SortBy, CurrentPage, PageSize, DisplayType), IQuery; \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostQueryHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostQueryHandler.cs deleted file mode 100644 index 3ab0245b..00000000 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostQueryHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using AutoMapper; -using Blog.Contracts.V1.Responses.CommentsResponses; -using Blog.EntityServices.Interfaces; -using Blog.Services.Core.Dtos; -using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; - -namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByPost; - -public class GetCommentsByPostQueryHandler( - ICommentsService service, - IMapper mapper) - : IQueryHandler -{ - public async Task Handle(GetCommentsByPostQuery query, CancellationToken cancellationToken) - { - query = query with { CurrentPage = query.CurrentPage ?? 1 }; - query = query with { PageSize = 10 }; - - var result = await service.GetPagedCommentsByPostId( - query.PostId, - mapper.Map(query)); - - return mapper.Map(result); - } -} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostRequest.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostRequest.cs new file mode 100644 index 00000000..18d00e08 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetCommentsByPost/GetCommentsByPostRequest.cs @@ -0,0 +1,7 @@ +using Blog.Contracts.V1.Responses.CommentsResponses; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetCommentsByPost; + +public record GetCommentsByPostCommand(int PostId, string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType) + : ICommand; \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsCommand.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsCommand.cs new file mode 100644 index 00000000..487c2ec8 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsCommand.cs @@ -0,0 +1,7 @@ +using Blog.Contracts.V1.Responses.CommentsResponses; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetPagedComments; + +public record GetPagedCommentsCommand(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType) + : ICommand; diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsCommandHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsCommandHandler.cs new file mode 100644 index 00000000..fa74ead9 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsCommandHandler.cs @@ -0,0 +1,22 @@ +using AutoMapper; +using Blog.Contracts.V1.Responses.CommentsResponses; +using Blog.EntityServices.Interfaces; +using Blog.Services.Core.Dtos; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetPagedComments; + +public class GetCommentsByFilterCommandHandler(ICommentsService service, IMapper mapper) + : ICommandHandler +{ + public async Task Handle(GetPagedCommentsCommand command, CancellationToken cancellationToken) + { + command = command with { CurrentPage = command.CurrentPage ?? 1 }; + command = command with { PageSize = 10 }; + + var result = await service.GetPagedComments( + mapper.Map(command)); + + return mapper.Map(result); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsEndpoint.cs new file mode 100644 index 00000000..cbc40746 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsEndpoint.cs @@ -0,0 +1,38 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.CommentsResponses; +using Carter; +using Mapster; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetPagedComments; + +public class GetCommentsByFilterEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Comments") + .MapToApiVersion(1.0) + .WithTags("Comments"); + + group.MapPost(ApiRoutes.CommentsController.GetCommentsByFilter, + async ([FromBody] GetCommentsByFilterRequest request, + [FromServices] ISender sender) => + { + var command = request.Adapt(); + + var result = await sender.Send(command); + + return result is null + ? Results.NotFound() + : Results.Ok(result); + }) + //.RequireAuthorization() + .WithName("GetPagedComments") + .Produces() + .Produces(400) + .WithSummary("Get Paged Comments") + .WithDescription("Get Paged Comments"); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsRequest.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsRequest.cs new file mode 100644 index 00000000..5b0f7140 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Comments/GetPagedComments/GetPagedCommentsRequest.cs @@ -0,0 +1,3 @@ +namespace BlogVerticalSliceCQRSMinimalApi.Features.Comments.GetPagedComments; + +public record GetCommentsByFilterRequest(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayTypel); diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/HealthCheck/Initialize/InitializeEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/HealthCheck/Initialize/InitializeEndpoint.cs new file mode 100644 index 00000000..00c1eff6 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/HealthCheck/Initialize/InitializeEndpoint.cs @@ -0,0 +1,55 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.UsersResponses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.HealthCheck.Initialize; + +public class InitializeEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("HealthCheck") + .MapToApiVersion(1.0) + .WithTags("HealthCheck"); + + group.MapGet("", async ([FromServices] ISender sender) => + { + try + { + var result = await sender.Send(new InitializeQuery()); + /* + var response = new HealthCheckResponse + { + Status = report.Status.ToString(), + Checks = report.Entries.Select(x => new HealthCheck + { + Component = x.Key, + Status = x.Value.Status.ToString(), + Description = x.Value.Description, + }), + Duration = report.TotalDuration, + }; + + return report.Status == HealthStatus.Healthy + ? this.Ok(response) + : this.StatusCode((int)HttpStatusCode.ServiceUnavailable, response);*/ + + return Results.Ok(); + } + catch (Exception e) + { + return Results.BadRequest(e.InnerException); + } + }) + //.RequireAuthorization() + .WithName("Initialize") + .Produces() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Initialize") + .WithDescription("Initialize"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/CreateMessage/CreateMessageEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/CreateMessage/CreateMessageEndpoint.cs index 645fee19..58088c53 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/CreateMessage/CreateMessageEndpoint.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/CreateMessage/CreateMessageEndpoint.cs @@ -4,6 +4,7 @@ using Carter; using Mapster; using MediatR; +using Microsoft.AspNetCore.Mvc; namespace BlogVerticalSliceCQRSMinimalApi.Features.Messages.CreateMessage; @@ -11,20 +12,14 @@ public class CreateMessageEndpoint : ICarterModule { public void AddRoutes(IEndpointRouteBuilder app) { - var versionSet = app.NewApiVersionSet() - .HasApiVersion(new ApiVersion(1, 0)) - .ReportApiVersions() - .Build(); + var group = app.MapGroup("Messages") + .MapToApiVersion(1.0) + .WithTags("Messages"); - var group = app.MapGroup(ApiRoutes.MessagesController.Messages) - .WithApiVersionSet(versionSet) - .MapToApiVersion(1.0) - .WithTags("Messages"); - - group.MapPost("/", - async (CreateMessageRequest request, - ISender sender, - HttpContext context) => + group.MapPost("", + async ([FromBody] CreateMessageRequest request, + [FromServices] ISender sender, + [FromServices] HttpContext context) => { var command = request.Adapt(); @@ -44,7 +39,6 @@ public void AddRoutes(IEndpointRouteBuilder app) .Produces>(201) .Produces(400) .WithSummary("Create message") - .WithDescription("Create message") - .HasApiVersion(1.0); + .WithDescription("Create message"); } } diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetAll/GetAllEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetAll/GetAllEndpoint.cs new file mode 100644 index 00000000..895b0336 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetAll/GetAllEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Messages.GetAll; + +public class GetAllEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Messages") + .MapToApiVersion(1.0) + .WithTags("Messages"); + + group.MapGet("", async ([FromServices] ISender sender) => + { + var result = await sender.Send(new GetAllQuery()); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetAll") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All") + .WithDescription("Get All"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetById/GetByIdEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetById/GetByIdEndpoint.cs new file mode 100644 index 00000000..20157364 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetById/GetByIdEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Messages.GetById; + +public class GetByIdEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Messages") + .MapToApiVersion(1.0) + .WithTags("Messages"); + + group.MapGet(ApiRoutes.MessagesController.Show, async ([FromRoute] int id, [FromServices] ISender sender) => + { + var result = await sender.Send(new GetByIdQuery(Id: id)); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetById") + .Produces() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get By Id") + .WithDescription("Get By Id"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetRecipientMessages/GetRecipientMessagesEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetRecipientMessages/GetRecipientMessagesEndpoint.cs new file mode 100644 index 00000000..19f0a621 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetRecipientMessages/GetRecipientMessagesEndpoint.cs @@ -0,0 +1,36 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Messages.GetRecipientMessages; + +public class GetRecipientMessagesEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Messages") + .MapToApiVersion(1.0) + .WithTags("Messages"); + + group.MapGet(ApiRoutes.MessagesController.GetRecipientMessages, async ([FromRoute] string recipientId, [FromServices] ISender sender) => + { + if (string.IsNullOrEmpty(recipientId)) + return Results.BadRequest("Something went wrong"); + + var result = await sender.Send(new GetRecipientMessagesQuery(RecipientId: recipientId)); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetRecipientMessages") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Recipient Messages") + .WithDescription("Get Recipient Messages"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetRecipientMessages/GetRecipientMessagesQueryHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetRecipientMessages/GetRecipientMessagesQueryHandler.cs index 91e82369..4dad8824 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetRecipientMessages/GetRecipientMessagesQueryHandler.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetRecipientMessages/GetRecipientMessagesQueryHandler.cs @@ -1,10 +1,8 @@ using AutoMapper; using Blog.Contracts.V1.Responses; -using Blog.Contracts.V1.Responses.Chart; using Blog.Data.Specifications; using Blog.EntityServices.Interfaces; using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; -using BlogVerticalSliceCQRSMinimalApi.Features.Comments.CommentsActivity; namespace BlogVerticalSliceCQRSMinimalApi.Features.Messages.GetRecipientMessages; diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetSenderMessages/GetSenderMessagesEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetSenderMessages/GetSenderMessagesEndpoint.cs new file mode 100644 index 00000000..ce515cba --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Messages/GetSenderMessages/GetSenderMessagesEndpoint.cs @@ -0,0 +1,36 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Messages.GetSenderMessages; + +public class GetSenderMessagesEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Messages") + .MapToApiVersion(1.0) + .WithTags("Messages"); + + group.MapGet(ApiRoutes.MessagesController.GetSenderMessages, async ([FromRoute] string senderEmail, [FromServices] ISender sender) => + { + if (string.IsNullOrEmpty(senderEmail)) + return Results.BadRequest("Something went wrong"); + + var result = await sender.Send(new GetSenderMessagesQuery(SenderEmail: senderEmail)); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetSenderMessages") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Sender Messages") + .WithDescription("Get Sender Messages"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommand.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommand.cs index c2a446d7..aa1fe419 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommand.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommand.cs @@ -4,6 +4,6 @@ namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.CreatePost; -public record CreatePostCommand(string Title, string Description, string Content, string ImageUrl, +public record GetPostsCommand(string Title, string Description, string Content, string ImageUrl, string AuthorId, DateTime CreatedAt, IList Tags) : ICommand>; diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommandHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommandHandler.cs index 708f0198..fc2552f9 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommandHandler.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostCommandHandler.cs @@ -6,10 +6,10 @@ namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.CreatePost; -public class CreatePostCommandHandler(IPostsService service, IMapper mapper) - : ICommandHandler> +public class GetPostsCommandHandler(IPostsService service, IMapper mapper) + : ICommandHandler> { - public async Task> Handle(CreatePostCommand command, CancellationToken cancellationToken) + public async Task> Handle(GetPostsCommand command, CancellationToken cancellationToken) { var post = new Post { diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostEndpoint.cs index ffabab51..c4efeff2 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostEndpoint.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostEndpoint.cs @@ -4,29 +4,24 @@ using Carter; using Mapster; using MediatR; +using Microsoft.AspNetCore.Mvc; namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.CreatePost; -public class CreatePostEndpoint : ICarterModule +public class GetPostsEndpoint : ICarterModule { public void AddRoutes(IEndpointRouteBuilder app) { - var versionSet = app.NewApiVersionSet() - .HasApiVersion(new ApiVersion(1, 0)) - .ReportApiVersions() - .Build(); - - var group = app.MapGroup(ApiRoutes.PostsController.Posts) - .WithApiVersionSet(versionSet) + var group = app.MapGroup("Posts") .MapToApiVersion(1.0) .WithTags("Posts"); group.MapPost("/", - async (CreatePostRequest request, - ISender sender, - HttpContext context) => + async ([FromBody] GetPostsRequest request, + [FromServices] ISender sender, + [FromServices] HttpContext context) => { - var command = request.Adapt(); + var command = request.Adapt(); var result = await sender.Send(command); @@ -44,7 +39,6 @@ public void AddRoutes(IEndpointRouteBuilder app) .Produces>(201) .Produces(400) .WithSummary("Create post") - .WithDescription("Create post") - .HasApiVersion(1.0); + .WithDescription("Create post"); } } diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostRequest.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostRequest.cs index 11922b88..4f57be8b 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostRequest.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/CreatePost/CreatePostRequest.cs @@ -2,5 +2,5 @@ namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.CreatePost; -public class CreatePostRequest(string Title, string Description, string Content, string ImageUrl, +public class GetPostsRequest(string Title, string Description, string Content, string ImageUrl, string AuthorId, DateTime CreatedAt, IList Tags); \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetAllPosts/GetAllPostsEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetAllPosts/GetAllPostsEndpoint.cs new file mode 100644 index 00000000..a08f380d --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetAllPosts/GetAllPostsEndpoint.cs @@ -0,0 +1,34 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.PostsResponses; +using Blog.Contracts.V1.Responses.UsersResponses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetAllPosts; + +public class GetAllPostsEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Posts") + .MapToApiVersion(1.0) + .WithTags("Posts"); + + group.MapGet("/posts", async ([FromServices] ISender sender) => + { + var result = await sender.Send(new GetAllPostsQuery()); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetAllPosts") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get All Posts") + .WithDescription("Get All Posts"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPostById/GetPostByIdEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPostById/GetPostByIdEndpoint.cs new file mode 100644 index 00000000..996e2d13 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPostById/GetPostByIdEndpoint.cs @@ -0,0 +1,34 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.PostsResponses; +using Blog.Contracts.V1.Responses.UsersResponses; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetPostById; + +public class GetPostByIdEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Posts") + .MapToApiVersion(1.0) + .WithTags("Posts"); + + group.MapGet(ApiRoutes.PostsController.Show, async ([FromRoute] int id, [FromServices] ISender sender) => + { + var result = await sender.Send(new GetPostByIdQuery(Id: id)); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("GetPostById") + .Produces() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Get Post By Id") + .WithDescription("Get Post By Id"); + } +} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsCommand.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsCommand.cs new file mode 100644 index 00000000..405268ab --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsCommand.cs @@ -0,0 +1,7 @@ +using Blog.Contracts.V1.Responses.PostsResponses; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetPosts; + +public record GetPostsCommand(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType, string Tag) + : ICommand; diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsCommandHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsCommandHandler.cs new file mode 100644 index 00000000..7ecad21e --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsCommandHandler.cs @@ -0,0 +1,24 @@ +using AutoMapper; +using Blog.Contracts.V1.Responses.PostsResponses; +using Blog.EntityServices.Interfaces; +using Blog.Services.Core.Dtos.Posts; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetPosts; + +public class GetPostsCommandCommandHandler(IPostsService service, IMapper mapper) + : ICommandHandler +{ + public async Task Handle(GetPostsCommand command, CancellationToken cancellationToken) + { + command = command with { OrderBy = command.OrderBy ?? "asc" }; + command = command with { SortBy = command.SortBy ?? "Title" }; + command = command with { CurrentPage = command.CurrentPage ?? 1 }; + command = command with { PageSize = command.PageSize ?? 10 }; + + var posts = await service.GetPostsAsync( + mapper.Map(command)); + + return mapper.Map(posts); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsEndpoint.cs new file mode 100644 index 00000000..07223064 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsEndpoint.cs @@ -0,0 +1,38 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.PostsResponses; +using Carter; +using Mapster; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetPosts; + +public class UserPostsEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Posts") + .MapToApiVersion(1.0) + .WithTags("Posts"); + + group.MapPost("", + async ([FromBody] GetPostsRequest request, + [FromServices] ISender sender) => + { + var command = request.Adapt(); + + var result = await sender.Send(command); + + return result is null + ? Results.NotFound() + : Results.Ok(result); + }) + //.RequireAuthorization() + .WithName("GetPosts") + .Produces() + .Produces(StatusCodes.Status400BadRequest) + .WithSummary("Get Posts") + .WithDescription("Get Posts"); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsQuery.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsQuery.cs deleted file mode 100644 index 3b7ef6df..00000000 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsQuery.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Blog.Contracts.V1.Responses.PostsResponses; -using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; - -namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetPosts; - -public record GetPostsQuery(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType, string Tag) - : SearchParametersQuery(OrderBy, SortBy, CurrentPage, PageSize, DisplayType), IQuery; \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsQueryHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsQueryHandler.cs deleted file mode 100644 index aba8a06f..00000000 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsQueryHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using AutoMapper; -using Blog.Contracts.V1.Responses.PostsResponses; -using Blog.EntityServices.Interfaces; -using Blog.Services.Core.Dtos.Posts; -using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; - -namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetPosts; - -public class GetPostsQueryHandler(IPostsService service, IMapper mapper) - : IQueryHandler -{ - public async Task Handle(GetPostsQuery query, CancellationToken cancellationToken) - { - query = query with { OrderBy = query.OrderBy ?? "asc" }; - query = query with { SortBy = query.SortBy ?? "Title" }; - query = query with { CurrentPage = query.CurrentPage ?? 1 }; - query = query with { PageSize = query.PageSize ?? 10 }; - - var posts = await service.GetPostsAsync( - mapper.Map(query)); - - return mapper.Map(posts); - } -} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsRequest.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsRequest.cs new file mode 100644 index 00000000..b28364b3 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/GetPosts/GetPostsRequest.cs @@ -0,0 +1,3 @@ +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.GetPosts; + +public class GetPostsRequest(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType, string Tag); \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/PostsActivity/PostsActivityEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/PostsActivity/PostsActivityEndpoint.cs new file mode 100644 index 00000000..aa3d779c --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/PostsActivity/PostsActivityEndpoint.cs @@ -0,0 +1,33 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.Chart; +using Carter; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.PostsActivity; +/* +public class PostsActivityEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Posts") + .MapToApiVersion(1.0) + .WithTags("Posts"); + + group.MapGet(ApiRoutes.PostsController.PostsActivity, async ([FromServices] ISender sender) => + { + var result = await sender.Send(new PostsActivityQuery()); + + return result == null + ? Results.NotFound() + : Results.Ok(result); + }) + .WithName("PostsActivity") + .Produces>() + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status404NotFound) + .WithSummary("Posts Activity") + .WithDescription("Posts Activity"); + } +}*/ \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsCommand.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsCommand.cs new file mode 100644 index 00000000..d2d2c37d --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsCommand.cs @@ -0,0 +1,7 @@ +using Blog.Contracts.V1.Responses.PostsResponses; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.UserPosts; + +public record UserPostsCommand(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType, string Tag, string Id) + : ICommand; diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsCommandHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsCommandHandler.cs new file mode 100644 index 00000000..1bb6bd46 --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsCommandHandler.cs @@ -0,0 +1,25 @@ +using AutoMapper; +using Blog.Contracts.V1.Responses.PostsResponses; +using Blog.EntityServices.Interfaces; +using Blog.Services.Core.Dtos.Posts; +using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.UserPosts; + +public class UserPostsCommandHandler(IPostsService service, IMapper mapper) + : ICommandHandler +{ + public async Task Handle(UserPostsCommand command, CancellationToken cancellationToken) + { + command = command with { OrderBy = command.OrderBy ?? "asc" }; + command = command with { SortBy = command.SortBy ?? "Title" }; + command = command with { CurrentPage = command.CurrentPage ?? 1 }; + command = command with { PageSize = command.PageSize ?? 10 }; + + var posts = await service.GetUserPostsAsync( + command.Id, + mapper.Map(command)); + + return mapper.Map(posts); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsEndpoint.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsEndpoint.cs new file mode 100644 index 00000000..ef1e825b --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsEndpoint.cs @@ -0,0 +1,40 @@ +using Asp.Versioning; +using Blog.Contracts.V1; +using Blog.Contracts.V1.Responses.PostsResponses; +using Carter; +using Mapster; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.UserPosts; + +public class UserPostsEndpoint : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.MapGroup("Posts") + .MapToApiVersion(1.0) + .WithTags("Posts"); + + group.MapPost(ApiRoutes.PostsController.UserPosts, + async ([FromBody] UserPostsRequest request, + [FromRoute] string id, + [FromServices] ISender sender) => + { + var command = request.Adapt(); + command = command with { Id = id }; + + var result = await sender.Send(command); + + return result is null + ? Results.NotFound() + : Results.Ok(result); + }) + //.RequireAuthorization() + .WithName("UserPosts") + .Produces() + .Produces(StatusCodes.Status400BadRequest) + .WithSummary("User Posts") + .WithDescription("User Posts"); + } +} diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsQuery.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsQuery.cs deleted file mode 100644 index f00c5064..00000000 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsQuery.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Blog.Contracts.V1.Responses.PostsResponses; -using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; - -namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.UserPosts; - -public record UserPostsQuery(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType, string Tag, string Id) - : SearchParametersQuery(OrderBy, SortBy, CurrentPage, PageSize, DisplayType), IQuery; \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsQueryHandler.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsQueryHandler.cs deleted file mode 100644 index 6ab993d5..00000000 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsQueryHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using AutoMapper; -using Blog.Contracts.V1.Responses.PostsResponses; -using Blog.EntityServices.Interfaces; -using Blog.Services.Core.Dtos.Posts; -using BlogVerticalSliceCQRSMinimalApi.CQRSExtensions; - -namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.UserPosts; - -public class UserPostsQueryHandler(IPostsService service, IMapper mapper) - : IQueryHandler -{ - public async Task Handle(UserPostsQuery query, CancellationToken cancellationToken) - { - query = query with { OrderBy = query.OrderBy ?? "asc" }; - query = query with { SortBy = query.SortBy ?? "Title" }; - query = query with { CurrentPage = query.CurrentPage ?? 1 }; - query = query with { PageSize = query.PageSize ?? 10 }; - - var posts = await service.GetUserPostsAsync( - query.Id, - mapper.Map(query)); - - return mapper.Map(posts); - } -} \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsRequest.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsRequest.cs new file mode 100644 index 00000000..9eedff1b --- /dev/null +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/Features/Posts/UserPosts/UserPostsRequest.cs @@ -0,0 +1,3 @@ +namespace BlogVerticalSliceCQRSMinimalApi.Features.Posts.UserPosts; + +public class UserPostsRequest(string OrderBy, string SortBy, int? CurrentPage, int? PageSize, string DisplayType, string Tag, string Id); \ No newline at end of file diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigureServicesInstallers/SwaggerInstaller.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigureServicesInstallers/SwaggerInstaller.cs index 1bf7f3ea..f4981bb6 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigureServicesInstallers/SwaggerInstaller.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigureServicesInstallers/SwaggerInstaller.cs @@ -35,11 +35,11 @@ public void InstallServices(IServiceCollection services, IConfiguration configur new HeaderApiVersionReader("x-api-version"), new MediaTypeApiVersionReader("x-api-version")); }) - .AddApiExplorer(options => + /*.AddApiExplorer(options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; - }); + })*/; //services.ConfigureOptions(); services.AddSwaggerGen(c => { diff --git a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigures/ConfigureRoutes.cs b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigures/ConfigureRoutes.cs index ce413081..2f51bd7c 100644 --- a/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigures/ConfigureRoutes.cs +++ b/BlogWebApp/BlogVerticalSliceCQRSMinimalApi/StartupConfigures/ConfigureRoutes.cs @@ -1,12 +1,13 @@ -using Carter; +using Asp.Versioning; namespace BlogVerticalSliceCQRSMinimalApi.StartupConfigures; -using System.IO; -using System.Net; +using CQRSExtensions; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Http; +using System.IO; +using System.Net; /// /// Configure routes. @@ -76,7 +77,13 @@ public static void Configure(WebApplication app) //endpoints.MapHealthChecks("/health"); }); - app.MapCarter(); + + var versionSet = app.NewApiVersionSet() + .HasApiVersion(new ApiVersion(1, 0)) + .ReportApiVersions() + .Build(); + + app.MapVersionedCarter(versionSet); app.MapDefaultEndpoints();