Skip to content

Commit

Permalink
#21 : Add categories
Browse files Browse the repository at this point in the history
  • Loading branch information
oliver254 committed Aug 5, 2022
1 parent a267945 commit 8531ad7
Show file tree
Hide file tree
Showing 29 changed files with 803 additions and 100 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
```
dotnet ef database update -c feeaderdbcontext -p ../Feeader.Infrastructure/Feeader.Infrastructure.csproj -s Feeader.Api.csproj
```
## Crédits
- [[microsoft / dotnet-podcasts](https://github.com/microsoft/dotnet-podcasts)], MIT License, .NET 6 reference application shown at .NET Conf 2021 featuring ASP.NET Core, Blazor, .NET MAUI, Microservices, and more!
Expand Down
65 changes: 65 additions & 0 deletions src/Services/Feeader.Api/Controllers/CategoriesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Monbsoft.Feeader.Api.Models;
using Monbsoft.Feeader.Application.UseCases.Categories;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace Monbsoft.Feeader.Api.Controllers
{
[Route("[controller]")]
[ApiController]
public class CategoriesController : ControllerBase
{
private readonly IMediator _mediator;
private readonly ILogger<CategoriesController> _logger;

public CategoriesController(IMediator mediator, ILogger<CategoriesController> logger)
{
_mediator = mediator;
_logger = logger;
}

// POST: categories
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Guid>> CreateAsync(CreateCategoryCommand request, CancellationToken cancellationToken)
{
var id = await _mediator.Send(request);
_logger.LogInformation($"Category {id} created");
return Ok(id);
}

// GET: categories
[HttpGet]
public async Task<IEnumerable<CategoryDto>> ListAsync(int? limit, CancellationToken cancellationToken)
{
var categories = await _mediator.Send(new ListCategoriesQuery
{
Limit = limit,

}, cancellationToken);
return categories.Select(c => new CategoryDto(c));
}

// GET api/<CategoriesController>/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}

// PUT api/<CategoriesController>/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}

// DELETE api/<CategoriesController>/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
2 changes: 2 additions & 0 deletions src/Services/Feeader.Api/Models/ArticleDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public ArticleDto(Article article)
Date = article.Date;
Url = article.Url;
Picture = article.Picture;
FeedName = article?.Feed?.Name;
}

public Guid Id { get; }
Expand All @@ -20,5 +21,6 @@ public ArticleDto(Article article)
public DateTime Date { get; }
public string Url { get; }
public string Picture { get; }
public string? FeedName { get; }
}
}
19 changes: 19 additions & 0 deletions src/Services/Feeader.Api/Models/CategoryDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Monbsoft.Feeader.Domain;

namespace Monbsoft.Feeader.Api.Models;

public record CategoryDto
{
public CategoryDto(Category category)
{
Id = category.Id;
Genre = category.Genre;
Created = category.Created;
Updated = category.Updated;
}

public Guid Id { get; }
public string Genre { get; }
public DateTime Created { get; }
public DateTime Updated { get; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Monbsoft.Feeader.Application.Interfaces
public interface IApplicationDbContext
{
DbSet<Article> Articles { get; }
DbSet<Category> Categories { get; }
DbSet<Feed> Feeds { get; }

Task<int> SaveChangesAsync(CancellationToken cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public ListArticlesHandler(IApplicationDbContext dbContext)

public async Task<List<Article>> Handle(ListArticlesQuery request, CancellationToken cancellationToken)
{
var articlesQuery = _dbContext.Articles.AsQueryable();
var articlesQuery = _dbContext.Articles.Include(a => a.Feed).OrderByDescending(a => a.Date).AsQueryable();
if (request.FeedId is not null)
articlesQuery = articlesQuery.Where(a => request.FeedId.Equals(a.FeedId));
if (request.Limit is not null)
articlesQuery = articlesQuery.Take(request.Limit.Value);
var articles = await articlesQuery.OrderByDescending(a => a.Date).ToListAsync(cancellationToken);
var articles = await articlesQuery.ToListAsync(cancellationToken);
return articles;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using MediatR;
using Monbsoft.Feeader.Application.Interfaces;
using Monbsoft.Feeader.Domain;

namespace Monbsoft.Feeader.Application.UseCases.Categories;

public class CreateCategoryCommand : IRequest<Guid>
{
public CreateCategoryCommand(string genre)
{
Genre = genre;
}

public string Genre { get; }
}

public class CreateFeedHandler : IRequestHandler<CreateCategoryCommand, Guid>
{
private readonly IApplicationDbContext _dbContext;

public CreateFeedHandler(IApplicationDbContext dbContext)
{
_dbContext = dbContext;
}

public async Task<Guid> Handle(CreateCategoryCommand request, CancellationToken cancellationToken)
{
var category = new Category(Guid.NewGuid(), request.Genre);
await _dbContext.Categories.AddAsync(category, cancellationToken);
await _dbContext.SaveChangesAsync(cancellationToken);
return category.Id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using MediatR;
using Microsoft.EntityFrameworkCore;
using Monbsoft.Feeader.Application.Interfaces;
using Monbsoft.Feeader.Domain;

namespace Monbsoft.Feeader.Application.UseCases.Categories;


public class ListCategoriesQuery : IRequest<List<Category>>
{
public int? Limit { get; set; }
}

internal class ListCategoriesHandler : IRequestHandler<ListCategoriesQuery, List<Category>>
{
private readonly IApplicationDbContext _dbContext;

public ListCategoriesHandler(IApplicationDbContext dbContext)
{
_dbContext = dbContext;

}

public async Task<List<Category>> Handle(ListCategoriesQuery request, CancellationToken cancellationToken)
{
var categoriesQuery = _dbContext.Categories.OrderBy(c => c.Genre).AsQueryable();
if (request.Limit is not null)
categoriesQuery = categoriesQuery.Take(request.Limit.Value);
var categories = await categoriesQuery.ToListAsync(cancellationToken);
return categories;
}
}
18 changes: 18 additions & 0 deletions src/Services/Feeader.Domain/Category.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Monbsoft.Feeader.SharedKernel;

namespace Monbsoft.Feeader.Domain
{
public class Category : EntityBase
{
public Category(Guid id, string genre)
{
Id = id;
Genre = genre;
}

public string Genre { get; private set; }
public DateTime Created { get; private set; } = DateTime.Now;
public DateTime Updated { get; private set; } = DateTime.Now;
public ICollection<Feed> Feeds { get; private set; } = new List<Feed>();
}
}
1 change: 1 addition & 0 deletions src/Services/Feeader.Domain/Feed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ public Feed(Guid id, string name, string url)
public DateTime Created { get; private set; } = DateTime.Now;
public DateTime Updated { get; private set; } = DateTime.Now;
public ICollection<Article> Articles { get; private set; } = new List<Article>();
public Category? Category { get; private set; } = null;
}
}
51 changes: 30 additions & 21 deletions src/Services/Feeader.Infrastructure/Data/FeeaderDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,40 @@
using Monbsoft.Feeader.Application.Interfaces;
using Monbsoft.Feeader.Domain;

namespace Monbsoft.Feeader.Infrastructure.Data
namespace Monbsoft.Feeader.Infrastructure.Data;

public class FeeaderDbContext : DbContext, IApplicationDbContext
{
public class FeeaderDbContext : DbContext, IApplicationDbContext
public FeeaderDbContext(DbContextOptions options)
: base(options)
{
public FeeaderDbContext(DbContextOptions options)
: base(options)
{
}
}

public DbSet<Article> Articles => Set<Article>();
public DbSet<Feed> Feeds => Set<Feed>();
public DbSet<Article> Articles => Set<Article>();
public DbSet<Category> Categories => Set<Category>();
public DbSet<Feed> Feeds => Set<Feed>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Feed>().HasData(ContextSeed.Feeds);
// Category
modelBuilder.Entity<Category>()
.Property(c => c.Created)
.ValueGeneratedOnAdd();
modelBuilder.Entity<Category>()
.Property(c => c.Updated)
.HasDefaultValueSql("getdate()")
.ValueGeneratedOnAddOrUpdate();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Feed>().HasData(ContextSeed.Feeds);
//Feed
modelBuilder.Entity<Feed>()
.Property(f => f.Created)
.ValueGeneratedOnAdd();
modelBuilder.Entity<Feed>()
.Property(b => b.Updated)
.HasDefaultValueSql("getdate()")
.ValueGeneratedOnAddOrUpdate();
//Feed
modelBuilder.Entity<Feed>()
.Property(f => f.Created)
.ValueGeneratedOnAdd();
modelBuilder.Entity<Feed>()
.Property(b => b.Updated)
.HasDefaultValueSql("getdate()")
.ValueGeneratedOnAddOrUpdate();

base.OnModelCreating(modelBuilder);
}
base.OnModelCreating(modelBuilder);
}
}
Loading

0 comments on commit 8531ad7

Please sign in to comment.