jasontaylordev / northwindtraders Goto Github PK
View Code? Open in Web Editor NEWNorthwind Traders is a sample application built using ASP.NET Core and Entity Framework Core.
License: MIT License
Northwind Traders is a sample application built using ASP.NET Core and Entity Framework Core.
License: MIT License
Hi,
First of all, thank You for such a nice code example. I do really like this architecture and will try to use it in the nearly future. However, I still have some questions.
How do You handle different HTTP response codes? I.e. what if I wrote a REST api and decided to use codes like 201, etc. It seems like You almost always return 200 on success.
Is this the "Vertical slice" architecture which is being promoted in various conferences by Jimmy Bogard?
Where do You put your domain/persistence validation (since You seem to be only validating user inputs)? In https://github.com/jbogard/ContosoUniversityCore Jimmy Bogard moves it into the domain model.
Does all of your domain/application logic go to handler? In https://github.com/jbogard/ContosoUniversityCore Jimmy Bogard takes domain handling logic, puts it into the domain model and calls it from the handler.
What are Your thoughts on these questions?
Hi @jasongt
I'm quite curious about the reasoning behind the Primary Keys of Entities like this one
https://github.com/JasonGT/NorthwindTraders/blob/a4ed2887e052a7495bab6d092c03df9202d1d78b/Northwind.Domain/Entities/Customer.cs#L12
then configuring the table column like this
https://github.com/JasonGT/NorthwindTraders/blob/a4ed2887e052a7495bab6d092c03df9202d1d78b/Northwind.Persistence/Configurations/CustomerConfiguration.cs#L14
To keep things simpler, I am thinking of Inheriting from a BaseEntity that implements something like this
public interface IEntity<TKey>
{
TKey Id { get; set; }
}
If we have uniform Id
field for the Entities, we can use Automapper to auto map the Primary keys for these
https://github.com/JasonGT/NorthwindTraders/blob/a4ed2887e052a7495bab6d092c03df9202d1d78b/Northwind.Application/Customers/Commands/CreateCustomer/CreateCustomerCommandHandler.cs#L27
Can you share your thoughts on how and why you came up with this design?
Maybe I am missing some key points here.
Hi Jason,
Good job setting up this repo, it contains really good guidelines.
I have a question related to the domain entity Order, inside it has a ICollection of OrderDetail which doesn't have a private set.
The other entities I look at it all have collections with private set, I think I remember from your video that the reasoning behind is to grantee that the collection is always initialized and dev are not confused if the collection was initialized before or not.
Please Add Milestone Of this project.
Hi @jasongt,
Is it possible to use ASP.NET Core Web Api in a Framework Application?
I try to use Nuget Package approch to reference a ASP.NET Web Api to my Framework-App but it s not work.
Goal:
I spent a lot of time for this issue.!!
where i can put paging logic.
domain? application ? or webui.
i think application is good location but not 100% sure.
can you guide me?
Looks like id
route parameter is never used
[HttpPut("{id}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesDefaultResponseType]
public async Task<IActionResult> Update(string id, [FromBody]UpdateCustomerCommand command)
{
await Mediator.Send(command);
return NoContent();
}
Actually, that's the thing i'm struggling with right now. For updates ID ususally comes from route, and all the rest comes from the body. And i got several options, in order from bad to worse:
UpdateCustomerDto
and create UpdateCustomerCommand from Dto and Id in controller -- too much boilerplateDid i miss something?
Can you explain Configurations section Northwind.Persistence
please explain what is exact use of that configuration section in project and it look slimier to query validator
in domain layer
I tried the following 2 approaches to register multiple Validators and both are giving me odd behavior.
.AddFluentValidation(fv =>
{
fv.RegisterValidatorsFromAssemblyContaining<QueryValidator1>();
fv.RegisterValidatorsFromAssemblyContaining<QueryValidator2>();
});
This will build and run, but every Validator is being run twice. This means if I have a rule like so:
RuleFor(v => v.SomeProp).NotEmpty();
the result with be:
["SomeProp can not be Empty", "SomeProp can not be Empty"]
Other approach:
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<QueryValidator1>())
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<QueryValidator2>())
on app.UseMvc() i get:
System.InvalidOperationException: 'Sequence contains more than one matching element'
System.Linq.Enumerable.SingleOrDefault<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
FluentValidation.AspNetCore.FluentValidationObjectModelValidator..ctor(IModelMetadataProvider modelMetadataProvider, IList<IModelValidatorProvider> validatorProviders, bool runMvcValidation) in FluentValidationObjectModelValidator.cs
Any idea?
Hello,
I'm new here. I'm really impressed with your architecture style and love it.
I have a simple question, I can't figure out why it works (build successfully).
So in the Startup.cs you have the:
using Northwind.Persistence;
....
services.AddDbContext<NorthwindDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("NorthwindDatabase")));
But I checked the dependency it shows it has no dependencies on Northwind.Persistence. How can this configuration works? Anyone can explain this to me, this would be great help. Thanks in advanced :D.
please Add Global Log integration in NorthwindTraders
Hello, Jason.
First, thank you for this great sample app.
I have abstract class Animal and his children Cat, Dog, Lion. Cat, Dog, Lion are stored in database. So I created 3 dto's CatDto, DogDto, LionDto, and in them it has been implemented Expression<Func<Cat, CatDto>, and so on, as in your app. I want to create abstract class AnimalDto, and combine the common initialization of Cat, Dog, Lion, and use Projection of AnimalDto in CatDto, DogDto, and LionDto. How can it be done? Or it has another way to solve?
Thanks a lot!
Hi,
is there a nice way to create a seeder to the User entities?
I mean using HasData() method.
When I try to do it I keep getting error that "The seed entity for entity type 'User' cannot be added because it has the navigation set."
When ever things change, you should tell the "outside" that something has changed.
We do that by raising events inside the handlers. Through an interface, implemented in the infrastructure.
In my company we are a bit insecure about the work with (Micro)Services.
Your Web API is the top end of the chain, but what if this is just something in between?
Real world would be that this Web API will be a Swagger/Swashbuckle Application.
Then you generate (with NSwag Studio for example) a service consumer class for your API.
Then you have a Web Application what uses the API Service Consumer class.
We discussed everything, the current state is to remove our Application Layer and put all the commands into the Web API, because you are exposing all the Commands and Queries with the Web API.
Would you do that also?
The second point is, in that real world example, there are colleagues that say:
"If we generate, based on the Swagger.json our Service Consumer class that will generate it's own model "copies" you don't need the Domain layer anymore, because the consumer can be a non C# client, that can't use our C# Domain models anyway and if he is a C# application, he can use the generated model from within the Service Consumer".
What do you think about that?
So, there are two layers under review :)
So, what we mean is, something like this:
No Domain Layer, no Application Layer, no Infrastructure Layer. Sure, all of them are somewhere in here but not separated.
And sure that only works, if you expose all your functionality with Web API's.
I'm very interested on your opinion.
Hi,
I have only recently started to look at GraphQL. Coming across to this repository also recently, I'm wondering where does GraphQL fit in this context.
From my understanding, GraphQL solves the problem of having too many API endpoints by providing a more flexible querying system:
Let me know if this is not the right place to ask questions here. Cheers!
Simon
I'm a young software developer who haven't finished reading the Clean Architecture. Love the content here. It answers many questions that I've had over in previous projects. So thank you :)
The file OrderExtensions.cs in Persistence layer has Northwind.Persistence.Infrastructure when it should be Northwind.Persistence.Extensions
The reference in NorthwindInitializer.cs needs to be updated too.
When testing the API there's a problem with the INotificationService, if you remove it from the constructor of the Handler, you are able to insert Customers.
I'd rather to continue using repository and IoC pattern in my projects but I liked the structure of the solution. Can anyone share how they can add those two principles in this project structure and remove the dependency between persistence and presentation layer?
Hi Jason , I really appreciate for your contribution . I have just step up my project as per your guidance but when i am adding the migration its showing me error "Cannot create instance of an interface" . I am not having any other interface in my project except this IDesignTimeDbContextFactory i am getting exception of this interface. Also i would like to know what this file really does in persistance layer "NorthwindInitializer.cs" . I did not created this file in my persistance layer. Does this file absence creating issue for me ? Pls check this file.
I am using core 2.1
ef error.txt
Hello, I am trying to launch the WebUI project but the web app is unresponsive. I can see the Dashboard but when I click on any menu item, the web app do not load anything.
Any idea?
Thanks!
Does this architecture support OData Core?
https://www.nuget.org/packages/Microsoft.OData.Core/ (3.5 million downloads for Core), this is an extremely heavily used library and the answer for having something comparable to GraphQL from other stacks in .NET Core.
Hello,
In the RequestLogger
public Task Process(TRequest request, CancellationToken cancellationToken)
{
var name = typeof(TRequest).Name;
// TODO: Add User Details
_logger.LogInformation("Northwind Request: {Name} {@Request}", name, request);
return Task.CompletedTask;
}
How would the User Details be implemented?
Best Regards,
Adriano AE.
Hi @jasongt,
Noticed that your project has a dependency on a version of the Microsoft.AspNetCore.Mvc package that has been marked as affected in Microsoft Security Advisory 4021279: Vulnerabilities in .NET Core, ASP.NET Core Could Allow Elevation of Privilege.
Chris
In one of your talks I believe you mentioned wanting to integrate Razor Pages into your sample. I'm not seeing that in the Roadmap. Are you still planning to add it? I would much appreciate it.
Thanks!
Laurie
Hi
As I follow your readme, I get SQL error
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
I have tried to do in the package console:
update-database
doing following in the webapi project throws exception in the SQL server
dotnet run
I have tried opening 1433 default SQL server port and still not working.
Hi,
firstly, thank you for this great sample app. I have used the app as template for my 2 projects. And it really helped me.
I placed authentication in the presentation layer. In StartUp class I added authentication service(Jwt) and used Authorize attributes in controllers. But I had problems with authorization of resources. For instance, one author cannot view papers of another author, therefore I had to add additional fields to queries like UserId to recognize who ask the paper, and if User was author, I allowed to give a resource, otherwise returned Forbid().
Thanks a lot for any response! Good luck!
@jasongt You are serious about NorthwindTraders project
i watching this repository from last 2 month nothing happen.Month Of the project contributor is inactive.
So Please tell us what is timeline of this changes.
So let us know ,
now i am not following this repository.. because no documentation,all contributor is inactive and new regular update
I was looking at the project last night, wish I had seen it a year ago before i started my current project at work, but was wondering if creating an interface defining the dbcontext and the methods required in the Application Layer, and then creating an implementation of this interface in your persistence layer encapsulating your actual persistence layer calls might make your application layer even more independent of your persistence layer. It does result in more code though. So for example my application layer defines that it needs a dbcontext of type IDbContext, which can be registered using dependency injection, and there is a method to add a customer, it doesnt care about the implementation just that it is guaranteed that there will be a add method. Doing this would also remove any dependency on actual ef core technologies and allow an easy change to other persistence mediums. What are your thoughts on this?
To run webclient use http://localhost:4200 path, not "Launch http://localhost:52468/ in your browser to view the Web UI" - as described at 6th step, otherwise you'll be getting error :
An unhandled exception occurred while processing the request.
SocketException: No connection could be made because the target machine actively refused it
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port, CancellationToken cancellationToken)
HttpRequestException: No connection could be made because the target machine actively refused it
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port, CancellationToken cancellationToken)
HttpRequestException: Failed to proxy the request to http://localhost:4200/, because the request to the proxy target failed. Check that the proxy target server is running and accepting requests to http://localhost:4200/.
The underlying exception message was 'No connection could be made because the target machine actively refused it'.Check the InnerException for more details.
Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task baseUriTask, CancellationToken applicationStoppingToken, bool proxy404s)
i try to get rid of autofac .
is there any way can do it? can anyone show me sample code?
What is the preferred approach for handling errors that can not be trapped with Fluent Validation? Let's say the there's a duplicate entry and it's surfaced in the Command Handler layer... Or attempting to delete an item that can't be deleted. Would these always transpire as 500 errors rather than a say a 412 Precondition failed or something similar.
Just curious.
When you create a new item, the NSwag code expects for a response code 200 or 204, if not it throws and exception. The creation command returns a 201 code.
This issue cause that you can't susbscribe to call to the create command.
Hey,
great work on this Clean Architecture example.
There is one contradiction that bothers me -
the Application Layer ReadMe states: It is dependent on the domain layer, but has no dependencies on any other layer or project.
Looking at the Northwind.Application project it has a dependency on Northwind.Persistence.
Imo this violates Clean Architecture principles because it introduces coupling with the persistence details.
Persistence should be just another plug-in into the Application Layer - just like the Northwind.Infrastructure is.
Some ways for fixing this I can think of are:
Will appreciate your opinion on the matter.
Issue:
The GetCustomerDetailQueryHandler handle method constructs the CustomerDetailModel manually, yet the CustomerDetailModel has a Create static method for doing the same.
Question(s):
Why has the project elected to not use the create method here?
Doesn't this break the DRY principle?
Am I missing something simple here?
Hi,
First, thank you for the great video and this sample app.
I have a question, where we should add authentication if we want to secure all/part of the WebApi?
Thank you again.
Hi Jason. Thank you very much for your sample. I like it very much!
I want to ask you about domain logic. What kind of logic should this layer contain?
Could it contain some business logic, e.g.?
Could you provide some clarifications, please.
implementing identity server 4
JasonGT i am trying to impliment identity server 4 in project
i create another Project as Northwid.identityServer and i have another project Northwid.WebUi(API)
2)Now I want to Configure and seed Identityserver4.Entityframework ....(https://identityserver4.readthedocs.io/en/release/quickstarts/8_entity_framework.html)
3)But really dot understand where i install Identityserver4.Entityframework package in Northwind.Persistence or Northwid.identityServer project
4)Also i want to Configure swaggr token base UI Layout and LOG management in identity server
Please help me .... I really try to understand this architecture
services.AddIdentityServer()
// The AddDeveloperSigningCredential extension creates temporary key material for signing tokens.
// This might be useful to get started, but needs to be replaced by some persistent key material for production scenarios.
// See http://docs.identityserver.io/en/release/topics/crypto.html#refcrypto for more information.
.AddDeveloperSigningCredential()
.AddInMemoryPersistedGrants()
// To configure IdentityServer to use EntityFramework (EF) as the storage mechanism for configuration data (rather than using the in-memory implementations),
// see https://identityserver4.readthedocs.io/en/release/quickstarts/8_entity_framework.html
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
.AddInMemoryApiResources(IdentityServerConfig.GetApiResources())
.AddInMemoryClients(IdentityServerConfig.GetClients())
According to modelling schema in pdf slides Domain layer is in the core of the application and only application layer should reference it. But in the solution persistence layer referencing domain layer because of the dbcontext. Is that correct way ?
Any advice how to implement core Identity and still keep Clean Architecture?
Background:
So if I understand correctly the principles of Clean Architecture, the only reliance that the Application Layer should have is inward to the Domain. But if this is the case then why does the Northwind.Application have a reference to the Persistence layer?
Even more stand to me is the GetCustomerDetailQueryHandler having a direct dependency on the implemenation of the persistence layer's NorthwindDbContext.
Question:
Why is the above acceptable if the project is trying to be constructed as per Clean Architecture principles?
Lets say we have 2 handlers - SignInHandler and SignUpHandler. It's handy to call sign-in right after successful sign-up. Where to put logic?
What are your suggestions?
As described in /Domain/ReadMe.md, it says
This will contain all entities, enums, exceptions, types and logic specific to the domain.
I wonder why we store exceptions in Application Layer,
My question is, should we store the exceptions in the related layer or all the exceptions must be in Domain Layer thus other Layers can access it.
I'm getting this error when sending a POST to create a new customer.
{
"error": [
"Error constructing handler for request of type MediatR.IRequestHandler`2[Northwind.Application.Customers.Commands.CreateCustomerCommand,Northwind.Application.Customers.Models.CustomerDetailModel]. Register your handlers with the container. See the samples in GitHub for examples."
],
"stackTrace": " at MediatR.Internal.RequestHandlerBase.GetHandler[THandler](ServiceFactory factory)\r\n at MediatR.Internal.RequestHandlerWrapperImpl`2.<>c__DisplayClass0_0.<Handle>g__Handler|0()\r\n at Northwind.Application.Infrastructure.RequestPerformanceBehaviour`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in N:\\Repos\\window-crm\\NorthwindTraders\\Northwind.Application\\Infrastructure\\RequestPerformanceBehaviour.cs:line 25\r\n at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)\r\n at Northwind.WebApi.Controllers.CustomersController.Create(CreateCustomerModel customer) in N:\\Repos\\window-crm\\NorthwindTraders\\Northwind.WebApi\\Controllers\\CustomersController.cs:line 33\r\n at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n at System.Threading.Tasks.ValueTask`1.get_Result()\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()"
}
When creating a new Product everything works. If you compare how a Customer and a Product are created you can see the overall design structure is different. For products you have a DTO and a ProductViewModel and no Create/Update specific model. However, for Customer you do not have a DTO, but you do have separate List/Create/Update models.
Based off this, i'm pretty sure I can get CreateCustomer to work, but I just want to know which is the correct design pattern; Product or Customer?
Thanks,
John
Hi,
Just seen the Clean Architecture with ASP.NET Core 2.1
talk and it was great, thanks for all of this hard work!
Have a question about solving validations in a DRY way. I've seen validation is done only in the Persistance layer (things like .HasMaxLength(15);
)
What if i want to render a widget in the UI and want to set it's max length too? It's a really common scenario.
This is why I've always had validations in a layer up both persistance and validation. I see how data annotations in the domain entities would fix this but since it's discouraged by the talk. What would be the best approach to tackle this? Maybe define fluent validation rules at the application layer and somehow retrieve those rules both in presentation and persistance?
Again, great talk! ^_^
Just wondering if there is any reason not to use MediatR's AsyncRequestHandler
which avoids the Unit return type?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.