Giter Site home page Giter Site logo

amantinband / clean-architecture Goto Github PK

View Code? Open in Web Editor NEW
1.2K 1.2K 177.0 15.26 MB

The ultimate clean architecture template for .NET applications ๐Ÿ’ช

License: MIT License

C# 99.33% Dockerfile 0.67%
asp-net-core clean-architecture dotnet dotnet-core software-architecture web-application

clean-architecture's People

Contributors

amantinband avatar amirhessampourhossein avatar ar0311 avatar jaceksmi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clean-architecture's Issues

Improving performance in "ApiController"

I am getting the CA1859 suggestion in visual studio when hovering over Problem(Error error) and ValidationProblem(List<Error> errors) in ApiController
is it really a good idea to change the return type from IActionResult to ActionResult or ObjectRresult ?

Errors about Order Usings

Hello Amichai,

Thanks for amazing project, that template I always looking for.

I have an issue about "Order usings directive."

image

The error is: Using directives should be ordered alphabetically by the namespaces (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1210.md)

I'm using Rider, do you have any idea to fix this, Currently I'm fixing it manually.

[Question] Where should complex business logic be in clean architecture?

Hi @amantinband !

First of all a huge thanks and bravo for the great work both here and on youtube.

The question in the title is pretty generic, but I wasn't sure what to write in so I'll try to give more details here.

I'll face soon a very complex project with a lot of functional requirement. As you know these bring a lot of business logic in the code and I'd love to use the clean architecture (along with CQRS) in the best and most powerful way.

In your example the CreateSubscriptionCommandHandler is in charge of checking whether an element already exists and create it.
In my case the CreateArticleCommandHandler should make the same verification with much more complexity (it's not just a matter of a field). If I try to figure out how to do it, I think to a Service working as "query/commands orchestrator" that contains all the BL, while the CreateArticleCommand is only in charge of writing the command to the DB.

What is your idea regarding this? How should I structure my project using CleanArchitecture?

Thanks!!

Adding constants for custom claims

In your JwtTokenGenerator class there are two magic strings used as custom claim names.
we could use constants like below ๐Ÿ‘‡

public static class CustomClaims
{
    public const string Id = "id";
    public const string Permissions = "permissions";
}

what do you think ? @amantinband

Ran into errors when building the solution

Hey Amichai,

Thanks a bunch for the cool project. I gave it a shot for the first time using these commands:

dotnet new install Amantinband.CleanArchitecture.Template
dotnet new clean-arch -o CleanArchitectureByAB

But I ran into errors when building the solution. Any suggestions on how to fix it?

image

Thanks once more!

A slight change in Bind Configuration

What do you think if you change:
Your code:

configuration.Bind(EmailSettings.Section, emailSettings);

The code becomes like this:

configuration.Bind(nameof(EmailSettings), emailSettings);

Similar to other settings, this will probably be more flexible for code, I think, have a nice day!

Question: Converters

Hey Amichai, I have a quick question. In this template, you're storing a list of IDs as a comma-separated string in the db (.HasListOfIdsConverter();), and you're also storing a dictionary as JSON in the database.

I'm wondering if it's a recommended/good approach, or just for this template? Wouldn't you normally store these in a separate table (like you did in your YT series)?

(I'm using SQL server, if it's db specific :) )

Query on Eventual Consistency Mechanism

Hi @amantinband!

Firstly, thank you for this amazing project! It's packed with fantastic features. ๐Ÿ™Œ

However, I have a question regarding how eventual consistency is ensured. If I understood correctly, domain events are stored in the HttpContext Items and then processed after the response is sent to the client. In the event of a server breakdown, wouldn't there be a risk of inconsistency?

Wouldn't it be more advisable to implement an outbox pattern for such scenarios?

Thank you!

Setup Subcutaneous testing with SqlServer

Hey,

First of all amazing template, I build a financial app with ease.

Now I'm getting around to writing my tests ๐Ÿ˜ž.

I see you used Sqlite for you test db in your integration tests.
I would like to use an SqlServer test db but can't seem to get it to work.

Error: Microsoft.Data.SqlClient.SqlException : Cannot open database "Testing" requested by the login. The login failed.

Tried:

  • creating the database 'Testing' in advance using SSMS.
  • removing the ensureDeleted();

The code based on your template is below.
Hopefully one you guys can help me further ๐Ÿ˜ƒ.

Thanks in advance,
Nathan

