Structuring Dependency Injection In ASP.NET Core The Right Way

  Рет қаралды 55,535

Milan Jovanović

Milan Jovanović

Күн бұрын

Пікірлер
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Get the source code for this video for FREE → the-dotnet-weekly.ck.page/clean-di Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@peleacezar6915
@peleacezar6915 2 жыл бұрын
The second approach is very elegant and at the same time a less common way to inject your dependencies into the project. Congratulations for another extremely useful material 😃
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thank you, I'm glad you saw something interesting
@pw.70
@pw.70 10 ай бұрын
I really like the reflection method you've used there. The fact that you can use that straight out of the box like that, just by implementing an interface... Excellent. I did have a bug, but that was down to me being stoopid. Top job, chap.
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
Hey, thanks a lot. Glad this was helpful. 😁
@this-is-bioman
@this-is-bioman Жыл бұрын
I used to be a fan of reflection mechanics liked this until I had to reverse engineer my own code several months later so now I think the explicit nature of the extension approach is going to cause you much less headaches in future.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Perhaps, but I don't think this is troublesome to maintain.
@Rob_III
@Rob_III 2 жыл бұрын
@0:40 "You can see we have close to 100 lines of code to configure our services". @8:10 Now we have 130 lines of code in another file. I would've gone one step further and put unrelated stuff (essentially each extension method in this example) in it's own separate file. Other than that: nice video, keep up the great work! I enjoy your videos very much!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Of course, each extension method could have been in its own file. 😅
@MohammadZare90
@MohammadZare90 2 жыл бұрын
Great approach. I think it's good to add an order property to specify which dependency should be injected first...
@Rob_III
@Rob_III 2 жыл бұрын
I would even consider an attribute (like a ServiceinstallerAttribute) for more configuration options.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
When did you need to order of registration?
@MarcusKaseder
@MarcusKaseder 2 жыл бұрын
@@MilanJovanovicTech Some registrations need ordering. Decorators (with Scrutor) for example. Or if you have multiple service registrations without TryAdd. But this would be a bad practice if you rely on something like that. But you can use that approach as "fallback registrations" if Noone registers a service, you use a fallback default implementation. Or if you switch to App and "Use". Middlewares do have order.
@aghoghobernard
@aghoghobernard 2 жыл бұрын
I was about to ask how ordering will be factored in. Good a thing I read comments first. That’s why I go with the extension methods. In my worst case I nest the extensions so it doesn’t grow on the program.cs side
@b000ta
@b000ta 8 ай бұрын
Doesn't order property limit the auto registration of the services in cases where we have to re-order when a new service needs to be introduced with higher priority? How will this be handled with order property?
@montanomariano
@montanomariano 2 жыл бұрын
I've been using the extension method approach for some time now. It's very clean. The Automatic installer is a very interesting approach too. I saw something very similar a while back, just before .NET Core dependency injection system, in a great instructor's channel from whom I learned a lot (Tim Corey) with Autofac Nuget Package.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Would you try out the second approach I suggested?
@montanomariano
@montanomariano 2 жыл бұрын
@@MilanJovanovicTech Yes, I think I would. Probably in solutions with complex Startup settings and large amount of projects.
@Swzvtlbngfd
@Swzvtlbngfd 2 жыл бұрын
Very helpful in understanding how to organize ever growing dependencies
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Glad it was helpful!
@vikasjoshi4708
@vikasjoshi4708 2 жыл бұрын
Thanks for introducing super compact and maintainable way of doing better DI @Milan
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
My pleasure 😊
@mrsajjad30
@mrsajjad30 2 жыл бұрын
Great lesson. Thank you for sharing these gems for free.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Glad you enjoyed it!
@dcuccia
@dcuccia Жыл бұрын
Nice summary. And a good reminder that I don't need Scrutor for simple tasks like this. One thought - with C#'s static virtual members in interfaces, we can avoid that extra step to instantiate IServiceInstaller objects, just to call a method (which can now be static).
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That would be super interesting to explore! I'll see what I can make of it 😁
@dcuccia
@dcuccia Жыл бұрын
@@MilanJovanovicTech credit to Nick Chapsas in a tutorial he did on bootstrapping Minimal APIs. I think factory patterns are about to get simpler across the board with this feature.
2 жыл бұрын
Thanks for the video when you use Extension methode , you can avoid returning IServiceCollection no need
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I know, I just like chaining the method calls.
@emwagner
@emwagner 2 жыл бұрын
You're a programming genius, Milan!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Haha, lovely! Thank you :)
@InshuMussu
@InshuMussu Жыл бұрын
Very nice approach, your all videos are awesome and unique.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thank you, I'm glad you find them unique!
@MrFunkyCabbage
@MrFunkyCabbage Жыл бұрын
YOu actually touched on some good points here, especially when it came to the service installers side of things... Super video! thanks.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I appreciate that!
@Isr5d
@Isr5d Жыл бұрын
The second approach is more like a modular design. if you need to go this route, you may need to implement an int property into your `Installer` interface, to be used for ordering the executions of the installer (e.g. SortOrder,. priority, etc..). This can be also extendable if you are into a modular systems ;).
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I used something similar for my Modular Monolith. Like an "IModuleInstaller"
@tonycaesar7934
@tonycaesar7934 2 жыл бұрын
I'm torn between the two options. I have tend toward the first extension strategy in the past. I like the idea of having a different file for each startup type regardless of the strategy. It keeps the code better organized and easier to find startup elements. The reflection approach has a certain sense of magic while still being clean and easy to maintain. Magic for me is bad because it detaches you from what is happening and can be harder to maintain. One catch to the reflection startegy is I may want to selectively switch between different startup extensions to cover different scenarios (mock, test environment, etc.). The reflection strategy makes that a little more difficult but not impossible. Which do you find yourself using more and why?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I use the IServiceInstaller approach in practice. I like that I can name my files properly and I can easily find them via search in VS. I haven't had any issues with it. It's more or less the same thing as with extension methods, just automatically applied.
@nothingisreal6345
@nothingisreal6345 2 жыл бұрын
Avoid reflection. It is an indirection hard to resolve and uncessary.
@mahi.tshooter
@mahi.tshooter 2 жыл бұрын
Thanks @Milan, it was a great resourceful video.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Glad it was helpful!
@rhlee063
@rhlee063 Жыл бұрын
Hi Milan, great video. You may use SHIFT ALT and . (dot) to select next occurrence, so you don't have to manually select and paste.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I have to be slow to make this video longer, that's how I earn my daily bread 😅
@rhlee063
@rhlee063 Жыл бұрын
@@MilanJovanovicTech you did really well and appreciate your content
@paikesitics
@paikesitics 2 жыл бұрын
Nice! I'll apply your approach. Thanks.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
You're welcome
@stef2528
@stef2528 6 ай бұрын
Awesome! Exactly what I was looking for. Thank you Milan.
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
Most welcome :)
@lazykoder
@lazykoder Жыл бұрын
Service.Install seems very clean, as we can use this at each project (class lib) level so services defined in diff project assembly can we added there only, which would be more clean and explicit.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I'm yet to explore static interface methods to see what can be done with it, may be able to avoid instantiating the service installers
@nage7447
@nage7447 2 жыл бұрын
Love aproach with reflection, doing like that for a some time already )
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Nice, one of the few!
@shakib4845
@shakib4845 2 жыл бұрын
I think a nice way to reduce dependency registrations, is using Interface marking, but not with tools like scrutor. because it will make application start up slow and heavy (because of reflection stuff). Instead we can create a source generator to wisely check the interface marks and inject them using a partial method.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Application startup time is usually the least of my concerns
@krccmsitp2884
@krccmsitp2884 2 жыл бұрын
The source generator idea sounds quite interesting. Would like to see a sample implementation.
@shakib4845
@shakib4845 2 жыл бұрын
@@MilanJovanovicTech when the project grows up and specialy if you use auto-scaling system like kubernates, stratup time concern gets bolder.
@danijelzg001
@danijelzg001 2 жыл бұрын
We are talking here about microseconds, miliseconds for net to scan the assembly, not sure what will you get by introducing source generator, make a benchmark dotnet and let us know results...
@shakib4845
@shakib4845 2 жыл бұрын
@@danijelzg001 Basically difference between reflection scanning assembly and explicitly define dependency is included in c# basics and if you want proof for that you can go and read "c# from scratch" documents and startup velocity is one of the hottest high level topics in architectural level of programming. As much as your project gets bigger, your assembly gets bigger and its scanning gets harder. I don't think anyone needs proof and benchmarks for principles. But you by your milliseconds theory just spoiled all computer science when it comes to various algorithms and stuff :D
@nevernerd
@nevernerd 2 жыл бұрын
I've chosen the extension methods approach thusfar. My biggest issue is the solution has about 30 microservice projects and I don't want to recreate all this every time we add a new project, so I'm shoving as much as possible into a class library, which seems to increase complexity a bit.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Doesn't it make sense for each microservice to handle it's own registrations?
@anthonybianue9206
@anthonybianue9206 Жыл бұрын
Lovely video. My only concerns are Jr dev learning curve and functional testing. The reflection part would complicate the test. But I like it. I am a fan of putting the dependencies at the project level itself. So the infrastructure layer would have one etc
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I don't usually test my DI code, and I don't think it's worthwhile. Possibly a functional test that crashes if a service is missing, I think Nick covered that topic in a recent video.
@jacobstamm
@jacobstamm Жыл бұрын
With the IServiceInstaller approach, how do you handle cases where different web apps need different services? As-is, your approach would install everything everywhere.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You can easily solve this by passing in the specific assembly to scan for IServiceInstaller implementations
@jacobstamm
@jacobstamm Жыл бұрын
@@MilanJovanovicTech Maybe I'm missing something, so thanks for bearing with me... but let's say WebApp1 needs both CachingServiceInstaller and InfrastructureServiceInstaller, but WebApp2 only needs CachingServiceInstaller. Are you saying the each web app would need to have duplicate implementations of CachineServiceInstaller?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@jacobstamm Yes. This implementation doesn't really take into account using it from multiple APIs. You'd need to rethink the solution to make it more generic like that.
@antonmartyniuk
@antonmartyniuk Жыл бұрын
Great approach with ServiceInstaller but it also has drawbacks because of reflection. It might be hard to trim your application correctly when using reflection and some apps do require to be self-contained and trimmed. Personally I use extensions methods but write them in different files. The future of DI will be with source generators, so the compiler can check that ServiceA has dependencies on ServiceB and ServiceC and if they are registered in DI. I hope this will be the future of DI which will solve many problems during compile time and it will be way faster than reflection. A quick startup of the app is often critical for such apps as Azure Functions and AWS lambdas
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Agreed. That would be awesome if something can be done with source generators
@sanampakuwal
@sanampakuwal 2 жыл бұрын
I use the 2nd approach!
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Wow, one of the few!
@avecesar
@avecesar 2 жыл бұрын
Nice and useful. Thank you.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Glad it was helpful!
@OleksiiKorniienko
@OleksiiKorniienko 2 жыл бұрын
Thanks for the video! 2nd approach is interesting. I'd like to mention it. Would it be great to make each layer to be responsible for its dependencies? By doing this we can apply an internal modifier where it is possible and the layer becomes more encapsulated with its own dependencies. Otherwise, we need to keep all implementations public just to register them.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Yes, we can make the implementations internal and inside each project/layer. Then we can scan for internal files and register it in the same way.
9 ай бұрын
What about puting those extestion methods into separate projects that they register? So AddInfractructure to Infrastructure project?
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
It's an okay approach
@javifrancia
@javifrancia Жыл бұрын
hi milan! thank you very much for your videos
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
So I can do method chaining like: AddApplication().AddInfrastructure().AddPersistence()
@andreybiryulin7207
@andreybiryulin7207 Жыл бұрын
Biggest concern I have about DI is how to express in code that one bunch of dependencies require some other shared ones, e.g. you have .AddFeatureX() .AddFeatureY() and they both use say IDistributedCache and you want to make sure you didn't forget .AddDistributedCache in your app, but don't want to bind it in either FeatureX or FeatureY, because it might be up to application to bind it to specific implementation and in specific scope maybe. Neither of proposed solutions help with that.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You can register distributed cache with both AddFeatureX and AddFeatureY using TryAddSingleton for example
@timur2887
@timur2887 9 ай бұрын
@@MilanJovanovicTech btw, TryAdd method iterates through all services each call. I wonder why it doesn't still use a dictionary to locate a service...
@riccarrasquilla379
@riccarrasquilla379 11 ай бұрын
thanks for the video
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
You're welcome
@spaarkytv6526
@spaarkytv6526 7 ай бұрын
Thank you so much for sharing! I'm learning Clean Architecture and I have a question... applying UseSqlServer to the DbContext doesn't create a dependency? So, the database layer won't be able to change so easily or am I wrong? Is there a more decoupled way to do it while still keeping dependency injection?
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
This isn't something I'm too concerned with most of the time. I like some ideas of Clean Architecture, but not all of them
@RajeshAravapalliAZ09
@RajeshAravapalliAZ09 Жыл бұрын
No no to reflection. First approach with multiple extension files - may be span across different projects is what i am doing.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's a solid approach, for sure
@MarcusKaseder
@MarcusKaseder 2 жыл бұрын
Always nice to see different approaches. I even have an analyzer rule that doesn't allow a big program.cs I usually go with Startup classes (same like your installer). Sometimes with interfaces and sometimes with static methods (no extensions). But the main difference to your solution is my encapsulation. Sometimes it's not enough to just register services and you have to do some app stuff. So, my Startup classes mostly have ConfigureServices(ServiceCollection) and also ConfigureApp(App). In that case AuthAndAuthStartup would have services.AddAuthentication() and app.UseAuthentication() Same with CorsStartup, SwaggerStartup, etc.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Agreed, there's more than just configuring services. How do you apply that analyzer for Startup.cs size?
@MarcusKaseder
@MarcusKaseder Жыл бұрын
@@MilanJovanovicTech Id did some digging and the rule for checking is: CA1506: Avoid excessive class coupling - Can't post link here but you'll find it :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@MarcusKaseder Very interesting rule!
@CarmenSantiNova
@CarmenSantiNova 2 жыл бұрын
We've been using a custom built plugin system for many years now and we use (sort of) the approach of your IServiceInstaller. It's all good when it comes to service registration but when it comes to handling middleware it needs coordination (since the middleware is sensitive to ordering). And since all of our plugins essentially know nothing about the other plugins, they cannot coordinate amongst themselves. So we added some meta-information that forms a dependency graph but it didn't solve the problem really. This is where I realized that there is no good solution to the problem of coordinating middleware order. Basically we're stuck with a hard-coded setup. Anyone else been playing around with that kind of setup!?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I didn't work with something like that, unfortunately
@CSharp_Dev2022
@CSharp_Dev2022 2 жыл бұрын
Great Tutorial, Can you make a tutorial about unit testing and Mocking testing specifically
@MrBan001
@MrBan001 2 жыл бұрын
I would also like to see something like this. Maybe something how to create a clean test setup with DI. E.g. using an in memory DB during tests.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Yes!
@Krilllind
@Krilllind 2 жыл бұрын
I like the reflection one more, but it would introduce a longer startup time, something to think about if cold starts in your projects is important for you. In lambdas for example, reflection approach might not be for you.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
We can measure it, I'm sure it's not a significant performance impact.
@Krilllind
@Krilllind 2 жыл бұрын
Like you said, we can measure it but saying "I'm sure it's not a significant performance impact" is not accurate, performance is contextual. In a lambda web api for example hosted in AWS, cold starts can eat up as much as 400ms and reflection would not make it faster. So always measure before making assumptions.
@kurtnelle
@kurtnelle 2 жыл бұрын
Why not use public partial class and refactor them as individual functions? That way the class inside of Program.cs is spread amonst 50 or so files?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
I have a disdain for partial classes
@kurtnelle
@kurtnelle 2 жыл бұрын
@@MilanJovanovicTech I'm not surprised. But partial classes are what allow code behind.
@CyborgT800
@CyborgT800 2 жыл бұрын
Do you have GitHub code repo with the code sample shown in the video?
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
No, I share the code on my Patreon
@calinmarian2553
@calinmarian2553 2 жыл бұрын
Second method seems cool, but it can be cases when order if instantiation must be preserved
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
When is that important for services?
@calinmarian2553
@calinmarian2553 2 жыл бұрын
@@MilanJovanovicTech in our solution (clean architecture) we exposed dependency injection.cs class per project (web, application, infrastructure) to group required Injection. Then these are called in the web project (like services.AddApplicationServices(), or services.AddInfrastructure()). I think that we can use the second approach but we must keep track of the order of assemblies.
@krccmsitp2884
@krccmsitp2884 2 жыл бұрын
@@calinmarian2553 Maybe you could extend the IServiceInstaller with an "int Order { get; }" property?
@ProtectedClassTest
@ProtectedClassTest Жыл бұрын
We've implemented the first approach on project and now I think neither the 1st or 2nd approach is good. Its just adding another layer of complexity for very simple di statements. What I would do now is just create a single extension method and put all the di code there just so to cleanup the main file
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How would putting everything in a single extension method help?
@kamarchand
@kamarchand Жыл бұрын
Awesome
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thanks Kevin! :)
@andreymetkiy9052
@andreymetkiy9052 Жыл бұрын
Why don't you make the method return void when creating methods? It should work
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
To support chaining of method calls
@lemonade2345-j4e
@lemonade2345-j4e Ай бұрын
If you have created this extension method directly upon builder object, you wouldn't have to explicitly pass configuration options. As these would be accessible via this.Configuration property.
@MilanJovanovicTech
@MilanJovanovicTech Ай бұрын
It's not the standard way it's done in .NET, so I didn't go down that route
@lemonade2345-j4e
@lemonade2345-j4e Ай бұрын
@@MilanJovanovicTech I have not tried either, however this thought has occurred to me, so I decided to share it.
@ryoman76
@ryoman76 2 жыл бұрын
Great
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
Thanks
@nothingisreal6345
@nothingisreal6345 2 жыл бұрын
The reflection approach is a bad idea. Reflection is rule based. Rules must be resolved by other programmers / yourself. It comes in handy when initially creating the project but later when someone else has to maintain it, this person has to resolve that rule base approach, which can be an obstacle. If you write down in a reasonable way - do it. Grouping the service registrations can be an effective way to improve readability and testability (e.g. you can step over a function if you know it works). On the other hand, you need to navigate to more code files. But both approaches don't make the code more robust. So that is something I would consider doing when nothing else is left to do.
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
There are so many libraries out there that rely on reflection, saying that it's a bad idea is not so straightforward.
@b0ysb3
@b0ysb3 8 ай бұрын
Looks alot like nopcommerce approach, thank you for sharing tho.
@MilanJovanovicTech
@MilanJovanovicTech 8 ай бұрын
I've worked with Nop before
@Caldaron
@Caldaron 2 жыл бұрын
fuck yeah
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
🔥
@timur2887
@timur2887 9 ай бұрын
yet another enumeration through all of the types in an assembly with a filter...
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
Once at startup, fine by me
@kostiantynshyshkovskyi630
@kostiantynshyshkovskyi630 2 жыл бұрын
About the second one, I reckon we can run it easier. We have one interface and a lot of implementations, and in this case, we can have something like this IEnumarable and then have foreach to call all of them one by one 🙂 Of course, first of all, we have to register all the implementation)
@MilanJovanovicTech
@MilanJovanovicTech 2 жыл бұрын
That's assuming you want to register the implementations, but then the question is how do you resolve them before building the service provider
@techpc5453
@techpc5453 Жыл бұрын
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
🙌
@MilanJovanovicTech
@MilanJovanovicTech 4 ай бұрын
👋
Extremely FAST Caching Repository With Decorator Pattern in ASP.NET Core
15:21
Don't throw exceptions in C#. Do this instead
18:13
Nick Chapsas
Рет қаралды 264 М.
“Don’t stop the chances.”
00:44
ISSEI / いっせい
Рет қаралды 62 МЛН
Quilt Challenge, No Skills, Just Luck#Funnyfamily #Partygames #Funny
00:32
Family Games Media
Рет қаралды 55 МЛН
Dependency Injection in .NET Core (.NET 6)
1:00:32
IAmTimCorey
Рет қаралды 196 М.
How To Implement Validation With MediatR And FluentValidation
18:33
Milan Jovanović
Рет қаралды 48 М.
How To Organize Minimal API Endpoints Inside Of Clean Architecture
8:01
Milan Jovanović
Рет қаралды 45 М.
Why I Use The Unit of Work Pattern With EF Core | Clean Architecture
11:34
The Right Way To Build Async APIs in ASP.NET Core
20:12
Milan Jovanović
Рет қаралды 23 М.
Make Your Business Rules Cleaner With Fluent Validation
15:14
Milan Jovanović
Рет қаралды 31 М.
Clean Architecture Project Setup From Scratch With .NET 7
12:02
Milan Jovanović
Рет қаралды 139 М.
How to structure a .NET Solution (project separation & architecture)
13:55
Master Refresh Tokens in ASP.NET Core (building from scratch)
17:19
Milan Jovanović
Рет қаралды 11 М.