LongCut logo

Forget Controllers and Minimal APIs in .NET!

By Nick Chapsas

Summary

## Key takeaways - **REPR pattern: one class per endpoint**: Fast Endpoints nudges you toward the Request-Endpoint-Response pattern, replacing fat controllers with single-responsibility endpoint classes for cleaner vertical slicing. [02:46], [03:21] - **Performance beats controllers, matches minimal APIs**: The name is intentional: Fast Endpoints is fast to create and faster than controllers, while being on par with minimal APIs but with built-in structure. [01:44], [02:18] - **Two-line setup gets you running**: Registration is just builder.Services.AddFastEndpoints() plus app.UseFastEndpoints(), no controllers or MapGet/MapPost plumbing required. [02:17], [02:46] - **HandleAsync or ExecuteAsync, your style**: You can override HandleAsync to call Send*Async responses imperatively, or override ExecuteAsync to return typed responses like in traditional APIs. [03:52], [06:24] - **FluentValidation and mappers built in**: Fast Endpoints ships with native support for FluentValidation and request-to-domain mappers, so you skip wiring extra NuGet packages yourself. [09:28], [10:34] - **Discriminated unions for multiple result types**: Endpoints can return Results<T1, T2> unions like Created<MovieResponse> or BadRequest, enabling type-safe branching across success and failure shapes. [10:43], [12:30]

Topics Covered

  • Fast Endpoints: Speed And Structure Aren't Mutually Exclusive
  • One Class Per Endpoint Replaces Fat Controllers
  • Fast Endpoints Ships Validation And Mapping By Default
  • Vertical Slicing Lowers Per-Endpoint Cognitive Load

Full Transcript

hello everybody I'm Nick and in this video I'm going to show you how you can get started with building apis in net using the alternative to controllers and minimal apis and my personal favorite called Fast end points now fast end

points is something I talked about long time ago when minimal apis first came out but there been two doted releases almost three at this point since then and there's many things that have changed the project is more alive than

ever many many download and very widely used and it's actually still what I use to build my own rest apis so in this video I want to get you started with fast and points and explain how they

differ from controllers or minimal apis and why in my opinion you should be using them as always this is an open source Library so if you like what you see there's a link in the description down below give it a start on GitHub it

really really helps the Creator develop it even further now what is fast end points well as you can see here fast end points is a developer friendly alternative to minimal apis and MVC or

traditional controllers and all it does is it nudges you towards the reaper design pattern which is the request and point response pattern which is actually how I had structured my minimal apis

already before I moved into using fast and points the documentation for the tool is great I highly recommend you check it out if you have any further question that I don't cover in this video there's definitely going to be an

answer in the documentation now very quickly I want to show you what I have here I have a movies API that has everything but the endpoint functionality so we have a movie service where I can go ahead and validate create

update get and delete a movie we have some validators some validation failed objects and then we have this program.cs

that has all the registration except for the end points and we don't have any controllers we don't have any minimal apis and that's where fast and point comes in and by the way the name is

intentionally fast and points because not only is it fast to create but it's also very fast as in performance fast and points give you way better performance in the grand scheme of

things than controllers and they are on par with minimal apis but with the added benefit of allowing you to have some buil-in structure to your apis and not needing to have this map get map post

and map put methods and having to wonder where to put them so what I'm going to do is go in new get and add fast end points I'm going to add the latest version so let's go ahead and add that

and I'm going to add the basic registration which is first in the services I have to say Builder do services. add fast end points I'm not

services. add fast end points I'm not going to customize anything and then for the middleware I'm going to say app do use fast end points and that's it that's all the registration I need and then

because I'm sort of slicing this application in a vertical way I'm going to go in this movies folder and I'm going to create my first endpoint let's say to return all the movies in the system so what I'm going to do is I'm

going to say get movies endpoint and that's how I'm going to name my class and each class that I will have will represent an endpoint as opposed to a controller that can have all the end points in a single class here we have a