// WebAppFactory
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
    TestDatabase = SqlServerTestDatabase.CreateAndInitialize();

    builder.ConfigureTestServices(services =>
    {
        services
            .RemoveAll<DbContextOptions<AppDbContext>>()
            .AddDbContext<AppDbContext>((sp, options) => options.UseSqlServer(TestDatabase.Connection));
    });

// SqlServerTestDatabase
public class SqlServerTestDatabase : IDisposable
{
    public SqlConnection Connection { get; }

    public static SqlServerTestDatabase CreateAndInitialize()
    {
        var testDatabase = new SqlServerTestDatabase("Server=localhost;Database=Testing;Trusted_Connection=True;TrustServerCertificate=true;");

        testDatabase.InitializeDatabase();

        return testDatabase;
    }

    public void InitializeDatabase()
    {
        Connection.Open();
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseSqlServer(Connection)
            .Options;

        using var context = new AppDbContext(options, null!);
        context.Database.EnsureDeleted();
        context.Database.EnsureCreated();
    }

    public void ResetDatabase()
    {
        Connection.Close();

        InitializeDatabase();
    }

    public void Dispose()
    {
        Connection.Close();
    }

    private SqlServerTestDatabase(string connectionString)
    {
        Connection = new SqlConnection(connectionString);
    }
}

Links to Figma designs?

Hey Amichai, I've been watching your videos for a while now, and I'm sure I'll use this template for future projects ๐Ÿ™Œ
Quick question. Could you share the link to the Figma designs you've used for this template (The folder structure/ test overviews, etc)?

I'd like to create similar designs/ update them for my projects.

Change "AddInfrastructureMiddleware" to "UseInfrastructureMiddleware"

Hello @amantinband
First of all, I want to thank you for your great clean architecture template. Recently, I have been learning about Clean Architecture and DDD and your YouTube channel taught me a lot about these topics. Thanks a million. ๐Ÿ™

I have noticed that you use the 'AddInfrastructureMiddleware' extension method to register your EventualConsistencyMiddleware
I think it would be a good idea to change the name to UseInfrastructureMiddleware.

Application Layer model validation

Hey, Amichai.

This is not an issue, but a question.

For some period of time we've been developing our applications following pretty much the same design. We really like it so far, it answers most of our questions we'd had with the other approaches. But there's one thing bothering me, it's validating commands and queries on the Application Layer side.

On the first glance there's nothing wrong with it, we're making sure that nothing gets processed in the application core without any input validation. Good stuff. But let's think how we handle the validation errors. Usually we throw/return them to the Presentation layer and then further to the client. And here's where the problem lies.

You see, between the Presentation and Application Layers we usually need to map this two worlds, one to another. REST world and CQRS world. And in some cases they do not match one-to-one. That leads us to some frustration on the client side. Let's say, sending an invalid property with the name "A" returns a validation error with the property "B" (if you need a real-world example, I can try to come up with something).

Of course, if a human reads the message, in 9 of 10 cases it should be clear what exactly went wrong. But what if we want to bind some kind of a handler on the front-end side? Make a fancy highlighting for the invalid textbox and whatnot.

So the questions are:
In this case, should the client know the Application Layer contracts structure?
Or should we copy-paste the whole validation to the Presentation Layer (kinda error prone and ugly, to be honest)?
Also moving the whole validation to the Presentation Layer is an option too. Less ugly than the second option, but no validation in the Application feels wrong too.

Please let me know what you think.
Thank you for your time and the contribution to the community.

[Question] Eventual Consistency in integration tests

Hey @amantinband !
First of all, thank you for this amazing template ๐Ÿ‘

I have a question on the EventualConsistencyMiddleware during integration testing.
Due to the transaction being commit after the request has return ok200, when testing for duplication how do you handle that ?

Do you add a delay in the test like below ? Or do you do something else ?
Thank you again !
Take care

   public async Task Register_RegisterIdentity_WhenEmailIsAlreadyUsed()
   {
      // Arrange
      var identity = _faker.Generate();
      await _identityRequest.RegisterAsync(identity);
      await Task.Delay(100); // Let the transaction being commited ?
      // Act
      var response = await _identityRequest.RegisterAsync(identity);

      // Assert
      response.IsSuccessStatusCode.Should().BeFalse();
      response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
      var problem = await response.Error!.GetContentAsAsync<ProblemDetails>();
      problem!.Detail.Should().Be(IdentityError.EmailAlreadyUsed(identity.Email).Description);
   }

