All Projects → rafaelfgx → Architecture

rafaelfgx / Architecture

Licence: mit
.NET 6, ASP.NET Core 6, Entity Framework Core 6, C# 10, Angular 13, Clean Code, SOLID, DDD.

Programming Languages

typescript
32286 projects
C#
18002 projects
HTML
75241 projects
SCSS
7915 projects

Projects that are alternatives of or similar to Architecture

Run Aspnetcore
A starter kit for your next ASP.NET Core web application. Boilerplate for ASP.NET Core reference application, demonstrating a layered application architecture with applying Clean Architecture and DDD best practices. Download 100+ page eBook PDF from here ->
Stars: ✭ 227 (-90.07%)
Mutual labels:  aspnetcore, aspnet-core, best-practices, dotnet-core, clean-architecture, ddd, clean-code, domain-driven-design
Aspnetboilerplate
ASP.NET Boilerplate - Web Application Framework
Stars: ✭ 10,061 (+340.31%)
Mutual labels:  aspnetcore, aspnet-core, best-practices, dotnet-core, architecture, domain-driven-design
Modular Monolith With Ddd
Full Modular Monolith application with Domain-Driven Design approach.
Stars: ✭ 6,210 (+171.77%)
Mutual labels:  dotnetcore, architecture, clean-architecture, ddd, clean-code, domain-driven-design
Event Sourcing Castanha
An Event Sourcing service template with DDD, TDD and SOLID. It has High Cohesion and Loose Coupling, it's a good start for your next Microservice application.
Stars: ✭ 68 (-97.02%)
Mutual labels:  solid, dotnetcore, clean-architecture, ddd, clean-code, domain-driven-design
Equinoxproject
Full ASP.NET Core 5 application with DDD, CQRS and Event Sourcing concepts
Stars: ✭ 5,120 (+124.07%)
Mutual labels:  aspnetcore, aspnet-core, architecture, ddd, clean-code
Dotnet New Caju
Learn Clean Architecture with .NET Core 3.0 🔥
Stars: ✭ 228 (-90.02%)
Mutual labels:  solid, clean-architecture, ddd, clean-code, domain-driven-design
Android Modular Architecture
📚 Sample Android Components Architecture on a modular word focused on the scalability, testability and maintainability written in Kotlin, following best practices using Jetpack.
Stars: ✭ 2,048 (-10.37%)
Mutual labels:  solid, best-practices, architecture, clean-architecture, clean-code
Domain Driven Hexagon
Guide on Domain-Driven Design, software architecture, design patterns, best practices etc.
Stars: ✭ 4,417 (+93.3%)
Mutual labels:  best-practices, architecture, clean-architecture, domain-driven-design
Cp Ddd Framework
A lightweight flexible development framework for complex business architecture with full ecosystem!轻量级业务中台开发框架,中台架构的顶层设计和完整解决方案!
Stars: ✭ 566 (-75.23%)
Mutual labels:  clean-architecture, ddd, clean-code, domain-driven-design
Awesome Microservices Netcore
💎 A collection of awesome training series, articles, videos, books, courses, sample projects, and tools for Microservices in .NET Core
Stars: ✭ 865 (-62.14%)
Mutual labels:  aspnetcore, aspnet-core, dotnet-core, dotnetcore
Sample Dotnet Core Cqrs Api
Sample .NET Core REST API CQRS implementation with raw SQL and DDD using Clean Architecture.
Stars: ✭ 1,273 (-44.29%)
Mutual labels:  clean-architecture, ddd, clean-code, domain-driven-design
Php Programming Best Practices
Referencia para los desarrolladores de Tiendanube y para la comunidad de PHP.
Stars: ✭ 138 (-93.96%)
Mutual labels:  solid, best-practices, clean-architecture, clean-code
Nlayerappv3
Domain Driven Design (DDD) N-LayeredArchitecture with .Net Core 2
Stars: ✭ 138 (-93.96%)
Mutual labels:  dotnet-core, dotnetcore, ddd, domain-driven-design
Eventflow.example
DDD+CQRS+Event-sourcing examples using EventFlow following CQRS-ES architecture. It is configured with RabbitMQ, MongoDB(Snapshot store), PostgreSQL(Read store), EventStore(GES). It's targeted to .Net Core 2.2 and include docker compose file.
Stars: ✭ 131 (-94.27%)
Mutual labels:  dotnet-core, dotnetcore, ddd, domain-driven-design
Revo
Event Sourcing, CQRS and DDD framework for C#/.NET Core.
Stars: ✭ 162 (-92.91%)
Mutual labels:  aspnetcore, aspnet-core, ddd, domain-driven-design
Clean Code Dotnet
🛁 Clean Code concepts and tools adapted for .NET
Stars: ✭ 4,425 (+93.65%)
Mutual labels:  solid, best-practices, clean-architecture, clean-code
Dev Stuff
😎 Programming stuff for everyone. Collection of articles, videos about architecture, Domain Driven Design, microservices, testing etc.
Stars: ✭ 105 (-95.4%)
Mutual labels:  architecture, clean-architecture, ddd, clean-code
Cronscheduler.aspnetcore
Cron Scheduler for AspNetCore 2.x/3.x or DotNetCore 2.x/3.x Self-hosted
Stars: ✭ 100 (-95.62%)
Mutual labels:  aspnetcore, aspnet-core, dotnet-core, dotnetcore
Dotnetcore
.NET 5 Nuget Packages.
Stars: ✭ 146 (-93.61%)
Mutual labels:  aspnetcore, dotnet-core, dotnetcore, dot-net
Cleanaspnetcorewebapi
Starter project for creating APIs built on ASP.NET Core using clean architecture.
Stars: ✭ 279 (-87.79%)
Mutual labels:  aspnet-core, architecture, clean-architecture, clean-code