single responsibility approach approach where one thing does one job I'll go ahead and say that this Endo to become a fast endpoint is an end point without a request why is it an endpoint without a

request because the endpoint we're going to be calling is the movies Endo there is no query string parameter no rout parameter and No Object so it is an end

point with that request and then the response type is a movie's response and that's what goes in this T parameter and then I need to configure it so I'm going

to say override the configure method and I'm going to specify a couple of things first the route so that is a get end point which is on the movies path and

then I want to allow Anonymous access in terms of O for this endpoint and then to handle requests I have two ways uh the first one is to override the handle

method and what I end up with is something like this I have a hand lacing method that has a cancellation token and then can do all of my processing here and because I don't have a request I

don't have an object to grab here you still have access to the HTTP context as a parameter because you extend this endpoint with that request class but I'm not going to use that all I'm going to

say is that I need a private read only IM movie service I'm going to inject it from The Constructor and then I'll go ahead and have my implementation since I'm getting all the movies all I'm going

to say is movies equals await movies service do get all async so a syn processing and then I'm going to create the response I'm going to say movies.

map to response and then I'm going to say I'm not going to return anything because this is just a generic task I'm going to say await send and now I can

choose any type of request or response I want to send so I have okay string file forbidden headers I can send anything I'm going to say send okay because I'm getting a collection and then I'm going

to say response and the response is that object and then I can also pass down the cancellation token and that is it and that's all I need to get started I'm going to go ahead and just run it and as

you're going to see I'll go to insomnia now my API is running and I'm going to get all movies in the system and as you're going to see I'm getting them and it's an empty collection because I have no movies if I stick a break point this

is all debuggable so I can go ahead here say send and I'm coming in here can go to the service get the request and then map it now I totally get if you don't like this approach of just sending

something and writing it but not really returning it and there is an alternative here for fast end points instead of doing a handle Ayn I'm going to just comment it out in case you want to grab

the code from the description down below I'm going to say override execute async and in this case now we grab that response object and we have it in the

response of that task and now same thing as before but instead of just writing it we can say return that and by default this will now say that this is okay of

course if you had to write not found there's a different way to handle that and we're going to see it when we Implement get by ID or slug but same behavior I'm going to put a break point here going to go back to insomnia call

that end point and as you're going to see same thing and we get the exact same behavior we have 200 and an empty collection now before I move on I'd like to let you know that after incredible

demand we just launched our very first Blazer course on dome train called getting started with blazer and it's an incredible 7-hour course introduction into Blazer by Jimmy egrom now Jimmy has

been using blazer from the very beginning using production he's written a book about it he's an MVP about it he has given International talks about it so he's one of the best people in the world to teach Blazer Blazer has

undergone lots of change since it released and it's widely used by Microsoft and other companies including things like net Aspire the dashboard is fully built in Blazer so it's not going anywhere but it has changed quite a bit

since it's launched so if you have previous knowledge on it it's probably outdated this is the best most upto-date course to get started with Blazer and in 7 hours you going to learn lots of things so this is not just an

introductory course you will be able to build Blazer applications after you take it I'm going to put a link in the description and the first for of you can use discount code GS Blazer 20 to get 20% off a checkout now back to the video

so great first and point out of the way now I'm going to duplicate that and I'm going to say get movie endpoint and I'm going to implement to get movie end point to just get a single movie and in

this case I do have something for the request it is a route parameter because my endpoint will be this and then the parameter is ID or Slug and if I want

that to be mapped what I could do is I could say end point and then I can say record get movie request and pass down a

parameter ID or Slug and if I was to do that then I would be able to say here's my endpoint pass this parameter and then update this method to accept this as a

parameter so request goes here then cancellation token and then the rest is history same thing as before but I don't have to create and allocate an entire object over here and waste this memory

what I could do is just say endpoint without request so same thing and then down here what I can say is get

me and just delete all that get me the ID or slug from the route so I can access the route parameter I can say the

