Preciso da sua ajuda no meu primeiro projeto backend!pt-3
Ola, meu nome e Caio e tenho 16 anos, estou desenvolvendo uma api de mangas usando .Net, caso nao tenha visto meus outros textos, texto 1: aqui e o texto 2: aqui.
Sobre o projeto
No repositorio do projeto, eu mudei a estrutura de pastas alem das modificações do projeto em si.Procurei seguir o modelo de Clean Architecture e de DDD.
Desde o meu ultimo texto modifiquei bem pouco o projeto, adicionei somente algumas ViewModels comecei a modificar as controllers, fora modificar algumas relações entre as models que nao estavam legais.
O que fiz ate agora
Primeiro, eu implentei alguns metodos nos repositorios de mangas, e das suas pages tambem.
MangaRepository:
public class MangaRepository : IMangaRepository
{
//props
//DI
public async Task<List<Mangas>> GetMangas()
{
return await _context.Mangas
.Include(m=> m.TagsModel)
.Include(m => m.CollectionPage)
.ToListAsync();
}
public async Task<Mangas> GetMangaById(string id)
{
return await _context.Mangas
.Include(m => m.TagsModel)
.Include(m => m.CollectionPage)
.FirstAsync(x => x.Id == id);
}
public async Task<List<Mangas>> FilterMangasByTag(string tag)
{
List<Mangas> mangasFounded = await _context.Mangas
.Where(model => model.TagsModel.Any(tagsModel => tagsModel.Tag == tag))
.ToListAsync();
return mangasFounded;
}
public Mangas Generate(MangasViewModel model)
{
var newManga = new Mangas()
{
Popularity = 0,
Id = Guid.NewGuid().ToString(),
Title = model.Title,
Author = model.Author,
Description = model.Description,
Group = model.Group,
Translation = model.Translation
};
newManga.TagsModel = model.Tags.Select(tag => new TagsModel()
{
MangaId = newManga.Id,
TagsId = Guid.NewGuid().ToString(),
Tag = tag
}).ToList();
return newManga;
}
public async Task AddManga(Mangas model)
{
await _context.Mangas.AddAsync(model);
await _context.Tags.AddRangeAsync(model.TagsModel);
await _context.SaveChangesAsync();
}
}
Neste repositorio eu queria implementar somente os metodos nos quais estao relacionados aos mangas, e nao as suas pages.
- GetMangas: retorna uma lista de mangas.
- GetMangaById: retorn um manga pelo seu id.
- FilterMangasByTag: retorna uma lista de mangas baseado em uma tag.
- Generate: gera um manga baseado em um ViewModel.
- AddManga: adiciona e salva os mangas no database.
PagesRepository:
public class PageRepository : IPageRepository
{
//props
//DI
public async Task<CollectionPage> GetPages(string id)
{
return await _context.CollectionPages.FirstAsync(x => x.MangaId == id);
}
public async Task<PageModel> GetPageById(string id)
{
return await _context.PageModels.FirstAsync(x => x.CollectionId == id);
}
public async Task<Mangas> GeneratePages(CollectionPageViewModel model, string id)
{
Mangas mangasFound = await _context.Mangas
.Include(mangas => mangas.CollectionPage)
.FirstAsync(x => x.Id == id);
var CollectionID = Guid.NewGuid().ToString();
mangasFound.CollectionPage = new CollectionPage()
{
MangaId = id,
CollectionId = CollectionID,
PageModels = model.Models.Select(x => new PageModel()
{
CollectionId = CollectionID,
PageNumber = x.PageNumber,
PageName = x.PageName,
MangaUrl = x.MangaUrl
})
.ToList()
};
await _context.CollectionPages.AddAsync(mangasFound.CollectionPage);
await _context.SaveChangesAsync();
return mangasFound;
}
}
Neste repositorio eu queria implementar todos os metodos relacionados as pages de cada CollecionPage.
- GetPages: retorna todas as pages de um manga especifico.
- GetPageById: retorna uma page baseada em um id de uma CollectionPage.
- GeneratePages: cria as pages pra um manga que ja esta registrado no database.
Agora minhas controllers, eu basicamente ja comecei a desenvolver as rotas de POST dos mangas, atualmente esta assim:
[ApiController]
public class MangaController : IMangaController
{
private readonly IValidator _validator;
private readonly IMangaRepository _mangaRepository;
private readonly IPageRepository _pageRepository;
private readonly AppDbContext _context;
public MangaController(
IMangaRepository mangaRepository,
IValidator validator,
IPageRepository pageRepository,
AppDbContext context)
{
_mangaRepository = mangaRepository;
_validator = validator;
_pageRepository = pageRepository;
_context = context;
}
[HttpGet("/api/v1/Mangas")]
public async Task<IActionResult> MangasGet([FromHeader] string authorization)
{
return new OkObjectResult(new
{
Mangas = await _mangaRepository.GetMangas()
});
}
[HttpGet("/api/v1/Tags")]
public async Task<IActionResult> TagsGet()
{
return new OkObjectResult(new
{
Tags = await _context.Tags.ToListAsync()
});
}
[HttpGet("/api/v1/Mangas/{id}")]
public async Task<IActionResult> MangaGetById( [FromRoute] string id)
{
if (string.IsNullOrEmpty(id))
return new BadRequestObjectResult("Id must not be null/empty!");
return new OkObjectResult(new
{
manga = await _mangaRepository.GetMangaById(id)
});
}
[HttpGet("/api/v1/Mangas/Tag")]
public async Task<IActionResult> MangaTagsFilterByOneTag( [FromHeader] string authorization, [FromQuery] string tag)
{
if (string.IsNullOrEmpty(tag))
return new BadRequestObjectResult("tag must not be null/empty!");
return new OkObjectResult(new
{
mangas = await _mangaRepository.FilterMangasByTag(tag)
});
}
[HttpGet("/api/v1/Manga/Tag")]
public Task<IActionResult> MangasTagGet(string authorization)
{
throw new NotImplementedException();
}
[HttpGet("/api/v1/manga/page/{id}")]
public Task<IActionResult> MangaPageById([FromRoute] string id, [FromQuery] int pageNumber)
{
throw new NotImplementedException();
}
[HttpGet("/api/v1/manga/pages/{id}")]
public Task<IActionResult> MangaPages(string authorization, string id)
{
throw new NotImplementedException();
}
[HttpPost("/api/v1/Mangas")]
public async Task<IActionResult> MangaPost( [FromHeader] string authorization, [FromBody] MangasViewModel model)
{
Dictionary<string, dynamic> errors = new();
ValidationResult response = await _validator.ValidateMangasViewModel(model);
if (!response.IsValid)
return new BadRequestObjectResult(errors["Erros"] = response.Errors.ToList());
var newManga = _mangaRepository.Generate(model);
await _mangaRepository.AddManga(newManga);
return new OkObjectResult(newManga);
}
[HttpPost("/api/v1/Manga/pages/{id}")]
public async Task<IActionResult> MangaPagesPost([FromHeader] string authorization, [FromRoute] string id, [FromBody] CollectionPageViewModel model)
{
Dictionary<string, dynamic> errors = new();
var responseValidation = await _validator.ValidateCollectionPagesViewModel(model);
if (!responseValidation.IsValid)
return new BadRequestObjectResult(errors["Errors"] = responseValidation.Errors.ToList());
var fulManga = await _pageRepository.GeneratePages(model, id);
return new OkObjectResult(new
{
fulManga,
fulManga.CollectionPage?.PageModels
});
}
[HttpPost("/api/v1/Mangas/Search")]
public Task<IActionResult> MangaSearch(string authorization, string search)
{
throw new NotImplementedException();
}
[HttpDelete("/api/v1/Mangas/DeleteMax")]
public async Task<IActionResult> MangaDeleteMax()
{
var mangas = await _context.Mangas.Include(m => m.TagsModel).ToListAsync();
_context.Mangas.RemoveRange(mangas);
foreach (var item in mangas)
{
_context.Tags.RemoveRange(item.TagsModel);
}
await _context.SaveChangesAsync();
return new OkResult();
}
}
Implementei as validações com o FluentValidation, entao as ViewModels estao todas sendo validadas antes de passar pela controller em si.
Falta implementar a Users Controller e a Animes Controller, porem ainda tenho algumas duvidas em relação a elas, quero que me ajudem com isso.
Tem muitas outras modificações que nao quero comentar aqui porque o texto vai ficar muito grande, então caso tenha se interessado acesse o repositorio do projeto: aqui.