Architecture

https://rafaelfgx-architecture.herokuapp.com

This project is an example of architecture using new technologies and best practices.

The goal is to share knowledge and use it as reference for new projects.

Thanks for enjoying!

Technologies

Practices

  • Clean Architecture
  • Clean Code
  • SOLID Principles
  • Separation of Concerns
  • DDD (Domain-Driven Design)

Run

Command Line

Prerequisites

Steps

  1. Open directory source\Web\Frontend in command line and execute npm i.
  2. Open directory source\Web in command line and execute dotnet run.
  3. Open https://localhost:8090.
Visual Studio Code

Prerequisites

Steps

  1. Open directory source\Web\Frontend in command line and execute npm i.
  2. Open source directory in Visual Studio Code.
  3. Press F5.
Visual Studio

Prerequisites

Steps

  1. Open directory source\Web\Frontend in command line and execute npm i.
  2. Open source\Architecture.sln in Visual Studio.
  3. Set Architecture.Web as startup project.
  4. Press F5.
Docker

Prerequisites

Steps

  1. Execute docker-compose up --build -d in root directory.
  2. Open http://localhost:8090.

Nuget Packages

Source: https://github.com/rafaelfgx/DotNetCore

Published: https://www.nuget.org/profiles/rafaelfgx

Layers

Web: Frontend and API.

Application: Flow control.

Domain: Business rules and domain logic.

Model: Data transfer objects.

Database: Data persistence.

Web

Frontend

Service

export class AppCustomerService {
    constructor(private readonly http: HttpClient, private readonly gridService: GridService) { }

    add = (customer: Customer) => this.http.post<number>("customers", customer);

    delete = (id: number) => this.http.delete(`customers/${id}`);

    get = (id: number) => this.http.get<Customer>(`customers/${id}`);

    grid = (parameters: GridParameters) => this.gridService.get<Customer>("customers/grid", parameters);

    inactivate = (id: number) => this.http.patch(`customers/${id}/inactivate`, {});

    list = () => this.http.get<Customer[]>("customers");

    update = (customer: Customer) => this.http.put(`customers/${customer.id}`, customer);
}

Guard

export class AppGuard implements CanActivate {
    constructor(private readonly appAuthService: AppAuthService) { }

    canActivate() {
        if (this.appAuthService.authenticated()) { return true; }
        this.appAuthService.signin();
        return false;
    }
}

ErrorHandler

export class AppErrorHandler implements ErrorHandler {
    constructor(private readonly appModalService: AppModalService) { }

    handleError(error: any) {
        if (error instanceof HttpErrorResponse) {
            switch (error.status) {
                case 422: { this.appModalService.alert(error.error); return; }
            }
        }

        console.error(error);
    }
}

