ASP.NET Core 6 Web API Using Entity Framework Core 6 Database First Approach

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey guys welcome back in this lesson we'll be creating our solution and our api project using visual studio now i'm using 2022 and that is the only way that you'll get done at six but if you're using 2019 then you should be able to follow along quite easily using.net five so we can go ahead and create a new project and i well traditionally you would go ahead and select the template you want but because we know we're going to have an api we're going to have client apps all in the solution i'm going to start off with a blank solution so if you don't have it in the recent project templates you can always just type in blank and just look for blank solution so we go ahead and select that and i'm calling this solution bookstore app then go ahead and hit create once you've done that then you'll get well a blank solution now we need to put some projects in there now i have my solution explorer to my left you probably would have it to your right by default but it is something that you can actually drag and drop into the section that you feel most comfortable with it being in so i prefer mine to the left but the functionality will remain the same so let us right click our solution and go down to add then we select new project and then we can choose our api project template so if you have it in the recent project templates no problem otherwise you can always just search for api and that template should appear if it still does not appear please revisit the installation instructions and ensure that you have the workload for web development uh selected so we can go ahead and select that template and i'm going to call this one bookstore app dot api so it is clear what this project is for then we can hit next i will be proceeding with the.net 6 framework and typically you would want to choose your authentication type but then that's they have different options for the api than they would for the regular web app and the option that i really want at least for this uh series of activities would be the individual accounts however it's not there so i'm going to leave it at none and we can set that up later on i can leave the configure for http https enabled we don't need docker and you can go ahead and use controllers and enable open api support so we go ahead and hit create now once that project is created what we have is a sample or a standard boilerplate layout of api of an api project for net or net core so if you're using dot net five you may see some differences and we're going to go through those differences in the next lesson where i give you a tour of each file and folder and we can see exactly what each one is doing for now however let us go ahead and hit our start button just to see what we get out of the box and this is a good site so what we have here is swagger right so swagger is supported by smart bear and it's built on top of the open api specification which is an option that we left enabled when we're creating our project and what swagger does is it gives you a document or at least documentation surrounding all of your endpoints what the data that might be returned looks like and what the codes would be and all of those things so swagger comes built into net 5 and net 6. if you're using dotnet 3.1 or donna core 3.1 you may have to do some manual effort to integrate slugger into your api but out of the box with net 5 and 6 you will have access to this document another cool thing about it is that it's actually a web app that allows you to test out the api so throughout the duration of this course we will be flipping between swagger and postman when we're making or doing our tests rather because they're both capable of triggering requests and displaying the response information based on what the endpoint will provide so that's really it for creating our project when we come back i'm going to walk you through each file and folder so you can have a full understanding of what is going on hey guys welcome back in this lesson we're going to be walking through all of the files that got generated with our project creation so let's start off with a solution we created a blank solution and the solution is really just like a register of all of the projects in theory when you're solving a problem you are applying a solution so the solution really is the directory for all of the projects and files that will be used to address the problem right in practicality it's really just a folder housing a bunch of folders and files so that moves us on to the first project that we have and we will have multiple projects in this one solution but this project is our api project and when i click that project file you'll notice that it opens up this xml file which is just like configurations one it's telling us the target framework which is net six if you use net5 then it would say not fi net 5.0 if you're using.net core 3.1 it would say net core 3.1 it also has some other configurations which you will see the use of as we go along i'm not trying to explain too much at this point just so you can have an appreciation of what's going on and then we have this item group which is housing the packages being made reference to so we we will be using new get package manager as we go along and that will help us to manage the different libraries and third-party tools that will help us to make our development easier so that's the cs proj file once again that is really just representing a folder and then inside of that folder all of the files for that project so we have connected services we have nothing at this time we have dependencies and you'll see some default libraries that are like out of the box with every project under packages you'll see the same packages being made a reference to the inside of the cs proj file on the properties we have launch settings which is just a json configuration file which has certain details about how the app should behave honestly i really do modify this file so you don't necessarily have to worry about this file until you have something major to do later down we have controllers now controllers literally do that they control the web traffic so when a request comes in and a response is given a request comes from the user or from the client app to a controller and then if he can recognize the type of request then it does whatever it needs to do and gives back a response so for every endpoint or behavior that we'll be introducing to our api we will be modifying creating and modifying controllers as we go along so we have a default one which is what we saw in our swagger app and it is for weather so it's a weather forecast controller and all it does is give back some data when that request is made accordingly right so here's where you define your verbs and your layout and your actions and we will be going through all of that in detail later on then we have the app setting.json here is where certain configurations like database connections any static configurations that we need for our app going forward they can be placed in here and we can access them rather easily from anywhere in our application with minimal effort using the dependency injection or the ioc container then we have the program.cs file so in.net or in versionsof.net and.net core prior to six you would have the program.cs file and a startup.cs file now in dotnet6 we have them both as one the only major difference is that instead of using two methods one to configure services and one to configure the app it now just does everything in one straight line so we just have a builder that is saying builder dot services dot the service we want to add and then later then we have the app dot and include the middleware so in a.net 5 or net core 3.1 up you would have seen something like a configure services as a method and then you would say services dot add the service that's the only major difference so if you're following along with net5 when we make modifications the code difference will be very very minor further down we end well basically with just a static class that represents a weather forecast object so this object has properties and these properties were being used by the controller to be populated and sent back so that's one of the advantages of apis with.net core we can use straight c sharp and built-in libraries will convert our data that we're applying to our c-sharp objects and and make them look like json in plain text for the client that is retrieving it so that's why it doesn't matter once again what kind of client app we're using at the top or what technology you're even using for the rest api as long as they're following certain standards they will be able to communicate all right welcome back in this lesson we're going to be setting up our course policy now course policies pretty much restrict the machines that are allowed to access an api yes they are set up for security reasons and you can use them to blacklist or alert reject certain requests coming from certain sources but generally speaking you want to leave them open and handle that kind of restrictions somewhere else in this lesson because we're building the clients and what will happen is that they're going to be coming from different ports so even though they're all in visual studio on your machine it will kind of simulate different servers hosting the api and the client apps and cores will be needed to or a course policy will need to be enabled to facilitate that kind of communication so in a few simple sets we can get that done and we'll start off in the program.cs file where we're going to add right above the or right underneath where we added serial log will say builder dot services and here we'll say dot add course all right so course is spelled c o r s so that's the one we're looking for and then what we want to do instead of this is start up like some options or configurations so let's say options with our configuration or lambda arrow and we'll create an object block so in that object blocked i need to say options dot and add a policy and i'm going to give this policy the name allow all simply because that's exactly what i'm going to allow so i'm going to allow all requests for any method from any header right so beside allo all inside of the parameters for add policy we're going to have to give it the policy object so i'm going to say builder or let me say b um which is really a builder but i don't want to con i don't want to conflict with the builder object that's already present in this file so i'll say builder lambda arrow or sorry b lambda r arrow then b dot and then i can start daisy chaining all of what i'm allowing so i'm going to allow any method check and then i'm going to say dot allow any header check and then i'm going to allow any origin so any you can always read you can hover over each one just to see exactly what it's allowing but this means allow any request type coming in with any header from anywhere right hello all and then after we do all of that i can close it so if you want it to look a bit neater you can always just break the line and make them all kind of chain down below the other one right so that is our course policy that we have built now we need to tell our app to use it so underneath in the app building section or the middleware section i am going to put that right underneath https use https redirection so i'm going to say app dot add cores so sorry use scores use course there we go so after doing that i have to give it the name of the policy that it should use and we just created a policy which is allow all so after doing all of that we have now enabled a nice course policy that will allow any client from anywhere to access so our restriction will be well if you want at the network level but more importantly at the authentication level because you can't get into certain endpoints or certain behaviors you can't interact with them unless you're authenticated so that's what we're really going to be using to restrict out of the box dot net core apis will restrict at the core's level so this policy is just like an alleviation of that default policy so that's really it um there's nothing to test really um the real the real test will come when we're building out our client apps and we get to interact with it so that's it for now hey guys welcome back in this lesson we're going to be creating our database for our projects now there are two predominant techniques that are used when creating a database support.net core app the first technique which is the one that we're going to be using is the traditional database first meaning that you would have already mapped out all of your system requirements and you would have built a database to match those system requirements then you would have gone into our management studio for sql build the database and then you build the app around the database that's the database first approach the next approach would be the code first approach which is more aligned with agile development where you're not necessarily sure which direction the database may or may not go during development so you build with the you build onto the database in accordance with the app development so you use the code to dictate the design of the database now most courses teach code first approach and we will take a look at it briefly but i want us to do the database first approach because what happens is a lot of the times when we have to build an api or an apps a lot of the times it's not necessarily from scratch sometimes it's a rebuild of an existing app and an existing database and we have to work around it so i'm going to show you how to work around the concept of there being a database already and you building and consuming that database using entity framework core so let's get started i'm going to basically do everything in visual studio but for the database bit if you are you know familiar with sql server then you can actually use the sql server management studio if you wish to go ahead and create the tables that you're going to see me create but i'm going to stick to visual studio i don't want to tell you to download too many tools and we can go to server explorer so if you don't see server explorer you just go to view and you will see server explorer listed there now under server explorer it allows us to view all of the database servers that are on the network just like we would with the management tools i can actually connect to a database here and what i will do is hit that go to microsoft sql server hit continue and then it will ask me for the server name so you will at this point you have already set up your sql express server if you're using sql server then no problem if you want to use the local db that came with visual studio then that would have been a different option but i'm assuming at this point that everybody has sql express so you can always just go connect to your server by its name you can say localhost backslash sql express because that is the name of the instance if you're not using sql express then localhost by itself should suffice for sqlx sql server if you're using the developer or enterprise or pro editions so with sql express we can do that we can leave it at windows authentication we can test the connection we see that it was successful then we can click ok we don't have to select our database because we haven't created the database just yet so when we click ok then what happens is that you'll now see that server listed as a connection and by default it connected to the master.dbo so what i can do now is right click and say create new sql server database and then it's going to ask for the server name once again which is localhost sql express or i can just use a dot or full stop to represent that local host and i'll give it the new database name i'm going to call it book store uh db let's just assume that the database was called bookstore db beforehand so after doing that now i will see that bookstore db listed so i'm actually just going to disconnect from this one because it's actually the master database i don't need that connection really so i'm just deleting that connection not the database just the connection to the database so now that we have our bookstore db connection we can actually start manipulating it from right here inside of visual studio so i'm going to go to tables right click add new table and our first table is going to be one for our author so the general outline of this is that we're going to have authors and we're going to have books so we can actually write our sql script if we want or we can just use the design view so i think i'm going to be flipping between them anyway so we always get a default id which is the primary key and i also wanted to have a few properties that are not there namely the property to be identity so when i right click and click properties you'll see that that little panel come up to the right hand side and then i want to choose the identity specification to be is identity true so that means it will auto increment and you see here the script got updated automatically right so for the table name i'm going to change the table name here in the script i'm going to call it authors all right so our table is going to be called authors we have the id which is a primary key and it is also our identity what else do we need i need a column for the first name and i'm going to make that one and invar char i think 50 sufficient i'm also going to say last name and inverter so you see if you're not so familiar with scripting and you prefer the design view this is a perfect mix of both worlds because as you do the design it shows you the script that you need so the next thing that i'm going to have is bio and for this one i'm just going to say envar char maybe 250 maybe maybe make it a bit bigger than just 50 so it can hold up to 250 characters so with all of that done let us go ahead and create so i can just go ahead and hit update database and what it will do is execute that script and it will ask me if i'm sure and i'll just say update database and when it's done we get that green take stating that the update has been completed successfully so that's table number one so let's do that again for our second table and as many tables as you feel your application might need so in this one we're going to be creating the books table so that's the name of the table the id i'm just going to write in identity i find it easier to just type it in now that i know what's up and to go ahead and hit the properties and i just went ahead and filled out the rest of the columns so i'll walk you through each one and what you have to look out for especially so we have the title inverter 50 year is integer isbn i set this invert chart 50 and i also give it a unique constraint all right so you can just type in the word unique inside of the scripting area summary inverter 250 image in varchar 50 the price i'm sitting as decimal 18 2 and if you're not very familiar with what the 18 and the two mean it means i'm supporting up to 18 digits and two decimal places and then we have author id int no so together we can set this up as a foreign key to the authors table so what i can do is right click or first they let me update so i prefer to actually create my tables and then set up the foreign keys so after you have all of that you go ahead update database and once that has been completed then we can backtrack and set up our foreign keys here so i can click on the column author id right click foreign keys and say add new foreign key it will then generate a name and i can just press enter and that action introduced a new line to the script where it's saying it's adding a constraint fk books to table foreign key and then we're going to specify that the foreign key is author id so i'll just replace the word column there with the word or words author id and then it will say references so the two table would be books so i'm just keeping sorry it would be authors right and the two table column would be the id column of the authors table so i say id right and then after doing all of that you see the red lines disappear because now it can make sense of what i'm asking it to do and then we go ahead and hit update again so it will generate the script and and update database and once that has been completed successfully we can now go back to our server explorer and expand our tables listing and we'll see our two tables with our respective sets of columns now the reason i said isbn as unique is that no two books should have the same isbn in the system so by setting it to unique that the database level will ensure that it cannot be repeated so that was that was a standard database creation activity uh if you're familiar with database creation then that should have been uh like a reflex action for you if not then i encourage you to check out my course on database development however let us proceed in the next lesson what we're going to do is reverse engineer this database into our application so our application can be made aware of the database that exists and the tables and their properties all right guys so coming off the heels of creating our database we need to let our app know that it should be able to connect to a database and that starts off with us making it aware that entity framework is present and then letting entity framework know where to look for the database so we have to install a few libraries so let's just jump over to new get packages and we're going to go to the browse section and what we want is microsoft.entityframeworkcore.sql server so if it appears on your front page then fine otherwise you can always go ahead and search so we're going to install that one once again always click ok and accept any prompts that you get and when that one is done we'll need another library which i'm not seeing readily so i'm going to go ahead and browse and the one that we want is entity framework core dot tools so this will allow us to run a few commands uh against the entity framework library so let's just go ahead and install that also and another library that we usually get is the design we may need it but all right let's just install it if we don't we can always clean up the solution afterwards so i'll just go ahead and get that design library also so that's step one get all the entity framework libraries into the project step two let's jump over to the app settings.json and we're going to have to extend this file a little bit more and what we're going to be putting in is our connection strings so you see here it's already auto completing that for me because that's just a part of the app settings that the app is expecting right so here i'm going to put a connection it could be default you could name it whatever you want so i'm going to say bookstore app db connection whatever name you want right by default or when you scuffle certain apps with database connectivity already enabled it would say something like default connection so it doesn't really matter but i do like when the name is explicit enough so when i have multiple connection strings i know which connection string is which based on the name now inside of this block of text i'm going to have a few parameters i'm going to have server and this is where the database is being hosted so in our case i'm using localhost backslash backslash sql express the reason i have two slashes is that because the backslash is like an escape character so a backslash s means something entirely different so i have to cancel the first one so it sees it as only one backslash but we already know how that connection would look inside of the management studio or when we were connecting once again whatever server it's on you go ahead and put that there so if it's on a machine that is not your machine then you probably want to use that machine's name or that ip address if you're only using sql server and not the express edition then you can just say localhost or whatever the instance name is you go ahead and use that instance name then we have a semicolon which is going to separate it from the name of the database so we say database is equal to and then we give it the name of the database which if i am not mistaken we called bookstore db so i'll just type that book store db after that we have two other options for security and connectivity um settings so i'm going to have one that says trusted connection is equal to true and then on the one that says multiple active result sets is equal to true so that allows for secure connections to the database and secure and multiple connections multiple simultaneous connections to the database so after doing all of that we have now created a connection string we need to let the app know about this connection string and let it use entity framework to initialize that connectivity operation when necessary so let's go back to our program.cs and then we're going to start writing in some more services into our container so i'm going to say var con string is equal to and i'll get my builder and look in the configuration remember that we interacted with that configuration before and you see here it's auto completing that get connection string for me and the name that i have to get it by is the name that we specified here so it's expecting me to say get the connection string look in the app settings that that configuration object represents our app settings and get that connection string by that name after doing that we can now say builder dot services dot and we want to add a db context there we go so courtesy of entity framework we have that db context and we don't yet have a db context file so i'm going to say uh bookstore db context we're going to have to create that file in a few so just work with me so builder.services.adb context so that db context will actually represent uh the connection to the database or the bridge between the app to the database but we're going to have to initialize some options and i'm going to say options.use sql or is it use sql all right i just have to type it out sql server and that is why we have to get that library because entity framework allows us to connect to many different database engines right so it doesn't have to be sql server it could be postgresql it could be mysql but we're using sql server so here i have to say use sql server and then i have to add a using statement so control dot and enter will give us that using statement for that particular extension method right next up we go ahead and create our db context so what happens now is that the db context usually is what we would write up and do it in a code first manner to say well modeler database based on this context so it would be forward engineering from code to the database now we have the database already so i'm not going to create this db context manually instead i'm going to let entity framework generate this db context on my behalf so i'm going to go to the package manager console if you don't see it at this point of your screen you can always go to tools and then you get package manager and then bring up that console so this acts like a terminal inside of our application and it allows us to add a few well run a few commands that you wouldn't always get to run otherwise so here we're going to say scaffold dash db context and then i'm going to have to give it the connection string so the connection string we have that we have it right here i'll just copy well i just need the database and the server so i'll just copy that so in management console i have a single quote paste in all of what i just copied and a single quote again all right and then after doing all of that i'm going to give it some more parameters so i'm going to say dash context dir and when you type you can just press tab and it will auto complete so i'm going to say go into a director directory sorry called data and then i'm going to say output output directory i'll just leave that also as data so i want it to create a directory called data and i'll put everything to data also right so i'm going to press enter and it is prompting me for the provider so our provider would be the library that we're using for our connection to sql server so i'm actually just going to copy the library name here and that is going to be the provider so i can just paste so i can't paste ah i'm sorry about that so i'm going to have to type it so all right make it easier let's ctrl c and cancel this entire operation or press escape there we go and then let's try this again so i just press up to get that last run command and then before i start specifying all of those other directories i am going to place this library reference there right so let's look at this again scaffold db context and then we have our connection string we have our provider so we're saying this is a connection string to an sql database and then our context directory is data and our output directory is data and while i'm here i just need one slash in this window i only need one slash so remove that extra slash if you have it so let us try that again all right so it usually does a build before so this is causing an error let me just comment it out right remove the error and then let us try that third time is the charm all right so i'm getting a lot of data here so it's saying that a connection was successfully established but they couldn't log in and i suspect that's because i took off the connectivity stuff so let's do this again no shame in trying until we succeed so i'm just going to take the rest of the connection string and then at the end of bookstore db semicolon and the trusted connection stuff press enter again and this time we now have liftoff so we have a new folder called data and then when i look in data i'm seeing that i have author book and bookstore db context all right so now i am seeing all of the files that i was what would expect so here's the db context so in program.cs i can actually comment this out and that error would go away once i had the using statement there we go so now i have my db context for the database that we had created manually all i did was scaffold it in our application here it has a default constructor and one that takes the or one that initializes some options which it passes over to the db context so db context here basically says this class becomes uh an entity framework recognized class representing the database that we're connecting to so that's very important then later down you see where it goes on to say that it is um initializing a db set of type author and it's calling it authors that's the name of our table and book and books the names of our tables they're initializing them to null and then it goes on to do the unconfiguring but it's giving us a warning it seemed to protect potentially sensitive information don't have it in the file like or we have it here and that's fine because that is exactly why we do it in the configuration and then we initialize it at startup like this so because of that i can actually just remove that entire line all those lines can go that's what unconfiguring can go then you're going to see some other on model creating um properties or directives here where these are configurations on the entities so based on the constraints that we had set in the table we would see that we have those constraints here so last name max then 50 bio maximum 250. we'll go down here you'll see here that the ice bin is unique right so these are all code first directives but these are not written by us first they're generated in code by the scaffolding engine so the reality once again is that you might end up working with a database that has more than two tables and tables with more than five properties at a time this is how you can use entity framework to generate in your own application what you want this application or this database rather to look like bb context and everything and then you can start working configuration wise all we have to do is let it know about the db context and it will go ahead and add it to the startup for us so our application can work now moving forward the situation might be that you may need to add other tables you may need to add other things to the database you will have two options option number one is that you can do it the same way you did it when you were creating the database and add them in the database engine itself and then do the scaffolding activity but that would require you to always be changing your db context that's option one option two is that going forward you do the code first approach so if i wanted a third table here i just need to go and add a class give it a name like maybe i'm going to this is just an example so this is just going to be called code first table and then you put what you want in code first table so you can say you know prop hint id so when you do code first and you say id it automatically knows that this is the primary key and this is going to be an identity and you can just fill in some other properties i'm just using the prompts given to me by by visual studio so after doing all of that what i would do is add it to the db context afterwards so now i can say that i want a db set of type code first table and the table name should be code first tables so going forward i can take that approach with every other table that i intend to add to the database once i do that i can now go to the package manager console and say add hyphen migration and then give it a name so i would say added code first table press enter and entity framework would then generate this migrations folder which is going to contain a file stating all of the changes that need to take place in the database table now if you pay close attention you realize that it's actually trying to create everything and what will happen is that you'll run into errors when you try to run update database because it cannot create authors as authors already exists so at this point we will need to modify the migration a bit but this was only a test i'm not going to proceed with this instead i'm going to remove migration and you just need to go back and type in the command remove hyphen migration it will undo the most recent migration that was generated and since we only had one it even got rid of the new folder and everything so i'm going to remove that new test table and the time when we're going to be doing our migrations with a bit more conviction will be when we're adding our user tables to our project so for now we've scaffolded the database that we've designed it's now in our app and ready for you so we can close out that activity at this point all right guys so i'm going to start off by fully explaining what's happening inside of this author class it's really simple one we scaffolded the database so what it did was create a class that has properties that model the properties that we would have added to the table called authors so we have this class which is a partial class meaning that we can extend it if we need to we can always create another class and we can say public partial class author and add other properties to it maybe override or extend some of the properties that are there but i'm not going to do all of that in this particular session what has been generated is fine you'll also notice that some of them are nullable so once you have that question mark it means that this property is nullable so because in the database design i did not set them to not null or i didn't tell the database that it can't accept a null value for first name last name and bio in generating the data types it reflected that as best as it could you'll also notice that it has a collection of books so one author can have many books so that is a one-to-many relationship that we created at the database level so our class model has author which has a collection of books that is how it shows that one-to-many relationship so that is all that i'm going to go into for the author model class of course it is being referenced inside the db context so this class is just a representation of what an author record will look like inside of our table called authors which once again is just being modeled as a collection type called the set so our task today is to create a controller that will allow requests to come in from any client app or from any user to interact with the data being stored in our author's table and the db context and our model class author will be very instrumental in helping that happen so to create a new controller we go to controllers right click click add and go to controller and here we want to create an api controller so you see i have regular controller we want the api controller now we have three options we can go with an empty controller we can have an api controller with read write options or actions rather and then we have an api controller with actions using entity framework so this one is actually the easiest one to get started with because it will come wired up with everything that we need to interact with the database so i'm going to go with this one we can double click it and then it's going to ask us what model class do we want to use well i only have a few and author is one of the few so i'm going to choose author then it's going to say okay which db context remember the db context here represents that connection or that gateway to the database so i'm going to go with the db context the controller name authors the authors controller i can leave that and i'll just go ahead and add now this process may take a while so i'll just go ahead and give you some insight while it's doing what it's doing if you get an error during this particular phase especially if you're using net5 or you're using dot net six beyond the version libraries that i have what happens is that when you have library version mismatches with entity framework you might get an error so if you do get an error about scaffolding or anything like that just go ahead and go to new get package manager and what you want to do is jump over to updates and make sure that you are running the latest versions of all the libraries all right i don't have any updates right now all of my libraries are in the same version and that is probably why it's playing nicely with me but experience teaches wisdom so i'm just helping you along just in case you run into that difficulty so what we got from that procedure is an controller called authors controller we have the root here that is defined as api slash the name of the controller so it's api authors and then inside of that we have a bunch of actions so a controller has actions every method that you see inside of a controller is called an action and these actions are optimized or well they're designed really for the different kinds of requests that will come in from the users so we already kind of explored requests as the verbs get post patch etc so you would get a few actions that go with the basic requests that you would get to go against any kind of data one to retrieve it or well two to retrieve one gives you all the other one gives you at least one or one based on the id we have one to put put is basically an update right so anytime that we need to update a record we use the put verb we have another one to do post post creates right so anytime we want to submit data to the database we're going to use the post and then we have delete which i think is self explanatory so if you ever used regular mvc then you're going to see a lot of familiarity between what you would have scaffolded in a regular mvc app and what we have scaffolded in this api controller however the mark differences one you notice that all of them are kind of decorated with annotations to depict what kind of verb is going to be used for this particular action so even though the action has its own name and this is really just because every method has to have a name right so it has a name and it takes parameters sure but if you look at the comments that you got from the generated code that would guide you on how you actually interact with the method or the action so that means when you're making the request you're not going to say you're not going to try to call get authors you're not going to do that you're actually just going to say my verb is get and i'm trying to go to the endpoint api authors the controller once it gets this kind of request will know that this is the get in the author's controller and it will return the the data that is requested so that is pretty much all that's happening when you see those comments it's just showing you what those requests need to look like so here when you get when it when it you sorry you'll notice that you have the same end point for the get as the put however the difference is that one is get and one is put so when it gets a put request with that particular endpoint it will know to go here and not here so let me just give you a quick tour of what the code is doing and then we will do some tests and when we come back we'll look at how we can optimize what we're looking at so our author's controller is inheriting from controller base generally speaking when you generate an api controller you're going to get that so you don't necessarily have to worry about that what is happening here is that it is injecting the context into the controller so when we talk about injection we talk about the inversion of control uh container or dependency inversion which is one of the solid principles that's actually the d in solid so what happens is that in the program.cs we register our services like would have registered the db context and once it's registered there it's now available for use in any other file once it can be injected or once it has been injected rather so once we inject what we're doing is we're saying give us a copy of the context that is in the container and i'll make a local copy and use that local copy inside here for my operations so that means one copy is being circulated around the place and later on we'll look at the different kinds of injection models that are there for no let's just focus on how this is happening so once we have a copy of the db context that now allows us to interact with the database because the context basically represents a database connection all of the objects that are in the database namely the tables that would have been listed here in our db context and using entity framework we can actually interact with them in different ways so for the get that is saying give me all the authors it is a task that is returning an action result that is also returning a collection of authors so here you see that we actually can specify the data type that is being returned and when we go into the swagger document and later on you see the value of having the return type specified inside of this heading but typically you might just see something more like returning a task of i of action results you wouldn't always necessarily see the return type like that right but when we do do it like this we can just return all right so basically this line context dot authors dot to list async is returning a select star from authors command so it's saying database get me this table and parse everything to a regular list and that is what i'm returning you'll also notice that they're decorated with async the methods have async and the commands have a weight so once you see async appended onto an entity framework method that means that you need to prepend that statement with a weight and the method in which this code is being called needs to have the tag async and it has to be a task so we'll see more of that when we're writing our own code but i'm just explaining what all of these elements mean so where are we so this is basically just going to return all of the authors so if you want you can also qualify it with a return type so earlier i had mentioned that you have different codes that you would generally return so when you return the data with no mishaps that's an okay return by default you can also specifically say that you are returning okay there are other kinds of return types so okay is 200 but then if we go down to the http get notice that this one is also a get but it is saying that we are expecting a parameter called id right and if you look at the the url you see it's api slash authors slash an example so once you put that number after that end point then it is going to get parsed into this variable and this one is get author now get author is going to say var author is equal to database look in the table called authors and find by id pretty much and of course that's async so this is await and that has the async flag now if we cannot find that author meaning that it went to the database and checked and there was none then we returned not found so that's another return type and not found is really just a 404 you can always hover over it and just read up on the status codes and you see it's returning a 404 so that's that error code that will go back when a user tries to find an author that doesn't exist however we will just return the author or once again you can qualify it and say return okay author so you know yes we found the author you got back at 200 and that's the author but once again if you don't specify that and you're returning actual data then it will always default to a 200 so i tend to put it because i like to have it explicit that i'm returning at 200 at this point so let's move on to the put put once again has a very similar looking endpoint to the get however the verb is http put this one is http get this one is put it also takes that parameter which is the id and it will also take an object of type author because when you're putting when you're updating something you have to send the record that you're updating so i don't know what changed i don't know if you change the author's first name or his bio i don't know so instead of sitting down and saying oh which one is different from the original i'm expecting the client to tell me the id of the record and give me back the full record now by default it's going to do some checks one is going to check if the id that came in matches the id on the record because sometimes clients made that mistake if they don't match then we're just going to say bad request bad request is a 400 quote so if i hover you'll see that that's a 400. so bad request note tells you that you asked me for something but you didn't ask properly or there's something wrong with what you asked so i can't help you that's what bad request means so then if we go beyond that bad request we're going to go ahead and set the entity state to modify because this represents the entity that you are updating so we're going to tell entity framework that it is a modified entity please watch it and save the changes accordingly so we're going to try to save the changes once again save changes async so that we have to await and that makes the method an async task so when we try to do that if we run into any errors then we're going to have to say okay not phoned or just throw the error based on what the situation is of course this is all default code we can modify that based on our needs and business rules outside of all of that we return and all content now no content is deceptive because the words no content suggests an error but it's really a 204 response so generally speaking when you talk about response codes 200 is good anything 200 to 299 i guess is good anything 400 and 500 is bad so 400 401 403 404 500 533 all of those are just bad right so generally speaking you want to do an old content because we updated i don't have anything to tell after i've completed this operation i don't have anything else to give you right it's not like when you requested data on an author or on all the authors you only gave me a directive and i completed the task so i'm going to tell you well the directive was done and i have nothing to show you for it but just know it was okay so that's what no content really means then we move on to post now post is where we create so you're going to send over the post request using the endpoint that looks very similar to the get but because it's a post we decorate it with http post and what we want is an object of type author that we are going to be adding so this will be gleaned from the body of the request and i'll show you how all of that works and then we go ahead and say database in the authors table please add an author actually i think that there's an ad a sync that we can use there we go so add async and then of course if i'm adding async i need to await all right so add a sync and then save the changes so whenever we do these kinds of changes add or even something like changing the state anything to modify the data we always have to do our save changes using entity framework after we've done these successfully then we will return and the creator that action is a 201 so this one is 201 created so it's specifically designed to say yes i have created it and what we're seeing is that it has been created at an action called get author and the new id is that with the author so basically the response the person will get after requesting to create an author is all of the details of the author that has now been created successfully including their id as it is now in the database and we would send them back to the endpoint get author now to me this um what this is what you call a magic string so i'm going to remove the magic string by saying get name of get author meaning this is the name of the endpoint but if there was an error here or if i changed the end point up top if what if i said get author by id what if i preferred it being called that there will be no way for the code to detect that these don't match anymore right so a simple change like that could create a massive error that could take us to debug so what we usually do is we say name off and then we can call the name of the method and because that method doesn't exist we get an error so i have to make sure that that method exists so that that error will disappear right so that's why you would see name off sometimes instead of the string representation of the action or the method or even the class sometimes now let's move on to delete so delete once again that's going to look just like the put just like the get it's taking a delete verb http delete right but we're passing in the id once again and then it's going to try and find the author so if you're requesting to delete an author that probably no longer exists or you give us the wrong id then we're going to tell you not phone that's a 404 otherwise i'm going to say database go into the authors table and remove that author record then save changes i don't believe that there is a remove async there is not right so remove is remove and then we return no content no content just like what we did when we did the update then another generated method which is not an action as you can see it's private as opposed to public like the others this one is just checking if the author exists so i can transform this into an asynchronous because there is an nea sync and if we make it any async that means we have to await and then that means that this has to return an async task that returns a boolean so that little activity that's your first taste of making something into an async method now this is async that means the calling code to the async method has to await so i would have to say if not await author exists then we return not phone and that's basically it that's the tour of the generated author controller and the thing is that you can do this all day right as many classes as you have that you want to build api endpoints for you can scaffold them using entity framework and you can do that as you can see in five minutes in less than five minutes you could have scaffolded quite a few and i just took a few minutes to explain what the code is doing so that you have a better appreciation of the different changes that you may need to make based on your business rules now there are a few downsides to the generated code and one of them is that you don't generally speaking you don't want your entity class to be the class that is being used to taxi data your entity class needs to be what the database interacts with not your action not your endpoint so when we come back what we're going to do is look at how we can control or have a or place some better controls around what data is being used by our endpoints and interacted with before we go though let's press our play button and do a quick test just to make sure that everything is working fine so this is our swagger dock and just by scaffolding our controller and everything we have new entries in our swagger dock so you can see here that it knows about the authors it still knows about weather forecast because that controller exists and if we look down here we'll see that we have different schemas so the schema here is just a depiction of what the json request body might end up looking like for author or for book or for weather forecast right so i'm going to try i get so if you look at the get this is what one can expect to get when they try to get an author right they're going to get the id of the author the first name last name bio and their books now you notice that we have the square brace different from the [Music] uh curly brace and when we were doing the app settings configurations you would have seen that the square brace represents a collection off and then the curly brace represents one object so books is a collection of objects that look like that and when we do i get as many authors as they are it will be a collection of objects that look like this we don't have any yet so i'm going to try a post first so in the post the request body needs to look something like this remember i said that the post endpoint is waiting on data waiting on data where is that post there we go that looks like an author and if we look at the fields inside of author i'll just hit f12 to jump over there then you'll see we have id first name last name bio and collection of books so here you're seeing that we have id first name last name bio and books we may need to create an author without creating books though so these are the things that i'm saying we we may want more control off when interacting with the api however let us take this for our test so i'm just going to click try it out and i'm going to delete the books section because i really don't want to provide a list of books and then i don't need an id because i'm creating so i can be telling entity framework what the id should be i'm only supposed to be telling it what the properties that i'm interested in are so let us try david uh david strong and bio first author all right and then execute and you see swagger is so convenient because no we don't have to always jump over to postman to do this but now you see that our request response our response rather 201 code it's letting us know the response body here is our new author so in the clients now you have the author that was just created you can actually show the user oh you know this is what was just created you can redirect them because now you have the id you can do so many things with that kind of return data so now that we have at least one author in our system if i go up to the get and then i say try it out and execute then i'm going to see i get a 200 response with a collection of authors i only have one so yes it's a collection or an array but i only have one if i go to that was the post so if i go to the get that requires the id say try it out and then i give it the id 2 then what should i get a 404 because there's no author in the system with the id2 so oh i'm sorry i meant one let me execute again there we go so now i'm getting a 200 response with the author that is in the system and that's really all there is to api development at the very basic level but like i pointed out there might be situations where we don't want to deal with or allow the user to have to deal with all of this at one time right so there when we come back we're going to look at data transfer objects which are the ideal way to have better control over the data that we choose to actually let our clients or users know about while obscuring what's really happening behind the scenes hey guys welcome back so the last time we were here we were discussing why we don't want to show the user all of and it's pretty simple for certain operations for instance the post we want to show them the bare minimum that we know that they need to provide to complete the operation however by default because we're just using our entity models which has you know all the data we could even have audit fields that the date created and the date last modified we don't need the users to be seeing all of that we don't want them to be able to interact with any of that data so what we want to do is create abstractions of the real data that we want to store behind the scenes and just show them what we think is best for them so what we're going to introduce at this point is dtos or data transfer object so data transfer objects generally look a lot like maybe the entity because they have to have the same names on the properties the same data types of course but they are more like models that represent the data and at a granular level we probably end up showing different models for the different types of operations to be completed so i'm going to explain what i mean by that let us start off by creating a new folder and i'm going to call this one models we can call it models we can call it dtos um you know whichever name is best for you so after doing that i'm going to add a new folder i'm going to call it authors so instead of models we're going to have models for our authors so or sorry author shouldn't call it authors author so my first model that i'm very interested in creating or my first dto would be the create author details so author create detail that's what i'm going to call it right so what do i want to show them when they're creating an author well yes i do want an id let's see what visual studio has in store for me so i'm going to say prop hint id all right what comes next only name but i don't want name i want first name right now that i have first name they're probably going to suggest the last name and maybe not so i'll just duplicate that and write in last name so ctrl d is what i used to duplicate just now and when you see the autocomplete come up you can just press tab to let it complete now you're seeing that it's warning me about potential null values so what i can do with dtos that i probably wouldn't necessarily want to do with my entity model is that i can enforce certain validations right so actually this is wrong so i don't want to show them the id so let me remove that right i apologize so all i want them to be able to provide for me when they're creating an author would be the first name the last name and the bio right nothing more than those three you can't be telling me the id so i don't want you to give me an id value i also want to have certain validation so i can use annotations above the properties like required and that's going to require me to add a using library so the first name is required i can also put restrictions on it to say like um string length right is 50 and that length is in keeping with what i expect for the database so these restrictions will happen on the api level and it allows me to enforce rules at that level that i would that would match the rules at the database level so i don't even have to get to the database side for the database to reject it or modify it i can reject it at the client side or the api side rather just by having these annotations right so i'm going to do required and 50 for both the first name and the last name and then maybe for the bio i don't need a bio but i will say the string length is 250 right so notice required remember that they are nullable in the database they're not really required at the database level but to me it doesn't make sense putting in a record that doesn't have a first name and a last name so at the api level i can enforce those rules so how do i use this dto at this point well what i can do is jump over to my controller and then i can now modify the post to say that you are supposed to be accepting a parameter of type author create dto not author dto but author create detail i also don't want to interact with author detail directly so i have to say author create detail so at that point now i'm faced with the dilemma because my database needs an object of type author not author create which is why i'm getting this error and you see here i'm getting other errors because the dto for creation does not have the id field so i have another little modification that i have to make here i can either one create a new author so so what i'm going to do is rename this to say dto so author here represents the data object so that's equal to a new author object and then i can go ahead and assign each value so i can say now the bio is equal to author dto dot bio and then the first name is equal to and you see i'm getting a little help here and that would be it and then we can send over that author to the database but that's a lot of work especially if we're not just dealing with three fields so that is where we call this new utility called autumn mapper into action so i'm going to jump over to my package manager and then i'm going to look for the automapper.extensions.microsoft.dependency injection so i have it here but if you don't see it there you can always just search for automapper but this is the one we want the extensions for dependency injection so you can go ahead and install that package and what this does is introduce a library that helps us to convert data types so pretty much we're going to be able to in one line convert from the author create dto to the author entity type so let's see how this works i'm going to create a new folder i'm going to call it configurations so anything that has to do with setup will go in there and then in configurations i'm going to have a class that i'm going to call mapper config so this mapper config class now what it will do is one inherit from a class called profile which comes those currency of autumn mapper so just add that using statement using autumn upper once again you can always use control dot to get that quick help and then i'm going to have a constructor so i'll just say ctor tab tab and then we get our constructor and then here i create the mapping configuration so i'll say create map and then basically it's saying from what type to what type so source the destination so source here would be like my author create dto and ctrl dot to get that namespace in there we go and then i would like to map to the author from our entity class right so that's pretty much it but then you know we may need to do the reverse also so what we can do is just say reverse map so in either direction the mapping would work and that is how we create the mapping configuration so going forward whenever we introduce a dto we are going to have those mapping configurations so one thing that we have to do is let our application know about automapper so we have to jump over to the program.cs and then somewhere here let's just add it underneath our setup for the database i am going to introduce a new line that says builder dot services dot services dot and i would say add auto mapper so because we have that library for dependency injection we can actually add the mapper right here and we will specify that the type it should be using is type off and then we call in the mapper config file that we just created so once we have done all of this we can now inject a copy of that configuration into any file where necessary so let's jump back over to our controller which is where we would like to do that conversion right so i'm going to now inject the mapper here so i'll just in the constructor say i mapper and i'm going to call it mapper so two things i need the using statement control dot get that in and then ctrl dot again and a quick way to get this injected is to say create an assigned field mapper so it will just handle that injection code for me so now we have a mapper object present so in the post i can now say mapper dot map and then i'm going to say i want to map into an object type of author and the data i want to map is the author dto of course this has to go somewhere so i need to introduce that var author is equal to and then that mapper code and then look at that so in one line i have now said i am getting author create dto but i want to convert it into an author object and then we will pass that over to the context so now everybody is happy so from the client side let me show you what the documentation will display so in swagger when i go to the documentation for post now i'm seeing a completely different schema this schema is the author create dto schema so you can see down here auto create detail where we're only asking for first name last name and bio and notice that it is telling you all of the constraints it is required hence the red star and it can only take a maximum length of 50. of course we can put on minimum length also based on once again your business rules but here we're seeing a lot more contextual data that is specific to the creation of an author and the validations thereafter right so what i'm going to try to do is create an author with invalid data right so if i say first name blank last name blank and then hit execute what's going to happen it's now returning a 400 and then it's automatically telling us what the errors are last name is required first name is required so we can't get past that gate we just got back to 400 automatically and i say automatically because i didn't write any explicit code in the post to handle any of that right so that is some automatic exception handling happening in the background and that's really good but my point is that at this uh based on this indication now there's validation and there are restrictions on the type of data that we're allowing in so even if you put in more fields like you try to include that id that i said we don't need right if i put in id as a field and i try to say id should be 20 when you're creating right so i'm going to say test author right and i'm specifying the id as 20 and the bio is this is a test to see if the id will get processed all right typically if if i didn't introduce the dto where i didn't have the id then i would have gotten an error because entity framework would reject it saying that you can't give me an id and then tell me to add however in this situation when i execute it will be successful right and the id will be two why is the id too because the schema is really just looking for first name last name and bio so anything else that is extra id even if you put in your own field you made up other fields age address whatever if the schema is not looking for it it will not get processed so by the time it got to this end point all that got gleaned from the whole payload of the data from the whole schema that we submitted were the three fields that we outlined first name last name bio they were automatically validated based on our annotations here and then having passed through they were converted into what an author entity for the database needs to look like an author record then added to the database and then we got our return uh message of 201 with where it was created and the data of the author so that's pretty much it for introducing autumn upper and dtos so my challenge to you at this point would be to create details that you feel are necessary for the rest of the data because when we're getting all the authors you may not necessarily want to see all the books right um when you're getting one author you may not necessarily want to see the list of books either you may want you may not want to but i don't want my entity records to be used at any point for the collection or retrieval of data so that's my challenge to you go ahead and change them out create other details i'm going to do it some you can hit pause right now challenge yourself create details and swap them out introducing the mapping of course and when we come back we can compare notes all right guys so i hope you at least took on the challenge to flesh out the other details if not no problem i'm going to walk you through each step and we can do them together so as i explain of course you can hit pause replicate what i have done but i am explaining all the changes that i've made since the last creation so the last thing that we did was to create the author create detail at this point you can make a decision whether you need a detail per operation or just one detail to rule them all the danger of one detail to rule them all is that you might end up exposing properties that you don't necessarily want to expose for certain operations so you want to be mindful of that as you go along so that is why i created author create dto specifically for the create operation it has only the fields that i know or properties i know i want during a create operation for an author however during an update operation i will need the same fields pretty much the same kind of validation but i also need the id field when updating because remember that the id field needs to be present so we know which record is being updated so you'll notice here that while this author update dto looks identical to the create one i also have an inheritance happening right here to a file that i created called base dto so i created base dto at the root of the models folder and base dto pretty much just has one property which is the public int id so every every type of detail or every detail that or sorry every entity that a dto is modeling will have an id at least based on the way that we have designed our database so this is just a base value to say everybody is going to have an id once you inherit from this dto i also made it abstract because i don't want it to be able to stand on its own it's only there for inheritance purposes so that way i don't have to repeat id every single time so our update dto definitely needs the id so i just inherit from base dto our author dto also needs the id and i'm using author dto for the read operation so i could probably even just call it author read only bto all right i think i'm going to do that i think that's far more explicit now that i've said it out loud so author read only dto by updating the file name i can just go ahead and say yes and it will update the class name also so this is not to be used for any deletion or any crud operation it's for reading so it's only going to be used for the gets so when we get an author we inherit from base detail because you should be able to get the id and you have the same fields or properties and probably even more and it could be that you know you want to expose certain ones for the get by id different from the ones for to get the list because when you get the list you probably don't want to send all 50 fields you only want to send five it's up to you once again however those are my details that i've created so we already know the create detail i have created the read-only detail as well as update dto and both the read-only and the update inherit from base dto which only has base properties that every dto should have and know about now let us look at what differences um would need to be infected sorry in the author's controller so we're already inheriting sorry we're already injecting our mapper we know that part i'm going to start off with the get so i've rewritten the get to take from the author read all the details so it's returning an innumerable of author read only dto and then i change the code to say var authors is equal to mapper dot map remember that we need to specify the data type that we're going to be mapping to so i'm specifying that i'm mapping to an innumerable of this data type and the data that i'm mapping into that would be await context authors list async so if that seems a bit confusing let me break it out a bit more right so i could say maybe var authors var authors is the data from the database we know that this is looking to the database and getting the list of authors i'm storing it in that then i can say var let's call this model model authors right just so it's specific that is detail or author details let's call it author details sometimes i get um caught up on my names right so authors from the database and also dtos would be equal to mapper.map into the data type we're interested in so it's a collection of author read only dtos and then we want the data that we're mapping that's authors and then we return the author details to the calling client all right let's move on to our other get by details so when we get by details yes we go and fetch the author yes we check if it was phoned and then here let's call this author detail again just so that we're clear with what it is instead of model so author detail at this point is now going to be equal to mapper please map into author this should be author dto right so we're mapping into author dto the author and i messed this one up so let me fix it with you guys alright so we have the author oh i'm sorry that's that's my that's oh the data type is author read only detail there we go all right so once again we go and fetch the record from the database if we find the record that means it only gets this far if the record was found we know that already then we're going to say mapper please convert author into type author read only dto and then we're returning the okay response with that dto so it would have stripped off anything that is not absolutely necessary so if once again you had audit fields that you don't necessarily need the client to see or know about that's what the dto does it's that line of defense moving on when we go down to the update i've converted the incoming parameter to author updates dto and then for the update operation this mapping is going to look slightly different so no i need to go and fetch the original record from the database based on the id that was provided which you already determined should be a valid id and then well actually i determined that the two ids much i haven't determined that this record exists so i need to introduce this kind of if statement after trying to fetch that record so that we don't run into any null problems so if the author that was fetched from the database is equivalent to null right then we move on to the mapping and i'm breaking my own rules here this needs to be find async right there we go so let me fix up my code should i fix this before i presented it but it's good to see mistakes we're all human right so let's go again var author is equal to await database go and fetch the record from the database we check if that record exists otherwise we give a 404 and if it does exist then we move down to the mapping so here we say mapper.map and then this method takes the source and the destination so pretty much what it's going to do is say i'm converting or i'm converging these data types so anything that is different in author detail that from author please copy it over so it's basically doing like an informal object update all right so it's updating the record values from the database with the values from the dto that came in with the update request and then we set it to modified and then we save changes now moving on when we are creating we went through that one already so i'll just skip to delete and there are no changes here in the delete because this one is only dealing with the id so there's no detail necessary for that so i'm going to execute once again and let's test now if you look in the schema areas you don't see anything about books and you don't say anything about author now you're only seeing the details and these are the details the data types that i am telling the clients they will be interacting with so here is also create detail with all the validations here's the read only with no validations here's the update with the id and the other fields and then well weather forecast is still sitting around somewhere so if i get authors we're going to be getting the dto so let's just make sure that our mapping works and oh that's not good it failed so it's telling us that we got a response 500 so that means the error is on our side 400 means the error is on the client's request side 500 means that it's on the server side so it's telling us that we have an error with the mapping so that is a vital step anytime you are doing this kind of mapping operation you need to let the configuration know that it should expect that kind of mapping so we need to go to our mapper config and update it so we introduced author update dto that should map to author and we introduced the author read only dto that should also map the author now with those changes made i'm just going to hit my fireball here for how to reload so we'll just do a rebuild and then we can just come back over and try that again so if i go to the get try it out and execute then we will see that we are getting our records so make sure that you save your files do a build make sure the build is successful and then if anything you refresh swagger and try again but here we go we are now seeing our records as they were in the database so we looked in the database we got the records we converted them to the dto and that is what the client is interacting with so if we do like a put then you'll see that the put is far more concise if i wanted to update the record with the id2 so of course i have to specify id2 in the body and i'm just going to leave everything else so record with id2 said test author and that nice long bio now i'm going to change everything to string string string execute and we got a 204 nothing to show it was successful however to validate that i can go to execute and now i see that it's now changed to string string string string so that is how you introduce details that's why you introduce details once again you may not end up with as many dto files based on your requirements or you may end up with more that's more of a design decision than me telling you what's wrong or right but the concept is that you don't want to have your entity class as the class that is being advertised by your api for interaction all right guys so let us start off fresh i've closed all tabs that are not absolutely necessary right now and the first that we're going to do is scaffold our controller so i'll just go to controllers hit add go to controller we want an api controller and once again i'm going to scaffold using entity framework this brings up our little menu where now we have far more classes to choose from but we know that we want to use the book and that will have us using the data context class and the control name will be books controller so we can hit add and once again if you experience any errors just make sure that all of your packages are up to date and are the same version so when that is completed we get our controller that we are already kind of familiar with so the only real difference differences in the code that you might find uh would be none actually i think this is the same boilerplate code that we would have seen with the authors only instead of authors we now have books right so the same dangers the same concerns that we had last time we do have no because one we see we're dealing with the actual entity type we need to change that out right we are also going to want to put in some error handling and some logging so we'll be doing all of that as we go along but for now let us just go ahead and test and see if our books controller is working the way that we expect it to so in swagger as expected we have our new endpoint but you would also notice that in all schemas are now reintroduced because authors are involved with books and vice versa so because we've now introduced books it has to bring back the author schema but we'll soon address that so let us try and create a new book this is a schema body for a book if we try it out we shouldn't be producing an id we can leave the title i won't change out anything that looks like it has a valid value right no image when we start doing the client app we will flesh that out price i'll move that to maybe 10 author id is zero at this point and then it's taking a whole payload for the author i don't think that's right i shouldn't have to be providing an author or the details for an author and the details for a a list of books while trying to create a book so you see all of these are reasons why we would always want to say have a dto manage the interaction so i'm going to remove the data that i know i don't need to provide and the author id i believe i have authors one and two in the system so i'll just leave that as author one for now and let me execute and once i have executed it is successful so i get the 201 and this is the first book in the system title is string year is zero price is 10 everything looks okay author is null all right we have to work with that and if i go to the get let me get all books try it out and execute then i see the list of books coming back with only one book object of course because that's all we have created so at least we know that the operation works the crud at the most basic level is working what makes crud require customization is one how we want the api to look like um for instance we don't want all of this data to be exposed so that's why we have the details and whatever other business rules might govern the creation or the interaction um between the api the incoming request from the api and the data related operations so that's where business logic and business rules will apply for now however we have completed the creation of the controller when we come back we will be retrofitting it with some dtos and with autumn upper all right guys welcome back so what we're going to be doing is setting up some details for our books controller right so in our models folder i'll just create a new folder and i'm going to call that one book book all right and here we are going to add a class let me call this first one book dto so book dto is going to represent or i should have said book read only detail so let me change that class name here and then i can use control dot to also rename the file right so there we go and i'm going to say base dto is what it inherits from so we know that it's going to have a minimum that id now what properties should that read only have i would want it to have well i will need the id we have that already you will need the title the year the isbn it will also need the summary uh pretty much everything here right so any book that is being listed probably we should provide all of these fields however if i am looking at the details of the book i would probably want to see the author's details which is what i would get through this property so how do we gauge that well book read-only detail right now i only want this to be what i use in the listing so let me update my controller here so i'm going to say i mapper kind of doing it mixed up but i'll be back and forth right so let's get the mapper in uh and inject it there we go and then for the get that is bringing back the list of the books i am going to say book read only dto that is what i wanted to return which means that i'm going to have to say var books is equal to go to the database and give me the list of books and then i'm going to say var book dtos [Music] is going to be equal to mapper.map into book read only dtos but of course this has to be a collection because if i'm booking one to one mapping sorry one to one then it's one to one if it's a collection to collection then i have to make sure i represent the collection as a mapping type from another collection and then we're returning an okay response with the book dtos of course we saw that the okay is kind of optional right so just for context this is when we're looking at the list of books so imagine the client side application just listing all the books certain details will need to be there certain details don't necessarily need to be there so if you're just looking at books you'll probably want to see what properties you'd want to see the name of the book you probably want to see the year it was published you probably don't need the isbn when you're looking at the list of books you probably don't need the summary either an image would be nice the price would be nice and maybe the author's name would make sense right so i'm just giving you an idea of why we have details so with the authors you probably didn't see the full picture because it was almost like for like but in the case of the books we we are thinking ahead we're saying okay what would we want to return when somebody's just looking for a list of books so i'm going to put in the properties that i know i would probably want to see so public string title right and what else was there i just duplicated that so i can just put them in so i don't need to see the year of the book year of publication maybe maybe not summary i don't need the summary for the list i will need the image so let's put image there no problem uh price would be nice so let's make sure that we have that so i'm going to write decimal price and then i would probably want where am i i would probably want not the author id but the author's name right and the author id might be a nice touch because maybe by clicking the name of the author you can go to the details page of the author right so i will include the author id and the author's name so id sorry int author id now remember that the properties have to have the same name and data type for a successful mapping to occur right so string author name all right so that is our read-only dto that is what we're returning to the client whenever they request a list of the books from our library so how do we make that happen all we're doing is looking at the database and then doing the mapping which means that it's getting all the records here and then it is systematically well taking what it can find as a mapping match and ignoring the rest so let us state that for a quick tour if we look in the get method for the books now we're seeing our dto and if we try it out then what we will get back is a mapping error all right so remember the cardinal rule if we introduce a mapping in the code we need to set up the config which i failed to do so we need to go over create map between book read-only detail and our entity called book so let's do that hit our fireball or just do ctrl shift and b so it does a rebuild jump back over to swagger it should have reloaded if not just go ahead and reload it try it out and execute again and this time we do get our 200 response now notice we're not getting the author name so we need the author name so everything is coming back except the name so we have a number of ways we could do this we could um for each one that came back we go and fetch the author record i don't like that one though so i'm going to show you the one might just show you my solution so i'm going to on the query to the books say include so an entity framework anytime we need to include details like if you did database you know that when you have um details in other tables apart from the table you're running the core against you use an inner join or a left join so include basically simulates that join for you or generates that join code for you so you just say include um sorry let me start from the top database go to this table table while you're being fetched please include the details and we just have a lambda expression here where i say include the details for the related entity which in this case is author because if we look at the book class definition for the entity we'll see that they have an author so this virtual property basically represents the author record that is related to any one book so just by saying include author it would automatically know to just do that left join and bring back the author details also and then we want everything to list now when we do that we can say an ebook object dot author dot name but i want the full name so i'm going to jump over to the mapper config and then i can actually say when you are mapping from the book to the book read only let me just make sure that that's what it is so when we do the create map i'm just trying to remind myself so i made the right decision the source is book read dt read only detail and the destination is book well that's not necessarily the case i mean it doesn't really matter because we have the reverse map but for what i want to do it will matter so the direction matters when you want to do certain things so i want to say when you're mapping from book to book read-only detail i wanted to do some transformations i can actually tuck on other methods here before the reverse map so i can say for property or for member actually not for property for member there we go and then i can use a lambda expression where i say four member author name then i can comma separate that from another lambda expression and nothing is being typed let me try that again there we go so comma separated from another line by expression i'll just call that one d where i can say and i have a number of options here all right but i'm going to say map from which then is a method that takes another lambda expression so i'm going to call that lambda object map and then i'm going to say uh let me just do an interpolated string where i'm going to put in map dot first name or sorry map dot author dot first name because map is giving me access to the book object that i'm looking in for the the transformation right so i'm going to say give me the included authored and his first name and then do the same thing for the last name and then that interpolated value when the mapping occurs will get stored inside of author name so that's a nice and easy way to let autumn upper handle that kind of operation for you and reduce any other additional queries that you might end up needing to write in the back end right so let's review what we just did we converted the listing to only use our book read-only dto we are querying the books database table but we are also including the details of the author and then we are mapping them into the dto that needs to come over and then we can go ahead and return now another thing that we could do well let's test first and then i can show you a shorter way we could have written that so let us go to the get where we know we're expecting the book read only exec and then when you look at the response now you're seeing the author name so it one included the details of the author and then two our mapping handled the conversion from first name and last name into just one field called author name i think that's pretty cool so i was mentioning that we could have written this in a shorter way and that is by using an extension method given to us by automapper that talks onto our entity framework core called project two so projection is an entity framework concept where if you are running a query but you want the results in a specific data type you could actually just say books so books has a data type and we know that when we run against books we're going to get macbook objects but what if i only wanted as a specific set of columns then i would say something like that select and then using projection i could use a lambda expression and say give me a new object and specify the different fields that i want and it would give me about that custom object with just maybe id and title of course this is not very strongly typed because you know i would have to do that over and over again which is why having a dto is better and it's easier using autumn upper now i want to just select into the mapped version of the book read-only detail instead of having to get the regular one and then get the books because what happens is that it's going to do a select star from books and including all the author details to just give me back a few records so that's a bit inefficient right so what we can do is say context.books dot include that uh that and then after that and i'm just going to break line so we can see where everything goes so books include the author details and then after that i'm going to say but project to and when you're writing in project 2 you might need to include a reference so just write what i have so far so that project tool and then we give it the data type that we want to project to and then we have to give it the mapper configuration that it should use so we can get that mapper configuration from our mapper object dot configuration provider so at that point you can just do control dot and you would you have to add the using statement for autumn upper queryable extensions and once you do that books will actually just return a list of the book read on the dto instead of the books that we then have to map so i can actually get rid of that extra line that is doing mapping and then just return books all right so let's test that theory so back in swagger the expectation is that we would see the same kind of results set even though we don't we removed the line that explicitly does the mapping so when i execute ah there we go we're still seeing the details that we expect so let me just review that with you once again using this method project 2 we can let entity framework be a bit more efficient because it will say i know i need to query books i know i need to include the details but based on the data fields that are required based on the mapping configuration and the data type that have been given i know which ones that i need to include in the select query so it won't be a select star anymore it will be a select title image price author id author dot name and auth author dot first name and author dot last name and then autumn upper based on this config will do the rest of the transformation and everything will come back based on the data type that we want so i can just say var book dtos is equal to database get me um all the records converted into this and a list and that's what i will return so you know as we go along i'm going to show you a little tidbits as you get more comfortable with the concepts so what i'm going to challenge you to do at this point as usual go ahead and swap out the rest of the endpoints to the dto equivalent of what you know needs to be in there and you can hit pause right now try it i'm going to do it and then we can come back and discuss all right guys so let's start off looking at the rest of the details that i would have created so my book create detail looks something like this i have required and streamlined 50 for the title i have required and the range for the year is 1800 to the max value so you can't put in any book for negative 100. of course i could easily say something more like 1000 being the first zero or one it's the minimum to the maximum right so whatever your tolerance is for the year value you can go ahead and use that i do require an isbn i do require a summary and the max length is 250 but the minimum length is 10 characters you well i made the image optional and you will have to produce a price and the price can be zero dollars because i guess it can be free up to whatever value is the maximum value of int so that's my create now the update generally looks just like the create but it inherits from the base details so it would have made sense if i could just say book create as part of the inheritance but it can't inherit from two classes at the same time so we'll just leave it as it is with all of those fields and repeated validations i also have book details detail which includes all of the other fields that were left out of the read-only dto but i've retained the author id and author name field really because while you're looking at a book you don't need any more details about the author than the name so we can make the client when you click the author's name then it goes over to the details of the author but while looking at the book this is all you need to know so once you have those if you you know you're close to that kudos to you if not feel free to just backtrack and pause and replicate what i have for the dtos but in the controller some of the changes that i would have made as expected i retrofitted the other actions to no use details so book details dto is what i'm using for the get book right and i'm doing the same kind of projection with the mapper configuration so on that note let me jump over to the mapper config and replicate that because i didn't do it i was waiting for this moment so we'll actually reuse the mapping configuration for the book read only dto because i want that same kind of setup for the book details detail where the author name should go ahead and be mapped from the first name and last name now while i was here i was making the point that we had to do the four member before the reverse map because order matters in terms of where you place the configurations and the reverse map before i swapped book and book read only it would have been saying that when i'm mapping from the book read only to book then this wouldn't be able to happen because the one that's on the left is the one that is going to be used in the map from the one that's on the right is the one that's going to be used on the left it's kind of weird but just think about it i'm going from book to read book read only so the configuration when i'm converting from book to book read only is that when i'm converting and i see the property called author name this is the value that i want to be stored in that when that conversion happens and then reverse map means that when i'm mapping from this direction to that direction i could actually have rules to govern that also so the order matters in that regard but i'm never going to be at least for the foreseeable future i'm not going to be mapping from the read only to book so i don't need a reverse map configuration for anything else so i'm just showing you how autumn upper can help you to put certain business rules in and kind of make it easy but i tend to use these only for read only up um operations right so read only detail and book details those are read only operations and both of them have that requirement for the author name to be flattened pretty much all right so other mapping configurations that i obviously would need would include the ones for the let me just do them here while i'm here so we need the book create dto to book so notice autumn upper is not giving me an error when i changed all the types right so if i said book update detail to author it's not going to know that there should never be that mapping it's just seeing two data types and it is making it you know making note of the fact that these two are there so you have to make sure you get your configurations correctly so we have create we have update and we have the two read only once and i don't need anything else let me just delete the excess right i think we can proceed with that right i think i might have okay yes i might have erased a vital one which is the read only so let me just so let me just fix it so you can see um that's what we need so we have the author mappings and then we have the book mappings below all right so there are three for the author but then i needed four and once again that's up to you on your business rules so now that i get i have the mapper config down let's continue with the controller and finish this up so for the details get the query get include the details go ahead and project it and then notice that i had to change it from the find async to first or default because once you put the include in the query the find async can't work so you might have ended up making that change or you might have had that error and you're wondering why so that is why all right so that is what the get book looks like our put looks like this we update the property in the parameter to be book update eto and then we go through we fetch the book record from the database we check if it's null and if it is then we return not found otherwise we go ahead and do the same kind of mapping and then update the entity state then allow it to do what it would have done naturally and then for the post we update the parameter type we go ahead and do our mapping and then add the book and then we return the details and nothing really was needed for the delete and i converted the book exists method into an asynchronous method which then means that this has to be an await operation so that's pretty much it i'm just going to do a build and make sure that everything is okay you know how to test so i encourage you to go through and test them out but before i leave i'll just show you what the swagger.now looks like and you can see that there are no more references to the author or to the book entity types just the details that's all that the clients need to know about so you can go ahead and you can try creating of course look out for those errors like the mapping errors in case you may have missed one and if you get any other errors you know just let me know and we can work through them all right guys so i think we're done with the two controllers and well what they can do what i'm going to skip for the books controller is the logging and the try catches we already discussed the different options that we have in the others controller but you can see that the control is kind of swelling with all of the try catches and all the logging errors and so on once again that's more up to you than me saying that this is the way it should go so if you want to introduce all of those things to the current controller the books controller then by all means do so but i'm going to leave one pristine and the other one in the more you know i'm going to say heavy looking way later on we look at more global things that we can do so we don't have to repeat that for every single controller that we ever build but for now i think we have gone to a good place with our configurations and our new controller con the functionality and our details so i'm just going to go ahead and in get changes put in my message and once you have done that also you can go ahead and commit all and sync and when we come back we'll start looking at authentication and authorization [Music]
Info
Channel: Trevoir Williams
Views: 19,821
Rating: undefined out of 5
Keywords: entity framework core, entity framework, asp.net core, .net 6, .net core, .net core web api entity framework database first, entity framework 6 code first, asp.net core 6 web api database first, entity framework 6, web api crud operations with entity framework, database first, asp.net core web api, web api crud and postman, web api crud operation, .net 6 core, web api crud, web api, database first approach in entity framework in asp.net core
Id: -yUsrUAUfHs
Channel Id: undefined
Length: 120min 26sec (7226 seconds)
Published: Tue May 10 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.