route parameter is a string and the name is ID or slag and that will get it automatically from the route then all I have to do and let me just turn this into a handl sync then all I have to do

is check if this is null and if it is I'm going to send a note found the 404 because nothing will match an empty ID or an empty slug then I will try to pause it as a good and if it is a good

I'm going to get it by ID otherwise by Slug and then in the end if the result is null I'm going to return nothing otherwise I'm going to say send okaya sync and send the result and the

cancellation token and I will need to map that to response a response object here we go and I can just simply delete that now I'm not using the execute async

here to return either an okay or a not found we'll see how we can do that in the created but I also want to show you how you can use handle and send now two things about fast and points if we go in

new get you'll see that in terms of dependencies we're going to get fluent validation by default in Fast and points that's because you can actually have

validation natively in Fast and points and all you need to do is create a validation class with the type of the request that's coming in so if I create

a validation class with generic type create movie result then all the logic will be automatically processed without me having to do anything when that request is coming in and then map it to

whatever we decide same goes with the mapper we can have native support as you can see over here request mapper we can make a request mapper for f points and

map from a contract to a domain object and vice versa very very handy there is documentation about it I don't want to go too deep this is more of an introduction but I want to make you aware these two are handled natively and

it's a Time Saver because you don't have to add many packages and have to worry about how everything is wired fast and points will will do it for you and will do it very very efficiently that's why

it's so fast now the last thing I want to create is the create movie endpoint the movie that allows me to create that movie and this will be a bit different we'll have an endpoint that accepts a

create movie request so we have our dto but the response will be of type results and those results can be two things it

can either be a created with a movie response or so we have a bit of a discriminated Union here or a bad request and that's about it and now I

can go and configure it same thing as before of course in this case it's a post so post movies allow Anonymous we're going to have to inject that I

movie service here we go and then use it in in this case I'm going to use the execute async method so I can have that return type so execute asyn we return

results of these two types so the only types I can return is either created the movie or a bad request first I'm going to get the request and map it to my internal Domain movie Object then I'm

going to send it to my service and this service is returning as you can see over here a result object so either movie succeeded or validation failed this is domain level validation it's not

endpoint level validation that's why it is here and then I'm going to map that request by using the match method on the result object to say that if it is a good request then map it to a created

object if it is a bad request then map it to a bad request response based on the validation failed object this is not the only way to do this in fact fast and

points has this add error method allows you to add an error or a message or the validation failed object in your response but in our case we don't need it so all we're going to say is return

response and then we can use a simple switch expression here to map it from one object to another so created movie Return that bad request return that otherwise it should be impossible so I

am going to say impossible ideally don't do this handle it properly I'm just showing you an example here and we have our create end point so what I can do now is I can go and just simply say run

my API and then I will go over here and the first thing I'm going to do is check on all the movies I have nothing then I'm going to say get a single movie by ID doesn't exist not found then create a

movie the movie I'm going to create is Nick the Greek the classic comedy of 2020 and then send that the movie has been created it's all in memory and then I'm going to get that ID try to get that

movie and as you're going to see it will all work fine if I had a mistake here then it's not going to work fine and if I used the slug to retrieve it this also

works so if I do that then that all works too and I can return everything it's extremely easy extremely productive so efficiently so performant again faster than controllers equally as fast

as minimal apis and you're getting so so many features by default and I really like that in my verticals I can have this single end point and that's about it I don't have to worry about cognitive load and what else might be in this

class and I also don't have to worry about what else can be injected in this class that is not used by every single endpoint now this is just scraping the surface you have Swagger support you have pre-processors postprocessors

pipelines you can do so so much with fast and points so again if you like fast and points link the documentation and give it to S GitHub I think it's an excellent project but now one from you

what do you think about this project and are you using any other alternative leave a comment down below let me know well that's all I had for you for this video thank you very much for watching and as always keep coding

Loading...

Loading video analysis...