Make Your ASP.NET Core API Controllers Incredibly Simple

  Рет қаралды 24,152

Milan Jovanović

Milan Jovanović

Күн бұрын

Пікірлер: 127
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@naldiojoaquim8920
@naldiojoaquim8920 Жыл бұрын
Why do you not create any Course about c#?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@naldiojoaquim8920 Still too early to do that, in my opinion :)
@nayanchoudhary4353
@nayanchoudhary4353 Жыл бұрын
Definitely clean, but harder to understand for average developers. I would prefer somewhat balanced simplicity.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I'd say a quick explanation will get anyone up to speed
@cwevers
@cwevers Жыл бұрын
I agree. Also about the same amount of lines in the controller but more complex and rigid.
@marcinzit
@marcinzit Жыл бұрын
Couldn't agree more. I'd be annoying to keep explaining to new people in the project the meaning of this obfuscated code. I would pick a bit more lines of clear code over shorter, but much more complex version every time.
@bozin3
@bozin3 Жыл бұрын
The point is to understand the code without explanation. This is hard to read especially for begginers and interns even for mid developers. I still prefer the first version of the code.
@itzW3LF
@itzW3LF Жыл бұрын
That's just because Monads and FP in general are almost always ignored when learning programming. There's nothing intrinsically hard to understand about this approach (albeit monads can be tricky to grasp), you just need to get familiar with it like with everything else
@ewkdev
@ewkdev Жыл бұрын
While this is nice looking and certainly functional, i think it's not a major improvement over the controller code you showed at the start of this video. Imo, the original version does comunicate intent way better than the new version does (specifically the bind portion is something that someone looking at this code for the first time will have to investigate before they are able to understand what is actually happening). Having the match function to decide on a handler to call given a certain result type ( success vs. failure) is nice, but i would personally leave it at that and keep the rest of the code as it was. Anyways: Thanks for showing of the more functional approch, definitely an intersting way to do it !
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I think if more people talked about FP it wouldn't be so confusing to people. But Bind is a straightforward concept, as is anything in FP honestly
@Defcon8Rolex
@Defcon8Rolex Жыл бұрын
How do you know that linq Where returns a filtered list? Because you're used to it. Same with bind and match
@GregRichardson-n6d
@GregRichardson-n6d Жыл бұрын
Looks nice and fancy afterwards, but by wrapping everything in static extension methods I would argue it is harder to read, debug and unit test. The original way was clean, simple, effective and easily tested.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Tell me you've never done functional programming before
@Cruize91
@Cruize91 Жыл бұрын
@@MilanJovanovicTech dude, I'd love to follow your content, but this response is disappointing. It's just a bit childish and unconstructive.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@Cruize91 Why is it rude? The main critics of this video (and any video I create about functional programming) are people who don't do any FP. They see everything through an OOP lens, and can't admit that pure functional code cam indeed be clean, simple, effective, and easily tested. Oh, and don't judge a person based on one comment... 😅
@Cruize91
@Cruize91 Жыл бұрын
​@@MilanJovanovicTech I didn't judge your person at all. I criticized the response. Secondly, you're putting words in my mouth. I didn't say 'rude'. You have two commenters here who are genuinely trying to interact with you and your content. The first comment was simply a voice of not understanding. You could've handled that so much better by replying with a friendly stock answer, if this is something that occurs so often. Secondly, I'm simply stating that I disagree with this kind of response, because aren't we here to learn? A guy comments with some genuine concerns, so it's a chance to educate nicely. I'm not saying this to scold you, I'm just saying that I like your content, and would like to keep following it, but this kind of behavior is gonna turn me away.
@morganskinner3863
@morganskinner3863 Жыл бұрын
We have been discussing this very thing at work and I really like your solution here. I’ve a feeling we will be using exactly this in our controllers from now on. Thanks for the video, it’s excellent!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Check out the OneOf library, it has this built in
@mohsinazamafridi8566
@mohsinazamafridi8566 Жыл бұрын
Milan Nice Explanation. One Suggestion , like you're using already created project for Video. I think it's hard for viewers to understand when you start coding in already created classes etc. I think it will be good if you demo it in sample small project. it will be easy to understand. :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I don't really have the luxury of going over a project from scratch in every video, since they would be too long and people would lose interest. :/
@itzW3LF
@itzW3LF Жыл бұрын
Man I'm so glad I took a functional programming course last semester at my Uni, monads are so awesome!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Man, I wish they taught FP in my uni when I studied 😂
@VladyslavHorbachov
@VladyslavHorbachov Жыл бұрын
I would prefer to have the old version for 3 reasons: easy to read, easy to debug, looks native.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Only because most people are not used to FP style code. Otherwise, this is also easy to read, and if anything it's even easier to read, since it follows a very natural flow from step to the other.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@michbushi Try a little rxjs or Reactive Extensions for .NET then come back to this. It's a mindset shift.
@shadowsir
@shadowsir Жыл бұрын
You've created a Result monad. This comes out of the box in most functional languages. It's such a round-about way of doing it in C# that I usually just don't bother writing all of the "extra code to make it more F#'y". The Result class makes it possible to make a distinction between an expected (validation / domain) error and an actual unexpected exception (e.g. the database is down or we accidently introduced a bug).
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I find it worthwhile going through the trouble, since I'm a fan of FP in C#
@shadowsir
@shadowsir Жыл бұрын
@@MilanJovanovicTech fair enough.
@topx777
@topx777 Жыл бұрын
Amazing content! You’re always surprise me with very useful content, thanks!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Happy to hear that!
@kodindoyannick5328
@kodindoyannick5328 8 ай бұрын
Super content. Thank you!, Milan
@MilanJovanovicTech
@MilanJovanovicTech 8 ай бұрын
You're welcome!
@ramytawfik9168
@ramytawfik9168 Жыл бұрын
Can you make a series on functional programming important concepts Milan ?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I just recorded one more about ROP, releasing in a few weeks
@ramytawfik9168
@ramytawfik9168 Жыл бұрын
@@MilanJovanovicTech Thanks very much for all your effort
@kopilkaiser8991
@kopilkaiser8991 Ай бұрын
Thank you for providing such a great content. I found it very useful and helpful 😊
@MilanJovanovicTech
@MilanJovanovicTech Ай бұрын
You're welcome!
@cyrilw1
@cyrilw1 Жыл бұрын
Great job Milan. Would be great to see a GraphQL video soon
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's on my learning list, since I didn't work with GraphQL before
@user-rp9iis1en6h
@user-rp9iis1en6h Жыл бұрын
Please make a video on how to implement identity server with role based auth + how to check the role conditionally in a common/shared method
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I was thinking of covering some other IDP actually
@javidibra6786
@javidibra6786 7 ай бұрын
Man your contents are just amazing.keep it up. good luck!
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
Thanks, will do!
@branislavpetrovic7486
@branislavpetrovic7486 Жыл бұрын
Great idea for refactoring! Could you make a introduction video on monads and discriminated unions in C#?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I think Zoran Horvat is much more adept to talk about those subjects, but I'll give it a try why not 😁
@vitek0585
@vitek0585 Жыл бұрын
I prefer fluent way as well, but performance has to be taken into consideration if it’s a priority 🚀
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Always appreciate an FP fan :)
@arthurfedotiew3609
@arthurfedotiew3609 Жыл бұрын
@MilanJovanovicTech, that is a super clean and easy to read design, thanks for your great ideas and inspirations. Don't pay to much attention to ones who say it's complex and unreadable. Even for average mind as mine it is quite straightforward (even given I have started to learn c# dotnet a few month ago). I could only think of better name for Bind, like Execute, but probably you have some convention as I see you always do in dotnet)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I have a few more videos on ROP, so if you're up for it check them out: - kzbin.info/www/bejne/mnXEpHSjpNx5qtU - kzbin.info/www/bejne/sKbcY51uq92aj8U - kzbin.info/www/bejne/rHjOmKaaqtyhmZY
@delegatethings
@delegatethings Жыл бұрын
Thanks for this content. Any suggestions on how to learn FP please tell us.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Practice FP daily :)
@delegatethings
@delegatethings Жыл бұрын
@@MilanJovanovicTech any articles?
@unskeptable
@unskeptable Жыл бұрын
I would prefer the first approach as well . Just keep it simple.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's fair 😁
@jbb4play
@jbb4play Жыл бұрын
On a side note, what is the benefit of using that pattern, is it simply to adhere to the "Clean architecture setup"? Performance wise, how is this better/worse than simply having some interface IService with method DoSomething(), and then injecting that service into the application? Of course I think the way you do it in this video is nice, but it also requires a little more boilerplate to get running. And lastly, thanks for the videos, I love them :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Performance wise it's slightly worse, because of more allocations and method calls. But FP is very nice to work with, although it takes some time getting used to. The end result is the same. I'm just trying to raise awareness about FP.
@kebbbek
@kebbbek Жыл бұрын
I think that instead of creating additional abstraction with those Bind and Match methods it could be simplified just by not going back to the controller with IsFailure, Value, Errors properties, instead returning the actual result (value) from the query and just a Task from command, and if there is a validation/business logic error - just thrown an exception with proper context and handle it to returned desired code & message in this way in the controller it would be just a 2 liner: public async Task UpdateMember(Guid id, [FromBody] UpdateMemberRequest request, CancellationToken cancellationToken) { await Sender.Send(request); return NoContent(); }
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Why would I have a Result object then - which is expressive - and obscure it with throwing an exception somewhere in the code?
@kebbbek
@kebbbek Жыл бұрын
@@MilanJovanovicTech let's assume that you send a command that violates some business rules that are checked in the domain layer, in this approach instead of throwing an exception, you have to pass information up from the domain layer about whether it failed or not, thus coupling domain, application and presentation layers by branching the 'IsFailure' property
@S3Kglitches
@S3Kglitches Жыл бұрын
How do you not have to write authentication scheme on the controller function? Which one is picked as default? If you only have one active, will it be picked as default?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You can place it on controller level
@S3Kglitches
@S3Kglitches Жыл бұрын
@@MilanJovanovicTech ah, I missed that!
@faximori
@faximori Жыл бұрын
We receive REST payload object to create another request inside controller and process it somewhere else? Well... It's far better to encapsulate logic in minimal API or FastEndpoints than using another layer.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
One is external (public) to the API, the other is internal to your application
@Scifer
@Scifer Жыл бұрын
Nice video! Btw, what's the name of you VS theme?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
ReSharper's dark theme
@hamitkarahan2973
@hamitkarahan2973 Жыл бұрын
Hi Milan, nice and efficient work, thanks for sharing it! I see you are using CancellationToken parameter in your Post Methods. I heard that we should not be using CancellationToken in our Post Methods because of in case of cancel there may be an inconsistency in the data as a result of the process being interrupted. What do you think about this?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
If you have one DB transaction it'll be fine
@Defcon8Rolex
@Defcon8Rolex Жыл бұрын
Hello Milan, Love the content. What do you think about LanguageExt library? Have you thought about doing a video on that?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I think it's great, although I didn't use it before
@hysapod
@hysapod 10 ай бұрын
Hvala puno na lekciji! Chao iz Rusije.
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
Нема на чему! :)
@rohit704
@rohit704 Жыл бұрын
Can you please make some videos on aws cloud formation + azure pipeline using .Net core , Wanted detail video how API triggers lambda through cloud formation.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's a very specific topic, I'll think about it
@MB-Kajtech
@MB-Kajtech Жыл бұрын
Love this with the ErrorOr library, have something very similar in place currently. In my opinion throwing Exceptions for errors which are expected (we know about) is logically incoherent since they are not exceptional in nature. What's your take on Errors vs Exceptions?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I'm on the Errors side
@vivekkaushik9508
@vivekkaushik9508 Жыл бұрын
Hi Milan. As much as I love the extension methods and the flexibility and clean code practices they bring to the codebase I'm skeptical of their impact on performance/memory. Static classes gets instantiated as soon as the application starts and they live in heap memory throughout application's lifetime. I'm not sure if using too many static classes/methods is going to have a significant impact on application's performance as it will cause frequent GC triggers? Correct me if I'm wrong please. Thankyou.
@krccmsitp2884
@krccmsitp2884 Жыл бұрын
Static classes get never instantiated, since no objects are created thereby.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
We have bigger problems to solve than a few extra allocations/method calls
@vivekkaushik9508
@vivekkaushik9508 Жыл бұрын
@@krccmsitp2884 But they live in heap memory forever. Sorry used the incorrect term 'instantiation'. One can say intilization I guess?
@vivekkaushik9508
@vivekkaushik9508 Жыл бұрын
@@MilanJovanovicTech That's where Nick and you might differ I guess. But I agree most clients are either unaware of or simply don't care about memory efficiency and performance. They just want working solution with minimal overhead.
@krccmsitp2884
@krccmsitp2884 Жыл бұрын
@@vivekkaushik9508 there's no heap allocation involved with static classes since there's no memory consumption necessary.
@YuriWithowsky
@YuriWithowsky Жыл бұрын
Hello Millan! Thanks for the great new video! I always share your videos with my friends in Brazil :) So I have a question, what do you think about adding a mapper from your DTO to Commands/Queries? like AutoMapper. I think your controller will have less lines of code, is that a good idea?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I prefer keeping it light on the mappers, and just call constructors directly. And if I do use mapper, I use a dynamic one like Maspter
@pilotboba
@pilotboba Жыл бұрын
Prefer/try explicit (or implicit) operators to your DTOs to do the mapping. Yes, you have to write the mapping code yourself, but that's a good thing, especially when it comes to static analysis and debugging.
Жыл бұрын
You can try mapperly, it uses source generators to create static mapping. So at any point you can remove it, and keep the code. It also does not hide references behind reflection. Drawback is that it does not support everything that Mapster does, ex. projections.
@charles_kuperus
@charles_kuperus Жыл бұрын
Wow nice method. I would love to see this on minimal API's of dotnet
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It would be pretty cool indeed 😁
@zameer.vighio
@zameer.vighio Жыл бұрын
Good work, every video we enjoy and learn something new & interesting, but what if think about time complexity, we usually try to make our codes more simple making reops or like this stuff, but is it suitable way keeping DATA-STRUCTURE/ALGORITHMS/TIME-COMPLEXITY/ in mind.... please guide. Thanks.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You'll find that such optimizations are negligible for most applications
@zameer.vighio
@zameer.vighio Жыл бұрын
@@MilanJovanovicTech yup That's also point... Well thanks buddy
@krccmsitp2884
@krccmsitp2884 Жыл бұрын
I like it. 🙂
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Sweet!
@marklnz
@marklnz Жыл бұрын
Interesting approach, but I wonder why go to all this trouble when you'd be able to achieve arguably a similar result using Minimal APIs. Also you really should have validation in there somewhere...
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Spreading awareness about FP :)
@marklnz
@marklnz Жыл бұрын
@@MilanJovanovicTech fair enough. Could do the same with minimal as well tho 😉
@kabal911
@kabal911 Жыл бұрын
I don’t see how any of the code in a minimal api would be different/simpler at all. You would just be using Results.* instead of ActionResult. The body of a minimal API and a controller action are identical, they are functions
@gardnerjens
@gardnerjens Жыл бұрын
that is selectmany right?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
What is?
@gardnerjens
@gardnerjens Жыл бұрын
@@MilanJovanovicTech bind i think is the same as .SelectMany, also i think if you name it that insted of bind you can use the "from" "in" keywords
@fieryscorpion
@fieryscorpion Жыл бұрын
This is just way too complicated, my goodness.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Where's the complexity though?
@nove1398
@nove1398 Жыл бұрын
Nice thumbnail haha
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Glad I'm finally getting better at making them 😁
@RonyCuzco
@RonyCuzco Жыл бұрын
Why use fp over oop?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Because FP is simply awesome
@S3Kglitches
@S3Kglitches Жыл бұрын
@@MilanJovanovicTech That's not a good reason.
@ucretsiztakipci6612
@ucretsiztakipci6612 Жыл бұрын
Does not extendable for other requirements.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
FP is much MORE extendable than OOP - just add another function :)
@ucretsiztakipci6612
@ucretsiztakipci6612 Жыл бұрын
@@MilanJovanovicTech No it is not. Sctricly Typed languages are horrible for the FP!
@alukardishe
@alukardishe Жыл бұрын
Readable and understanding vs thin controller. And you failed I think) But you show me interesting solution
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Why would you say I failed?
@Wfmike
@Wfmike Жыл бұрын
That looks similar to the oneof lib
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It's called a Monad, and it's a concept from FP. That's why it looks similar
@MortvmMM
@MortvmMM Жыл бұрын
I wished before the video that its not MediatR. Not that I don't like it, just hoped for something new
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Haha, sorry to disappoint! 🤣
@MortvmMM
@MortvmMM Жыл бұрын
@@MilanJovanovicTech don't worry 😂 it's not your fault they didn't come up with something better yet
Don't Use Polly in .NET Directly. Use this instead!
14:58
Nick Chapsas
Рет қаралды 68 М.
Sigma baby, you've conquered soap! 😲😮‍💨 LeoNata family #shorts
00:37
啊?就这么水灵灵的穿上了?
00:18
一航1
Рет қаралды 94 МЛН
CAN YOU DO THIS ?
00:23
STORROR
Рет қаралды 41 МЛН
Use These 4 Best Practices For Your .NET Project Setup
10:10
Milan Jovanović
Рет қаралды 41 М.
Brutally honest advice for new .NET Web Developers
7:19
Ed Andersen
Рет қаралды 229 М.
JWT авторизация. Основы JWT - механизма.
6:45
Хочу вАйти
Рет қаралды 13 М.
Should I Create A Minimal API Or Full API?
7:40
IAmTimCorey
Рет қаралды 38 М.
CQRS & MediatR in a .NET 8 Web API 🚀
22:00
Patrick God
Рет қаралды 12 М.
Swagger is Gone in .NET 9! Replace It With This.
9:34
Nick Chapsas
Рет қаралды 60 М.
.NET 7  💥  - Integrate OpenAI ChatGPT with Web API
34:50
Mohamad Lawand
Рет қаралды 17 М.
3 .NET "Best Practices" I Changed My Mind About
10:16
Nick Chapsas
Рет қаралды 104 М.
The Logging Everyone Should Be Using in .NET
15:34
Nick Chapsas
Рет қаралды 77 М.
Sigma baby, you've conquered soap! 😲😮‍💨 LeoNata family #shorts
00:37