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.