CRUD with React, Typescript & .NET 8 Web API, EF Core, SQLite

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello guys my name is remik and in today's very long video that you'll actually need the cup of coffee to complete this video at once we'll create the net 8 web API together with fluent validation cqs pattern mapping with mapster uh and also the global exception handling that will have the approach of the net 8 and also the react together with typescript site we'll display the list of movies we'll create those movies we update them and also will be able to delete them and uh it will be the full complete web application so if you like this video then please hit the Subscribe button like button and now we are going straight into the uh demo section that I will show you what we'll actually build all right guys so as I have said we have the list of the movies displayed in the table in our react front end uh application we have the title description created date category and also actions that we can perform on the certain movie we can edit uh the movie we can delete uh the certain movie and also create new one I can just create the new one so it will be the movie 4 desk 4 and also category 4 so we are uh now we were navigated to the create movie form that is actually uh the same form that we are using also for editing the certain movie uh we can submit and now as you see we have created the new movie and this is uh this movie is in our database so this is with the call to the API by the Swagger we can just see that we have four methods so we can get all the movies get only certain one that is used for instance right now so we are getting the movie with the ID of 17 we can uh edit this movie with the ID of 17 and also delete so uh as you see see we can just we can just simulate the error I have the validation that category cannot be longer than 30 characters so I'll just inspect so I'll just inspect my page so in the console when we submit as you see we have the 400 bad request from our uh API movies sl7 uh from the put uh request and as you see we have the uh exus error and inside we have the property category and also the category cannot be longer than 30 characters so it's coming from our a API uh by uh the axus Interceptor so we will create the also Interceptor for all the errors uh that uh will get uh potentially from our uh API and we can delete the certain movie and this is refreshed view so as you see everything uh here is displayed correctly after delete statement as well all right so we'll start with the creation of the new net8 web API project so I'll just create the project name it will be the movies. presentation the solution name will be just movies the project name I have to change will be movies presentation solution directory I'll just assign to apps create git repository web API and we'll just hit create all right as you see we have already the presentation uh so our web fpi itself so we will just remove everything that is not needed as you see we have uh some sort of the the basic one we forecast method that for sure is well known for you so we'll just remove those summaries and also this this end point that is from the minimal API just remove this the forecast of the we from the Microsoft this as well all those comments all right guys so we would like to create now uh many different projects just to have our net web application to be separated to be independent to not depend on the certain classes but on the abstractions that we can then uh reuse and change uh to something else uh that we'll need in the future so we'll need uh the couple different projects so it will be the infrastructure domain contracts and also the application projects so I just quickly create those projects so just add new project it will be the the class library and we will call this movies do application in this movies. application will'll uh have all the cqrs uh cqs classes so it will be the queries to our database and also the commands to our database also the mappings and also the validators from the fluent validation so this is important to have this uh layer created uh in your solution we'll create another another one so it will be the infrastructure so everything that is needed for uh our Entity framework core uh to be properly configured so the migrations the uh the snapshot as well of our DB context and DB context as well so it will be the movies.in infra infrastructure we delete the this sample class we create as well the movies movies. domain so everything that is based on our domain so related uh movie entities so we'll create this here to keep our database entities and and also the last one will be the movies. contracts in this project actually we'll keep all the responses the requests that our react application uh will uh will send and will just get from our API and as well we'll keep here the exceptions uh that will be handled by our Global exception middleware so I'll remove as well the first class and we will be ready to go all right guys now we are going to set up the connection to our SQL light database because in this video we are going to use the SQL light as the database provider and uh we'll use D framework core to connect uh with this database so we need a couple of nuggets to installed in our presentation and in our infrastructure project so we'll just start with the uh manage nugget packages and we'll install uh following nugget packages so ntity framework core so this first one we have to install have to install as well the anti [Music] framework SQL light related nugget package so it will be this one and also the Entity framework design nugget package so install in the mov movies. presentation project and we have to install as well the design in our infrastructure project where we'll store our uh DB context so or install this one as well here we need Entity framework core the normal one we're going to use also the tools so core. tools and also the relational so anti framework. relational nugget pckage so I'll install this as well infrastructure and we will be done with nugget installation so we need to create our first class so it will be the movies DB context and we have to inherit from the DB DB context class from Ed framework core so do this like that now we have to create the Constructor for the movies DB context and we'll have to pass the DB context options called as options and call the base Constructor and pass those options there and now now we have to declare the DB set so the uh the tables that we will have uh to create uh in our database so we have to uh get some certain entities uh for DB context to create those tables so in our domain project we have to create the directory called entities and in this directory we'll create the first class that will be abstract one so the base entity entity will be that kind of the class and we will create the public int ID get set and also the public dat time date time create date and we will create the movie. Cs file finally and we'll inherit from the base entity so this base entity actually can be accessed uh by many other entities that we can create here if we'll just enrich our uh API with another models so we can just inherit from this and will not have to declare once again the uh ID uh of the entity and also the create date so we'll just have everything in this base entity and for the movie itself we'll have the public string title Public public string description and also we'll have the public rink category and we can go back to our DB context and we can just declare public DB set of the movie movie and movie we have to uh reference the project of the domain of course yes and we'll call this movies so this is it will be the name of the table that will be created by The Entity framework core okay now we can go to our program CS in our movies. presentation in our web API and we can set up the Entity framework core together with the SQL light so we'll just write builder. services do add DB content and we have to pass here the movies DP context and of course to add the reference to it from our web API so it will be the movies. infrastructure reference and we'll pass here the options and to just write opt do use SQL light and we have to pass the the DB connection string that we will set uh just in a moment so the Builder configuration. get connection string so in that case we'll get the specific section of the connection strings from our upsetting Json configuration file and the name will be DB connection string like that and we have to go to our up settings Json file add the specific section called connection strings and now it will be the DB connection string DB connection string and it will be called data source it will be equal to movies. DB so this is it will be the file uh of our SQL light database and now we are ready to create our first migration so in order to create the migration to create for us the database with this movie uh entity and to create the table called to movies we have to pass two commands in our command line so we'll just write here net EF migrations migrations at and he uh here we will have the name so it will be in it so the initial uh one we have to specify with the flag of s the the place where we have our web API so it will be the movies movies. presentation and with the flag of P we have to pass the place where we have uh our our movie D context so it will be the movies do infrastructure feel started and succeeded as you see we have the migrations folder that was created for us so we have this init file so as you see this is the this is the create table statement for for our database just to be created so we have this ID title description category and the create date and we have the primary key for the ID as it always uh is being done by the database engines just to have the the primary key as the ID and here we have also the down methods just to drop this table so just to uh undo do this specific migration here we have also the DB context snapshot so we'll have everything over there what actually our DB context uh representation is so we have this init file and model snapshot and now just to apply this migration we have to pass another uh another Comm another command so it will be the it will be the as well net EF database a database update we have to pass as well the with the flag s where we have our web API so it will be the movies. presentation and with the flag P it will be the movies. infrastructure where we have our DP context as you see builds started I I haven't written this properly so data base update once again and as you see the create table movie statement was performed correctly and actually it executed in our database and we have this movie movies DB here uh I can just connect to it and as you see we have the movies database with the four tables migration history site Master sequence and also the movies and as you see we have nothing there but but we have all of these five properties in our movies table already now we can talk about cqrs pattern and how to set up this in our project so cqrs pattern that is used with the mediator so this is the way of handling the request and the responses with the only one centralized point so the dependencies they don't know about each other uh it's only the one point to handle the request so just to briefly show you so we have the request color this request goes to the mediator one point this mediator only knows so it's like the secretary in the company she only knows where to pass my request to to which person then it goes to the Handler and this Handler then passes the request to the database uh with the usage of the DB context uh that we have just set up and then it goes to the DB and then we have the response back to the request request caller so uh this is the media Ator part and also we will just separate so the cqrs will just separate the commands with the queries so the command so this is everything that we that we write to to the database so we create we update and also we delete some sort of entities and the queries so just get get get movie by ID or get all of the movies so it will be completely separated so now have to install the specific mediator uh nugget packages so in the presentation we have the mediator mediator nugget package we can use we'll just install in the presentation part and in the application where all our handlers our commands queries will be started we will have to as well install the same nugget package together with that nugget package called contracts all right now we can create two directories in our application project so it will be the first one called commands that I have just explained you what is this all about and also the queries and now we'll create full directories called movies and also the movies because we can extend this this project just to not only handle the movies but as well something else so we'll just create two directories called movies and now the first one will be create movie update movie and also to delete movie and in query section we'll have the get movies and also get movie by ID that will be used by our by our movie form in the react it will be by ID and now we'll just create the specific query for getting the movies so we have to create the get movies query and it will be the type of the record public record get this query and have to inherit from the I request request from the mediator nugget and here we have to return some kind of the response so in that case I'll just return the get movies response but we don't have this get movies respon created yet so we have to go to this contracts project and we will'll add One Directory called responses and also just for the future requests and the responses it will be the get movies response will be the SW type of the record so it will be immutable and it will be the list of movie dto that we have just to create movie dto so it will be the representation of our movie entity so we'll just create another directory called dto and it will be called movie movie dto Cs and as you remember we had the integer ID we had the string string title ring description date time create date and also the string category is the representation of our movie entity from our database so now we can reference the project of the contracts and in get movies we have also to patch this movie dto from the contract itself and now we have our first query so we can create as well the Handler just to handle this get request to retrieve all the movies from our database so it will be the get movies where Handler inherit from I request Handler as you see so we have to pass the request so it will be the get movies Sor and we'll return the get movies response we'll just Implement missing members as you see we have the handle method so we have to create the Constructor for it and use our DB context here so movies DB context reference project of the infrastructure mov DP context we introduce the WR only field now we can retrieve all the movies from our database so it will be await movies DP context movies do to list asnc and we will pass the canellation token just in case here and as you see we have the list of movies so we don't have even the list of the movie dto but we have the list of movie We would like just to have this wrapped into the get movies response that will be then retrieved from our react react uh request caller so uh we can do this manually here just to have multiple lines or we can set up at once the mapster and the mapping configuration and have this done in only one line so we'll just go and manage nugget packages in our application project and we'll add the two mapster nugget packages so it will be the first one so the normal mobster and also we install not the pre-release but normal version of the uh mster do dependency injection we install I'll install two of them here and we'll create separated directory called map pinks and will create the mapping config CS okay and now we have to create the public static for configure method and now we have to map from the movie up to the get movie mov response and also the movie to get movie by ID response at once so we'll just write the type adapter config and we will pass the as you remember list of movie and it has to be mapped to the get movies response so we'll just type new config and then we have to map the test to the destination will be the movie DTS from The Source called source so the so the destination of the movie DS will be the same as you have here in the movie so it will be mapped properly to the get movies response now we can create the dependency injection docs class where we can uh configure our mobster and also the mediator so dependency objection. CS it will be the static class and it will be the public static I service collection and it will be called at application and this is the extension method so this I service collection services and now now we have to we have to add our mapping config so mapping config do configure then for config it will be the type adapter config do global settings then we have to configure the scan so it will be the scan method with the from this assembly so from this project and then services at Singleton our our config for the mapping so it will be this have to return of course the services and also we can set up the essential mediator method so it will be the services at mediator configuration and we can just type register services from assembly so from this project get executing assembly so as you see it will just register various handlers from this assembly so each Handler that we can uh here configure uh in our application project so now we are back in our handle method of the get mov query Handler class and now as you see we can just return movies dot adapt and it will be the get movies response and we'll be safe we'll have the get movies response properly mapped in that case as you see this ad application is not used anywhere so we have to go to the program Cs and write following statement so the Builder services at application so we have to reference the project of the movies. application and now we see that it will be registered properly so the mediator of the all handlers and also the the mapping config of the mapster now as we have our get movies query and query Handler uh properly written so now we can go to the get movie by ID and do the same for it so we'll just write get movie by ID query yes and it will be the record so we'll just write here int ID because we'll pass the specific ID of the movie just to get this resarch from the database and we will have to inherit from uh as before from the I request and now once again get movie by ID response so we haven't created it yet so we have to go to to our contracts project and create the response as this so it will be get movie by ID response. CS it's the record and it will be the movie dto movie dto we can just Port this and we'll just create the Handler for it so it will be the get movie by ID query for Handler and as before inher from I request Handler the first one is the request so the query in that case get movie by ID query and the response will be get movie by ID response Implement missing members of course it will be the asynchronous so async and as before we can just copy from another Handler so it will be this one and add the DB context and now we have to write V movie it will be the await movies DB context movies first or default async and it will be the the ID will be equal to request do ID and the canellation token and now if if movie is null then Pro new exception then we will handle the exception in the later phase of this video if not just return movie do adapt from mster and it will be get movie by ID respond and we have to go to our mapping config and also configure the mapping config for it so it will be the type adapter config from movie to get movie by ID response so as before new config and map destination destination. mov dto and it will be from the source source now once we have created all of the queries we can start with the commands so we can start with the create movie so can write create movie command CS it will be a record and as remember we have to pass the title of the movie we have to pass the description and also the category and we have to erit from the I request and we return the int so it will be the the created ID of the movie and now we will create the Handler so it will be create movie command handler. Cs and we will inherit from I Handler we'll pass the create movie command and we return the integer so we have to implement this method and of course as before movies DB context as the parameter movie CB context and we'll create the read only field and now now we have to create the new movie so from this request we are patching all the title category and description now we are performing the movie BB context do movies do Asing this movie that we have created we can pass the canellation token and then we can get this ID so it will be a wait moveies DB context save changes async and we will have the idid and we will return this ID from this method we'll assign this to create date equals date time now to Universal time as you see when you're are retrieving the ID based of on the safe changes async result it it will just return for us the number of rows affected if we would like to return the specific ID after the safe changes async we can just access this movie do ID and it will be assigned automatically so we'll just change this and we'll return the movie. ID after the save changes method now we can deal with the update movie so create update movie command for it the new record and yeah we'll pass the ID string title string description description category and to inherit from I request and will return nothing so the mediator we have to return the unit type so as you see this is the represents the void type we'll create update movie command Handler yes as before I request Handler pass the update movie command and to return the unit out of that have to create Constructor movies maybe context context read only field and assign the async keyword and now now we have to retrieve this movie based on the ID to check if actually this movie exists in our database or not if not then we have to throw an exception so movie to update is equal to await mov DP context movies first or default async where ID is equal to request. ID and constellation token if this movie to update will be null then throw new exception that will handle later on with the global exception handling and if not then this movie to update do description will be the same as the request do description and so on and so forth so mov to update do title will be the same as the request tile and movie update. category as well be the same as the request content that we have here then we have to ask the mov DB context movies update and it will be the movie to update and then of course await with the be context save changes async with the canellation token and we will return the unit unit dot value and now the last command will be the delete movie command so delete movie command. CS record and we have to pass the ID and inherit from the I request and return the unit we create as well the command for it Comm Handler so it will be delete movie command Handler and the same as before we are passing the command and what we are returning don't forget about the acing keyword and also to pass the context so movie DB context context and now as before in the update uh movie command Handler that we have been retrieving the first or default movie based on the ID we can copy that and only just to re name this variable as the movie to delete so we have to retrieve uh the movie that we would like to delete based on the ID if if this movie to delete is null then we'll just throw new exception out from that if not then movies D to context movies do remove and we are passing this movie to delete then we are writing the AWA movies DB context save changes Asing to perform this operation our database and we are returning unit dot value now once we have created everything related to our secure pattern we can set up our end points to actually use uh all of those handlers uh and perform the operations on the database so in the presentation uh project we'll create the directory called modules and I'll will call this movies module CS will be the static class will create extension method so it will be the public static Bo at mov end points so we will extend the I endpoint root Builder Builder and we'll create the first endpoint so it will be app dot m get here we will have the prefix so the API slash p and now we have to pass that it will be the async and in the parenthesis all right I made theator creator and then constellation token and now we have to return the movies so it will be movies equals to now wait mediator. send and we are creating the new movie get movie query then we are passing also the canellation token to it and as you see we'll have the get movies response so you're just returning the results dot okay and we are passing those movies that we have retrieved uh from our database and then we have to write with tax just to have the special section in our Swagger as the movies we can create another get end point so it will be the map get API slash this and the curly brackets ID then it will be the same so I'll just copy copy that with tax movies and here just write for movie await mediator send new get get movie by ID query and we need also the ID for it so we'll pass the ID and this ID from the request itself here and then return results do okay in this movie that is actually the get movie by ID response but this is the movie dto itself the next Endo will be to create the movie so map post we have the flash API movies and then asnc I mediator mediator and then we need to have the request so we need to create the create movie request create movie request create movie request just do it in a minute with tax movies we need to create this request in the contracts so will be directory called movies and it will be the create movie request and it will be the record create with request with a title description and the category we can just create in in the same time the update movie request. Cs and this request will look like that so we need to pass the ID title description and the category useful for the next endpoint we'll create right now we have to create the command so it will be new create movie command and we will pass the create movie request title create movie request description and then create movie request category to it and now a score VAR result and it will be the await mediator send and we are passing this command and also the constellation token that we haven't alert here so consolation token token that also there we haven't passed the canellation token I'll just fix it now and we are returning results okay with this result now we're ready to create also the uh put method so it will be map put for our update of the movie so API movies slid as we had with the get by ID request will be the async I mediator then ID then it will be the update movie request and also the canellation token write the with tax and it will be the movies as before and we'll do the one modification in our update movie request just to remove that ID because we'll fetch this from from our URL and now it will be exactly the same as we have in the post but it will be the update movie command we'll just change name for the update movie request as we see we have also the ID so we'll pass the ID and do we have everything correctly done so we have the title description and then category title description category and also the ID okay guys and now as the last end point it will be the map delete so we are passing API movies and the specific ID and then async and we'll pass the mediator as before Med Ator mediator then it will be the int ID and also the canellation token we add with tax compliant with all the endpoints and now we'll create the command as delete movie command and will pass the ID and then it will be the same as for all of the commands so result return okay from the result now we have to use the method in our program CS file so it will be app. add movies end points and we are ready to go we can finally run our web API and check how our end points will look like so we have five of them we have the get so it will return for us the get movies response with the movie dtto we have the post so we'll just try with the title movie One desk one and also category one as we see we have the one as the response so probably we'll have yeah we will have the movie dto return from our our database we can also delete the first one because it was invalid it will pass the ID one the empty response body and here we have only the ID of two and we can also try to get the second one so we have the mov dto if if we execute with the first one it will be not found so the exception that we can handle in the later phase of this video and also we'll pass the ID of two and we will change this to let's say W's W's W's and it was changed properly now there's the time to finally set up our validators so we'll use the fluent validation in order to check what we have in our request and if you will not satisfy our requirements that we will set in our validator rules then we will return the 400 b request response so the first thing to do is to of course install the essential nugget package so it will be the fluent validation. dependency injection extensions I'll install this in our movies do application where we have our uh our commands and our queries and we'll start with the create movie command Handler so create movie command po dator so we'll check if we'll proceed further to our Command Handler or not we have to inherit from the abstract validator and we'll pass that command next thing to do is to create the Constructor and now we are using the rule 4 method and we can start that the category for instance has to be not empty so if it will be empty in the create movie command then we return uh the for 400 response with the message with message name of movie dot category cannot be empty with maximum with the maximum length of 30 characters and also we have with the message that name of movie do category cannot be longer than 30 30 characters the next rule will be for the description and also for the title so we can copy the content of it and we'll change this accordingly so we have the category so changes for the description and also for the for the movie title so we'll change this that description and also the title they cannot be empty and the title cannot be longer than let's say 100 characters and description than 1,000 1,000 characters so it will be 1,000 and one 100 and we have to do this for all of of the commands that we have here so we can just proceed with the delete movie command validator movie command validator or inherit from the abstract validator will pass the delete movie command and in the Constructor itself we set one rule that the ID is not empty and with the message that name of movie. ID cannot be cannot be empty and now we'll create as well the update movie command validator and it will be absolutely the same as we have for the create movie command so it will be the update movie command to create the Constructor for it and since we have all the same rules we can just can just copy that and also we have to create one additional rule that the ID is not empty empty and with message from the delete movie command validator we'll just copy and paste it that movie ID from this movie command cannot be empty as well in order to update the movie that we have in our database now the last validator that we'll create is for the get movie by uh ID query and it will be the simple one so get movie by ID where validator Cs and it will be the same as we have the rule for the delete movie command because we're requesting the movie by specific ID so it cannot be empty as well so abstract validator get movie but ID query I'll create the Constructor for it and I'll just copy paste what we have in our deletion of the movie and now we have to set up the dependency injection to register all the validators itself so right in our dependency injection at application method we'll just write services do at validators from assembly assembly. getet executing assembly now in order to use those validators we have to create one centralized point of handling the validation errors so we will create something called validation Behavior so it will be set up up to uh our Pipeline and that mediator actually handles the requests so we have to create the directory called behaviors and the class will be called validation behavior and we have to specify that it will be the T request and T response and we have to inherit from I pipeline behavior and we have to pass the request the response as well and we're implementing missing members and we have to right that will inject all of the validators for the specific T requests so it will be the private read only I aable from the I validator from the fluent validations and also the E request as the type we'll call them value ators create the Constructor and to assign those validators here and now we are going to create the context and it will be called new validation context context of the type T request so it will be generic based on the request that is going through our validation Behavior pipeline behavior and now we can just write validation failures are equal to a wait task when all validators do select and we're use the it's not visible at all we'll use the validate async method based on the context and also we'll pass the constellation token there so as you see here we will use all the validators and based of that we'll validate and get the validation result so we have the validation failures there and now we can get those Valu ation failur and we can filter them and we'll check for all of them that are not valid so those validation results that are not valid at all and we are selecting many of those and we will get the errors of those it will not be actually the validation failures but validation results and from those validation results that are not valid we selecting the errors and then we'll just select the specific trailer and we'll create new validation error and this validation error will actually create in the contracts so I'll create One Directory called errors and it will be the validation error. Cs and it will be the string property and also string it could be error message we'll go back there and we'll assign that the property will be the property name and also the error message will be the error message itself and then we use the to list to create the list of those validation errors and then if we have any of those then then we'll throw new validation exception we'll call this custom validation exception and then we'll pass those failures there but we have to create this custom validation exception so we'll create another directory called exceptions and to create custom validation exception CS will inherit from the the exception will be the public list of the the validation error validation errors list of validation error and validation errors will be what will pass in the in the Constructor and if everything went fine then we have the proper proper validation performed and we can just write response is the await await next and then return this response and next will be the request handle delegate based on the response now the last thing to do is to register our Behavior so will be the in the add application method in the add mediator we have to add one line called at open behavior and it will be type of validation behavior and it will be the generic so we are passing here the comma and we can go and check in our validation Behavior how it will work like to simulate the scenario that we'll have some failure I run the Swagger and as you see we'll use the post method to create the movie but everything will be actually empty as you see we have the one validation result that the category cannot be empty description and the title cannot be empty so we have three of those errors and then we are throwing the custom validation exception with this validation error you will have the error message and also the property of the movie and when we will go back we have the 500 internal server error and we have have the exception of the custom validation exception type that it was actually thrown so this is the one centralized point of handling all the validation errors that will occur as you remember also we were using uh the general exception in case of any null that was returned from database based on the ID for instance here in the get movie by uh by ID query Handler so we can create our custom not found exception in our exceptions directory in the contracts project so will be the not found exception and we will change this to be more precise we pass string message and inherit from the exception and pass the message there and in case of any no we'll just reuse this exception we have pass also the message so in my case it will be name of movie with ID so also with movie.id with id request. id was not found in database and we have to go as well to the delete movie Handler and also to the update movie Handler in the create movie we we are not checking if we have the resource in database or not all right and now we're ready to create the exception Handler uh with the net8 approach so one centralized point of the exception handling so if we have the not font exception or any type of exception or also the validation exception we have to based on this exception type return the proper status code and also the uh response uh to the caller uh in case of any failure so we'll create another directory called handlers in our presentation project and we'll create the exception Handler CS have to inherit from my exception Handler or implement the missing members have to pass the async keyword and yeah we'll start with the creation of the problem details so we'll create one private static problem details create problem details method based on the exception that will come to our Handler and yes now we have to write problem details problem details equals exception switch and yeah if it will be not not found not found exception so our exception that we were discussing uh the moment ago so then we have to create problem details but it will be another method so private static problem details create problem details and we pass the status the integer string title and also string detail and it will be the factory method so we're creating the return new problem details and we'll return the status as the status integer title as the title and also detail as detail so we creating the program details and if it was not found exception then we are passing as the first parameter status status codes do not found then the title will be not found and then exception. message if it was actually the validation our Custom Custom validation exception then we are creating progr details with the status code of 400 b request validation error and as the detail to be one or more validation errors and in case of any other type of exception we'll create the problem details with the 500 so it will be internal server error internal server error and as the detail will be called an unexpected error occurred but wait wait we haven't we have forgot about the errors that we are passing from our validation Behavior here so we have the validation errors with the property and also the error message so we have to go there and in case that the exception that was passed there is the is the validation validation exception validation exception then and only then we are appending the extension so problem details do extensions as errors we are passing the custom validation exception do validation errors and then we are returning the problem details from it and now we have to create the problem the details so we are using the create problem details based on the exception type and now HTP context dot response. status code it will be the problem details dot status if we don't have any status just in case then we are returning of course the 500 so the internal internal server error file 500 then we have to write as the Json our problem details so we will use the HTTP context response right as Json async method and we are passing the problem details along with the constellation token and we are returning returning true and now we have to configure in our program CS our exception Handler so we'll write Builder dot services do at exception Handler of type exception Handler and we have to write well app use exception Handler and Define it like that and now we'll check how the responses now look like from our exception Handler we can also use the break point to see what kind of problem details will return in case of any f so as before we can simulate the validation error as you see we have the problem details and one or more validations occurred have the extensions and we have the errors category cannot be empty title and description we have the status 400 and now when we'll resume as you see we have a very fancy response from our API in case of bad request in case of any other exception it will also have the specific structure of the problem details that we can adjust just in a moment in our react application in case of any failures as well and properly display them in the console now once we have our buckon site created and configured properly we are ready to start with the react development so we can create the new react app but at first you have to make sure that you have the nodejs installed with the version that will be higher than 16 so I recommend just to download the latest one with the long-term support now once we have our nodejs installed we can create in our movies. presentation new directory called client and we'll create the new react application there so I'll open the terminal in this directory and we'll write the npm create V add sign latest the project name will be the movies and we'll use the react and also the typescript plus the S swc so it's the Speedy web compiler it will speed up the build process for instance now we can write CD and go to the movies and we'll write the npm install just to install all the depend Tendencies as you see it's done we have our movies react application created now we can type npm run Dev to see how our template looks like as you see this is the default V plus react template we can increase the number of count by pressing the button so it works I'll just switch this off I'll press terminate and we have a couple things to do just to start with our react development we have to remove couple of those template files because all of them will not be needed we remove this v logo also we have this react. SVG file as well we can remove it and go to the index do HTML and we will change the title to movies app and in the app. TSX we can just remove all the content that we have here because it will not be needed at all set count hook as well in app dot CSS as well this is the basic CSS file from our template I'll remove it now we have to think a bit how our application will look like uh in terms of the components in react so components are the small parts that are gathering other smaller parts of the code that we can reuse them later on in the different uh different places of our react application so in here as you see we have the movie table and this movie table this is the one big component and this component has also the parent components so as as you'll probably guess this is only one component that is shared based on the specific ID that is fetched from the whole list of movies so we have one component uh movie table and one component movie table item so for each item of those we are using the same component then when we click edit that then as you see we are directed to the specific component and this component is the same actually as for the create movie so in our application we have three main components so the table movie table movie table item and also the movie form for editing or creating those movies now we can start with the directory structure of our react application so the first thing to do is to create One Directory called components and as we were discussing a moment ago we'll create the components for the for the movies and here we'll create those threee components that we use in our app so it will be the movie table. TSX we create another one called movie table item. TSX and also movie forum. DSX now we will write the export default function this function will be called movie forum and in here we'll just return the empty component so return that for a while and we can use the same structure for the movie table and also for the movie table item but will'll change only the the name of the functions function components movie table also movie table item now we need to create another directory called models and here we will have the responses from our API and also the model itself that we use as the movie dto so we can create all of those so it will be the get movie by ID response TS another one will be get movies response TS and also the last one we'll start with the movie dto so we'll write the export interface called movie and we can go to our movie dto that we have in our contracts and see what we'll need we'll need the ID typ title description create date and also the category so we'll start with the ID it will be the type of the number or it could be also undefined because when we'll create another movie that will pass to our API the API will assign the ID will not assign this in our react application so it could be also undefined title will be of course the type of string then description be the same type so string create date will be the type of string but also when we will create it will be undefined and also the category will be the type of string now we can go and create the interface for the get movies response so export interface get movies response and in get movies response we'll have the list of the movie dto so we can write movie DTS movie dto as the collection and we have it and the last one will the export interface get movie by ID response and we have the movie dto of the type movie dto now we can create another directory it will be for the routing purposes that will route from our movie table up to the movie form so it will be called router but not with the capital letter and inside we'll create the component called routes. TSX and it will be empty for a while we create also the directory called interceptors and we'll create the axos Interceptor dots file TS file and this axis Interceptor will be the purpose of displaying the errors based on the response from our API it will be also empty for a moment we'll create now the last directory it will be called API and in this directory will have one file called API connector so it will be the one centralized point of Performing HTP request to our API and we'll start with this file our react development so we need to have one npm package installed to perform the those HTTP requests and this package called axios so we can open our terminal and write npm installed install AOS and so once have installed this package we'll create one configuration file to keep our API URL in the one Central Point will be called config dots as you see our URL for the API is Local Host with the port 5028 so we can write a export HST API base URL is equal to http Local Host 5028 and we'll use this in our API connector and now once we have our API base URL set up we can go to the API connector and start with writing our request to our API so we'll write const API API connector equals now the first end point will be to get all the movies so we have to declare that it will be the async call and as the return type we'll have the movie dto with promise have to import the movie dto and now in the try catch block the first one will be the try we have the const response type exos response of the type get movies movies response have to import axios and it will be a weight axios get have to import as well the axos get and you have to write the URL so it will be the our variable API base URL from the config with the slash movies and here we have the response and we have to write const movie and it will be equal to the response have to access the data and movie DTS and as far as I remember the return type of the of the create date will be the full date time and we would like to display only the year months and days not like the whole date so we have to map all of those movies and we have to extend each movie so use all of the properties in the each movie dto that we have but for the create date we have to slice so we have to substring let's say the create date and we have to take from the index zero up to 10 so it will only be the date as the year year year year then month month and day day and if it will be null then we will return empty string and we are returning the movies and then in the catch block write error for this error we'll just write console.log error patching movies and we'll pass this error there the next end point will be to create the movie so create movie we will declare as well that it will be the async call and we have to pass as the parameter the movie dto and as the return type we'll have the void because we not return anything and here as well have the try and catch error and await we'll use the axus library with the post it will be the number what it will return and we will pass as well this API base URL with the the slash of the movies but we have to pass the movie to our call and we console.log the error and we'll throw this error the next call will be the edit movie so it will be the same so async we are passing the movie with the type of movie dto to our API and we are returning nothing from it so the promise of type void and it will look very similar to our cre create movie request but we're not posting it but we are using the put using the put method and we have to use the arrow as well there and now we declare that delete movie so delete movie function it will be the async call as well and we are taking as a parameter only the movie ID of the type number because we would like to delete movie based on the ID as we have declared this in our API so as the return type will be the promise of the type void we are passing the arrow and we can copy paste it but it will be the delete and we are using only the URL there so we have to write slash with the dollar sign and take this movie ID that we have in our parameter of that method and the last end point will be the get movie by ID so as you remember will all also be the async call as the parameter will take as we we have declared in the delete movie method also the movie ID so movie ID of the type number and it will return the promise of the type movie dto or undefined we are passing the arrow and also in the tri catch block we can write const response it will be await axos get and we are taking the same URL so we are passing the movie ID but we have the get method not the delete one and we can declare because this is the typescript that will have the get movie by ID response in that case so we have to extract from the response axio response uh our movie dto to return this so return response. data dot movie dto rrap this into the tri catch block so we use also the catch to catch the [Music] error and to write console. log. error and also row throw that error and as the last last thing we have to export this API connector so we write export default API connector in order to use this API connector in our components now we are almost ready to start with the movie table and with the styling that table and fetching from the API all related movies to display them in that movie table but at first we have to install one package it will be the semantic UI so we will not use the bootstrap there but we'll use the semantic UI so I'll run the terminal and I will write npm install semantic Das UI - react n sign 3.0.0 Das beta do0 semantic - ui- CSS after the installation of that package we have to import one thing in our main. TSX we have to import semantic UI CSS semantic mean. CSS in order to use this in our react app and as well at once we can change the import of that index. CSS file because we will not use this at all we'll use the app. CSS so change the import statement to app. CSS and at once we can assign the body of our app just to be gray and for the future we'll use the margin top for all related container style containers from the semantic UI and now we can start with our movie table finally so at first we would like to import all of the movies into our component from our API so we'll use the react hook that will the that will set all of the movies based on our API call so we'll write movies set movies and it will be use State hook of the type movie dto list of movie dto and the initial state will be empty we have to import as well that hook so we will write import use state from react then we'll use the use effect hook we have to import as well this Hook from react and in here we'll just write const P data will be equal to async call and H patched movies from our API we AWA API connector get movies and then we will set those movies with the usage of our hook to the fetched movies and then we'll use this now as you see our movies are not used anywhere so create our movie table I will hide this so at first we have to write container for it from the semantic UI at import from semantic UI react and as you remember in our CSS file we have created the class name called cont container style to have that margin top so we have to declare it here that we'll use that class container style and now we'll create the table the normal table with the class last name UI in inverted table and now we have to write that EAD style the head style will be equal to text Al line Center just to have everything centered properly and inside of here we'll just write the table record and we write that the first record will be the column names so as you remember we have the ID so the first one I will copy the title will have description create date category and also we have the action for the edit and delete so I will write the proper column names be the title description create date category and also action for the edit and delete will be as the header and as the body and as the body we will have the condition that if movies dot length is not equal to zero so we fetched actually something from our API and we have those movies there then and only then we for each of those movies we'll create one movie table item as the key will be the index and as the movie we'll have the movie because we have to pass to that component the movie itself and as you see we need to pass the movie to our movie table item so at once we can go to our movie table item and we have to define the interface so interface props it will be the type of movie movie dto you have to import the movie dto and in here we have to distract the movie from the props and we'll use this later on but just for now will not do anything and under this table we'll create one button the button from the semantic UI itself so it will be the button floated righted right of the top type button content will be to create create movie create movie and it will be the positive now we will fill up the content of that movie table item component so as you remember it will be the each row of the specific movie so we have to create the table row of the class name Center aligned just to be everything in the center and then TD as the as the specific cell of the data label ID it will be the the movie do ID that we passed from our movie table component up to this movie table item and then we'll create everything for the rest of the properties so it will be the title as the next one and the movie dot title then it will be description description movie. description then the create Date Movie dot create date category category and the last one will be the action but the action will be two buttons to edit or to delete the specific movie so we will create at first the button we import this from the semantic UI will be the color color yellow and also the type of the submit and as for now we'll just leave as edit we will not have any nvlink yet because we don't have the routing set up and the next button will be for the deletion of our movie so we can can write but it will be the type of of the button negative just for it to be with the color of red one click event and in here and write async and then we can use our API connector API connector do delete movie and we'll pass the movie.id and it could be the undefined or not but as we remember in the movie table when we don't have any movies fetched from our database then will will not display at all this row as the movie table item so we can normally use that exclamation mark there to not have this kind of error that we are getting from the typescript and then we'll just refresh and to write delete now we have to go to our app. ESX component and we can import our movie table and check how it will look like so I will just [Music] run our API and also run our react app with the usage of npm runev command terminal npm run def as you see we have our table we have our create movie button but unfortunately we have an error that the access was blocked by the course policy because we haven't done the course policy yet in our API site so we have to go to our API and said that from this kind of the URL so from The Local Host 5173 we are accepting the HTTP request in order to configure our course policy and be able to have uh our HTTP request accepted by our API we have to write the following statement Builder do services at course with the options as options dot at policy course policy and then policy Builder and in here we have to use the policy Builder and type allow any header allo any method with Origins and with this origin that we have our react up we'll use that and then we have to type use course as the middleware in that section use course with the name of the course policy as you see we have our movies not found because in our API connector we haven't specified all Alo the API uh before the movies itself so have to go there in our config TS have to slash API and now as you see we have our movies from our database and when we press delete as you see we don't have this movie anymore so our delete functionality works as expected so far now we have to deal with the routing uh in our react application in order to use properly the movie form when we are pressing the create button or we are pressing the edit button from our actions in the movie table so we have to install one package in our react app so I'll open the terminal and try right npm install react-router dasd and now in our routes. TSX file we have to define those routes so we'll write the export monst routes will be the type of the root object equals I have to import this from the react router Dom package and now as the path will be a slash it will be the element up onon it and as the children we have the following components for the PA create movie for that path we have the element of the movie Forum as the key as the key we have the create those keys are actually very important because we're using the same component for two different routes so as you see this statement once we have this PA edit movie with the ID we are using the same component movie form and our router needs to have the different key in order to properly serve function and as the PA Aster will have the element of the movie table that's we have to export const router and we use the create browser router to pass the routes and now in our main. TSX file we have to remove that app and type here router provider router is equal to router and to import this remove that app component and we'll use that add import from react router Dom and now in our app. TSX file we have to also use our router properly so I will use the location write con law location use location as the hook and now we'll use that condition if the location. PA name will be equal to flash then we'll return the movie table component if not then we'll create the container as the class name container style and in here we will have our outlet and this Outlet of course is from the react router Dom so it will handle for us all the routing we also import the semantic UI react and as you see when we'll go to the create movie then we we are forwarded to the specific component as the movie form and in here we have our movie table and now once we have our routing set up properly we can use also our button to create movie to be directed to our movie form component so we'll just change this button to be as navlink as nov link we have to import that nov link to to the create movie so it has to be compliant with our routes we have the create movie there then in our movie table item as well we have to change our button and also use this as nvlink so then we'll have this redirection to the specific component a sing from the react router Dom to to edit movie slash have to use the dollar sign movie do ID now when we'll check this when we press edit then we are directed to the edit movie slash ID of Two And when we create movie then we are the create movie as the blank component so far now we have to implement also the movie form in order to be redirected not to the empty component but the field one so we can start with the getting the ID from the movie for in case that it will be redirected by the edit movie button so we can access this ID by using the use use params hook have to import this hook and also we will use later on the navigate as they use navate hook also we have to import this and the first thing to do you have to create also the use State hook of the movie dto so have to write movie Set movie function and use state of the type movie dto import everything use State hook as well from the react and now as the the initial State we have to type the default values for the specific properties of the move dto so undefined will be the ID title will be empty string description as well create date will be undefined and also the category will be an empty string now we can write also the use effect Hook from react we have to import this hook and when this component will Mount then it will check if we have actually the ID from our params if we have have the ID in our pams then it means that we were redirected by the edit movie button so we have already this ID and we can request our API connector and use this get movie by ID function we pass the ID and then when we'll get this movie from our API then we will set set this movie and then as the dependency pass the ID I see that we have one issue that we are passing the movie ID as the number so we have to change have to change this movie ID to be the type of string and anyway it will be converted properly in our API site so if we have this ID then we'll set this movie that was fetched from our API we have to write as well the function function to submit because we will have the two scenarios we will have the edit scenario and and also create movie so the brand new one scenario so we'll create the function and this function will be called handle submit and in this function we'll check if our movie ID will not be present then we'll use API connector create movie we'll pass this movie that we have already in our component and then navigate navigate to our main page so to our movie table and the else statement if we have this ID then it means that we have to edit this movie we'll pass the movie as the parameter and then also use the navigate in order to be redirected to our main page now we can focus on the actual form so in the return statement we have to write segment and this segment is from the semantic UI write the the clearing that it will clear out and inverted as the color type and inside of it we will use the form also from the semantic UI and in on submit we'll use the function handle submit autoc complete will be off just in case and the class name will be your inverted form and inside of it we have to create three different fields so the first one will be the form do input and the placeholder will be called title because we have to fill in the title of the movie of the name title and value will be movie do all right Co the next form will be for the for the category so the place will be category with the name category and the value be movie dot category and be between those we have the form. text area because the description will be longer than the normal text input and the placeholder will be called description the name description and in here we have the value equal to movie dot description and we have the button from the semantic Qi as well that will be floated to the right we'll write this as it is it will be the positive type because we'll create now the submit button of the type submit and the content will be submit and then this button next one will be the cancel button so we have to use the nav link as before so the love nav link from the react router Dom to the main page and it will be floated fled right of the type button so the normal one and the content will be called consel now we have to create the function that will actually react on the two kind of the events so the HTML input element change event and also the change event of the HTML text area element because here we have the input and also the text area so when we'll write something in into the description field it has to be reflected as well in this movie that will'll assign later on so we have to create function called handle input change and with the parameter we'll handle the change change event from react and it will be the HTML in HTML input element or html text area element and in here we have to take the name and also the value from this event event dot. Target and then we can use our set movie function from the hook just to take everything that we have in our current movie and change the value of the name so the property as the value so the name will be this name so the title so the movie. title will be changed for this value based on this change event so then we have to use this on change to assign our function handle input change and we can take this declaration and also use there and for the the category as well now we can press the edit button and as you see everything was filled by our API call also this movie with all of those values and also this movie with the a as well it's filled based on the API call when we create the movie as you see we have everything that is blank so we have the create movie we have the create movie form type and now we can just create one movie for us movie One description one and the category cut one and we'll see if it will work yes as we see everything is now in our database we can edit this movie as well we can just change this for the movie 2 description 2 Category 2 when we pressed submit we were not redirected to our homepage so we have to handle this as well now we have to check why we have some sort of the not okay scenario here when we are pressing the submit as you see the request failed with the status code 405 method not allowed we have to make sure if we have everything correctly done so based on the movie form we are navigating to the homepage and edit movie probably something wrong with it yes I see that we are not passing the ID uh into the URL so we will use the dollar sign and take this movie movie ID and this movie ID will be fetched from the movie do ID we'll check once again as you see we were redirected properly so edit one more movie One 2 three one 2 3 one two three yeah everything is fine we don't have any more [Music] errors so now we will handle the exceptions with the usage of the axios Interceptor that we have uh blank as the last file in our tutorial now as the last thing to do we we have to handle also the errors that can occur in our API when we are performing some sort of the requests so as you remember we have in our API the rule in the fluent validation that the category cannot be longer uh than 30 characters so when I click submit as you see I have the 400 b request with the response and then inside I have something like data so the problem details and also the errors and the property and so on and so forth so this is the very nested uh error message that we can based on the response uh status code display in the console so we can deal with it we can go to our axus Interceptor and based on the status code display everything properly so we write export h setup error error handling intercept Interceptor and this Interceptor will take the response from our API and based on that do something with it and then it will forward it to the component we have to do this once so we have to set up this Interceptor only once so we'll use one variable so is Interceptor this Interceptor setup it will be equal to false and then after setting up the Interceptor we'll set this variable to true so then our app component will not do this once again we'll check if is Interceptor set up so when it's false so only the first the first attempt we use the axios so we have to import this from the axus do interceptors dot response dot use and then on F field so it will be there response the type axio response so we have to import this as well from the axio will be the response and on rejected it will be the error and now if we have something as the error dot response then we can extract the status status code from it so it will be the [Music] error do response dot status code and also the data of that error error. response. data and now we can use the switch statement based on the status code and now when it will be the 400 so our fluent validation checked our request and it was not fine then if have errors inside of the data so as you remember it was very nested inside so we have those errors and the errors as the reminder as the errors we have assigned there in our problem details extensions so validation errors then you can write the const model State errors will be equal to empty array and then for every HST item of data do errors so for each one of those we have to extract the property so item property and also the error message item do error message and then if we have the property and also we have the error message available then and only then we are pushing to our empty array so model St State errors dot push and it will be the property and error message and then we are using the console dolog to return the model State errors after that we have to use break next thing will be to handle the 401 so if it will be the 401 so then con console.log we can just display it unauthorized authorized also the break then case oral three or fre it will be the Forbidden so console.log forbidden from our API when it will be the 404 so we throw our not found exception because then we'll return the status 404 not found then we will just display console.log found and then as the default as the default will display that will be the generic error so console do log generic error and then we'll write return promise do reject and we'll pass the error after that if statement we have to assign the is Interceptor setup variable to through true so then it will not be mounted once again and this error handling Interceptor then can be used in our app do PSX so we'll use the use effect Hook from the react so we have to import it at import from react and in this use effect hook we can use set error handlink Interceptor now we can check how our exception handling Interceptor will work like based on the specific status codes from our API so I will just enrich this content of the category I'll press submit and as you see we have this kind of structure that we fetched from our axio error that we have the CATE category and category cannot be longer than 30 characters can use this kind of structure to display it as for instance the toasts here on the bottom or somewhere else but in the API connector as you remember and as you see here even that we are catching the error and we are throwing it and we are console logging it actually but since we have that exception exception handling Interceptor we don't have to do this once again so we'll just we'll just remove those tries and catches and let our Interceptor to return only what is essential for us so I'll remove that try that catch on as well and I will return those movies from that get movies have to move all of those lines to the side remove try catch from the create movie from the edit movie as well now from the elite movie as well also from the get movie by ID we can remove all of those lines that are not so useful we can refresh it clear the console and we'll check that now we have only this kind of response when we'll clean the console I have changed some kind of logic in our edit movie command Handler to return not found exception when we actually found this movie so I can show you that in update movie command Handler I changed this from if movie to update is null then to throw but when it's not null and we'll see when we'll have the proper content we'll have the response not found and 12 when we change this from the not found exception to the for instance argument exception we'll check if we'll have the general error so it will be the internal server error now we'll press some new content as you see we have the internal server error and the generic error so our exception handling Interceptor works perfectly and we can adjust this as it is needed on your own so in that case we are ready with our app I'll just close this console we can edit the movie we can create the new one we can create it we can display it we can delete those movies and edit those movies as well all right guys so that's the end of this very long video H I hope that it was not too boring for you and not too complicated at all because uh we went through a lot of different concepts of net web API development and also the react together with typescript development I wish you that very nice day don't forget to hit the Subscribe button and like button and see you in the next video
Info
Channel: Remigiusz Zalewski
Views: 2,409
Rating: undefined out of 5
Keywords: .net 8, .net 8 web api, .net react, .net react crud, crud react .net, fullstack .net react, .net fluent validation, mapster, .net 8 exception handlling, .net core, .net core 8, react typescript .net, entity framework core, ef core, ef core sqlite, react interceptors, react routing
Id: g3is3wQK70Q
Channel Id: undefined
Length: 165min 17sec (9917 seconds)
Published: Wed Jan 31 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.