Add fluent validation
This commit is contained in:
parent
d81f8eb46f
commit
ad6e0d2015
9 changed files with 118 additions and 22 deletions
|
@ -1,7 +1,9 @@
|
|||
using System.Runtime.Intrinsics.X86;
|
||||
using GitHubActionsDemo.Api.Models;
|
||||
using GitHubActionsDemo.Api.Mappers;
|
||||
using GitHubActionsDemo.Service;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using FluentValidation;
|
||||
|
||||
namespace GitHubActionsDemo.Api.Controllers;
|
||||
|
||||
|
@ -10,42 +12,59 @@ namespace GitHubActionsDemo.Api.Controllers;
|
|||
public class AuthorsController : BaseController
|
||||
{
|
||||
private readonly ILibraryService _libraryService;
|
||||
private readonly IValidator<AuthorRequest> _authorValidator;
|
||||
private readonly IValidator<PageParameters> _pageValidator;
|
||||
|
||||
public AuthorsController(
|
||||
ILibraryService libraryService
|
||||
ILibraryService libraryService,
|
||||
IValidator<AuthorRequest> authorValidator,
|
||||
IValidator<PageParameters> pageValidator
|
||||
)
|
||||
{
|
||||
_libraryService = libraryService ?? throw new ArgumentNullException(nameof(libraryService));
|
||||
_authorValidator = authorValidator ?? throw new ArgumentNullException(nameof(authorValidator));
|
||||
_pageValidator = pageValidator ?? throw new ArgumentNullException(nameof(pageValidator));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddAuthorAsync([FromBody] AuthorRequest authorRequest)
|
||||
public async Task<IResult> AddAuthorAsync([FromBody] AuthorRequest authorRequest)
|
||||
{
|
||||
var validationResult = await _authorValidator.ValidateAsync(authorRequest);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
return Results.ValidationProblem(validationResult.ToDictionary());
|
||||
|
||||
|
||||
var result = await _libraryService.AddAuthorAsync(authorRequest.Map());
|
||||
return result.Match(
|
||||
success => Ok(success.Value.Map()),
|
||||
success => Results.Ok(success.Value.Map()),
|
||||
error => InternalError()
|
||||
);
|
||||
}
|
||||
|
||||
[HttpGet("{authorId}")]
|
||||
public async Task<IActionResult> GetAuthorAsync(int authorId)
|
||||
public async Task<IResult> GetAuthorAsync(int authorId)
|
||||
{
|
||||
var result = await _libraryService.GetAuthorAsync(authorId);
|
||||
return result.Match(
|
||||
success => Ok(success.Value.Map()),
|
||||
notfound => NotFound(),
|
||||
success => Results.Ok(success.Value.Map()),
|
||||
notfound => Results.NotFound(),
|
||||
error => InternalError()
|
||||
);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAuthorsAsync([FromQuery(Name = "page")] int page = 1, [FromQuery(Name = "pageSize")] int pageSize = 10)
|
||||
public async Task<IResult> GetAuthorsAsync([FromQuery] PageParameters parameters)
|
||||
{
|
||||
var result = await _libraryService.GetAuthorsAsync(page, pageSize);
|
||||
var validationResult = await _pageValidator.ValidateAsync(parameters);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
return Results.ValidationProblem(validationResult.ToDictionary());
|
||||
|
||||
var result = await _libraryService.GetAuthorsAsync(parameters.Page, parameters.PageSize);
|
||||
|
||||
return result.Match(
|
||||
success => PagedResult(page, pageSize, success.Value.Select(x => x.Map()).ToList()),
|
||||
success => PagedResult(parameters.Page, parameters.PageSize, success.Value.Select(x => x.Map()).ToList()),
|
||||
error => InternalError()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ namespace GitHubActionsDemo.Api.Controllers;
|
|||
|
||||
public class BaseController : ControllerBase
|
||||
{
|
||||
public IActionResult InternalError()
|
||||
public IResult InternalError()
|
||||
{
|
||||
return new StatusCodeResult((int)HttpStatusCode.InternalServerError);
|
||||
return Results.StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
|
||||
public IActionResult PagedResult<T>(int page, int pageSize, T result) where T : IList
|
||||
public IResult PagedResult<T>(int page, int pageSize, T result) where T : IList
|
||||
{
|
||||
return Ok(new PagedResponse<T>(page, pageSize, result));
|
||||
return Results.Ok(new PagedResponse<T>(page, pageSize, result));
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ using GitHubActionsDemo.Api.Models;
|
|||
using GitHubActionsDemo.Api.Mappers;
|
||||
using GitHubActionsDemo.Service;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using FluentValidation;
|
||||
|
||||
namespace GitHubActionsDemo.Api.Controllers;
|
||||
|
||||
|
@ -10,42 +11,58 @@ namespace GitHubActionsDemo.Api.Controllers;
|
|||
public class BooksController : BaseController
|
||||
{
|
||||
private readonly ILibraryService _libraryService;
|
||||
private readonly IValidator<BookRequest> _bookValidator;
|
||||
private readonly IValidator<PageParameters> _pageValidator;
|
||||
|
||||
public BooksController(
|
||||
ILibraryService libraryService
|
||||
ILibraryService libraryService,
|
||||
IValidator<BookRequest> bookValidator,
|
||||
IValidator<PageParameters> pageValidator
|
||||
)
|
||||
{
|
||||
_libraryService = libraryService ?? throw new ArgumentNullException(nameof(libraryService));
|
||||
_bookValidator = bookValidator ?? throw new ArgumentNullException(nameof(bookValidator));
|
||||
_pageValidator = pageValidator ?? throw new ArgumentNullException(nameof(pageValidator));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetBooksAsync([FromQuery(Name = "page")] int page = 1, [FromQuery(Name = "pageSize")] int pageSize = 10)
|
||||
public async Task<IResult> GetBooksAsync([FromQuery] PageParameters parameters)
|
||||
{
|
||||
var result = await _libraryService.GetBooksAsync(page, pageSize);
|
||||
var validationResult = await _pageValidator.ValidateAsync(parameters);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
return Results.ValidationProblem(validationResult.ToDictionary());
|
||||
|
||||
var result = await _libraryService.GetBooksAsync(parameters.Page, parameters.PageSize);
|
||||
|
||||
return result.Match(
|
||||
success => PagedResult(page, pageSize, success.Value.Select(x => x.Map()).ToList()),
|
||||
success => PagedResult(parameters.Page, parameters.PageSize, success.Value.Select(x => x.Map()).ToList()),
|
||||
error => InternalError()
|
||||
);
|
||||
}
|
||||
|
||||
[HttpGet("{bookId}")]
|
||||
public async Task<IActionResult> GetBookAsync(int bookId)
|
||||
public async Task<IResult> GetBookAsync(int bookId)
|
||||
{
|
||||
var result = await _libraryService.GetBookAsync(bookId);
|
||||
return result.Match(
|
||||
success => Ok(success.Value.Map()),
|
||||
notfound => NotFound(),
|
||||
success => Results.Ok(success.Value.Map()),
|
||||
notfound => Results.NotFound(),
|
||||
error => InternalError()
|
||||
);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddBookAsync([FromBody] BookRequest bookRequest)
|
||||
public async Task<IResult> AddBookAsync([FromBody] BookRequest bookRequest)
|
||||
{
|
||||
var validationResult = await _bookValidator.ValidateAsync(bookRequest);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
return Results.ValidationProblem(validationResult.ToDictionary());
|
||||
|
||||
var result = await _libraryService.AddBookAsync(bookRequest.Map());
|
||||
return result.Match(
|
||||
success => Ok(success.Value.Map()),
|
||||
success => Results.Ok(success.Value.Map()),
|
||||
error => InternalError()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="11.5.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.5" />
|
||||
<PackageReference Include="OneOf" Version="3.0.255" />
|
||||
<PackageReference Include="Serilog" Version="3.0.1" />
|
||||
|
|
7
src/GitHubActionsDemo.Api/Models/PageParameters.cs
Normal file
7
src/GitHubActionsDemo.Api/Models/PageParameters.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace GitHubActionsDemo.Api.Models;
|
||||
|
||||
public class PageParameters
|
||||
{
|
||||
public int Page { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 10;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using FluentValidation;
|
||||
|
||||
namespace GitHubActionsDemo.Api.Models.Validators;
|
||||
|
||||
public class AuthorRequestValidator : AbstractValidator<AuthorRequest>
|
||||
{
|
||||
public AuthorRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.FirstName).NotEmpty();
|
||||
RuleFor(x => x.LastName).NotEmpty();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using FluentValidation;
|
||||
|
||||
namespace GitHubActionsDemo.Api.Models.Validators;
|
||||
|
||||
public class BookRequestValidator : AbstractValidator<BookRequest>
|
||||
{
|
||||
public BookRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Title).NotEmpty();
|
||||
RuleFor(x => x.AuthorId).NotEmpty();
|
||||
|
||||
RuleFor(x => x.Isbn)
|
||||
.NotEmpty()
|
||||
.MinimumLength(10)
|
||||
.MaximumLength(17)
|
||||
.Matches(@"^(?:ISBN(?:-1[03])?:? )?(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0 - 9X]{ 13}$| 97[89][0 - 9]{ 10}$| (?= (?:[0 - 9] +[- ]){ 4})[- 0 - 9]{ 17}$)(?: 97[89][- ] ?)?[0 - 9]{ 1,5}[- ]?[0 - 9]+[- ]?[0 - 9] +[- ]?[0 - 9X]$");
|
||||
|
||||
RuleFor(x => x.DatePublished)
|
||||
.NotEmpty();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using FluentValidation;
|
||||
|
||||
namespace GitHubActionsDemo.Api.Models.Validators;
|
||||
|
||||
public class PageParametersValidator : AbstractValidator<PageParameters>
|
||||
{
|
||||
public PageParametersValidator()
|
||||
{
|
||||
RuleFor(x => x.Page).GreaterThan(0);
|
||||
RuleFor(x => x.PageSize).InclusiveBetween(1, 100);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
using GitHubActionsDemo.Service.Infrastructure;
|
||||
using GitHubActionsDemo.Persistance.Infrastructure;
|
||||
using Serilog;
|
||||
using FluentValidation;
|
||||
using GitHubActionsDemo.Api.Models;
|
||||
using GitHubActionsDemo.Api.Models.Validators;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
@ -10,6 +13,10 @@ var logger = new LoggerConfiguration()
|
|||
.CreateLogger();
|
||||
builder.Logging.AddSerilog(logger);
|
||||
|
||||
builder.Services.AddScoped<IValidator<AuthorRequest>, AuthorRequestValidator>();
|
||||
builder.Services.AddScoped<IValidator<BookRequest>, BookRequestValidator>();
|
||||
builder.Services.AddScoped<IValidator<PageParameters>, PageParametersValidator>();
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
|
Loading…
Reference in a new issue