The Best Way To Organize Your Program.cs In ASP.NET
Vložit
- čas přidán 7. 07. 2024
- All videos in this playlist: • ASP.NET 8 REST API Tut...
In today's video, we'll see how to organize Program.cs file in an ASP.NET application.
Organizing the dependency injection and request pipeline in our Program.cs can make a huge difference in how easy it is to understand how our application is wired together, and how easy it is to onboard the project and understand how things are configured.
Join us on discord: / amantinband
Get the source code: / amantinband
Support the channel: / amantinband
Connect with me on 'em socials:
Twitter: / amantinband
LinkedIn: / amantinband
GitHub: github.com/amantinband
Check out all my courses on DomeTrain:
dometrain.com/author/amichai-...
Support the channel and get the source code:
/ amantinband
Thanks for watching, don't forget to like & comment & subscribe! ❤️ 💻 - Věda a technologie
The evolution has made its turn and now we are constructing back our Startup class manually.
Tbh its not the same since when we had to have Startup class we did the same stuff with organizing our application via such extentions.
I actually like being able to look at one file and read how the application is configured. Plus I have to admit, I like large source files as it makes me feel like I've done a lot of work. 😆
Split project into modules where each module has it's own Add extension which registers all the services/configuration/hosted services from this module.
Avoid extracting stuff out based on technical terms(like Services) cause it eventually gets as ugly as having them in the Program.cs but now you need to also jump around to see the whole picture.
But! Only do this as your project grows. It is absolutely okay to register services in Program.cs if it's a single-feature-module service.
Your approach would work for normal architectures and I personally would use it like that as well, but Amichai is mostly teaching Clean Architecture.
From the Clean Architecture viewpoint, it would be bad if the inner layers (your Services) had to deal with outer layers (service registration/ApplicationBuilder). Only the outer layers know what happens inside the inner layers, and not vice versa.
@@wildmusical On the contrary, you make a module responsible for registering it's own dependencies and configuring it's required options, therefore the program.cs only needs to call one extension method to register the whole module and more importantly: without having to know anything about the internals of that module. If your program.cs has to know everything you might as well go for a single project app, why bother with all the clean architecture fanfare in that case.
Great video!
Hello Amichai, what tool are you using for the colored lines and circles you are drawing on your screen when you are describing your code?
Presentify (it's MacOS only. ZoomIt is a good windows alternative)
Thank u! I have a question:
Whats the difference(or sense behind) when we use void and instance(IServiceCollection) as return type for extension method?
When you use IServiceCollection instance, you have an ability to do so called "method chaining". As Amichai shown that in the video, we can write builder.AddServices().AddPersistence().AddSwagger()... and etc. It you were using void, it would be like that: builder.AddServices(); builder.AddPersistence(); builder.AddSwagger() and so forth.
P.S. It's usually a matter of convenience, but that specific thing is widely used with Builder pattern (in fact, we have a builder.Build() call in Program.cs, so consider this as Builder implementation)
Returning IServiceCollection enables the fluent/chaining style that Amichai uses in the Program.cs ie. builder.Services.AddServices().AddControllers().
@@winchester2581 Thanks!
@@curtmantle7486 Thanks!
Nice Thanks!
I like extension methods like these, especially organizing in terms of modules. My reasons:
- readability
- reduced merge conflict problems - many times somebody from my work team happens to wipe out some configuration, while resolving a merge conflict in that class file
- if we keep the modules and their "module installer" extension methods in separate projects, that also helps with being strict about the direction of dependency between the projects.
I've seen how Clean architecture is the overall goal, but there is room for violating that when the API project, being the running instance and having the Program.cs class, has reference to every other project and package dependency for the service registrations. Why? Because sometimes you might be "in a hurry" (lazy) and work with the infrastructure directly - in certain controllers/endpoints, in background workers etc.
So I'm in favor of project per module. As for the module installer methods - either in their respective module project, or a separate "all knowing" DI configuration project for the whole application.
What tool do you use to draw on the screen?
Presentify
Hello Amichai, thanks for the sharing. I've used that all my entire career and really like that approach. Also, how do you think it profitable to register services via reflection directly to the DI instead of classic approach with registring every service manually?
i mean someting like:
var types = typeof(DI).Assembly.GetTypes()
.Where(x => !x.IsInterface
&& !x.IsAbstract
&& x.IsAssignableFrom(typeof(IService)))
.ToArray();
foreach (var type in types)
{
services.AddScoped(type);
}
return services;
Perfectly fine to do that when you want to register services in bulk (e.g validators) that all implement the same interface. You take the performance hit of reflection on startup and that's it.
Hi,
I personally prefer partial Program.ABC.cs classes instead of boilerplating my project with folders and separate files
gonna be honest..just put it all in the one file its much simpler
This approach causes mess of extension method and classes for mid/large size projects, I prefer go with modularity.
How is that? It is highly modular. You you choose to initialize the modules you need in a short and precise manner. Your modules are initialized with a single call to the extension. Even Microsoft uses this exact approach in their code: every aspect/module of the web application and hosting are configured through extension methods that precisely declare the intent and type of module to use (i.e. AddDbContext(i => i.UseNpgsql()) or AddLogging(i => i.UseSimpleConsole()))
care to elaborate?
@@amantinband what specifically? The viceo creator here nicely explained how to organize the extension methods. Each covering the configuration of a single module.
I agree with you. I curious what Efe is suggesting as an alternative.
@@cn-ml Modularity can be achieved in two different ways. You can define your modules based on technical aspects or domains. I always prefer to go with the second way. Each module can have specific dependencies. I prefer to define separate dependency installers for each module, and that helps manage dependencies. You should stop comparing Microsoft with other projects. There is a huge difference between Framework development and typical business projects. Even from Microsoft's point of view, we can say each NuGet package is a module, and the .NET Framework team creates separate extensions for each of them, BUT it doesn't mean you can create a lot of extension methods. if you want to keep maintainable your project, you should be fan of the simplicity.
why do this when you can #region ### SERVICES ### hehe
Extension methods nonsense should be banned
Imagine writing c# in vscode kek