HttpInterceptor

export class AppHttpInterceptor implements HttpInterceptor {
    constructor(private readonly appAuthService: AppAuthService) { }

    intercept(request: HttpRequest<any>, next: HttpHandler) {
        request = request.clone({
            setHeaders: { Authorization: `Bearer ${this.appAuthService.token()}` }
        });

        return next.handle(request);
    }
}

API

Program

var builder = WebApplication.CreateBuilder();

builder.Host.UseSerilog();

builder.Services.AddSecurity();
builder.Services.AddResponseCompression();
builder.Services.AddControllers().AddJsonOptions().AddAuthorizationPolicy();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSpa();
builder.Services.AddContext();
builder.Services.AddServices();

var application = builder.Build();

application.UseException();
application.UseHttps();
application.UseRouting();
application.UseResponseCompression();
application.UseAuthentication();
application.UseAuthorization();
application.UseEndpointsMapControllers();
application.UseSwagger();
application.UseSwaggerUI();
application.UseSpa();

application.Run();

Controller

[ApiController]
[Route("customers")]
public sealed class CustomerController : ControllerBase
{
    private readonly ICustomerService _customerService;

    public CustomerController(ICustomerService customerService) => _customerService = customerService;

    [HttpPost]
    public IActionResult Add(CustomerModel model) => _customerService.AddAsync(model).ApiResult();

    [HttpDelete("{id}")]
    public IActionResult Delete(long id) => _customerService.DeleteAsync(id).ApiResult();

    [HttpGet("{id}")]
    public IActionResult Get(long id) => _customerService.GetAsync(id).ApiResult();

    [HttpGet("grid")]
    public IActionResult Grid([FromQuery] GridParameters parameters) => _customerService.GridAsync(parameters).ApiResult();

    [HttpPatch("{id}/inactivate")]
    public IActionResult Inactivate(long id) => _customerService.InactivateAsync(id).ApiResult();

    [HttpGet]
    public IActionResult List() => _customerService.ListAsync().ApiResult();

    [HttpPut("{id}")]
    public IActionResult Update(CustomerModel model) => _customerService.UpdateAsync(model).ApiResult();
}

Application

Service

public sealed class CustomerService : ICustomerService
{
    private readonly ICustomerFactory _customerFactory;
    private readonly ICustomerRepository _customerRepository;
    private readonly IUnitOfWork _unitOfWork;

    public CustomerService
    (
        ICustomerFactory customerFactory,
        ICustomerRepository customerRepository,
        IUnitOfWork unitOfWork
    )
    {
        _customerFactory = customerFactory;
        _customerRepository = customerRepository;
        _unitOfWork = unitOfWork;
    }

    public async Task<IResult<long>> AddAsync(CustomerModel model)
    {
        var validation = new AddCustomerModelValidator().Validation(model);

        if (validation.Failed) return validation.Fail<long>();

        var customer = _customerFactory.Create(model);

        await _customerRepository.AddAsync(customer);

        await _unitOfWork.SaveChangesAsync();

        return customer.Id.Success();
    }

    public async Task<IResult> DeleteAsync(long id)
    {
        await _customerRepository.DeleteAsync(id);

        await _unitOfWork.SaveChangesAsync();

        return Result.Success();
    }

    public Task<CustomerModel> GetAsync(long id)
    {
        return _customerRepository.GetModelAsync(id);
    }

    public Task<Grid<CustomerModel>> GridAsync(GridParameters parameters)
    {
        return _customerRepository.GridAsync(parameters);
    }

    public async Task<IResult> InactivateAsync(long id)
    {
        var customer = new Customer(id);

        customer.Inactivate();

        await _customerRepository.UpdateStatusAsync(customer);

        await _unitOfWork.SaveChangesAsync();

        return Result.Success();
    }

    public Task<IEnumerable<CustomerModel>> ListAsync()
    {
        return _customerRepository.ListModelAsync();
    }

    public async Task<IResult> UpdateAsync(CustomerModel model)
    {
        var validation = new UpdateCustomerModelValidator().Validation(model);

        if (validation.Failed) return validation;

        var customer = _customerFactory.Create(model);

        await _customerRepository.UpdateAsync(customer);

        await _unitOfWork.SaveChangesAsync();

        return Result.Success();
    }
}