Using options pattern in a different way

Currently, this is how your JwtSettings is configured ๐Ÿ‘‡

var jwtSettings = new JwtSettings();
configuration.Bind(JwtSettings.Section, jwtSettings);
services.AddSingleton(Options.Create(jwtSettings));

What's your opinion about the approach below ๐Ÿ‘‡

services.AddOptions<JwtSettings>().BindConfiguration(JwtSettings.Section);

we could also add validation in two different ways :

  • Data Annotations (built-in)
services.AddOptions<JwtSettings>()
    .BindConfiguration(JwtSettings.Section)
    .ValidateDataAnnotations()
    .ValidateOnStart();
  • Fluent Validation
public class FluentValidateOptions<TOptions>
    : IValidateOptions<TOptions>
    where TOptions : class
{
    private readonly IServiceProvider _serviceProvider;
    private readonly string? _name;

    public FluentValidateOptions(IServiceProvider serviceProvider, string? name)
    {
        _serviceProvider = serviceProvider;
        _name = name;
    }

    public ValidateOptionsResult Validate(string? name, TOptions options)
    {
        if (_name is not null && _name != name)
            return ValidateOptionsResult.Skip;

        ArgumentNullException.ThrowIfNull(options);

        using var scope = _serviceProvider.CreateScope();

        var validator = scope.ServiceProvider.GetRequiredService<IValidator<TOptions>>();

        var result = validator.Validate(options);

        if (result.IsValid)
            return ValidateOptionsResult.Success;

        var errors = result.Errors
            .Select(x => $"Validation failed for {x.PropertyName} with the error: {x.ErrorMessage}")
            .ToList();

        return ValidateOptionsResult.Fail(errors);
    }
public static OptionsBuilder<TOptions> ValidateFluentValidation<TOptions>(
        this OptionsBuilder<TOptions> optionsBuilder)
        where TOptions : class
    {
        optionsBuilder.Services.AddSingleton<IValidateOptions<TOptions>>(
            serviceProvider => new FluentValidateOptions<TOptions>(
                serviceProvider,
                optionsBuilder.Name
                ));
        return optionsBuilder;
    }
builder.Services.AddOptions<JwtSettings>()
    .BindConfiguration(JwtSettings.ConfigurationSectionName)
    .ValidateFluentValidation()
    .ValidateOnStart();

[Question] Isn't the Eventual Consistency Middleware coupling Infrastructure to Presentation?

Hi @amantinband,

I have a question concerning the Eventual Consistency Middleware.

By implementing an Eventual Consistency Middleware in the infrastructure layer that relies on the HttpContext, you are, in a sense, creating a dependency on a specific presentation mechanism (ASP.NET Core's HTTP handling), i.e. coupling the infrastructure layer with the presentation layer.

If you decide to switch the presentation layer technology (e.g., to a Blazor server application), this will break because there isn't a valid HttpContext available.

What are your thoughts/views about this? I could be wrong, so please correct me if I'm mistaken.
Would something like the Outbox pattern be a solution for this?

P.S. This may be unrelated here, but are you ever planning on making a video about the Event Patterns you can implement for scenarios where event 1 sends a success email but event 2 fails, and how to tackle these challenges?

Purpose of just calling Property()

I have seen the code below in your fluent configuration for User

builder.Property(u => u.Email);

builder.Property(u => u.LastName);

builder.Property(u => u.FirstName);

Is there a reason for calling only the .Property() method with nothing else ?

Refactoring "SaveChangesAsync" - Popping DomainEvents

Hello @amantinband
Thank you for responding to my issue (#3) โค

I have noticed the following piece of code in your "SaveChangesAsync" method ๐Ÿ‘‡

var domainEvents = ChangeTracker.Entries<Entity>()
   .Select(entry => entry.Entity.PopDomainEvents())
   .SelectMany(x => x)
   .ToList();

couldn't we use the following piece of code instead ? ๐Ÿ‘‡

var domainEvents = ChangeTracker.Entries<Entity>()
   .SelectMany(entry => entry.Entity.PopDomainEvents())
   .ToList();

Resource-based authorizarion

Hello amantinband,

Great initiative, thank you very much for your contribution. I see that you have implemented role-based authorization, permissions, and policies. However, how would you go about implementing resource-based authorization in your architecture? For instance, if you need to secure a resource exclusively for its creator or accessible only to an admin.

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.