Factory

public sealed class CustomerFactory : ICustomerFactory
{
    public Customer Create(CustomerModel model)
    {
        return new Customer
        (
            model.Id,
            new Name(model.FirstName, model.LastName),
            new Email(model.Email)
        );
    }
}

Domain

Entity

public sealed class Customer : Entity<long>
{
    public Customer(long id) => Id = id;

    public Customer
    (
        long id,
        Name name,
        Email email
    )
    {
        Id = id;
        Name = name;
        Email = email;
        Activate();
    }

    public Name Name { get; private set; }

    public Email Email { get; private set; }

    public Status Status { get; private set; }

    public void Activate() => Status = Status.Active;

    public void Inactivate() => Status = Status.Inactive;
}

ValueObject

public sealed record Name(string FirstName, string LastName);

Model

Model

public sealed record CustomerModel
{
    public long Id { get; init; }

    public string FirstName { get; init; }

    public string LastName { get; init; }

    public string Email { get; init; }
}

ModelValidator

public abstract class CustomerModelValidator : AbstractValidator<CustomerModel>
{
    public void Id() => RuleFor(customer => customer.Id).NotEmpty();

    public void FirstName() => RuleFor(customer => customer.FirstName).NotEmpty();

    public void LastName() => RuleFor(customer => customer.LastName).NotEmpty();

    public void Email() => RuleFor(customer => customer.Email).EmailAddress();
}
public sealed class AddCustomerModelValidator : CustomerModelValidator
{
    public AddCustomerModelValidator() => FirstName(); LastName(); Email();
}
public sealed class UpdateCustomerModelValidator : CustomerModelValidator
{
    public UpdateCustomerModelValidator() => Id(); FirstName(); LastName(); Email();
}

Database

Context

public sealed class Context : DbContext
{
    public Context(DbContextOptions options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.ApplyConfigurationsFromAssembly(typeof(Context).Assembly).Seed();
    }
}

Configuration

public sealed class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        builder.ToTable(nameof(Customer), nameof(Customer));

        builder.HasKey(customer => customer.Id);

        builder.Property(customer => customer.Id).ValueGeneratedOnAdd().IsRequired();

        builder.Property(customer => customer.Status).IsRequired();

        builder.OwnsOne(customer => customer.Name, customerName =>
        {
            customerName.Property(name => name.FirstName).HasColumnName(nameof(Name.FirstName)).HasMaxLength(100).IsRequired();

            customerName.Property(name => name.LastName).HasColumnName(nameof(Name.LastName)).HasMaxLength(200).IsRequired();
        });

        builder.OwnsOne(customer => customer.Email, customerEmail =>
        {
            customerEmail.Property(email => email.Value).HasColumnName(nameof(User.Email)).HasMaxLength(300).IsRequired();

            customerEmail.HasIndex(email => email.Value).IsUnique();
        });
    }
}

Repository

public sealed class CustomerRepository : EFRepository<Customer>, ICustomerRepository
{
    public CustomerRepository(Context context) : base(context) { }

    public Task<CustomerModel> GetModelAsync(long id)
    {
        return Queryable.Where(CustomerExpression.Id(id)).Select(CustomerExpression.Model).SingleOrDefaultAsync();
    }

    public Task<Grid<CustomerModel>> GridAsync(GridParameters parameters)
    {
        return Queryable.Select(CustomerExpression.Model).GridAsync(parameters);
    }

    public async Task<IEnumerable<CustomerModel>> ListModelAsync()
    {
        return await Queryable.Select(CustomerExpression.Model).ToListAsync();
    }

    public Task UpdateStatusAsync(Customer customer)
    {
        return UpdatePartialAsync(new { customer.Id, customer.Status });
    }
}

Expression

public static class CustomerExpression
{
    public static Expression<Func<Customer, CustomerModel>> Model => customer => new CustomerModel
    {
        Id = user.Id,
        FirstName = user.Name.FirstName,
        LastName = user.Name.LastName,
        Email = user.Email.Value
    };

    public static Expression<Func<Customer, bool>> Id(long id) => customer => customer.Id == id;
}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].